4
votes

We have a Delphi 2007 application and have recently enabled MainFormOnTaskBar for better support of Windows Aero. However because the main form would not come to the top of all child forms when clicked we added the following code.

procedure TBaseForm.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);

  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
  Params.WndParent := 0; 
end;

One side effect of this is that when pressing an Alt + key hotkey on a child form that does not handle that particular hot key the main form flicks to the front and then back again. If the hot key is handled then this behavior does not occur, probably because the hotkey is swallowed.

Has anyone else experienced this behavior and can advise a workaround.

Thanks

1
You do not need to override CreateParams() like that when MainFormOnTaskbar is true. The base implementation already sets those same values for you. Clicking on the MainForm should be bringing it to the top when clicked, that is normal window behavior.Remy Lebeau
@Remy - All secondary forms are owned by the main form when MainFormOnTaskbar is true. That prevents the main form from coming in front of secondary forms.Sertac Akyuz
You'll likely hit other issues as well. One mentioned here in workaround section. Probably others too...Sertac Akyuz
@SertacAkyuz: "All secondary forms are owned by the main form when MainFormOnTaskbar is true" - that is a good point, I forgot about that. In that case, you would have to override CreateParams() on the secondary forms to break that ownership.Remy Lebeau

1 Answers

5
votes

The observed behavior is the result of VCL's accelerator support for a possible main menu on the main form, so that you can select menu items from the main form's menu even when another form is active.

The activation of the main form takes place by a SetFocus call on the main form's handle while the "Application" is handling the CM_APPSYSCOMMAND message which is sent from the WM_SYSCOMMAND handler of a "WinControl" (secondary form) when command type is SC_KEYMENU (window menu activation - Alt key).

Note that this behavior is not a side effect of using MainFormOnTaskBar and then overriding CreateParams to have forms that can be brought to front. The same behavior occurs regardless of the setting of MainFormOnTaskBar. The only difference is that the activated main form cannot come in front of secondary forms when it is set, but the main form is activated all the same.

You can intercept to modify the behavior in a number of places, like a WM_SYSKEYDOWN handler on the secondary form, or in OnKeyDown of the secondary form. Semantically more correct override, IMO, should be done on the IsShortCut of the secondary form. As you have found out, when the secondary form handles a key combination, the processing of the system key terminates. You can, then, tell the VCL that your form requires the key:

type
  TSecondaryForm = class(TForm)
    ..
  public
    function IsShortCut(var Message: TWMKey): Boolean; override;

...

function TSecondaryForm.IsShortCut(var Message: TWMKey): Boolean;
begin
  Result := True;
end;

Of course you can fine tune to conditionally return true depending on the parameter.