在使用cursesncurses库的程序中,getch()函数可以识别普通字符(如'x')或箭头和功能键发送的转义序列。例如,键入向上箭头键可能会发送序列(Escape,“[”,“A”),但getch()将返回intKEY_UP。它甚至使用计时信息来区分自己发送的转义字符和作为序列一部分的转义字符。
要成功使用getch(),首先必须调用initscr(),这将清除屏幕,以便光标可以控制显示的内容。
有没有一种不占用屏幕就识别特殊键的方便方法?理想情况下,我希望在不首先调用getch()的情况下调用initscr(),并让它返回与调用initscr()时返回的值相同的值,但实验表明这不起作用。
这是一个非工作的例子,我正在努力做什么。程序提示用户输入Up、Down、Escape、Left、Right,并确认输入了正确的键。
使用-c运行程序将调用initscr()并允许其正常工作。运行它而不首先调用-c调用getch();所有initscr()调用都不等待输入而失败,返回getch()ERR)。

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

没有-1选项的输出(在Ubuntu 17.04 x86_64上)是:
Press UP, DOWN, Escape, LEFT, RIGHT
Incorrect input: (-1, -1, -1, -1, -1)

更新:使用诅咒以外的其他方法解决问题是可以的。它必须直接或间接地使用terminfo来知道要查找哪些输入序列。(在我看来,识别特殊的键输入应该很简单,而不是与接管整个屏幕紧密相关。)

最佳答案

filter函数在initscr之前调用,它告诉游标使用一行(而不是整个屏幕)。在ncurses-examples中有一个使用(名为“filter”)的示例,它由一个命令提示符组成。
getch更新屏幕的至少一部分,例如,当它回显输入时。该更新可能只影响一行(使用filter),也可能影响整个屏幕。如果你很聪明,你可以关闭echo,并且(因为filter会抑制屏幕擦除),假装它什么也不更新。例如,可以使用/dev/null初始化游标,将输出重定向到newterm
回送输入只是故事的一部分:诅咒确实会初始化屏幕,而由refresh完成的相关getch将很难以可移植的方式避免这一点。示例程序中有一个ncurses特定的选项,它可以在正常/备用屏幕之间进行不必要的切换,这可能在屏幕初始化期间发生。
这是“过滤器”的截图,显示它并没有占据整个屏幕。反向视频是由于ncurses初始化颜色(黑白),但如帮助消息所示,这是可配置的。如果不拍电影,很难证明它能处理特殊的按键,但阅读source code就足够了。
c - 无需接管屏幕即可识别特殊键-LMLPHP

关于c - 无需接管屏幕即可识别特殊键,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48715793/

10-11 22:08
查看更多