getch和箭头代码

我正在编写一个使用getch()扫描箭头键的程序。 我的代码到目前为止是:

 switch(getch()) { case 65: // key up break; case 66: // key down break; case 67: // key right break; case 68: // key left break; } 

问题是当我按'A''B''C''D' ,代码也会被执行,因为65'A'的十进制代码等等。

有没有办法检查一个箭头键没有打电话给别人?

谢谢!

通过按一个箭头键getch将三个值推入缓冲区:

  • '\033'
  • '['
  • 'A''B''C''D'

所以代码将是这样的:

 if (getch() == '\033') { // if the first value is esc getch(); // skip the [ switch(getch()) { // the real value case 'A': // code for arrow up break; case 'B': // code for arrow down break; case 'C': // code for arrow right break; case 'D': // code for arrow left break; } } 

getch()函数返回箭头键(和一些其他特殊键)的两个键码,如FatalError的注释中所述。 它首先返回0(0x00)或224(0xE0),然后返回一个标识被按下的键的代码。

对于箭头键,首先返回224,然后是72(上),80(下),75(左)和77(右)。 如果num-pad箭头键(NumLockclosures)被按下,则getch()首先返回0而不是224。

请注意,getch()没有任何标准化,这些代码可能因编译器而异。 这些代码由Windows上的MinGW和Visual C ++返回。

一个方便的程序来查看getch()对各种键的操作是:

 #include <stdio.h> #include <conio.h> int main () { int ch; while ((ch = _getch()) != 27) /* 27 = Esc key */ { printf("%d", ch); if (ch == 0 || ch == 224) printf (", %d", _getch ()); printf("\n"); } printf("ESC %d\n", ch); return (0); } 

这适用于MinGW和Visual C ++。 这些编译器使用名称_getch()而不是getch()来表示它是非标准函数。

所以,你可以这样做:

 ch = _getch (); if (ch == 0 || ch == 224) { switch (_getch ()) { case 72: /* Code for up arrow handling */ break; case 80: /* Code for down arrow handling */ break; /* ... etc ... */ } } 

所以,经过很多的斗争,我奇迹般的解决了这个日复一日的问题! 我试图模仿一个linuxterminal,并卡住了它保持命令历史的部分,可以通过上下方向键来访问。 我发现ncurses lib很难理解并且学得很慢。

 char ch = 0, k = 0; while(1) { ch = getch(); if(ch == 27) // if ch is the escape sequence with num code 27, k turns 1 to signal the next k = 1; if(ch == 91 && k == 1) // if the previous char was 27, and the current 91, k turns 2 for further use k = 2; if(ch == 65 && k == 2) // finally, if the last char of the sequence matches, you've got a key ! printf("You pressed the up arrow key !!\n"); if(ch == 66 && k == 2) printf("You pressed the down arrow key !!\n"); if(ch != 27 && ch != 91) // if ch isn't either of the two, the key pressed isn't up/down so reset k k = 0; printf("%c - %d", ch, ch); // prints out the char and it's int code 

这是一种大胆的,但它解释了很多。 祝你好运 !

keypad将允许用户terminal的键盘允许function键被解释为单个值(即,无转义序列)。

正如手册页所述:

小键盘选项启用用户terminal的小键盘。 如果启用(bf为TRUE),则用户可以按function键(例如箭头键),wgetch返回表示function键的单个值,如在KEY_LEFT中。 如果禁用(bf为FALSE),则curses不会专门处理function键,程序必须自行解释转义序列。 如果terminal中的键盘可以打开(发送)和closures(在本地工作),打开此选项将导致terminal键盘在wgetch被调用时打开。 键盘的默认值是false。

实际上,读取箭头键需要读取其扫描码。 以下是按箭头键生成的扫描码(不是按键释放)

当数字lockingclosures

  • 离开E0 4B
  • E0 4D
  • 上E0 48
  • 向下E0 50

当Num Lock开启时,这些键以E0 2A开头

  • 字节E0是-32
  • 字节48是72 UP
  • 字节50是80向下

     user_var=getch(); if(user_var == -32) { user_var=getch(); switch(user_var) { case 72: cur_sel--; if (cur_sel==0) cur_sel=4; break; case 80: cur_sel++; if(cur_sel==5) cur_sel=1; break; } } 

在上面的代码中,我假设程序员只想移动4行。

对于使用带有工作代码和初始化ncurses的解决scheme,请参阅getchar()为上下方向键返回相同的值(27)

我用getch写了一个函数来获取箭头代码。 这是一个quick'n'dirty解决scheme,但function将返回一个ASCII代码根据箭头键:向上:-10下:-11右:-12左:-13

此外,使用此function,您将能够区分ESCAPE触摸和箭头键。 但是你必须按下ESC 2才能激活ESC键。

这里的代码是:

 char getch_hotkey_upgrade(void) { char ch = 0,ch_test[3] = {0,0,0}; ch_test[0]=getch(); if(ch_test[0] == 27) { ch_test[1]=getch(); if (ch_test[1]== 91) { ch_test[2]=getch(); switch(ch_test[2]) { case 'A': //printf("You pressed the up arrow key !!\n"); //ch = -10; ch = -10; break; case 'B': //printf("You pressed the down arrow key !!\n"); ch = -11; break; case 'C': //printf("You pressed the right arrow key !!\n"); ch = -12; break; case 'D': //printf("You pressed the left arrow key !!\n"); ch = -13; break; } } else ch = ch_test [1]; } else ch = ch_test [0]; return ch; }