【问题标题】:Use Ctrl+/ as shortcut in Delphi program在 Delphi 程序中使用 Ctrl+/ 作为快捷方式
【发布时间】:2013-09-10 16:18:44
【问题描述】:

这甚至可能吗?例如 Notepad++ 就可以做到,但简单地尝试将其分配给操作或菜单项等组件是行不通的。它分配给的事件根本不会触发。

所以,我向 Google 提出了我的问题。纳达。然后,我尝试逐步了解各种快捷功能,在本例中为 TextToShortCut 和 ShortCutToText。

第一个,TextToShortCut,将 'Ctrl+A'(一个字符串)之类的东西转换为以下 16 位值:

(uint)A | (uint)Ctrl

大部分情况下工作正常。但是,我观察到以下奇怪现象:

// Try converting back and forward...
TextToShortCut('Ctrl+/') = 16495

// That's incorrect. It should be:
Ord('/') or scCtrl = 16431

// Incorrect too
ShortCutToText(16495) = 'Ctrl+/'

// This is the shortcut the first line actually creates (Ctrl+o)
Ord('o') or scCtrl = 16495 // wut?

// Which is invalid, cause only caps are used
ShortCutToText(16431) = ''

这里发生了什么?目前,我认为错误在于 TextToShortCut 的最后部分:在处理完 + 号之前的部分(本例中为“Ctrl”)后,它将尝试为剩余部分(“/”)找到快捷方式。 但是,在目前的形式中,+ 之后的部分本身也必须是一个有效的快捷方式。

for Key := $08 to $255 do { Copy range from table in ShortCutToText }
  if AnsiCompareText(Text, ShortCutToText(Key)) = 0 then
  begin
    Result := Key or Shift;
    Exit;
  end;

所以,因为:

ShortCutToText('/') = 0 (failure)
MapVirtualKey('/',MAPVK_VK_TO_VSC) = 0 (failure)

...循环未能将“/”检测为有效的快捷方式。

这是一些 VCL 错误还是我遗漏了什么?

这是一个概念证明(是的,我正在截取代码,但将其与组件面板混合在一起比直接使用此代码要快):

编辑 1:

编辑 2:

手动将 16431 分配给菜单项不起作用。

【问题讨论】:

  • 在这里工作正常。尽管仅在作为数字键盘一部分的 / 键上。但这就是 npp 所做的。它的恢复缩放快捷方式映射到Ctrl+Num /
  • Notepad++ 使用常规的(美国国际上的 Shift 左侧)也用于跳到插入符号处的单词开头。

标签: delphi delphi-7 shortcut


【解决方案1】:

如果将OnShortCut 事件处理程序分配给菜单的父级TForm,您将看到按Ctrl+/ 会导致TShortCut 值为来自Menus.ShortCutFromMessage() 的16575,这是VCL 在为快捷键处理分派击键时在内部使用的函数。

ShortCutToText(16495)ShortCutToText(16575) 都返回 'Ctrl+/',所以让我们分解一下:

scCtrl = $4000
16495 = $406F
16575 = $40BF

两个快捷方式都有 scCtrl 标志。

ShortCutToText($6F)ShortCutToText($BF) 都返回 '/'。这是因为MapVirtualKey() 为虚拟键$6F (VK_DIVIDE) 和$BF (VK_OEM_2 - 美国键盘的/? 键) 返回相同的扫描码 ($350000)。

在调度快捷方式时,VCL 会精确比较 TShortCut 的值。因此,当您将 16495 指定为快捷方式时,它不会触发,因为系统报告的是 16575 的快捷方式,即使它们都映射到 Ctrl+/

当我将 16575 分配给 TMenuItemTActionShortCut 属性时,按 Ctrl+/ 会按预期触发该项目。 p>

所以诀窍是系统报告了一个使用VK_OEM_2 虚拟键的快捷方式/,但您希望它使用VK_DIVIDE 虚拟键代替。

【讨论】:

    【解决方案2】:

    OnKeyDown 事件处理程序对Key 的简单调查显示了两种不同类型的正斜杠:

    • 数字键盘上的/ = 111(结合 CTRL = 16575
    • / 旁边的 shift 键 = 191 (结合 CTRL = 16495

    不可能创建一个同时响应两者的快捷方式。

    但是,您可以附加一个具有SecondaryShortCuts 属性的操作,而不是在 memu 项上设置快捷方式。然后使用:

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Action1.ShortCut := 16575;
      Action1.SecondaryShortCuts.Add('Ctrl+/');
    end;
    

    【讨论】:

    • SecondaryShortCuts 属性总是存在的
    • 我不想同时绑定两者,我只是想绑定到 191 的那个。谢谢你的回答。
    • 我只是想绑定到 191。 为什么问题没有说明这一点?我们是用来猜测的吗?
    • @DavidHeffernan:我写的时候完全忘记了小键盘版本 / 的存在。对此感到抱歉。
    • 这是可以理解的。但你的评论听起来不太感激。 感谢您的回答。但是你不喜欢这个答案实际上是那个遗漏的结果。我想这就是我反应的原因。支持我的回答者!
    猜你喜欢
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 2014-06-01
    • 2012-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多