这甚至可能吗?例如,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:
编辑2:
手动将16431分配给菜单项不起作用。
答案 0 :(得分:12)
如果您将OnShortCut
事件处理程序分配给菜单的父TForm
,您会看到按 Ctrl + / 导致TShortCut
的{{1}}值为16575,这是VCL在调度快捷键处理时的内部函数。
Menus.ShortCutFromMessage()
和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会对/?
值进行精确比较。因此,当您将16495指定为快捷方式时,它将不会触发,因为系统正在报告16575的快捷方式,即使它们都映射到TShortCut
。
当我将16575分配给Ctrl+/
或ShortCut
的{{1}}属性时,按 Ctrl + / 会触发该项正如所料。
所以诀窍是系统正在报告使用TMenuItem
TAction
虚拟密钥的快捷方式,但您希望它使用VK_OEM_2
虚拟密钥。
答案 1 :(得分:7)
对Key
事件处理程序中OnKeyDown
的简单调查显示了两种不同类型的正斜杠:
/
= 111
(结合 CTRL = 16575
)/
= 191
(结合 CTRL = 16495
)无法创建响应两者的单一快捷方式。
但是,您可以附加具有SecondaryShortCuts
属性的操作,而不是在memu项目上设置快捷方式。然后使用:
procedure TForm1.FormCreate(Sender: TObject);
begin
Action1.ShortCut := 16575;
Action1.SecondaryShortCuts.Add('Ctrl+/');
end;