键盘检测程序
最近在看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