curses
またはncurses
ライブラリを使用するプログラムでは、getch()
関数は通常の文字 ( など'x'
) または矢印キーとファンクション キーによって送信されるエスケープ シーケンスのいずれかを認識できます。たとえば、上矢印キーを入力すると、シーケンス (Escape、'['、'A') が送信される場合がありますが、値getch()
が返されます。さらに、タイミング情報を使用して、それ自体が送信したエスケープ文字と、シーケンスの一部であるエスケープ文字を区別します。int
KEY_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 を使用する必要があります。(特別なキー入力を認識することは簡単で、画面全体を引き継ぐことと密接に結びついているべきではないように私には思えます。)