getch和箭头代码

时间:2012-05-05 15:18:39

标签: c character decimal arrow-keys 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是{的十进制代码{1}}等等......

有没有办法检查箭头键而不打电话给其他人?

谢谢!

11 个答案:

答案 0 :(得分:54)

按一个箭头键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;
    }
}

答案 1 :(得分:18)

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

对于箭头键,它首先返回224,然后是72(向上),80(向下),75(向左)和77(向右)。如果按下数字键盘箭头键(关闭NumLock),则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 ... */
    }
}

答案 2 :(得分:2)

所以,经过多次斗争,我奇迹般地解决了这个棘手的问题! 我试图模仿一个linux终端并且卡在它保存命令历史的部分,可以通过按向上或向下箭头键来访问它。我发现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

它有点大胆,但它解释了很多。祝你好运!

答案 3 :(得分:2)

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

  

当num Lock关闭时

  • 左E0 4B
  • 右E0 4D
  • Up E0 48
  • 向下E0 50
  

当Num Lock开启时,这些键前面加上 E0 2A

  • 字节E0是-32
  • 字节48是72 UP
  • 字节50为80 DOWN

    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行。

答案 4 :(得分:1)

keypad将允许用户终端的键盘允许将功能键解释为单个值(即没有转义序列)。

如手册页所述:

  

键盘选项启用用户终端的键盘。如果   启用(bf为TRUE),用户可以按功能键(例如   箭头键)和wgetch返回表示该函数的单个值   key,如KEY_LEFT。如果禁用(bf为FALSE),curses不会处理   特别是功能键,程序必须解释逃逸   序列本身。如果可以打开终端中的键盘(制作   传输)和关闭(在本地工作),打开此选项   当调用wgetch时,会导致终端键盘打开。该   键盘的默认值为false。

答案 5 :(得分:0)

对于使用ncurses的工作代码和ncurses初始化的解决方案,请参阅getchar() returns the same value (27) for up and down arrow keys

答案 6 :(得分:0)

我用getch编写了一个函数来获取箭头代码。它是一个快速的解决方案,但该函数将根据箭头键返回ASCII码: UP:-10 下:-11 右:-12 左:-13

此外,使用此功能,您可以区分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;
}

答案 7 :(得分:0)

我只是一个初学者,但我创建了一个char(for example "b"),我做b = _getch();(它是一个conio.h库的命令) 并检查

If (b == -32)
b = _getch();

并检查按键(72向上,向下80向,向右向右77向,75向左)

答案 8 :(得分:0)

尝试这个怎么样?

void CheckKey(void) {
int key;
if (kbhit()) {
    key=getch();
    if (key == 224) {
        do {
            key=getch();
        } while(key==224);
        switch (key) {
            case 72:
                printf("up");
                break;
            case 75:
                printf("left");
                break;
            case 77:
                printf("right");
                break;
            case 80:
                printf("down");
                break;
        }
    }
    printf("%d\n",key);
}

int main() {
    while (1) {
        if (kbhit()) {
            CheckKey();
        }
    }
}

(如果您无法理解为什么有224,那么请尝试运行此代码:)

#include <stdio.h>
#include <conio.h>

int main() {
    while (1) {
        if (kbhit()) {
            printf("%d\n",getch());
        }
    }
}

但我不知道为什么会这样做224.如果你知道为什么,你能写下评论吗?

答案 9 :(得分:0)

    void input_from_key_board(int &ri, int &ci)
{
    char ch = 'x';
    if (_kbhit())
    {
        ch = _getch();
        if (ch == -32)
        {
            ch = _getch();
            switch (ch)
            {
            case 72: { ri--; break; }
            case 80: { ri++; break; }
            case 77: { ci++; break; }
            case 75: { ci--; break; }

            }
        }
        else if (ch == '\r'){ gotoRowCol(ri++, ci -= ci); }
        else if (ch == '\t'){ gotoRowCol(ri, ci += 5); }
        else if (ch == 27) { system("ipconfig"); }
        else if (ch == 8){ cout << " "; gotoRowCol(ri, --ci); if (ci <= 0)gotoRowCol(ri--, ci); }
        else { cout << ch; gotoRowCol(ri, ci++); }
        gotoRowCol(ri, ci);
    }
}

答案 10 :(得分:0)

尝试一下...

我在Windows 7中使用Code :: Blocks

while (true)
{
    char input;
    input = getch();

    switch(input)
    {
    case -32: //This value is returned by all arrow key. So, we don't want to do something.
        break;
    case 72:
        printf("up");
        break;
    case 75:
        printf("left");
        break;
    case 77:
        printf("right");
        break;
    case 80:
        printf("down");
        break;
    default:
        printf("INVALID INPUT!");
        break;
    }
}