Delphi 12中OnKeyPress按下Ctrl+V时Key为#$16的原因是什么?
关于Delphi中Ctrl+V触发OnKeyPress时Key值为#$16的疑问
我正在测试一个继承自TDBMemo的组件,该组件可在“隐藏模式”下将DataField切换为带星号的internalCalc字段,以星号替代实际数据显示。在隐藏模式下编辑控件意义不大,因此我设置了OnKeyPress事件来拦截除粘贴组合键(Ctrl+V和Shift+Ins)之外的所有按键操作,并通过procedure WMPaste(var Message: TWMPaste); message WM_PASTE;确保更新原始数据集字段而非星号字段。
以下是OnKeyPress处理程序:
procedure TPasteCatchDBMemo.PasteCatchDBMemoKeyPress(Sender: TObject; var Key: Char); var lCtrl, lShift, lPaste: Boolean; begin if not FPasswordMode then Exit; // Everything allowed lCtrl := (GetKeyState(VK_CONTROL) < 0); // High bit set lShift := (GetKeyState(VK_SHIFT) < 0); lPaste := lCtrl and ((Key = 'V') or (Key = 'v') or (Key = #$16)) or lShift and (GetKeyState(VK_INSERT) < 0); if not lPaste then Key := #0; end;
问题:当按下Ctrl+V时,Key的值不是'V'(十进制86)或'v'(十进制118),而是#$16(十进制22),我必须添加该值才能使功能正常工作。请问这个#$16来自哪里?这是一个Delphi 12的Win32/Win64测试应用。
解答
#$16是ASCII控制字符中的SYN(同步)字符,对应十进制22,它的来源可以从两方面说明:
- ASCII标准定义:在传统ASCII编码规则里,Ctrl+字母键的组合会被映射为对应的控制字符——将字母的ASCII码减去64(大写字母)或96(小写字母),得到的就是控制字符编码。比如大写V的ASCII是86,86-64=22,对应十六进制的$16,也就是#$16。
- Windows与Delphi事件机制:Delphi的
OnKeyPress事件基于Windows的WM_CHAR消息实现。当按下Ctrl+V时,系统发送的WM_CHAR消息中携带的字符码就是对应的ASCII控制字符#$16,而非字母V的ASCII值。因为OnKeyPress的设计目标是处理可打印字符和控制类输入,Ctrl+字母这类组合属于控制操作范畴,所以会传递控制字符而非字母本身。
如果想简化按键判断逻辑,也可以改用OnKeyDown事件,直接通过虚拟键码和Shift状态判断,不需要依赖控制字符映射:
procedure TPasteCatchDBMemo.PasteCatchDBMemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if FPasswordMode then begin // 只允许Ctrl+V或Shift+Ins if not ((ssCtrl in Shift) and (Key = Ord('V')) or (ssShift in Shift) and (Key = VK_INSERT)) then Key := 0; end; end;
内容的提问来源于stack exchange,提问作者Jan Doggen
相关产品推荐
相关产品推荐

