使用RAD Studio 12开发Delphi Linux控制台程序,如何无等待捕获键盘输入?
在Linux下的Delphi控制台程序实现无回车按键捕获及高级控制台操作
一、核心思路:切换终端到原始模式(Raw Mode)
Linux控制台默认处于规范模式(Canonical Mode),必须等待回车键才会提交输入。要实现类似top的即时按键捕获,需要先将终端切换到原始模式,操作完成后再恢复默认状态,避免终端异常。
二、具体实现方案
1. 终端模式切换(替代Windows控制台状态控制函数)
通过Linux系统的tcgetattr和tcsetattr函数修改终端属性,这两个函数可直接在RAD Studio 12的Posix.Base单元中调用。
示例代码:
uses System.SysUtils, Posix.Base, Posix.Termios; var OldTermios, NewTermios: termios; begin // 保存当前终端属性 tcgetattr(STDIN_FILENO, @OldTermios); NewTermios := OldTermios; // 切换到原始模式:关闭规范输入、回显、信号触发等 cfmakeraw(@NewTermios); // 立即应用新属性 tcsetattr(STDIN_FILENO, TCSANOW, @NewTermios); try // 在此编写按键捕获及业务逻辑 finally // 程序退出前必须恢复终端原始属性 tcsetattr(STDIN_FILENO, TCSANOW, @OldTermios); end; end;
2. 无回车捕获按键输入(替代ReadConsoleInput)
原始模式下,使用read函数直接从标准输入读取单个字节,无需等待回车。
示例代码:
var Buffer: array[0..0] of Byte; BytesRead: Integer; begin while True do begin BytesRead := read(STDIN_FILENO, Buffer[0], 1); if BytesRead > 0 then begin // 示例:按ESC键退出循环 if Buffer[0] = 27 then Break; Writeln('捕获到按键: ', Char(Buffer[0])); end; end; end;
注意:方向键、功能键等特殊按键会发送多字节序列(比如方向上键是
ESC[A),需要额外逻辑缓存输入并匹配序列来识别。
3. 修改控制台文本/背景颜色(替代SetConsoleTextAttribute)
Linux终端支持ANSI转义序列,直接输出对应转义码即可修改颜色:
- 前景色范围:
\033[30m(黑色)~\033[37m(白色) - 背景色范围:
\033[40m(黑色)~\033[47m(白色) - 重置颜色:
\033[0m
示例代码:
Writeln(#27'[31m红色前景文本'#27'[0m'); Writeln(#27'[42m绿色背景的文本'#27'[0m');
4. 窗口状态捕获(替代GetConsoleScreenBufferInfo)
通过监听SIGWINCH信号捕获窗口大小变化,结合ioctl函数获取当前终端尺寸:
示例代码:
uses Posix.Signal, Posix.Unistd, Posix.SysIoctl, Posix.Termios; var WinSize: winsize; procedure SigWinchHandler(Sig: Integer); cdecl; begin if ioctl(STDIN_FILENO, TIOCGWINSZ, @WinSize) = 0 then Writeln('窗口尺寸更新: ', WinSize.ws_col, '列 x ', WinSize.ws_row, '行'); end; // 程序初始化时注册信号处理 signal(SIGWINCH, @SigWinchHandler);
三、关键注意事项
- 必须在程序退出前恢复终端原始模式,否则终端会出现输入不回显等异常状态。
- 特殊按键的多字节序列需要额外编写解析逻辑,避免误判单字节输入。
- ANSI转义序列兼容大部分现代Linux终端,老旧终端可能存在兼容性问题。
内容的提问来源于stack exchange,提问作者Codrut
相关产品推荐
相关产品推荐

