如何在C 语言中监听CTRL键?
我正在用C 编写一个程序,禁用了canonical模式和回显模式,使用 termios.h。
我在想,怎样才能监听CTRL快捷键(在我的情况下,是 CTRL + Q):
- 我尝试查找CTRL快捷键的按键码,但没有找到任何东西。
- 然后再深入一点,发现了
signal.h,但我想监听CTRL+Q,不是一个宏。 - 我一直在搜索,但其实没找到什么,只有在《用C 构建文本编辑器》中的一段内容:
#define CTRL_KEY(k) ((k) & 0x1f)
除了当我尝试监听 CTRL + Q 时:
case CTRL_KEY('q'):
cin_ignore();
clear_screen();
reset_termios();
main_menu();
break;
它并不工作,因为我期望在同时按下 CTRL 和 Q 时会调用相应的函数。
顺便说一下,我尝试读取按键的方式如下:
当调用函数 "write_screen" 时:
init_termios(); // disable echo and canonical mode
global_signal = 0; // ignore
while (1)
{
write_check(content); // check what user input is , for example if it is CTRL + Q, then quit the program
if (read(STDIN_FILENO, &content, 1) == -1 && errno != EAGAIN)
{
error_handle("read"); // perror() function
}
type_check(content); // check if the character is printable, if it is arrows keys etc , if it is printable then print the content
}
那么,我到底哪里出错了?如果不能那样实现,还有其他方法吗?
规格:
- 操作系统:Linux
- 解释器:Visual Studio Code
下面是一段最小的代码:
#include <unistd.h>
#include <stdio.h>
#include <termios.h>
#include <errno.h>
#include <type.h>
char c;
int global_signal = 0;
static struct termios old, new1;
#define CTRL_KEY(k) ((k) & 0x1f)
void init_termios()
{
tcgetattr(0, &old);
new1 = old;
new1.c_lflag &= ~ICANON;
new1.c_lflag &= ~ECHO;
new1.c_lflag &= ~IGNBRK;
tcsetattr(0, TCSANOW, &new1);
}
void reset_termios()
{
tcsetattr(0, TCSANOW, &old);
}
void type_check(char content)
{
if (isprint(content))
{
// print ..
}
}
void write_check(char content)
{
switch (content)
{
case CTRL_KEY('q'):
printf("CTRL + Q pressed\n");
break;
}
}
void write_screen(int global_signal, char content)
{
if (global_signal == 0)
{
init_termios();
global_signal = 0;
while (1)
{
write_check(content);
if (read(STDIN_FILENO, &content, 1) == -1 && errno != EAGAIN)
{
// error function..
}
type_check(content);
}
}
}
int main()
{
write_screen(0, c);
}
那么,是我这边的问题吗?我是不是在不应该运行它的地方运行了它?就这种情况而言?
解决方案
你的代码在标准终端的MATE(mate-terminal)和 WezTerm 下对我来说工作正常,但在 xterm 和 Alacritty 时会有问题。
问题可能是因为某些终端为了自身使用会拦截 Ctrl+Q(以及 Ctrl+S)。
如果我设置
new1.c_iflag &= ~IXON;
那么它对我就起作用。
通常它会与 IXOFF 一起出现
new1.c_iflag &= ~(IXON|IXOFF);
pty - IXON与 IXOFF tty属性有什么区别? - Unix & Linux Stack Exchange
对 [termios] 的手册:
IXON Enable XON/XOFF flow control on output.
IXOFF Enable XON/XOFF flow control on input.
还有一些关于 Ctrl+Q 和 Ctrl+S 的信息
VSTART (021, DC1, Ctrl-Q) Start character (START). Restarts
output stopped by the Stop character. Recognized when IXON
is set, and then not passed as input.
VSTOP (023, DC3, Ctrl-S) Stop character (STOP). Stop output
until Start character typed. Recognized when IXON is set,
and then not passed as input.
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。