1

cursesまたはncursesライブラリを使用するプログラムでは、getch()関数は通常の文字 ( など'x') または矢印キーとファンクション キーによって送信されるエスケープ シーケンスのいずれかを認識できます。たとえば、上矢印キーを入力すると、シーケンス (Escape、'['、'A') が送信される場合がありますが、値getch()が返されます。さらに、タイミング情報を使用して、それ自体が送信したエスケープ文字と、シーケンスの一部であるエスケープ文字を区別します。intKEY_UP

getch()正常に使用するには、最初に を呼び出す必要initscr()があります。これにより、curses が表示内容を制御できるように画面がクリアされます。

画面を引き継がに特殊キーを認識する便利な方法はありますか? 理想的には、getch()最初に を呼び出さずに を呼び出しinitscr()、 を呼び出した場合に返される値と同じ値を返すようにしたいのですinitscr()が、実験ではそれが機能しないことが示されています。

これは、私がやろうとしていることのうまくいかない例です。プログラムはユーザーに Up、Down、Escape、Left、Right を入力するように促し、正しいキーが入力されたことを確認します。

-c呼び出しを使用してプログラムを実行するinitscr()と、正しく動作するようになります。最初に呼び出すことなく、-c呼び出しなしで実行します。入力を待たずにすべての呼び出しが失敗し、 ( ) が返されます。getch()initscr()getch()ERR-1

// gcc arrows.c -o arrows -lncurses
#include <term.h>
#include <stdio.h>
#include <curses.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv) {
    int use_curses = 0;
    if (argc == 2 && strcmp(argv[1], "-c") == 0) {
        use_curses = 1;
    }
    else if (argc != 1) {
        fprintf(stderr, "Usage: %s [-c]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    WINDOW *win;
    if (use_curses) {
        win = initscr();
        cbreak();
        noecho();
        nonl();
        intrflush(stdscr, FALSE);
        keypad(stdscr, TRUE);
        mvaddstr(0, 0, "Press UP, DOWN, Escape, LEFT, RIGHT");
    }
    else {
        puts("Press UP, DOWN, Escape, LEFT, RIGHT");
    }

    int keys[5];
    for (int i = 0; i < 5; i ++) {
        keys[i] = getch();
    }
    int ok;
    if (keys[0] == KEY_UP &&
        keys[1] == KEY_DOWN &&
        keys[2] == '\x1b' &&
        keys[3] == KEY_LEFT &&
        keys[4] == KEY_RIGHT)
    {
        ok = 1;
        if (use_curses) {
            mvaddstr(2, 0, "OK");
        }
        else {
            puts("OK");
        }
    }
    else {
        ok = 0;
        char message[100];
        sprintf(message,
                "Incorrect input: (%d, %d, %d, %d, %d)",
                keys[0], keys[1], keys[2], keys[3], keys[4]);
        if (use_curses) {
            mvaddstr(2, 0, message);
        }
        else {
            puts(message);
        }
    }
    if (use_curses) {
        mvaddstr(4, 0, "Press any key to quit ");
        (void)getch();
        endwin();
    }
    exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
}

-cオプションなしの出力(Ubuntu 17.04 x86_64) は次のとおりです。

Press UP, DOWN, Escape, LEFT, RIGHT
Incorrect input: (-1, -1, -1, -1, -1)

更新: curses 以外のものを使用したソリューションで問題ありません。検索する入力シーケンスを知るには、直接または間接的に terminfo を使用する必要があります。(特別なキー入力を認識することは簡単で、画面全体を引き継ぐことと密接に結びついているべきではないように私には思えます。)

4

1 に答える 1

2

filter関数は before で呼び出され、initscrcurses に (画面全体ではなく) 1 行を使用するように指示します。コマンドプロンプトで構成されるncurses-examplesに、その使用例 (「フィルター」という名前) があります。

getchたとえば、入力をエコーするときなどに、画面の少なくとも一部を更新します。その更新は、( を使用してfilter) 1 行だけ、または画面全体に影響を与える可能性があります。賢ければ、エコーをオフにして (filter画面の消去を抑制するため)、何も更新しないふりをすることができます。たとえば、/dev/nullcurses を で初期化することにより、出力を にリダイレクトできますnewterm

入力のエコーはストーリーの一部にすぎません。curses は画面を初期化しますが、関連するrefreshdone によってgetch移植可能な方法で回避するのが難しくなります。サンプル プログラムには ncurses 固有のオプションがあり、画面の初期化中に発生する可能性がある通常画面と代替画面の間の不要な切り替えを回避します。

これは「フィルター」のスクリーンショットで、画面全体を占有しないことを示しています。反転したビデオは、ncurses が色 (黒地に白) を初期化するためですが、ヘルプ メッセージが示すように、それは構成可能です。ムービーを作成しないと、特殊キーを処理できることを実証するのは困難ですが、ソース コードを読むだけで十分です。

フィルタプログラムの例

于 2018-02-10T00:52:43.573 に答える