Monday, 15 February 2021

Closing in on Modal Jump Lists

- or getting a WM_SYSCOMMAND to a modal dialog.

An idea that initially seemed clever, has been haunting me a bit lately - I did put a modal dialog into a project before the main Application block (Initialize .. Run). Shame on me.

So the code looks similar to like this:

if (TfrmLaunchSetting.Execute = mrOK) then
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.Title := 'MyApplication';
  Application.CreateForm(TfrmMain, frmMain);
  Application.Run;
end;

and the TFrmLaunchSetting.Execute is just a class function returning the ModalResult, from its ShowModal.

But here comes the issue at hand - the Close Window in the task bars Jump List sends a WM_SYSCOMMAND that goes to the system menu in the main window - but if a modal form is shown the main window is disabled - and in this case I do not even have a main form yet.

So TApplication.HookMainWindow to the rescue - that would enable me to intercept messages sent to the main form - and act upon these.

So in the FormCreate of my modal dialog I hook the my hook function up like this:

Application.HookMainWindow(AppHookFunc);

And on FormDestroy I do the following:

Application.UnHookMainWindow(AppHookFunc);

The AppHookFunc goes as follows:

function TfrmLaunchSetting.AppHookFunc(var Message: TMessage): Boolean;
begin
  Result := False;
  if Message.Msg = WM_SYSCOMMAND then
  begin
    PostMessage(Handle, WM_CLOSE, 0, 0);
    Result := True;
  end;
end;

This way modal dialogs can react to Windows messages that normally be intended for the main form.

There are probably side-effects - but the issue at hand is solved - for now?

BTW: Yesterday was Delphi 26th birthday - I did not forget - but I am still wrapping up the present. Stay tuned.

/Enjoy