Home

Introduction to Controls Events

 

Introduction

In a typical application, every class is mostly meant to interact with others, either to request values and methods of the other classes or to provide other classes with some values or a behavior they need. When a class A requests a value or service from another class B, class A is referred to as a client of class B. This relationship is important not simply because it establishes a relationship between both classes but also because class B should be ready to provide the value or behavior that a client needs at a certain time.

While a class B is asked to provide some values to, or perform some assignment(s) for, another class A, many things would happen. In fact, there is an order that the actions should follow. For example, during the lifetime of a program, that is, while a program is running, a class may be holding a value it can provide to its client but at another time, that value may not be available anymore, for any reason; nothing strange, this is just the ways it happens. Because different things can happen to a class B while a program is running, and because only class B would be aware of these, it must be able to signal to the other classes when there is a change. This is the basis of events: An event is an action that occurs on an object and affects it in a way that its clients must be made aware of. 

Event Creation

An event is declared like a pseudo-variable but based on a delegate. Therefore, to declare an event, you must have a delegate that would implement it. To actually declare an event, you use the Event keyword with the following formula:

[modifier] Event Name(Argument) As Type

The modifier can be Public, Private, Protected, or Friend. The Event keyword is required. It is followed by the name of the delegate that specifies its behavior. If the event as arguments, enter them in its parentheses. The declaration of an event must specify its type, and the type must be a delegate.

Here is an example that declares an event:

Imports System.Drawing
Imports System.Windows.Forms

Module Exercise

    Private Delegate Sub Display()

    Public Class Starter
        Inherits Form

        Private Event Evidence As Display

        Dim components As System.ComponentModel.Container

        Public Sub New()
            InitializeComponent()
        End Sub

        Public Sub InitializeComponent()
            
        End Sub

    End Class

End Module

When the event occurs, its delegate would be invoked. This specification is also referred to as hooking up an event. As the event occurs (or fires), the procedure that implements the delegate runs. This provides complete functionality for the event and makes the event ready to be used.

Adding an Event Handler

Before using an event, you must specify the procedure that will carry the event. This procedure is referred to as a handler. Obviously you must first have created a procedure. Here is an example:

Imports System.Drawing
Imports System.Windows.Forms

Module Exercise

    Private Delegate Sub Display()

    Public Class Starter
        Inherits Form

        Private Event Evidence As Display
        Dim components As System.ComponentModel.Container

        Public Sub New()
            InitializeComponent()
        End Sub

        Public Sub InitializeComponent()
            
        End Sub

    End Class

    Private Sub Viewer()
        MsgBox("The Viewer")
    End Sub

End Module

To add a handler to the program, you use the AddHandler operator with the following formula:

AddHandler EventName, AddressOf Procedure

The AddHandler and the AddressOf operators are required. The EventName placeholder is used to specify the name of the event that is being dealt with. The Procedure factor is the name of the procedure that will implement the event. Here is an example:

Imports System.Drawing
Imports System.Windows.Forms

Module Exercise

    Private Delegate Sub Display()

    Public Class Starter
        Inherits Form

        Private Event Evidence As Display
        Dim components As System.ComponentModel.Container

        Public Sub New()
            InitializeComponent()
        End Sub

        Public Sub InitializeComponent()

            AddHandler Evidence, AddressOf Viewer

        End Sub

    End Class

    Private Sub Viewer()
        MsgBox("The Viewer")
    End Sub

End Module

Raising an Event

After adding a handler for the event, it is ready but you must launch its action. To do this, you can use the RaiseEvent operator with the following formula:

RaiseEvent EventName()

The RaiseEvent operator is required. The EventName placeholder is used to specify the name of the event, and it must be followed by parentheses. Here is an example:

Imports System.Drawing
Imports System.Windows.Forms

Module Exercise

    Private Delegate Sub Display()

    Public Class Starter
        Inherits Form

        Private Event Evidence As Display
        Dim components As System.ComponentModel.Container

        Public Sub New()
            InitializeComponent()
        End Sub

        Public Sub InitializeComponent()

            AddHandler Evidence, AddressOf Viewer
            RaiseEvent Evidence()

        End Sub

    End Class

    Private Sub Viewer()
        MsgBox("The Viewer")
    End Sub

    Function Main() As Integer

        Dim frmStart As Starter = New Starter

        Application.Run(frmStart)

        Return 0
    End Function

