Подтвердить что ты не робот

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' и т.д.

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

Спасибо!

4b9b3361

Ответ 1

При нажатии одной клавиши со стрелкой 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;
    }
}

Ответ 2

Функция

getch() возвращает два ключа для клавиш со стрелками (и некоторые другие специальные клавиши), как указано в комментарии FatalError. Сначала он возвращает либо 0 (0x00), либо 224 (0xE0), а затем возвращает код, идентифицирующий нажатую клавишу.

Для клавиш со стрелками он возвращает 224, а затем 72 (вверх), 80 (вниз), 75 (слева) и 77 (справа). Если нажаты клавиши со стрелками num-pad (с выключенным NumLock), getch() возвращает 0 сначала вместо 224.

Обратите внимание, что getch() никоим образом не стандартизирован, и эти коды могут отличаться от компилятора к компилятору. Эти коды возвращаются MinGW и Visual С++ в 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 С++. Эти компиляторы используют имя _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 ... */
    }
}

Ответ 3

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

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

Ответ 4

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

Когда num Lock отключен

  • Левый E0 4B
  • Right 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 строки.

Ответ 5

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

Как указано на странице руководства:

Опция клавиатуры включает клавиатуру пользовательского терминала. Если (bf - ИСТИНА), пользователь может нажать функциональную клавишу (например, стрелка), а wgetch возвращает одно значение, представляющее функцию, как в KEY_LEFT. Если отключено (bf ЛОЖЬ), проклятия не лечат функциональные клавиши, и программа должна интерпретировать выход самих последовательностей. Если клавиатура в терминале может быть включена (сделана для передачи) и выключения (для работы на месте), включение этой опции заставляет клавиатуру терминала включаться при вызове wgetch. значение по умолчанию для клавиатуры - false.

Ответ 7

Я написал функцию, использующую getch для получения кода стрелки. это быстрое решение, но функция вернет код ASCII в зависимости от клавиши со стрелкой: UP: -10 ВНИЗ: -11 ПРАВО: -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;
}