Click here to Skip to main content
15,867,835 members
Articles / Desktop Programming / Windows Forms
Article

Application Event Handler for WinForms

Rate me:
Please Sign up or sign in to vote.
4.77/5 (16 votes)
11 Nov 20046 min read 156.7K   1.9K   83   5
In this article, you will get a walkthrough of creating an Application Event Handler Component (AEHC) for any WinForms application in .NET.

Screenshot

Contents

Introduction

In this article, you will get a walkthrough of creating an Application Event Handler Component (AEHC) for any WinForms application in .NET. AEH is an event handler for your WinForms application. The primary functionality of this component is to raise an event after every form loads into memory so that we can handle its event for performing any custom code processing and return the control to the form after processing.

Let’s consider a scenario. While implementing security into our application, we may have to disable or enable certain controls on every form according to the role of the user accessing the form. For this, we will call a custom method [for instance, AuthorizeMe()] to perform custom authentication and authorization from each and every form in our application. Suppose, if in any case, we forget to call its method from one of our forms, in result, there will be no security applied to that form.

Now, with AEHC, we only call the method AuthorizeMe() once per application from AEHC, and then it's AEHC’s responsibility to execute AuthorizeMe() every time after the form is loaded.

What is Application Event Handler Component?

In ASP.NET, we can create custom HTTP Modules for adding custom processing to each and every web page in web applications at a global level. One of the benefits you get using a HTTP Module is that you do not need to call them from each and every web page; they will automatically get executed for each of them. In Application Event Handler, you will achieve a similar functionality of HTTP Modules. However, AEHC will be specific to every application in contrast with HTTP Modules which can be used machine wide.

Application Event Handler Component keeps track of the forms being loaded and unloaded throughout the application’s lifecycle and generates events like FormLoaded() and FormUnloaded() at application level. Just like HTTP Modules, you too can write your own modules to manipulate the forms properties in these events (see Figure 1).

Application Event Handler Component Lifecycle

Figure 1 Application Event Handler Component Lifecycle

VB
Dim WithEvents myHandler As New AEHC.ApplicationEventHandler
Public frCol As ArrayList

Public Sub main()
    'Attaches the Form Filter to the Application
    myHandler.Init()

    Application.Run(New Form1)
End Sub

Private Sub myHandler_FormLoaded(ByRef sender As System.Windows.Forms.Form, _
      ByVal e As AEHC.AppEventHandlerArgs) Handles myHandler.FormLoaded
    sender.Text = Now.ToLocalTime
End Sub

Private Sub myHandler_FormUnloaded(ByVal e As AEHC.AppEventHandlerArgs) _
                                           Handles myHandler.FormUnloaded
    MsgBox(e.FormsCollection.Count & " in memory")
End Sub

Architecture of Application Event Handler Component

Application Event Handler component is built upon window messages released by WinForms. The core part of AEHC is a FormFilter, which is a custom message filter class created by implementing IMessageFilter.

Let’s get into the details and see how Application Event Handler component works (see Figure 2). When you load a WinForms application, it generates messages for most of its events. You can filter the message queue by using a custom message filter.

Let’s create a Forms Collection to hold all the forms which are being loaded throughout the application. Get the Active Form in the application. Check if the form exists in the Forms Collection, add the Form in the collection if not.

Now add a handler to Form Closed event, which you will use to remove the form from the collection when the form receives its Close event. Now, raise the FormLoaded() for passing the control to the user. User can handle the event and perform some custom processing like custom authentication, adding new controls in the loaded form changing the form’s appearance.

Workflow of Application Event Handler Component

Figure 2 Workflow of Application Event Handler Component

Creating an Application Event Handler Component

