鍵盤檢測程序
最近在看Neil Matthew和Rick Stones的Beginning Linux Programming, 在 terminals 學到了如何檢測按鍵的方法.話不多說先上代碼:
#include <unistd.h>
#include <stdlib.h>
#include <curses.h>
#define LOCAL_ESC_KEY 27
int main()
{
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
clear();
mvprintw(5, 5, "Keypad Detection demo. Press 'q' to quit");
move(7, 5);
refresh();
int key = getch();
while(key != ERR && key != 'q') {
move(7, 5);
clrtoeol();
if( (key >= 'A' && key <= 'z') ||
(key >= 'a' && key < 'z')) {
printw("Key was %c", key);
} else if( (key >= '0' && key <= '9') ) {
printw("Key was %c", key);
} else if( (key >= KEY_F0 && key <= KEY_F0+12) ) {
printw("Key was F%d", key-KEY_F0);
} else {
switch(key) {
case LOCAL_ESC_KEY: printw("Esc key");break;
case KEY_END: printw("END key");break;
case KEY_BEG: printw("BEGINNING key");break;
case KEY_RIGHT: printw("RIGHT key");break;
case KEY_LEFT: printw("LEFT key");break;
case KEY_UP: printw("UP key");break;
case KEY_DOWN: printw("DOWN key");break;
// you may add more here...
default: printw("Unmatched %d", key);break;
}
}
refresh();
key = getch();
}
endwin();
exit(0);
}
編譯: gcc -o proc main.c -lcurses
這裏使用了 curses,所以在編譯的時候要加上-lcurses選項.
而所有的 curses 程序都少不了這兩個函數
WINDOW *initscr(void);
成功則返回一個指向stdscr 的指針,否則返回 NULL 並打印報錯信息到 stderr. initscr通常是 curses 程序的第一個函數,起到初始化 curses 的作用
int endwin(void);
成功返回 OK, 失敗返回 ERR.
基本結構清楚後,這裏介紹終端的兩種輸入模式:cooked mode和cbreak mode.
cook mode 下終端會將輸入緩存, 程序只有在 ENTER 鍵按下後才能獲得輸入;而 cbreak mode 在按鍵按下的同時,程序即獲得輸入,也就是說前者有 buffer 緩衝而後者沒有.程序正是使用cbreak mode的輸入即得來檢測按鍵.
當initscr成功返回時,程序即進入cooked mode, 這時調用cbreak後終端即進入cbreak mode,另外爲了不讓按鍵輸入出現在屏幕上,程序調用noecho禁止回顯.
爲了獲得鍵盤輸入與功能按鍵(如方向鍵, F1等)的關係, 需要調用 keypad 函數
int keypad(WINDOW *win, bool bf);
這裏第一個參數傳入stdscr 指針即可.這樣環境初始化就完成了,接下來就可以檢測按鍵了, 有關按鍵的宏定義, 可以參見curses.h中的 KEY_ 開頭的宏, 具體命令:
cat /usr/include/curses.h | grep “KEY_”
這裏方便起見, 先貼出來:
#define KEY_CODE_YES 0400 /* A wchar_t contains a key code */
#define KEY_MIN 0401 /* Minimum curses key */
#define KEY_BREAK 0401 /* Break key (unreliable) */
#define KEY_SRESET 0530 /* Soft (partial) reset (unreliable) */
#define KEY_RESET 0531 /* Reset or hard reset (unreliable) */
#define KEY_DOWN 0402 /* down-arrow key */
#define KEY_UP 0403 /* up-arrow key */
#define KEY_LEFT 0404 /* left-arrow key */
#define KEY_RIGHT 0405 /* right-arrow key */
#define KEY_HOME 0406 /* home key */
#define KEY_BACKSPACE 0407 /* backspace key */
#define KEY_F0 0410 /* Function keys. Space for 64 */
#define KEY_F(n) (KEY_F0+(n)) /* Value of function key n */
#define KEY_DL 0510 /* delete-line key */
#define KEY_IL 0511 /* insert-line key */
#define KEY_DC 0512 /* delete-character key */
#define KEY_IC 0513 /* insert-character key */
#define KEY_EIC 0514 /* sent by rmir or smir in insert mode */
#define KEY_CLEAR 0515 /* clear-screen or erase key */
#define KEY_EOS 0516 /* clear-to-end-of-screen key */
#define KEY_EOL 0517 /* clear-to-end-of-line key */
#define KEY_SF 0520 /* scroll-forward key */
#define KEY_SR 0521 /* scroll-backward key */
#define KEY_NPAGE 0522 /* next-page key */
#define KEY_PPAGE 0523 /* previous-page key */
#define KEY_STAB 0524 /* set-tab key */
#define KEY_CTAB 0525 /* clear-tab key */
#define KEY_CATAB 0526 /* clear-all-tabs key */
#define KEY_ENTER 0527 /* enter/send key */
#define KEY_PRINT 0532 /* print key */
#define KEY_LL 0533 /* lower-left key (home down) */
#define KEY_A1 0534 /* upper left of keypad */
#define KEY_A3 0535 /* upper right of keypad */
#define KEY_B2 0536 /* center of keypad */
#define KEY_C1 0537 /* lower left of keypad */
#define KEY_C3 0540 /* lower right of keypad */
#define KEY_BTAB 0541 /* back-tab key */
#define KEY_BEG 0542 /* begin key */
#define KEY_CANCEL 0543 /* cancel key */
#define KEY_CLOSE 0544 /* close key */
#define KEY_COMMAND 0545 /* command key */
#define KEY_COPY 0546 /* copy key */
#define KEY_CREATE 0547 /* create key */
#define KEY_END 0550 /* end key */
#define KEY_EXIT 0551 /* exit key */
#define KEY_FIND 0552 /* find key */
#define KEY_HELP 0553 /* help key */
#define KEY_MARK 0554 /* mark key */
#define KEY_MESSAGE 0555 /* message key */
#define KEY_MOVE 0556 /* move key */
#define KEY_NEXT 0557 /* next key */
#define KEY_OPEN 0560 /* open key */
#define KEY_OPTIONS 0561 /* options key */
#define KEY_PREVIOUS 0562 /* previous key */
#define KEY_REDO 0563 /* redo key */
#define KEY_REFERENCE 0564 /* reference key */
#define KEY_REFRESH 0565 /* refresh key */
#define KEY_REPLACE 0566 /* replace key */
#define KEY_RESTART 0567 /* restart key */
#define KEY_RESUME 0570 /* resume key */
#define KEY_SAVE 0571 /* save key */
#define KEY_SBEG 0572 /* shifted begin key */
#define KEY_SCANCEL 0573 /* shifted cancel key */
#define KEY_SCOMMAND 0574 /* shifted command key */
#define KEY_SCOPY 0575 /* shifted copy key */
#define KEY_SCREATE 0576 /* shifted create key */
#define KEY_SDC 0577 /* shifted delete-character key */
#define KEY_SDL 0600 /* shifted delete-line key */
#define KEY_SELECT 0601 /* select key */
#define KEY_SEND 0602 /* shifted end key */
#define KEY_SEOL 0603 /* shifted clear-to-end-of-line key */
#define KEY_SEXIT 0604 /* shifted exit key */
#define KEY_SFIND 0605 /* shifted find key */
#define KEY_SHELP 0606 /* shifted help key */
#define KEY_SHOME 0607 /* shifted home key */
#define KEY_SIC 0610 /* shifted insert-character key */
#define KEY_SLEFT 0611 /* shifted left-arrow key */
#define KEY_SMESSAGE 0612 /* shifted message key */
#define KEY_SMOVE 0613 /* shifted move key */
#define KEY_SNEXT 0614 /* shifted next key */
#define KEY_SOPTIONS 0615 /* shifted options key */
#define KEY_SPREVIOUS 0616 /* shifted previous key */
#define KEY_SPRINT 0617 /* shifted print key */
#define KEY_SREDO 0620 /* shifted redo key */
#define KEY_SREPLACE 0621 /* shifted replace key */
#define KEY_SRIGHT 0622 /* shifted right-arrow key */
#define KEY_SRSUME 0623 /* shifted resume key */
#define KEY_SSAVE 0624 /* shifted save key */
#define KEY_SSUSPEND 0625 /* shifted suspend key */
#define KEY_SUNDO 0626 /* shifted undo key */
#define KEY_SUSPEND 0627 /* suspend key */
#define KEY_UNDO 0630 /* undo key */
#define KEY_MOUSE 0631 /* Mouse event has occurred */
#define KEY_RESIZE 0632 /* Terminal resize event */
#define KEY_EVENT 0633 /* We were interrupted by an event */
#define KEY_MAX 0777 /* Maximum key value is 0633 */
上面的程序只做了對於數字,字母,方向鍵, F n鍵以及 ESC 鍵檢測.而根據這些宏, 你就可以完善上述程序.
參考
Beginning Linux® Programming 4th Edition, Neil Matthew && Richard Stones