<Window x:Class="WebBrowser.Window1" |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
Title="Window1" Height="300" Width="300" |
Loaded="Window_Loaded" Activated="Window_Activated"> |
<Grid> |
<WebBrowser Name="WB" IsVisibleChanged="WB_IsVisibleChanged"/> |
</Grid> |
</Window> |
I'd like the web browser object to have focus at all times: When the application starts and also whenever the application becomes active (by switching from another app). So I put event handlers at various locations: on Loaded, on Activated and on VisibilityChanged.
private void Window_Loaded(object sender, RoutedEventArgs e) |
{ |
WB.NavigateToString("<HTML>Hello</HTML>"); |
IHTMLDocument2 doc2 = (IHTMLDocument2) WB.Document; |
doc2.designMode = "On"; |
SetFocus(); |
} |
Loaded is also when I switch the control to design mode.
Then
private void Window_Activated(object sender, EventArgs e) |
{ |
SetFocus(); |
} |
private void WB_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) |
{ |
if (WB.IsVisible) |
{ |
SetFocus(); |
} |
} |
First, I tried to implement SetFocus() as a call to WB.SetFocus(), but I got an System.ExecutionEngineException.
Instead, I call focus() on the browser.
private void SetFocus() |
{ |
// This throws System.ExecutionEngineException |
// WB.Focus(); |
IHTMLDocument4 doc4 = (IHTMLDocument4)WB.Document; |
if (doc4 != null) |
{ |
doc4.focus(); |
Debug.Print("focus {0}", doc4.hasFocus()); |
} |
} |
It doesn't work. The focus is not on the editor as startup. I can click on the main window and write things, but the focus is lost when I go to another window and come back.
With SPY++, I noticed that on window activation, the SetFocus() function transfers the focus to the web browser but then it is taken back by the WPF main window.
Then I added a hook to intercept any WM_FOCUS message. It's brutal and I'd rather not do this even.
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) |
{ |
const int WM_SETFOCUS = 0x0007; |
switch (msg) |
{ |
case WM_SETFOCUS: |
SetFocus(); |
handled = true; |
break; |
} |
return IntPtr.Zero; |
} |
and added
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); |
source.AddHook(WndProc); |
to Window_Loaded.
Now the focus is given to the web browser control when I switch from another app, but not at startup.
It seems like it is because SetFocus() is called before the web browser is fully materialized. SetFocus() is called but hasFocus remains false. At startup, the Debugger Output shows
focus False
focus TrueI tried putting several SetFocus() calls at different places during the setup but I can't make it to work.
Do you have a recommendation?
Thanks,
--h