views:

2508

answers:

4

How do I get the KeyDown event to work in a Delphi (2007) MDI Applications Parent window, even if a Child window has focus?

I would like to implement a shortcut key (F1) that brings up a help screen in a MDI application, I have added the KeyDown procedure to the MDI Parent window and enabled KeyPreview in both the Parent and Child windows, but it does not work as expected.

If I put a break point in the Parents KeyDown code I can see it never executes, even it there are no child windows open. But if I add the same code to the child window it works fine.

Is there a way to get the parent window to receive the key presses, even if the child window has focus, as adding the code to 25+ forms seams a little wasteful?

+1  A: 

You could use a local (global is not needed) keyboard hook. You could also derive all your MDI Child forms from a signle form base class and implement it there once. You will find that this design comes in handy for other problems as well.

edit

Application wide hotkeys/shortcuts can also be implemented with the TApplication.OnShortCut event. See http://delphi.about.com/od/adptips2004/a/bltip0904_3.htm

F1 is already the standard help shortcut which triggers TApplication.OnHelp. So maybe you want to use the OnHelp event? And if you use the HelpFile, HelpContext, HelpType and HelpKeyword properties you probably don't even need to implement any code at all.

Lars Truijens
Great advise. I have always used a baseclass for MDI children. It just feels right to do so.
Gamecat
A: 

F1 help processing is built into Delphi, so all you have to do is handle the help messages properly. This may be as little as setting the helpfile property for the application. You can set particular pages using the form's help??? properties.

Basically, just use the help system supplied and forget keydown. This is Delphi - you don't have to work hard.

mj2008
+2  A: 

I had the exact same problem this week! I fixed it by creating an action in the ActionManager on the mainform. This action opens the help file and has the F1-key set as shortcut. It also works for all MDI child screens.

birger
This should definitely work; besides, using TActionLists or TActionManagers for this sort of thing is the right way anyway!
onnodb
do you happen to know why/how this works? does TAction implement a local keyboard hook?
PA
A: 

How do I get the KeyDown event to work in a Delphi (2007) MDI Applications Parent window, even if a Child window has focus?

As a more generic solution (for applications other than F1 for help) I use code similar to this to trap a keydown event in the main form. This gets all keys no matter what, even when an MDI child is active. In this example I'm doing the opposite of what you are trying to do (I want the message to be handled by my child form instead of the main form), but the concept of catching the keys in the parent is the same).

Application.OnMessage := AppMessage;

procedure TMainForm.Appmessage(var Msg: TMsg; var Handled: Boolean);
var
  message: TWMKey;
begin
  If (msg.message = WM_KEYDOWN) and
     ( LoWord(msg.wparam) = VK_TAB ) and
     (GetKeyState( VK_CONTROL ) < 0 ) and
     Assigned( ActiveMDIChild ) then
  Begin
    Move( msg.message, message.msg, 3*sizeof(Cardinal));
    message.result := 0;
    Handled := ActiveMDIChild.IsShortcut( message );
  End;
end;
Jeremy Mullin