End Module

A Parameterized Event

The event we used in the previous sections did not take any argument. Just like a delegate, an event can take an argument. The primary rule to follow is that both its delegate and the procedure associated with it must take the same type of event. The second rule is that, when raising the event, you must pass an appropriate event to it. Here is an example:

Imports System.Drawing
Imports System.Windows.Forms

Module Exercise

    Private Delegate Sub Display(ByVal Message As String)

    Public Class Starter
        Inherits Form

        Private Event Evidence As Display
        Dim components As System.ComponentModel.Container

        Public Sub New()
            InitializeComponent()
        End Sub

        Public Sub InitializeComponent()
            Dim m As String

            m = "Welcome to the wornderful world of events"

            AddHandler Evidence, AddressOf Viewer
            RaiseEvent Evidence(m)

        End Sub


    End Class

    Private Sub Viewer(ByVal msg As String)
        MsgBox(msg)
    End Sub

    Function Main() As Integer

        Dim frmStart As Starter = New Starter

        Application.Run(frmStart)

        Return 0
    End Function

End Module

Just like an event can take an argument, it can also take more than one argument. The primary rules are the same as those for a single parameter. You just have to remember that you are dealing with more than one argument. Here is an example:

Imports System.Drawing
Imports System.Windows.Forms

Module Exercise

    Private Delegate Sub Description(ByVal Name As String, _
                                                         ByVal Salary As Double)

    Public Class Starter
        Inherits Form

        Private Event Recorder As Description
        Dim components As System.ComponentModel.Container

        Public Sub New()
            InitializeComponent()
        End Sub

        Public Sub InitializeComponent()
            Dim FullName As String
            Dim HourlySalary As Double

            FullName = "Paul Bertrand Yamaguchi"
            HourlySalary = 24.55

            AddHandler Recorder, AddressOf ShowRecord
            RaiseEvent Recorder(FullName, HourlySalary)

        End Sub


    End Class

    Private Sub ShowRecord(ByVal id As String, ByVal wage As Double)
        MsgBox("Employee Name: " & id & vbCrLf & _
                     "Hourly Salary: " & CStr(wage))
    End Sub

    Function Main() As Integer

        Dim frmStart As Starter = New Starter

        Application.Run(frmStart)

        Return 0
    End Function

End Module

Instead of a parameter of a primitive type, you can create an event that takes a class as argument.

Events and Windows Controls

 

Introduction

An application is made of various objects or controls. During the lifetime of an application, its controls regularly send messages to the operating system to do something. These messages are similar to human messages and must be processed appropriately. Since most of the time more than one application is running on the computer, the controls of such an application also send messages to the operating system. As the operating system is constantly asked to perform these assignments, because there can be so many requests presented unpredictably, the operating system leaves it up to the controls to specify what they want, when they want it, and what behavior or result they expect. These scenarios work by the controls sending events.

Events in the .NET Framework are implements through the concepts of delegates and events as reviewed previously. The most common events have already been created for the objects of the .NET Framework controls so much that you will hardly need to define new events. Most of what you will do consists of implementing the desired behavior when a particular event fires. To start, you should know what events are available, when they work, how they work, and what they produce.

To process a message, it (the message) must provide at least two pieces of information: What caused the message and what type of message is it? Both values are passed as the arguments to the event. Since all controls used in the .NET Framework are based on the Object class, the first argument must be an Object type and represents the control that sent the message. 

As mentioned already, each control sends its own messages when necessary. Based on this, some messages are unique to some controls according to their roles. Some other messages are common to various controls, as they tend to provide similar actions. To manage such various configurations, the .NET Framework considers the messages in two broad categories.

As it happens, in order to perform their intended action(s), some messages do not require much information. For example, suppose your heart sends a message to the arm and states, “Raise your hand”. In this case, suppose everything is alright, the arm does not ask, “how do I raise my hand?”. It simply does because it knows how to, without any assistance. This type of message would be sent without much detailed information.

In the .NET Framework, a message that does not need particular information is carried by a class named EventArgs. In the event implementation, an EventArgs argument is passed as the second parameter.

Consider another message where the arm carries some water and says to the mouth, “Swallow the following water”. The mouth would need the water that needs to be swallowed. Therefore, the message must be accompanied by additional information. Consider one more message where the heart says to the tongue, “Taste the following food but do not swallow it.” In order to process this message, the tongue would need the food and something to indicate that the food must not be swallowed. In this case, the message must be accompanied by detailed pieces of information.

When a message must carry additional information, the control that sent the message specifies that information by the name of the second argument. Because there are various types of messages like that, there are also different types of classes used to carry such messages. We will introduce each class when appropriate.

Event Implementation

Although there are different means of implementing an event, there are two main ways you can initiate its coding. If the control has a default event and if you double-click it, the designer would initiate the default event and open the Code Editor. The cursor would be positioned in the body of the event, ready to receive your instructions.

As another technique, display the form and click either the body of the form or a control on it. Then, on the Properties window, click the Events button Events, and double-click the name of the event you want to use.

Another alternative you can use consists of displaying the form, right- clicking the form and clicking View Code. Then, in the Class Name combo box, select the name of the control:

Class Name

In the Method Name combo box, select the event you want to implement:

Method Name

Overview of Events

 

Control Painting

While an application is opening on the screen or it needs to be shown, the operating system must display its controls. To do this, the controls colors and other visual aspects must be retrieved and restored. This is done by painting the control. If the form that hosts the controls was hidden somewhere such as behind another window or was minimized, when it comes up, the operating system needs to paint it (again).

When a control gets painted, it fires the Paint() event. The syntax of the Paint() event is:

Private Sub Control_Paint(ByVal sender As System.Object, _
                            ByVal e As System.Windows.Forms.PaintEventArgs) _
                            Handles MyBase.Paint

End Sub

This event is carried by a PaintEventHandler delegate declared as follows:

Public Delegate Sub PaintEventHandler ( _
	sender As Object, _
	e As PaintEventArgs _
)

The PaintEventArgs parameter provides information about the area to be painted and the graphics object to paint.

Control Resizing

When using an application, one of the actions a user can perform on a form or a control is to change its size, provided the object allows it. Also, some time to time, if possible, the user can minimize, maximize, or restore a window. Whenever any of these actions occur, the operating system must keep track of the location and size of a control. For example, if a previously minimized or maximized window is being restored, the operating system must remember where the object was previously positioned and what its dimensions were.

When the size of a control has been changed, it fires the Resize() event, which is a EventArgs type.

Custom Message Implementation

 

Introduction

It is possible, but unlikely, that none of the available events featured in the controls of the .NET Framework suits your scenario. If this happens, you can implement your own event. To do this, you should first consult the Win32 documentation to identify the type of message you want to send.

There are two main techniques you can use to create or send a message that is not available in a control. You may also want to provide your own implementation of a message.

Sending a Custom Windows Message

In order to send a customized version of a Windows message from your control, you must first be familiar with the message. A message in the .NET Framework is based on the Message structure. One of the properties of this structure is Msg. This property holds a constant integer that is the message to send. The constant properties of messages are defined in the Win32 library. To send a message, you can declare a variable of type Message and define it. Once the variable is ready, you can pass it to the DefWndProc() method. Its syntax is:

Protected Overridable Sub DefWndProc(ByRef m As Message)

To know the various messages available, you can consult the Win32 documentation but you need a way to get the constant value of that message. Imagine you want to send a message to close a form when the user clicks a certain button named Button1. If you have Microsoft Visual Studio (any version) installed in your computer, you can open the WINUSER.H file. In this file, the WM_CLOSE message that carries a close action is defined with the hexadecimal constant 0x0010

You can then define a constant integer in your code and initialize it with this same value.

Creating a Custom Event

To process a Windows message that is not available for a control you want to use in your application, you can implement its WndProc() method. Its syntax is:

Protected Overridable Sub WndProc(ByRef m As Message)

In order to use this method, you must override it in your own class. Once again, you must know the message you want to send. This can be done by consulting the Win32 documentation.

 

Home Copyright © 2008 FunctionX, Inc.