Subclassing in .NET - The pure .NET way






4.46/5 (11 votes)
Capturing the Windows Messages for Windows Forms Controls
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
'To Subclass any Control, You need to Inherit From
'NativeWindow Class
Public Class SubClassing
Inherits System.Windows.Forms.NativeWindow
'Event Declaration. This event will be raised when any
'Message will be posted to the Control
Public Event CallBackProc(ByRef m As Message)
'Flag which indicates that either Event should be
'raised or not
Private m_Subclassed As Boolean = False
'During Creation of Object of this class, Pass the Handle
'of Control which you want to SubClass
Public Sub New(ByVal handle As IntPtr)
MyBase.AssignHandle(handle)
End Sub
'Terminate The SubClassing
'There is no need to Create this Method. Cuz,
'when you will create the Object
'Of this class, You will have the Method Named ReleaseHandle.
'Just call that as you can see in this Sub
'Public Sub RemoveHandle()
' MyBase.ReleaseHandle()
'End Sub
'To Enable or Disable Receiving Messages
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 'If Subclassing is Enabled
RaiseEvent CallBackProc(m) 'then RaiseEvent
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
'The Object of Subclassing to SubClass any Control
Dim WithEvents abc As theAngrycodeR.SubClassing
#Region "Subclassing Current Form Only"
'If you want to Subclass the Current Form only,
'then just remove these Comments
'You can not SubClass any Control using this method
Protected Overrides Sub WndProc(ByRef m As Message)
Select Case m.Msg
'If from Meny Close Is Selected then
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)
'MsgBox("Key Down : Virtual Code : " & m.HWnd.ToInt32
'& vbCrLf & "Key Data : " & m.LParam.ToInt32)
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.