By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,694 Members | 1,795 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,694 IT Pros & Developers. It's quick & easy.

Hidden WebBrowser stealing focus

P: n/a
I am using a WebBrowser object in my .NET 2.0 application, but it is not
shown to the user. Every time a timer event triggers it to perform a
m_WebBrowser.Navigate() I get that classic IE 'click' and it steals the focus
from the user's current application.

How can I prevent the hidden WebBrowser from stealing focus? (And better
yet can I even suppress that click?_
Jul 13 '06 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Hi Dbooksta,

Thanks for your post!

Yes, I can reproduce out this behavior. Based on my research, it is the
mshtml.dll(which is the internal component of WebBrowser) that calls
SetFocus to change the application focus into the page. Since WebBrowser
control does not expose any interface for changing this behavior and the
code is embeded deep inside mshtml.dll, there is no perfect solution to
resolve this issue.

To workaround this issue, we have to reset back the focus into the original
focused control. This can be easily done with Control.Focus method. The key
problem is when and where to call this method. It is easy to conclude that
we should call it after the focus is changed to the WebBrowser. But after
testing all the events of WebBrowser, I found that all the events are
called before the focus is changed, so they all do not meet our need. A
simple workaround is place a second timer in DocumentCompleted event and
delay the calling. Something like this:

void webBrowser1_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
this.timer2.Interval = 100;
this.timer2.Start();
this.timer2.Tick += new EventHandler(timer2_Tick);
}

void timer2_Tick(object sender, EventArgs e)
{
this.textBox1.Focus();
this.timer2.Stop();
}
The disadvantage of this approach is that it is hard to determine the
interval for timer2. You may have to do some test to choose a most suitable
interval.

My another thought is hooking Focused control's Leave event and reset the
focus in this event. However, based on my test, this event does not fire at
all. Based on the further research, I found a WM_KILLFOCUS message is also
sent to the original focused control, so logically, we can monitor
WM_KILLFOCUS message and reset the focus back while this message appears.
However, monitoring an arbitrary control's message is not easy to be done
in .Net Winform, we have 2 choices: using NativeWindow to subclass that
control or we can use a local process hook to monitor all the messages of
all the controls in the application.

This approach is more complex than the first one, but it does not depend on
an Interval. If you are curious with this approach, please feel free to
tell me, I will help you to work this approach out. Thanks!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

Jul 14 '06 #2

P: n/a
This is both fascinating and unfortunate.

It is easy enough to wrap the call to the browser's .Navigate in a function
that reads and resets focus. I.e., instead of having the WebBrowser
subscribe to the Timer, my own event handler subscribes to it and within the
eventhandler I:
1. Make a note of the current user focus
2. Call .Navigate()
3. Reset the focus to what it was before

But the problem is compounded by the fact that the user may have switched to
another application. Even this brief flicker of focus is enough to disrupt
any controls with which the user is interacting (e.g., scrolling).

So if you there is another way to prevent the WebBrowser from taking focus
at all that would be best. (Should I submit that requirement as a support
incident for a custom solution?)

But if that's not immediately possible, could you provide sample code to
read the user's focus even if it's in another application, and return focus
to that application and its active control?
""Jeffrey Tan[MSFT]"" wrote:
Hi Dbooksta,

Thanks for your post!

Yes, I can reproduce out this behavior. Based on my research, it is the
mshtml.dll(which is the internal component of WebBrowser) that calls
SetFocus to change the application focus into the page. Since WebBrowser
control does not expose any interface for changing this behavior and the
code is embeded deep inside mshtml.dll, there is no perfect solution to
resolve this issue.

To workaround this issue, we have to reset back the focus into the original
focused control. This can be easily done with Control.Focus method. The key
problem is when and where to call this method. It is easy to conclude that
we should call it after the focus is changed to the WebBrowser. But after
testing all the events of WebBrowser, I found that all the events are
called before the focus is changed, so they all do not meet our need. A
simple workaround is place a second timer in DocumentCompleted event and
delay the calling. Something like this:

void webBrowser1_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
this.timer2.Interval = 100;
this.timer2.Start();
this.timer2.Tick += new EventHandler(timer2_Tick);
}

void timer2_Tick(object sender, EventArgs e)
{
this.textBox1.Focus();
this.timer2.Stop();
}
The disadvantage of this approach is that it is hard to determine the
interval for timer2. You may have to do some test to choose a most suitable
interval.

My another thought is hooking Focused control's Leave event and reset the
focus in this event. However, based on my test, this event does not fire at
all. Based on the further research, I found a WM_KILLFOCUS message is also
sent to the original focused control, so logically, we can monitor
WM_KILLFOCUS message and reset the focus back while this message appears.
However, monitoring an arbitrary control's message is not easy to be done
in .Net Winform, we have 2 choices: using NativeWindow to subclass that
control or we can use a local process hook to monitor all the messages of
all the controls in the application.

This approach is more complex than the first one, but it does not depend on
an Interval. If you are curious with this approach, please feel free to
tell me, I will help you to work this approach out. Thanks!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

Jul 14 '06 #3

P: n/a
Hi Dbooksta,

Thanks for your feedback!

Sorry, do you mean that you reset the focus after Navigate() method and it
works in your scenario? However, based on my test, this does not work on my
side, below is my testing code snippet:
void timer1_Tick(object sender, EventArgs e)
{
this.webBrowser1.Navigate("http://www.google.com");
this.textBox1.Focus();
this.timer1.Stop();
}
I recommend you give it a recheck. Anyway, if it works on your side, you
may go with it.

