What you're trying to do goes against the VCL, and probably goes against usual user expectations: When a new window is shown, unless it's a tool window, the usual (and expected) behavior is to move focus to it. The Win32 Api to show a window is ShowWindow and it'll activate the window, unless the SW_SHOWNOACTIVATE
flag (or one of it's variants) is specified.
When you make a VCL form visible, a call to that function is also made. The call to ShowWindow
is buried in procedure TCustomForm.CMShowingChanged(var Message: TMessage)
, a 135 lines procedure that hard-codes the SW_SHOWNORMAL
flag (ie: an Activating flag) for the ShowWindow
call that the VCL makes. Unfortunately that's a big piece of code and overriding it is not going to be easy. If this was my program I'd probably attempt changing the code in place: I'd add a DoNotActivate:Boolean
flag to TCustomForm
and change the single line of code in CMShowingChanged
that calls ShowWindow
for non-MDI forms to take that flag into account and simply call ShowWindow(Handle, SW_SHOWNOACTIVATE)
. If changing the VCL is not something you'd do light-hearted, you can use the following hacky solution:
The trick I'm suggesting is to create the new form (the one holding TWebBrowser
) but do NOT set it's Visible
property to True
. Instead, make manual calls to ShowWindow(Handle, SW_SHOWNOACTIVATE
) to show the form without activating it. Because this code would no longer code through the usual Delphi VCL, owned controls would not automatically be created and shown, so the ShowWindow(...)
call needs to be made recursively, for all TWinControl
descendants of the form:
procedure TForm15.Button1Click(Sender: TObject);
var F: TForm16;
procedure RecursiveShowNoActivate(W: TWinControl);
var i:Integer;
begin
ShowWindow(W.Handle, SW_SHOWNOACTIVATE);
for i:=0 to W.ControlCount-1 do
if W.Controls[i] is TWinControl then
RecursiveShowNoActivate(TWinControl(W.Controls[i]));
end;
begin
F := TForm16.Create(Application);
F.Top := Top + height; // So the new form doesn't overlap mine
RecursiveShowNoActivate(F);
F.WebBrowser1.Navigate('http://msdn.microsoft.com/en-us/library/ms123401');
end;
There's an other catch with this code: Make sure you navigate to a web page that doesn't have a form that's automatically focused. Navigating to microsoft's MSDN library might be unusual for a code sample, but that canonical example (www.google.com) sets focus to the search form.