Application Event Handler is composed of two classes:

  1. FormMessageFilter Class: This class is responsible for filtering messages being dispatched by a form or control. It implements an IMessageFilter to design a custom message filter (IMessageFilter interface is used to capture a message before it gets dispatched to a form or control).

    Declare two events FormFound(), FormUnload() and an ArrayList to store the Forms collection.

    In PreFilterMessage method of IMessageFilter, check the Msg property of the message with message codes (see Table 1) and trap the events. Return False to dispatch the message and vice versa.

    Compare the MSG property to &HF for filtering the window paint messages. Look for the Form.ActiveForm property to identify the form and add the Form to the Forms Collection. Attach an event handler to form, for removing it from the collection after it is closed.

    MessageCodePurpose
    WM_PAINT0x000FSent when the system or another application makes a request to paint a portion of an application's window
    WM_KEYDOWN0x0100Posted to the window with the keyboard focus when a non system key is pressed
    WM_KEYUP0x0101Posted to the window with the keyboard focus when a non system key is released
    WM_MOUSEMOVE0x0200Posted to a window when the cursor moves
    WM_LBUTTONDOWN0x0201Posted when the user presses the left mouse button while the cursor is in the client area of a window
    WM_LBUTTONUP0x0202Posted when the user releases the left mouse button while the cursor is in the client area of a window
    WM_LBUTTONDBLCLK0x0203Posted when the user double-clicks the left mouse button while the cursor is in the client area of a window
    WM_RBUTTONDOWN0x0204Posted when the user presses the right mouse button while the cursor is in the client area of a window
    WM_RBUTTONUP0x0205Posted when the user releases the left mouse button while the cursor is in the client area of a window
    WM_RBUTTONDBLCLK0x0206Posted when the user double-clicks the right mouse button while the cursor is in the client area of a window
    Note: See WINUSER.H for more message codes

    Table 1: Message Codes for using in the Custom Filter Class

    VB
    Friend Shared frmCollection As New ArrayList
    Public Event FormFound(ByRef sender As Form)
    Public Event FormUnload()
    
    'Method for filtering the message
    Public Function PreFilterMessage(ByRef m As _
           System.Windows.Forms.Message) As Boolean Implements _
           System.Windows.Forms.IMessageFilter.PreFilterMessage
    
        'Blocks messages related to Window Paint event (WM_PAINT 0x000F)
        If (m.Msg = &H200) Then
            If Not (Form.ActiveForm) Is Nothing Then
                Dim curForm As Form = Form.ActiveForm
    
                'Search the forms in the Forms Collection to prevent 
                'duplication of forms in the collection
                If Not (Search(curForm, frmCollection)) Then
                    frmCollection.Add(curForm)
                    AddHandler curForm.Closed, AddressOf MyForm_Closed
                    RaiseEvent FormFound(curForm)
                End If
            End If
        End If
        'Must return false to dispatch the Message
        Return False
    End Function
    
    'Event Handler for Form Close event
    Private Sub MyForm_Closed(ByVal sender As Object, _
                               ByVal e As System.EventArgs)
        Dim k, j As Integer
    
        'Removes the forms which are disposed 
        '(Form.Dispose) rather being closed(Form.Close) 
        For i As Integer = 0 To frmCollection.Count - 1
            j = i - k
            If j > (frmCollection.Count - 1) Then Exit For
    
            'Checks the IsDisposed Property of the Form 
            'in the Forms Collection
            If frmCollection(j).IsDisposed = True Then
                frmCollection.Remove(frmCollection(j))
                k = k + 1
            End If
        Next
    
        'Removes the form which raised the close event
        If Not (sender) Is Nothing Then frmCollection.Remove(sender)
            RaiseEvent FormUnload()
        End Sub
    
        'Search Method searches fr(form) in the forms collection (frmArray)
        Private Function Search(ByVal fr As Form, _
                ByVal frmArray As ArrayList) As Boolean
            Dim fr1 As Form
            For Each fr1 In frmArray
                If fr.Equals(fr1) Then Return True
            Next
            Return False
        End Function
    End Class
  2. Application Event Handler: adds the FormMessageFilter to the application's message pump to filter out the form paint messages. And a shared read only FormsCollection property to access the collection of forms at runtime.
    VB
    Public Class ApplicationEventHandler
        Public Event FormLoaded(ByRef sender As Form)
        Public Event FormUnloaded()
    
        'Use this property to access your loaded forms
        Public Shared ReadOnly Property FormsCollection() As ArrayList
            Get
                Return FormMessageFilter.frmCollection
            End Get
        End Property
    
        'Attaches FormFilter to the application
        Public Sub Init()
            Dim MyFilter As New FormMessageFilter
    
            AddHandler MyFilter.FormFound, AddressOf pFormLoaded
            AddHandler MyFilter.FormUnload, AddressOf pFormUnLoaded
    
            Application.AddMessageFilter(MyFilter)
        End Sub
    
        'Called when any form is loaded in the application
        Private Sub pFormLoaded(ByRef CurForm As Form)
            RaiseEvent FormLoaded(CurForm)
        End Sub
    
        'Called when any form is unloaded in the application
        Private Sub pFormUnLoaded()
            RaiseEvent FormUnloaded()
        End Sub
    End Class

    You have successfully created the Application Event Handler component.

