65.9K
CodeProject is changing. Read more.
Home

Detect Change In ActiveControl

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4 votes)

Feb 25, 2013

Apache

1 min read

viewsIcon

18062

UpdateDefaultButton - Allows detecting change in ActiveControl

Introduction

Occasionally, the topic comes up of how to detect which control in a WinForm has received focus. Most programmers learn that the form property ActiveControl typically (more on this later) points to the control with focus on a given form. You could also use a global event handler attached to all form's controls' GotFocus event as well to gather this information.

However, there is a little known Protected method that has existed in Container Controls (a form is a container control) since .NET 2.0 that is called UpdateDefaultButton. This method is called whenever a containercontrol's ActiveControl property changes. This change typically is the result of either a mouse or keyboard action, but it may also be set programmatically.

This method can be used as a global GotFocus event handler as long as you do not programmatically set the ActiveControl property to a non-focusable control.

Using the Code

How you use this information is up to you. Here is one possible implementation.
In this, I have defined a custom event named FocusChanged and a custom event argument for the event. The event is raised when form calls the UpdateDefaultButton method.

   Friend Class FocusChangedArg
      Inherits EventArgs
      Public LastControlWithFocus As Control
      Public Sub New(ByVal Last As Control)
         LastControlWithFocus = Last
      End Sub
   End Class

   Private LastActiveControl As Control = Me
   Friend Event FocusChanged As EventHandler(Of FocusChangedArg)

   Protected Overrides Sub UpdateDefaultButton()
       RaiseEvent FocusChanged(Me, New FocusChangedArg(LastActiveControl))
       LastActiveControl = Me.ActiveControl ' Store this for the next time Focus changes
   End Sub

   Private Sub Form1_FocusChanged(ByVal sender As Object, _
   	ByVal e As FocusChangedArg) Handles Me.FocusChanged
       'do something
   End Sub 

Points of Interest

One thing that I discovered is that UpdateDefaultButton is called before the Click or DoubleClick events are fired. Therefore, it is possible to attached their respective handlers in the UpdateDefaultButton method and if the ActiveControl changed due to a mouse click, these handlers will then be called.

    Protected Overrides Sub UpdateDefaultButton()
       RaiseEvent FocusChanged(Me, New FocusChangedArg(LastActiveControl))

       If LastActiveControl IsNot Nothing Then
          RemoveHandler LastActiveControl.Click, AddressOf anycontrol_Click
          RemoveHandler LastActiveControl.DoubleClick, AddressOf anycontrol_DoubleClick
       End If
       LastActiveControl = Me.ActiveControl ' Store this for the next time Focus changes

       AddHandler LastActiveControl.Click, AddressOf anycontrol_Click
       AddHandler LastActiveControl.DoubleClick, AddressOf anycontrol_DoubleClick

    End Sub

    Private Sub anycontrol_Click(ByVal sender As Object, ByVal e As System.EventArgs)
      ' do something
    End Sub

    Private Sub anycontrol_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs)
      'do something
    End Sub