【问题标题】:getch and arrow codesgetch 和箭头代码
【发布时间】:2012-05-14 20:18:53
【问题描述】:

我正在编写一个使用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()时,对于“特殊”键它实际上返回了两次。第一次返回 0,然后是特殊键的代码,以便您可以将其与其他键区分开来。
  • 65 仅适用于字符 A。您必须使用控制代码来接收这些密钥。看到这个帖子。 stackoverflow.com/questions/2876275/…
  • @FatalError 对不起,我迟到了大约 7 年,但你所说的激起了我的好奇心。 getch() 怎么可能返回两次?一个函数只能返回一次,对吧?
  • @AnchithAcharya:你很幸运,因为我还在 7 年后 ;-)。我的意思是,要读取“特殊密钥”,您必须实际调用 getch() 两次。第一次调用将返回 0(即表示下一个值将是一个特殊键)。然后在第二次调用getch() 时,它将返回一个不同的值,指示按下了哪个特殊键。请注意,getch() 是 DOS 时代的非标准工件,因此它很可能因编译器而异。但这是 MSDN 上的一个示例:docs.microsoft.com/en-us/cpp/c-runtime-library/reference/…
  • @FatalError 啊,我现在明白了。谢谢!

标签: c character decimal arrow-keys getch


【解决方案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;
    }
}

【讨论】:

  • 这并不能真正回答 OP 问题,因为您的“UP”也会由 H 字符触发。
【解决方案2】:

试试这个怎么样?

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

【讨论】:

  • 请重新格式化您的代码。此外,添加对为什么如何您的代码如何工作的解释,尤其是像224这样的幻数
【解决方案3】:
    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);
    }
}

【讨论】:

  • C++ 与 C 不同。
【解决方案4】:

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

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

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

【讨论】:

    【解决方案5】:

    我已经编写了一个使用 getch 来获取箭头代码的函数。这是一个快速的'n'dirty解决方案,但该函数将根据箭头键返回一个ASCII码: 上:-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;
    }
    

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

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

        当 num Lock 关闭时

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

        【讨论】:

        • 你能解释一下你的答案吗?
        【解决方案8】:

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

        【讨论】:

        • 这个答案是否正确?这里的代码是您在使用getchar 时从大多数终端获得的代码。它们不是你从getch&lt;conio.h&gt; 得到的。
        • 你知道为什么在我的终端中我看到一个'O'而不是'['作为第二个字符吗?仅供参考,我在 tmux 会话中运行 zsh。谢谢!
        • @Cheersandhth.-Alf 是的,这是 Unix 领域的 getch,特别是 getch from the ncurses library(禁用“键盘”模式)。
        • getch() -&gt;getchar()
        • 在 Windows 上,_getch(来自 conio.h)必须调用两次才能处理箭头键。第一个返回值是 224,第二个是 'A' , 'B' 等如上。
        【解决方案9】:

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

        如手册页所述:

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

        【讨论】:

          【解决方案10】:

          所以,经过一番挣扎,我奇迹般地解决了这个烦人的问题! 我试图模仿一个 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
          

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

          【讨论】:

            【解决方案11】:

            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 ... */
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-02-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多