Is this even possible? Notepad++ for example does it, but simply trying to assign it to components like actions or menu items doesn't work. The event it is assigned to simply doesn't trigger.
So, I took my question to Google. Nada. Then, I tried stepping through the various shortcut functions, in this case TextToShortCut and ShortCutToText.
The first one, TextToShortCut, converts stuff like 'Ctrl+A' (a string) to the following 16bit value:
(uint)A | (uint)Ctrl
Works fine, mostly. However, I observed the following weirdness:
// 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) = ''
What's going on here? For now, I believe the error lies in the final part of TextToShortCut: after handling the part before the + sign ("Ctrl" in this case), it will try to find a shortcut for the remaining part ("/"). However, in its current form the part after + must be a valid shortcut on its own too.
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;
So, because:
ShortCutToText('/') = 0 (failure)
MapVirtualKey('/',MAPVK_VK_TO_VSC) = 0 (failure)
... the loop fails to detect '/' as a valid shortcut.
Is this some VCL bug or am I missing something?
Here's a proof of concept (yes, I'm taking screenshots of code, but mashing this together with the Component Palette is faster than using this code directly):
Edit 1:

Edit 2:
Manually assigning 16431 to the menu item does not work.
If you assign an OnShortCut event handler to your menu's parent TForm, you will see that pressing Ctrl+/ results in a TShortCut value of 16575 from Menus.ShortCutFromMessage(), which is the function that the VCL uses internally when dispatching keystrokes for shortcut handling.
Both ShortCutToText(16495) and ShortCutToText(16575) return 'Ctrl+/', so lets break it down:
scCtrl = $4000
16495 = $406F
16575 = $40BF
Both shortcuts have the scCtrl flag present.
ShortCutToText($6F) and ShortCutToText($BF) both return '/'. This is because MapVirtualKey() returns the same scan code ($350000) for both virtual keys $6F (VK_DIVIDE) and $BF (VK_OEM_2 - the /? key for US keyboards).
When dispatching a shortcut, the VCL does exact comparisons of TShortCut values.  So when you have 16495 assigned as your shortcut, it will not trigger because the system is reporting a shortcut of 16575 instead, even though they both map to Ctrl+/.
When I assign 16575 to the ShortCut property of a TMenuItem or TAction, pressing Ctrl+/ triggers the item, as expected.
So the trick is that the system is reporting a shortcut that uses the VK_OEM_2 virtual key for /, but you are expecting it to use the VK_DIVIDE virtual key instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With