You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,它的来源可以从两方面说明:

  1. ASCII标准定义:在传统ASCII编码规则里,Ctrl+字母键的组合会被映射为对应的控制字符——将字母的ASCII码减去64(大写字母)或96(小写字母),得到的就是控制字符编码。比如大写V的ASCII是86,86-64=22,对应十六进制的$16,也就是#$16。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:03:26