Use Ctrl + / as a shortcut in Delphi

Is it possible? For example, Notepad ++ does this, but just trying to assign it to components, such as actions or menu items, does not work. The event to which it is assigned simply does not fire.

So, I took my question to Google. Nada. Then I tried to perform various quick access functions, in this case TextToShortCut and ShortCutToText.

The first, TextToShortCut, converts the material as "Ctrl + A" (string) to the following 16-bit value:

(uint)A | (uint)Ctrl 

Works fine, mostly. However, I noticed the following oddity:

 // Try converting back and forward... TextToShortCut('Ctrl+/') = 16495 // That 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? At the moment, I believe that the error lies in the final part of TextToShortCut: after processing the part before the + sign (in this case, "Ctrl"), it will try to find a shortcut for the remaining part ("/"). However, in its current form, the part after + should also be a valid label.

 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 cannot detect '/' as a valid shortcut.

Is this some VCL error or am I missing something?

Here's a proof of concept (yes, I'm taking screenshots of the code, but merging this together with the component palette is faster than using this code):

Change 1:

enter image description here

Edit 2:

Manually assigning item 16431 to a menu item does not work.

+6
source share
2 answers

If you assign an OnShortCut event OnShortCut your parent TForm menu TForm , you will see that pressing Ctrl + / will result in a TShortCut value of 16575 from Menus.ShortCutFromMessage() , which is a function that VCL uses internally when sending keystrokes to manage shortcuts.

Both ShortCutToText(16495) and ShortCutToText(16575) return 'Ctrl+/' , so ShortCutToText(16575) it off:

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

Both labels have the scCtrl flag.

ShortCutToText($6F) and ShortCutToText($BF) return '/' . This is due to the fact that MapVirtualKey() returns the same scan code ($ 350,000) for the virtual keys $6F ( VK_DIVIDE ) and $BF ( VK_OEM_2 - /? For American keyboards).

When sending a shortcut, VCL performs an exact comparison of TShortCut values. Therefore, when you have 16495 assigned as your shortcut, it will not start because the system reports an abbreviation of 16575 instead, although they are both mapped to Ctrl+/ .

When I assign 16575 to the ShortCut property for TMenuItem or TAction , pressing Ctrl + / starts the item as expected.

So, the trick is that the system reports a shortcut that uses the VK_OEM_2 virtual key for / , but you expect it to use the VK_DIVIDE virtual key.

+12
source

A simple Key exploration from the OnKeyDown event OnKeyDown reveals two different types of slashes:

  • / on the numeric keypad = 111 (in combination with CTRL = 16575 )
  • / next to shift = 191 (in combination with CTRL = 16495 )

It is not possible to create one shortcut that answers both.

But instead of setting a shortcut in the memu element, you can apply an action that has the SecondaryShortCuts property. Then use:

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

Source: https://habr.com/ru/post/953579/


All Articles