Using Application Event Handler Component

Now all said and done, you have finished creating the Application Event Handler Component. Let’s learn to use the same, in your WinForms project.

Create a new WinForms application in VB.NET. To use AEHC with VB.NET WinForms application, you will need to add a module and code a Sub main method.

Add a reference to AEHC, and instantiate in the module using WithEvents, when you want to trap the FormLoaded() and FormUnloaded() events.

Initialize the instance by calling Init() method. Init() will register AEHC for the application and starts monitoring the message queue.

In the FormLoaded() event, add code for adding a Label control to the loaded form, and for FormUnloaded() event, just add a message box and use the FormsCollection property of the AEHC to get the number of loaded forms by myHandler.FormsCollection.Count.

VB
Dim WithEvents myHandler As New AEHC.ApplicationEventHandler

Public Sub main()
     ‘Initialize the component
    myHandler.Init()
    Application.Run(New Form1)
End Sub

Private Sub myHandler_FormLoaded(ByRef sender As _
        System.Windows.Forms.Form) Handles myHandler.FormLoaded
    Dim label1 As System.Windows.Forms.Label
    label1 = New System.Windows.Forms.Label
    sender.SuspendLayout()

    'Initialize the Label
    label1.Font = New System.Drawing.Font("Arial", 14.25!, _
                      System.Drawing.FontStyle.Bold, _
                      System.Drawing.GraphicsUnit.Point, CType(0, Byte))
    label1.Location = New System.Drawing.Point(8, 8)
    label1.Name = "Label1"
    label1.Size = New System.Drawing.Size(208, 23)
    label1.TabIndex = 0
    label1.Text = " Application Event Handler Component Magic "
    '
    sender.Controls.Add(label1)
    sender.ResumeLayout(False)

End Sub

Private Sub myHandler_FormUnloaded() Handles myHandler.FormUnloaded
    MsgBox(myHandler.FormsCollection.Count)
End Sub

Run your project to see the magic of your Application Event Handler Component. You will see a label with text “Application Event Handler Component Magic” on your form. To do more testing, you can also place a button on the form and create new instances of the form; you will get amazing functionality like all the forms being displayed with the label control.

Conclusion

Application Event Handler Component is remarkably very powerful for WinForms developers, which they can extensively use in UI Customization of WinForms, along with other tasks. They can make use of the FormCollection property too, for manipulating forms in their application.

Message Filters are one of the easiest ways to add custom processing for each Form in your WinForms application. In fact, you can imitate some more good features of ASP.NET in your WinForms apps by using the same mechanism. In future columns, I'll explore more on implementing ASP.NET's features in WinForms, like Caching, etc.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
India India
Saurabh Verma works as an Architect, possessing over 10 years designing and developing software and currently assists product companies to scale and writing flexible software. He has vast experience in designing Web 2.0 solutions using Microsoft Technologies; WF, WCF and AJAX.ASP.NET, and practicing AGILE Methodologies and Domain Driven Design for the implementation. He likes to perform superbike stunts in his free time. Smile | :)

He has been awarded Microsoft Most Valuable Professional, MCSD.NET, MCAD.NET, MCDBA and Microsoft Web Rock Star 2007.

He maintains his blog at http://www.domaindrivendesign.info for all the aspiring architects and developers.

You can reach him at saurabhdotnet@hotmail.com

Comments and Discussions

 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey12-Mar-12 21:52
professionalManoj Kumar Choubey12-Mar-12 21:52 
GeneralNice Article Pin
MCSDvikasmisra25-Oct-07 22:53
MCSDvikasmisra25-Oct-07 22:53 
GeneralImprovement :) Pin
roman_lviv20-Dec-06 3:53
roman_lviv20-Dec-06 3:53 
In PreFilterMessage method will be validated only currently active form for the application, but in the case if we use (MDI) multiple document interface should be added validation for Form.ActiveForm.ActiveMdiChild form.Smile | :)



GeneralRe: Improvement :) Pin
pachiflyer2-Apr-08 5:09
pachiflyer2-Apr-08 5:09 
QuestionInheritance? Pin
mikasa17-Nov-04 3:53
mikasa17-Nov-04 3:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.