Regarding your further question, I am not sure if I understand it
completely. If you invoked Navigate() method and switch to another
application what is the problem you are encounterring? Thanks for clarify.

Normally, I think you may hook Form.Activated event and reset the focus
into the original focused control, like this:
private void Form1_Activated(object sender, EventArgs e)
{
this.textBox1.Focus();
}

Then whenever the user switch back to your application, the Activated event
handler will reset the focus as your need.

Finally, based on my research, not all web page you are accessing will
steal the focus, it is the javascript/jscript Element.focus() function that
causes the focus stealing behavior. If you view the source code of
www.google.com, you will find the following line in it:
function sf(){document.f.q.focus();}

Any web page does not call the focus internally will not steal the focus.
So I do not think there is any way to prevent the WebBrowser control from
stealing the focus, it is the javascript/Jscript code that steals the
focus. This behavior is by design. If you are curious, below is call stack
I captured with windbg for this stealing focus:

0013b84c 4a570824 USER32!NtUserSetFocus
0013b858 4a5ce628 mshtml!CDoc::TakeFocus+0x2a
0013b880 4a63fc0b mshtml!CElement::BecomeCurrent+0x167
0013b8b4 4a63fb72 mshtml!CElement::focusHelper+0xcc
0013b8c0 4a587c85 mshtml!CElement::focus+0x1d
0013b8cc 4a5d7477 mshtml!Method_void_void+0x17
0013b94c 4a57fae8 mshtml!CBase::ContextInvokeEx+0x462
0013b97c 4a575413 mshtml!CElement::ContextInvokeEx+0x72
0013b9b0 76fa5295 mshtml!CElement::ContextThunk_InvokeEx+0x44
0013b9e8 76fa5208 jscript!IDispatchExInvokeEx2+0xa9
0013ba20 76fa5323 jscript!IDispatchExInvokeEx+0x56
0013ba90 76fa577b jscript!InvokeDispatchEx+0x78
0013bad8 76fa57c6 jscript!VAR::InvokeByName+0x1c1
0013bb18 76fa4ab0 jscript!VAR::InvokeDispName+0x43
0013bb3c 76fa5a14 jscript!VAR::InvokeByDispID+0xfb
0013bd30 76fa46d8 jscript!CScriptRuntime::Run+0x195b
0013bdf4 76fa506e jscript!ScrFncObj::Call+0x69
0013be6c 76fa5f6a jscript!CSession::Execute+0xb8
0013bf6c 76fa672f jscript!NameTbl::InvokeDef+0x183
0013c040 76fa5295 jscript!NameTbl::InvokeEx+0xd2

Hope this helps. Also, please feel free to feedback any concern or
questions. Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscripti...ult.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscripti...t/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

Jul 17 '06 #4

P: n/a
OK, just to clarify:

1. I see that this focus problem is associated with navigating to web pages
that demand focus, e.g., through jscript .focus().

2. I am running calls to .Navigate() to such pages using a Timer.
Therefore, the user will probably be in a completely different application
when the .Navigate() is called. So the trick would be preventing the
WebBrowser from stealing focus from that other application.

3. Or, not as good as preventing the focus-change to begin with, at least
having the WebBrowser process return the focus to the other application and
whatever control the user had active in that other application.

I hope this is clear. If so: Is either 2 or 3 possible in a trivial way?
Or should I submit this requirement it for paid support?
Jul 17 '06 #5

P: n/a
Hi Dbooksta,

Thanks for your feedback!
So the trick would be preventing the
WebBrowser from stealing focus from that other application.
If I did not misunderstand you, do you mean that while the Navigate method
is executing with Timer, you are currently working on some other
application(the WebBrowser application is in background), and you find that
WebBrowser.Navigate method will steal focus from the foreground
application.

However, based on my experience, the background application can not steal
the focus of foreground application. My testing application also uses a
timer to execute the Navigate method after clicking a button 3 seconds,
like this:

private void button1_Click(object sender, EventArgs e)
{
this.timer1.Start();
this.timer1.Interval = 3000;
this.timer1.Tick += new EventHandler(timer1_Tick);
}

void timer1_Tick(object sender, EventArgs e)
{
this.webBrowser1.Navigate("http://www.google.com");
this.timer1.Stop();
}
In my testing application, after clicking the button, I switch to a notepad
immediately, the WebBrowser application in background can not steal the
focus from the foreground notepad application.

If you are seeing the different behavior, is it possible to provide a
little sample to demonstrate stealing focus from another application
behavior?
>Or should I submit this requirement it for paid support?
Yes, I want to continue help you on newsgroup for this issue. Anyway, if
you feel the PSS case support is more efficiently, please feel free to go
ahead and tell me.

Thanks!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscripti...ult.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscripti...t/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

Jul 18 '06 #6

P: n/a
Shoot, it looks like I can't produce a simple example of that extended
behavior I thought I was seeing.

Let's assume this problem is no more complicated than you described ...
unless in the future I discover otherwise.

Thanks for the help!

Jul 18 '06 #7

P: n/a
Ok, if you need further help, please feel free to post, I will work with
you. Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscripti...ult.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscripti...t/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

Jul 19 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion.