c++ ncursesw应用程序无法捕获ctrl-C/S/Z

rbpvctlc  于 2023-05-02  发布在  其他
关注(0)|答案(2)|浏览(211)

我正在尝试使用ncursesw创建一个c++应用程序。
我想为自己的功能使用一些快捷键。

  1. Ctrl+C
  2. Ctrl+S
  3. Ctrl+Z
    我知道我可以直接捕获信号,但显然很多文档都告诉我,这不应该是必要的,ncursesw提供了这个功能。据我所知,您应该能够通过使用raw();并启用keypad(stdscr, true);函数来捕获这些键码。但这对我没用。
    我有点怀疑,可能有一些其他的应用程序捕捉这些键之前,他们到达我。我正在以下堆栈中运行我的应用程序:
  • 新Windows终端
  • WSL
  • Tmux
  • 日什
  • myapp

下面是我用来测试它的代码:

#include <iostream>
#include <ncursesw/ncurses.h>

using namespace std;

void quit();

int main(int argc, const char *argv[])
{
    // Init Curses ----------
    setlocale(LC_ALL, "");
    WINDOW* win = initscr();
    atexit(quit);
    raw(); // disable line buffering
    curs_set(0); // hide cursor
    use_default_colors(); // enable transparent black
    start_color(); // enable color
    clear(); // clear screen
    noecho(); // disable echo
    cbreak(); // disable line buffering
    keypad(stdscr, true); // enable function keys
    mousemask(ALL_MOUSE_EVENTS, NULL); // enable mouse events
    
    // the following loop is just test code
    int input;
    do {
        input = getch();
    } while(input != 'q');
    
    return 0;
}

void quit() {
    endwin();
}

这段代码的目标是只能够使用'q'退出,而不是使用Ctrl-C,但它仍然使用Ctrl-C退出。
有没有人知道,如果有些是造成问题,或者如果它实际上甚至不可能捕捉这些键只是通过使用诅咒库?

izkcnapc

izkcnapc1#

OP的程序有一个错误,这使它无法按预期工作:

raw(); // disable line buffering

被覆盖

cbreak(); // disable line buffering

(删除该行,getch将返回^C,依此类推。)

p5cysglq

p5cysglq2#

按以下顺序:

  • 通过调用keypad(stdscr, true)启用键盘功能键。在termios.h中定义。
  • 通过调用signal(SIGINT, SIG_IGN)禁用Ctrl-C信号。
  • 通过使用tcgetattrtcsetattr功能配置终端,启用Ctrl-Z和Ctrl-S键。在termios.h中定义。

我们只能使用按键'q'退出,而不能使用标准的终端退出:Ctrl-C

#include <iostream>
#include <ncursesw/ncurses.h>
#include <termios.h>
#include <unistd.h>

using namespace std;

void quit() {
    endwin();
}

int main(int argc, const char *argv[]) {
    // Init Curses ----------
    setlocale(LC_ALL, "");
    WINDOW* win = initscr();
    atexit(quit);
    raw(); // disable line buffering
    curs_set(0); // hide cursor
    use_default_colors(); // enable transparent black
    start_color(); // enable color
    clear(); // clear screen
    noecho(); // disable echo
    cbreak(); // disable line buffering
    keypad(stdscr, true); // enable function keys

    // Disable Ctrl-C signal
    signal(SIGINT, SIG_IGN);
    
    // Enable Ctrl-Z and Ctrl-S keys
    struct termios term;
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag &= ~(ICANON | ECHO);
    term.c_cc[VMIN] = 1;
    term.c_cc[VTIME] = 0;
    term.c_cc[VSTOP] = _POSIX_VDISABLE;
    term.c_cc[VSUSP] = _POSIX_VDISABLE;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);

    int input;
    do {
        input = getch();
        switch(input) {
            case KEY_CTRLC:
                // Ctrl-C pressed
                break;
            case KEY_CTRLZ:
                // Ctrl-Z pressed
                break;
            case KEY_CTRL('s'):
                // Ctrl-S pressed
                break;
        }
    } while(input != 'q');
    
    return 0;
}

unistd.h是访问STDIN_FILENO常量所必需的,该常量表示标准输入文件描述符。我们将此常量传递给tcgetattrtcsetattr函数,以修改标准输入的终端设置。

相关问题