коды 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', etc...

есть ли способ проверить наличие клавиши со стрелкой без вызова других?

спасибо!

10 ответов


нажатием одной клавиши со стрелкой getch будет толкать три значения в буфер:

  • '3'
  • '['
  • 'A', 'B', 'C' или 'D'

таким образом, код будет примерно таким:

if (getch() == '3') { // 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 (с выключенным NumLock) нажаты, getch () сначала возвращает 0 вместо 224.

обратите внимание, что getch () никоим образом не стандартизирован, и эти коды могут отличаться от компилятора к компилятору. Эти коды возвращаются MinGW и Visual C++ в Windows.

удобная программа для просмотра действия 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 ... */
    }
}

Итак, после много борьбы, я чудесным образом решена эта проблема everannoying ! Я пытался имитировать терминал 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

Это смелый, но это многое объясняет. Удачи !


на keypad позволит клавиатуре терминала пользователя разрешить интерпретацию функциональных клавиш как одного значения (т. е. без escape-последовательности).

как указано в man-странице:

опция клавиатуры включает клавиатуру терминала пользователя. Если включено (BF истинно), потребитель может отжать функциональную клавишу (как стрелка) и wgetch возвращает одно значение, представляющее функцию ключ, как в KEY_LEFT. Если отключено (bf FALSE), проклятия не лечит функциональные клавиши специально и программа должна интерпретировать escape сама последовательность. Если клавиатура в терминале может быть включена (сделано для передачи) и off (сделано для работы локально), включив эту опцию вызывает включение клавиатуры терминала при вызове wgetch. Этот значение по умолчанию для клавиатуры-false.


на самом деле, чтобы прочитать клавиши со стрелками, нужно прочитать его код сканирования. Ниже приведен код сканирования, сгенерированный клавишами со стрелками Нажмите (не отпустите клавишу)

когда блокировка num выключена

  • слева E0 4B
  • справа E0 4D
  • До Е0 48
  • Вниз E0 50

когда Num Lock находится на этих клавишах, предшествует Е0 2А

  • байт Е0 является -32
  • байт 48 72 вверх
  • байт 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 с рабочим кодом и инициализацией ncurses см. getchar () возвращает то же значение (27) для клавиш со стрелками вверх и вниз


Я написал функцию, используя getch, чтобы получить код стрелки. это быстрый, нежели'dirty решения, но функция возвращает ASCII-код в зависимости от стрелка : Итог : -10 Вниз : -11 Справа : -12 Слева : -13

кроме того, с помощью этой функции вы сможете различать ESCAPE touch и клавиши со стрелками. Но вы должны нажать 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;
}

Я просто стартер, но я создал char(for example "b"), а я b = _getch(); (это библиотеки ) И проверьте

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

и проверьте наличие ключей (72 вверх, 80 вниз, 77 вправо, 75 влево)


    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);
    }
}

Как насчет этого?

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. вы можете Написать комментарий, если знаете почему?