RAPID PUBLISHING ARTICLES PROVIDE INFORMATION DIRECTLY FROM WITHIN THE MICROSOFT SUPPORT ORGANIZATION. THE INFORMATION CONTAINED HEREIN IS CREATED IN RESPONSE TO EMERGING OR UNIQUE TOPICS, OR IS INTENDED SUPPLEMENT OTHER KNOWLEDGE BASE INFORMATION.
You have a Microsoft .NET Windows Forms application where a form contains a hierarchy of contained controls. For example, the form contains a UserControl, which contains a Panel control, which contains other controls. When setting focus to one of the lowermost controls in this hierarchy, the application encounters a high CPU condition and stops responding to user input (hangs).
This behavior can occur if you manually set focus to a control contained within several layers of other container controls, and there is custom code on the control's Enter event which attempts to set focus to a different control. This is a bug in Windows Forms.
Change the code on the Enter event to use a Delegate with the BeginInvoke method. This will post a message to the form's message queue, and allows the current Windows Forms code to complete and unwind from the call stack before running the code that changes focus. The following example assumes you are familiar with scenario described in the "Steps to Reproduce Problem" section below.
1. Repeat Steps 1 -Â 5 of the "Steps to Reproduce Problem" section below.
2. Add the following code to the UserControl. Note the changes to TextBox3_Enter.
Public Class MyUserControl
   'Define an event
   Public Event NotifyEnter()
   'Raise the event
   Public Sub OnNotifyEnter()
       RaiseEvent NotifyEnter()
   End Sub
   Private Sub TextBox3_Enter(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox3.Enter
       'Call our custom OnNotifyEnter method to raise our custom event
       'whenever Textbox3 receives focus
       'Create an instance of MethodInvoker and call BeginInvoke
       Dim m As MethodInvoker
       m = New MethodInvoker(AddressOf OnNotifyEnter)
       Me.BeginInvoke(m)
   End Sub
End Class
3. Follow the remaining steps in the "Steps to Reproduce Problem" section below. Note that when you click into TextBox3 now, that focus successfully goes to the TextBox on the main form.
When setting focus to a control contained within other controls, internally Windows Forms sets the focus to each control in the "path" down the hierarchy of contained controls. For example, if focus is set to a TextBox that is contained within a Panel that is contained within a UserControl contained on a form, then Windows Forms first sets focus to the UserControl, then to the Panel, and then to the TextBox. For each step in this process, Windows Forms raises the OnEnter event notification to allow controls that are receiving focus to process any code that needs to run when the control receives focus.
Internally Windows Forms tracks the currently focused control, and the control to receive the focus. In the scenario where custom code attempts to set focus elsewhere from within a control's OnEnter event notification, the state of the currently focused control within the path of contained controls is not reset correctly; which causes the hang to occur.
Steps To Reproduce Problem
========================
1. Start Microsoft Visual Studio 2008Â and create a new Windows Forms application using Visual Basic. Form1 is created by default.
2. Add a new UserControl item to the project named "MyUserControl".
3. Add a Panel control to the UserControl designer.
4. Add three TextBox controls (named TextBox1, TextBox2, and TextBox3 respectively)Â to the Panel control.
5. On the View menu, click Code.
6. Add the following code to the UserControl.
Public Class MyUserControl
   'Define an eventÂ
   Public Event NotifyEnter()
   'Raise the event
   Public Sub OnNotifyEnter()
       RaiseEvent NotifyEnter()
   End Sub
   Private Sub TextBox3_Enter(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox3.Enter
       'Call our custom OnNotifyEnter method to raise our custom event
       'whenever Textbox3 receives focus
       OnNotifyEnter()
   End Sub
End Class
7. Save MyUserControl.vb and close it.
8. Build the solution.
9. Open Form1 in design view.
10. Add an instance of MyUserControl to the form designer.
11. Add two TextBox controls to the form designer, named TextBox1 and TextBox2 respectively.
12. On the View menu, click Code.
13. Add the following code to the Form.
Public Class Form1
   Private Sub MyUserControl1_NotifyEnter() Handles MyUserControl1.NotifyEnter
       Me.TextBox1.Select()
   End Sub
End Class
14. Save the form and close it.
15. Build the solution and run it.
16. When the form is displayed, click on the third textbox (TextBox3) contained within the UserControl. Note that the application stops responding and begins consuming high CPU.
MICROSOFT AND/OR ITS SUPPLIERS MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY, RELIABILITY OR ACCURACY OF THE INFORMATION CONTAINED IN THE DOCUMENTS AND RELATED GRAPHICS PUBLISHED ON THIS WEBSITE (THE “MATERIALSâ€) FOR ANY PURPOSE. THE MATERIALS MAY INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS AND MAY BE REVISED AT ANY TIME WITHOUT NOTICE.
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, MICROSOFT AND/OR ITS SUPPLIERS DISCLAIM AND EXCLUDE ALL REPRESENTATIONS, WARRANTIES, AND CONDITIONS WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO REPRESENTATIONS, WARRANTIES, OR CONDITIONS OF TITLE, NON INFRINGEMENT, SATISFACTORY CONDITION OR QUALITY, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, WITH RESPECT TO THE MATERIALS.
Article ID: 970951 - Last Review: May 5, 2009 - Revision: 1.1
APPLIES TO
- Microsoft .NET Framework 1.1
- Microsoft .NET Framework 2.0
| kbrapidpub kbnomt KB970951 |