|
ms
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Hidden WebBrowser stealing focusI 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?_ 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. 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: Show quoteHide quote > 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. > > 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/subscriptions/managednewsgroups/default.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/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. 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? Hi Dbooksta,
Thanks for your feedback! > So the trick would be preventing the If I did not misunderstand you, do you mean that while the Navigate method > WebBrowser from stealing focus from that other application. 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/subscriptions/managednewsgroups/default.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/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. 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! 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/subscriptions/managednewsgroups/default.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/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Other interesting topics
Dynamically loading DLLs dynamically that have dependencies...
Reflection and Nullables Reading test data for NUNIT from a file Help extending textbox with an additional property Winforms and WebForms Regex Xml validation - Should fail but does not Interface Question Limit to range of colors displayed by Label control? connect to Oracle server by using csharp |
|||||||||||||||||||||||