繁体   English   中英

在Delphi程序中使用Ctrl + /作为快捷方式

[英]Use Ctrl+/ as shortcut in Delphi program

这甚至可能吗? 例如,Notepad ++可以实现,但只是尝试将其分配给操作或菜单项等组件不起作用。 它被分配的事件根本不会触发。

所以,我把我的问题提交给谷歌。 纳达。 然后,我尝试逐步执行各种快捷方式功能,在本例中为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错误还是我错过了什么?

这是一个概念证明(是的,我正在拍摄代码的截图,但是将它与Component Palette混合在一起比直接使用此代码更快):

编辑1:

在此输入图像描述

编辑2:

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

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

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

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

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

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

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

当我给你16575的ShortCut一的财产TMenuItemTAction ,按下Ctrl + /触发项目,符合市场预期。

因此,关键的是,该系统报告使用该快捷方式VK_OEM_2的虚拟键/ ,但你希望它使用VK_DIVIDE虚拟键代替。

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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM