基本上,这在很大程度上取决于您如何立即定义。
这里有两个任务。第一个是禁用大多数 C 输入库中内置的常规键回显。第二种是打印出新字符而不是旧字符。
在伪代码中。
echo(off);
while (capturing && charIsAvailable()) {
c = readOneChar();
if (c == '\n') {
capturing = false;
}
printf("%c", c++);
}
echo(on);
有许多系统进行通信以捕获按键。
- 键盘
- (可能)USB 总线
- CPU 中断处理程序
- 操作系统
- X 窗口服务器进程
- 具有焦点的 X“窗口”。
最后一步是通过一个程序完成的,该程序运行一个连续循环,从 X 服务器捕获事件并处理它们。如果你想以某种方式扩展这个程序(获取按键被按下的时间长度),你需要告诉其他程序你想要“原始”键盘事件,这意味着你不会真正收到完全“熟” “ 人物。因此,您必须跟踪哪些键是向上和向下的,以及多长时间,并处理程序中所有奇怪的元键行为(这不是“a”而是“A”,因为 shift 已关闭,等等)。
还需要考虑其他处理模式,例如规范和非规范,它们将控制您是希望在面向行的块(行事件)还是面向字符的块(字符事件)中接收事件。同样,由于需要让上游程序了解下游客户端的需求,这有点复杂。
现在您已经对自己的环境有了一些了解,让我们重新审视抑制字符输出所需的实际代码。
// define a terminal configuration data structure
struct termios term;
// copy the stdin terminal configuration into term
tcgetattr( fileno(stdin), &term );
// turn off Canonical processing in term
term.c_lflag &= ~ICANON;
// turn off screen echo in term
term.c_lflag &= ~ECHO;
// set the terminal configuration for stdin according to term, now
tcsetattr( fileno(stdin), TCSANOW, &term);
(fetch characters here, use printf to show whatever you like)
// turn on Canonical processing in term
term.c_lflag |= ICANON;
// turn on screen echo in term
term.c_lflag |= ECHO;
// set the terminal configuration for stdin according to term, now
tcsetattr( fileno(stdin), TCSANOW, &term);
即使这也不是即时的。要立即获得,您需要更接近源,这最终意味着一个内核模块(它仍然不如键盘微控制器那么直接,它不如开关实际关闭时那么直接)。在源和目标之间有足够多的项目,最终可能会注意到差异,但是,在实践中,寻求性能和灵活性之间最佳折衷的人们已经对这段代码进行了很多工作。