Question

I have an application with a TTrayIcon Component that I use to "Hide" and "Restore" my MainForm. Here is what I use to "Hide" (OnTrayClick)

procedure TMainWindow.TrayIcon1Click(Sender: TObject);
var
  I : Integer;
begin
  if Application.MainForm.Visible then begin
    { Hide }
    Application.MainForm.Visible := FALSE;
  end else begin
    { Restore }
    Application.MainForm.Visible := TRUE;
    WindowState := wsNormal;
    Application.BringToFront();
    { Workaround for ModalForms }
    for I := 0 to Screen.FormCount-1 do begin
      if (fsModal in Screen.Forms[I].FormState) then begin
        Screen.Forms[I].BringToFront;
        Screen.Forms[I].SetFocus;
        break; // Stop looking for more ModalForms
      end;
    end;
  end;
end;

This example works just fine if there are no other (Modal) Forms open. But if there is a ModalForm open and restore my MainForm, the ModalForm seems to be behind the MainForm and I can't reach it. How can I activate/focus the ModalForm and put it in front of my MainForm after my MainForm has been restored? My Application.MainFormOnTaskbar is set to False

EDIT: If a ModalForm is open and I restore my MainForm, both of the forms won't focus at all.

Was it helpful?

Solution

The setting of MainFormOnTaskbar seems to be causing the problem. You really need to keep that set to true.

You could choose to not hide any forms if there is a modal windows. In that case check for Application.ModalLevel > 0 in your hide code. You could even show a balloon hint stating that the application cannot be minimized until messages are closed.

Otherwise if you really want to minimize all windows the code below works well for me. Hide all of the open windows including the modal window. This will cause the main taskbar icon to go away and everything is off the screen. The one thing you need to do is keep track of which windows were just open. I did that below by setting the Tag value on the forms that were just hidden. Then in the restore code you can set the visible of those windows back to true.

The only case this does not deal with is hiding the main window but leaving the modal window visible. I'm not sure why you would want to do that and personally I would find that confusing as a user.

procedure TForm1.TrayIcon1Click(Sender: TObject);
var
  I : Integer;
begin

  if Application.MainForm.Visible then
  begin
    //  Hide
    for I := 0 to Screen.FormCount-1 do
    begin
      if Screen.Forms[i].Visible = true then
      begin
        Screen.Forms[i].Visible := false;
        Screen.Forms[i].Tag := 1;
      end;
    end;

  end
  else
  begin
    // Restore
    for I := 0 to Screen.FormCount-1 do
    begin
      if Screen.Forms[i].Tag = 1 then
      begin
        Screen.Forms[i].Visible := true;
        Screen.Forms[i].Tag := 0;
      end;
    end;

    Application.BringToFront();

  end;
end;

You may need need to set the PopupParent property on the Modal Form to be your main form. This is set to pmAuto for new forms but if this is an old project it could be pmNone.

Here is a link to a blog post by Allen on PopupMode and PopupParent and here is another Stackoverflow questions that address the topic Newly created modal window loses focus and become inacessible in Windows Vista

I normally use something like this:

MyPopupForm := TMyForm.Create(Owner);
MyPopupForm.PopupMode := pmAuto;
MyPopupForm.PopupParent := Owner;
MyPopupForm.ShowModal;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top