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

时间:2013-09-10 16:18:44

标签: delphi delphi-7 shortcut

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

所以,我把问题提交给谷歌。纳达。然后,我尝试逐步执行各种快捷方式功能,在本例中为TextToShortCut和ShortCutToText。

第一个,TextToShortCut,将“Ctrl + A”(字符串)等内容转换为以下16位值:

(uint)A | (uint)Ctrl

工作正常,主要是。但是,我观察到以下奇怪之处:<​​/ p>

// 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:

enter image description here

编辑2:

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

2 个答案:

答案 0 :(得分:12)

如果您将OnShortCut事件处理程序分配给菜单的父TForm,您会看到按 Ctrl + / 导致TShortCut的{​​{1}}值为16575,这是VCL在调度快捷键处理时的内部函数。

Menus.ShortCutFromMessage()ShortCutToText(16495)都返回ShortCutToText(16575),所以让我们将其分解:

'Ctrl+/'

这两个快捷方式都有scCtrl = $4000 16495 = $406F 16575 = $40BF 标志。

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

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

当我将16575分配给Ctrl+/ShortCut的{​​{1}}属性时,按 Ctrl + / 会触发该项正如所料。

所以诀窍是系统正在报告使用TMenuItem TAction虚拟密钥的快捷方式,但您希望它使用VK_OEM_2虚拟密钥。

答案 1 :(得分:7)

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

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

无法创建响应两者的单一快捷方式。

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

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