web-dev-qa-db-ja.com

ゲッチと矢印コード

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'の10進コードであるため、コードも実行されることです。 _など...

他の人を呼び出さずに矢印キーを確認する方法はありますか?

ありがとう!

36
qwertz

1つの矢印キーを押すと、getchは3つの値をバッファーにプッシュします。

  • '\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;
    }
}
55
qwertz

getch()関数は、FatalErrorのコメントに記載されているように、矢印キー(およびその他の特殊キー)の2つのキーコードを返します。最初に0(0x00)または224(0xE0)を返し、次に押されたキーを識別するコードを返します。

矢印キーの場合、最初に224を返し、続いて72(上)、80(下)、75(左)、77(右)を返します。テンキーの矢印キー(NumLockがオフの場合)が押されると、getch()はまず224ではなく0を返します。

Getch()は決して標準化されておらず、これらのコードはコンパイラごとに異なる可能性があることに注意してください。これらのコードは、MinGWおよびWindows上の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 ... */
    }
}
18

だから、多くの闘争の後、私はこの永遠に続く問題を奇跡的に解決しました! 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
kundrata

実際、矢印キーを読み取るには、スキャンコードを読み取る必要があります。以下は、矢印キーを押すことで生成されるスキャンコードです(キーリリースではありません)

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行だけを移動したいと想定しています。

2
Shubham

keypad を使用すると、ユーザーの端末のキーボードでファンクションキーを単一の値として解釈できます(つまり、エスケープシーケンスなし)。

Manページに記載されているとおり:

キーパッドオプションは、ユーザーの端末のキーパッドを有効にします。有効(bfがTRUE)の場合、ユーザーはファンクションキー(矢印キーなど)を押すことができ、wgetchはKEY_LEFTのように、ファンクションキーを表す単一の値を返します。無効(bfがFALSE)の場合、cursesはファンクションキーを特別に処理せず、プログラムはエスケープシーケンス自体を解釈する必要があります。端末のキーパッドをオン(送信用)およびオフ(ローカルで動作可能)にできる場合、このオプションをオンにすると、wgetchが呼び出されたときに端末のキーパッドがオンになります。キーパッドのデフォルト値はfalseです。

1
tijko

これを試してみませんか?

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なのかわかりません。理由がわかっていればコメントを書き留めることができますか?

私はただのスターターですが、私はchar(for example "b")を作成し、b = _getch();(そのconio.hライブラリのコマンド)そしてチェック

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

キーを確認します(72が上、80が下、77が右、75が左)。

0
Ant Redstone

作業コードとncursesの初期化でncursesを使用するソリューションについては、 getchar()が上下の矢印キーに同じ値(27)を返す

0
ralf htp
    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);
    }
}
0
Malik fawad01

Getchを使用して矢印コードを取得する関数を作成しました。それは手っ取り早い解決策ですが、関数は矢印キーに応じてASCIIコードを返します:上:-10下:-11右:-12左:-13

さらに、この機能を使用すると、ESCAPEタッチと矢印キーを区別できます。ただし、ESCキーを有効にするには、ESC 2回を押す必要があります。

ここにコード:

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