How can I make a form visible and maximize it to fill a secondary monitor without it activating?

Viewed 871

I have an application which is designed for multiple monitors. It starts up, and we try to avoid activating windows that do not need to be activated, because the user only does keyboard input in one place, and each time we Activate a new form on a secondary monitor, it grabs keyboard focus, something we wish to avoid.

Our in-house base TForm class has a method like this, which is using the Win32 ShowWindow function directly, avoiding the VCL framework's internal visibility change system which grabs focus:

procedure TOurForm.ShowWithoutActivate;
begin
    ShowWindow(Self.Handle, SW_SHOWNOACTIVATE);
    Self.Visible := true;
end;

If I just did this, it would grab focus:

 Self.Visible := true; // TWindow.Visible = true, will grab focus, plus make window visible.

This works, but the next thing I'd like to be able to do is set Maximized state so that the form will maximize itself on the Monitor that it is currently on. How do we get it onto a particular monitor? The same way it always worked, with modification of the Left and Top properties of the Form. We have to take care that if we store Left/Top/Width/Height on form, and then restore it, that the results are still valid when we reload it. That is NOT what I'm asking about.

I'm specifically asking about how to maximize the form now that I have "showed" it using the above custom function. One hack begets another hack. Here is how far down this rabbit hole I've gone:

  • When a TForm, which is also a TWinControl's private field FShowing is false, setting Form.Maximized has no effect.
  • When a TForm has its TWinControl.FShowing field set true, setting the windowState to wsMaximized also causes the form to activate.

Is it possible to both make this form visible and make it take the window state I want it to take without activating? If I can't do this, then users are going to lose their keyboard focus when I show this form on a secondary monitor, something that I really want to avoid.

What I tried is to use Win32 ShowWindow API to do SW_SHOWMAXIMIZED:

  ShowWindow(Self.Handle, SW_SHOWMAXIMIZED);

The above seems to grab focus (activate).

2 Answers
Related