1
votes

In a very complex Delphi 10.4.2 VCL Application, an unknown control or component seems to "steal" the CTRL+A shortcut. In an attempt to detect the object stealing the shortcut, I try using the TApplicationEvents.OnShortCut event handler:

procedure TformMain.ApplicationEvents1ShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
  case Msg.CharCode of      
    VK_A:
      begin
        //CodeSite.Send('TformMain.ApplicationEvents1ShortCut: ', ???);
      end;
  end;
end;

Can this event handler be used to detect the "thief", or which method would you suggest?

1
Why not searching all .PAS files for the text ctrl or ssCtrl?AmigoJack
@AmigoJack: That will miss a very large number of all possible scenarios, for instance, when you have a TAction with its Shortcut set to Ctrl+A. That's stored (utterly numerically) in the DFM.Andreas Rejbrand
@AndreasRejbrand That's true: The Action's CTRL+A shortcut is stored in the DFM as ShortCut = 16449.user1580348

1 Answers

7
votes

There are many ways to implement shortcuts, so there might not be a single quick approach that can catch them all. But the following should cover many (if not most) cases.

All background knowledge you need can be found in Peter Below’s A Key’s Odyssey.

First, if you know that some code is executed as a result of this shortcut, you can put a breakpoint in this code and the call stack will likely tell you all you need to know.

For instance, if I create a new VCL application, add a TActionList, and a TAction with shortcut Ctrl+T and an OnExecute handler which calls the CreateFrog procedure, I can put a breakpoint in this procedure, and I get the following call stack:

Call stack

Here we immediately see that CreateFrog was called due to an action named aTest with a matching shortcut. In fact, if you go down all the way down to TControl.WndProc (say) you can even see that the T (84) key was depressed (CN_KEYDOWN = 48384):

Screenshot of local variables

If you don't have any nice place to put a breakpoint, you can put a conditional breakpoint in TControl.WndProc with condition (Message.Msg = CN_KEYDOWN) and (Message.WParam = 84):

Screenshot of Source Breakpoint Properties dialog box

Then, if you run the app and trigger the shortcut, you will be able to step through the source code and see what happens.