Introduction
If you are a Visual Basic 6 programmer then you are
obviously aware of the sub-classing power. My article demonstrates the same
thing for .NET. If you are a C# programmer, then you can easily change
this code to fit into a C# Project. This project demonstrates how can you use the .NET way to subclass any control. This
is the pure .NET way.
Using the code
Actually, you do not have to much to subclass your
controls. What you have to do, is to create a class which should inherit from
System.Windows.Forms.NativeWindow
class. This class, as the
name says, is the base class of a window. Using this class, you can use a function
named AssignHandle
which takes one parameter, the
HWND
of the object (control). And finally, you have to override
a method named WndProc
(method of NativeWindow
Class). If you
see the complete listing, then it will be clearer.
Imports System.Windows.Forms
Namespace theAngrycodeR
Public Class SubClassing
Inherits System.Windows.Forms.NativeWindow
Public Event CallBackProc(ByRef m As Message)
Private m_Subclassed As Boolean = False
Public Sub New(ByVal handle As IntPtr)
MyBase.AssignHandle(handle)
End Sub
Public Property SubClass() As Boolean
Get
Return m_Subclassed
End Get
Set(ByVal Value As Boolean)
m_Subclassed = Value
End Set
End Property
Protected Overrides Sub WndProc(ByRef m As Message)
If m_Subclassed Then RaiseEvent CallBackProc(m) End If
MyBase.WndProc(m)
End Sub
Protected Overrides Sub Finalize()
MyBase.Finalize()
End Sub
End Class
End Namespace
OK, you have prepared your class. Now come back in your
form's code to use it. In the demo project, I used two command buttons and one
text-box. And wrote the following code.
Private Const WM_CLOSE As System.Int32 = &H10
Private Const WM_QUERYENDSESSION As System.Int32 = &H11
Private Const SC_CLOSE As System.Int32 = &HF060&
Private Const WM_SYSCOMMAND As System.Int32 = &H112
Private Const WM_KEYDOWN As System.Int32 = &H100
Private Const WM_DESTROY As System.Int32 = &H2
Private Const SC_MAXIMIZE As System.Int32 = &HF030
Private Const SC_MINIMIZE As System.Int32 = &HF020
Private Const SC_RESTORE As System.Int32 = &HF120
Dim WithEvents abc As theAngrycodeR.SubClassing
#Region "Subclassing Current Form Only"
Protected Overrides Sub WndProc(ByRef m As Message)
Select Case m.Msg
Case Is = WM_SYSCOMMAND
Select Case m.WParam.ToInt32
Case Is = SC_CLOSE
MsgBox("Closing")
Case Is = SC_MAXIMIZE
MsgBox("Maximize")
Case Is = SC_RESTORE
MsgBox("Restore")
End Select
Case Is = WM_DESTROY
MsgBox("Destroy")
Case Is = WM_CLOSE
MsgBox("Close")
Case Is = WM_KEYDOWN
MsgBox(m.HWnd.ToString)
End Select
MyBase.WndProc(m)
End Sub
#End Region
Private Sub frmMain_Load(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles MyBase.Load
abc = New theAngrycodeR.SubClassing(Button1.Handle)
abc.SubClass = True
End Sub
Private Sub abc_CallBackProc(ByRef m As System.Windows.Forms.Message)
Handles abc.CallBackProc
Const WM_MOUSELEAVE = &H2A3
Const WM_MOUSEMOVE = &H200
Const WM_MOUSEHOVER = &H2A1
Select Case m.Msg
Case WM_MOUSELEAVE
TextBox1.Text += "Message Mouse Leave" & vbCrLf
Case WM_MOUSEMOVE
TextBox1.Text += "Message Mouse Moved" & vbCrLf
Case WM_MOUSEHOVER
TextBox1.Text += "Message Mouse Hover" & vbCrLf
End Select
End Sub
Private Sub Button2_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button2.Click
abc.ReleaseHandle()
End Sub
Note that if you want to filter messages for the
current form, then you can just write the code inside the WndProc
method which
is declared as Protected Overrides Sub WndProc ( ByRef m As
Message ).
For getting the messages for other windows, you can use the
same code written above. The sample project is attached with this article. You
can check this out and comment too.