Взаємодія з клавіатурою

Основи

Ніякий графічний користувацький інтерфейс не вважатиметься досконалим без надійного способу взаємодії з користувачем. Програма curses повинна бути чутливою до натиснених клавіш або мишки користувача. Спершу, давайте розглянемо клавіші.

Як ви вже побачили з попередніх прикладів, отримати ввід користувача дуже легко. Найпростіший спосіб отримати натиснену клавішу, це скористатися з функції getch(). Для цього необхідно ввімкнути cbreak(), щоб бути в змозі читати окремі натиски клавіш, змість цілих рядків тексту (які, як правило, закінчуються знаком нового рядка). Щоб бути спроможним читати функціональні клавіші та стрілки, потрібно викликати keypad(). Дивіться розділ про ініціалізацію для подробиць.

getch() повертає ціле, що відповідає натисненій клавіші. Якщо це звичайний знак, ціле значення відповідатиме цьому символу (згідно з ascii(7)). У протилежному випадку, функція поверне число, яке можна буде порівняти з константами, визначеними в curses.h. Приміром, якщо користувач натисне F1, повернуте ціле дорівнюватиме 265. Воно відповідатиме одному з макросів KEY_F(), означеному в curses.h. Це дозволяє машинонезалежне та зручне читання клавіш.

Наприклад, якщо ви викличите getch() як

int ch;

ch = getch();

getch() зачекає натиску користувачем клавіші (хіба ви зазначили ліміт часу), і коли користувач її натисне, поверне відповідне ціле. Після цього, ви можете порівняти це число з константами, визначеними в curses.h, щоб дізнатися, якій клавіші воно відповідає.

Наступний кусочок коду здійснить це.

if(ch == KEY_LEFT)
    printw("Left arrow is pressed\n");

Тепер, давайте напишемо невелику програму, що створить меню, по якому можна буде переміщуватися за допомогою клавіш зі стрілками вверх і вниз.

Простий приклад задіяння клавіш

Приклад 10. Використання клавіш

#include <stdio.h>
#include <ncurses.h>

#define WIDTH 30
#define HEIGHT 10

int startx = 0;
int starty = 0;

char *choices[] = {
                   "Choice 1",
                   "Choice 2",
                   "Choice 3",
                   "Choice 4",
                   "Exit",
                  };
int n_choices = sizeof(choices) / sizeof(char *);
void print_menu(WINDOW *menu_win, int highlight);

int main()
{       
    WINDOW *menu_win;
    int highlight = 1;
    int choice = 0;
    int c;

    initscr();
    clear();
    noecho();
    cbreak();       /* Line buffering disabled. pass on everything */
    startx = (80 - WIDTH) / 2;
    starty = (24 - HEIGHT) / 2;

    menu_win = newwin(HEIGHT, WIDTH, starty, startx);
    keypad(menu_win, TRUE);
    mvprintw(0, 0, "Use arrow keys to go up and down, Press enter to select a choice");
    refresh();
    print_menu(menu_win, highlight);
    while(1)
    {       
        c = wgetch(menu_win);
        switch(c) {       
            case KEY_UP:
                if(highlight == 1)
                    highlight = n_choices;
                else
                    --highlight;
                break;
            case KEY_DOWN:
                if(highlight == n_choices)
                    highlight = 1;
                else
                    ++highlight;
                break;
            case 10:
                choice = highlight;
                break;
            default:
                mvprintw(24, 0, "Charcter pressed is = %3d Hopefully it can be printed as '%c'", c, c);
                refresh();
                break;
        }
        print_menu(menu_win, highlight);
        if(choice != 0) /* User did a choice come out of the infinite loop */
            break;
    }
    mvprintw(23, 0, "You chose choice %d with choice string %s\n", choice, choices[choice - 1]);
    clrtoeol();
    refresh();
    endwin();
    return 0;
}

void print_menu(WINDOW *menu_win, int highlight)
{
    int x, y, i;

    x = 2;
    y = 2;
    box(menu_win, 0, 0);
    for (i = 0; i < n_choices; ++i) {       
        if (highlight == i + 1) {  /* High light the present choice */
            wattron(menu_win, A_REVERSE);
            mvwprintw(menu_win, y, x, "%s", choices[i]);
            wattroff(menu_win, A_REVERSE);
        } else
            mvwprintw(menu_win, y, x, "%s", choices[i]);
        ++y;
    }
    wrefresh(menu_win);

}