46

我正在编写一个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'

有没有办法在不打电话给别人的情况下检查箭头键?

谢谢!

4

11 回答 11

82

通过按一个箭头键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;
    }
}
于 2012-07-11T12:26:29.037 回答
24

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 ... */
    }
}
于 2012-05-06T18:59:44.230 回答
6

So, after alot of struggle, I miraculously solved this everannoying issue ! I was trying to mimic a linux terminal and got stuck at the part where it keeps a command history which can be accessed by pressing up or down arrow keys. I found ncurses lib to be painfuly hard to comprehend and slow to learn.

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

It's kind of bold but it explains alot. Good luck !

于 2013-02-14T04:00:01.857 回答
3

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

如手册页所述:

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

于 2015-12-14T00:12:47.250 回答
2

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

当 num Lock 关闭时

  • 左 E0 4B
  • 右 E0 4D
  • 向上 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 行。

于 2015-04-01T11:54:03.737 回答
1

试试这个怎么样?

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。如果你知道为什么,你能写下评论吗?

于 2018-03-21T13:45:23.117 回答
1

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

于 2017-09-07T13:10:59.250 回答
0

我已经使用 getch 编写了一个函数来获取箭头代码。这是一个快速的'n'dirty解决方案,但该函数将根据箭头键返回一个ASCII码:UP:-10 DOWN:-11 RIGHT:-12 LEFT:-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;
}
于 2017-10-14T22:27:57.613 回答
0

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

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

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

于 2018-02-21T23:43:33.260 回答
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);
    }
}
于 2018-05-02T17:10:38.557 回答
-1

尝试这个...

我在 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;
    }
}
于 2019-06-03T09:24:53.770 回答