Click here to Skip to main content
15,886,786 members
Articles / Programming Languages / Visual Basic

Subclassing in .NET - The pure .NET way

Rate me:
Please Sign up or sign in to vote.
4.46/5 (13 votes)
22 Nov 2002CPOL1 min read 258.1K   1.6K   63   32
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.

VB
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.

VB
    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

VB
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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Pakistan Pakistan
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalexternal windows Pin
Evs_1-Sep-08 10:16
Evs_1-Sep-08 10:16 
Generalconstants for subclassing Pin
Alessandro7714-Mar-06 22:34
Alessandro7714-Mar-06 22:34 
QuestionDebugging-please help! Pin
skyhi8-Jan-06 21:04
skyhi8-Jan-06 21:04 
QuestionPlease help me! Pin
Kunal Mukherjee28-Aug-05 7:33
Kunal Mukherjee28-Aug-05 7:33 
QuestionSubclassing in a Windows Service? Pin
meraydin10-Apr-05 1:05
meraydin10-Apr-05 1:05 
QuestionSubclassing Menus? Pin
AndrewVos4-Mar-05 23:55
AndrewVos4-Mar-05 23:55 
GeneralHelp Me Pin
safirc6-Jul-04 18:11
safirc6-Jul-04 18:11 
GeneralOne Question Pin
HakunaMatada5-Oct-03 3:39
HakunaMatada5-Oct-03 3:39 
Generalanother subclassing question Pin
powerdude19-Jun-03 14:37
professionalpowerdude19-Jun-03 14:37 
GeneralAttaching to Existing Window Pin
Detlef Grohs24-Feb-03 7:18
Detlef Grohs24-Feb-03 7:18 
QuestionSubclassing multiple controls? Pin
FruitBatInShades29-Jan-03 8:07
FruitBatInShades29-Jan-03 8:07 
GeneralExtender Controls Pin
Allann16-Jan-03 1:08
Allann16-Jan-03 1:08 
Hi,
I have used "sub-classing" to great lengths coming from VB6 land, but since converting to .NET (VB or C#) I have not used sub-classing in the sense mentioned here. Instead I have found that creating extender controls gives much more flexibility and easy of use for developers using your solution.

This is not to discourage anyone from using subclassing it had it's use but now there are better and more efficient ways to do the same thing.

Allan
GeneralRe: Extender Controls Pin
Heath Stewart12-Feb-03 8:52
protectorHeath Stewart12-Feb-03 8:52 
GeneralRe: Extender Controls Pin
Allann12-Feb-03 11:18
Allann12-Feb-03 11:18 
GeneralRe: Extender Controls Pin
Roger Alsing18-Jul-03 0:32
Roger Alsing18-Jul-03 0:32 
GeneralSubClassing... Pin
mikasa14-Jan-03 8:26
mikasa14-Jan-03 8:26 
GeneralRe: SubClassing... Pin
Sameers (theAngrycodeR )14-Jan-03 10:15
Sameers (theAngrycodeR )14-Jan-03 10:15 
GeneralThe PURE .Net way Pin
Chris Martinez12-Dec-02 5:15
Chris Martinez12-Dec-02 5:15 
GeneralRe: The PURE .Net way Pin
Sameers (theAngrycodeR )17-Dec-02 12:21
Sameers (theAngrycodeR )17-Dec-02 12:21 
GeneralRe: The PURE .Net way Pin
Cory Smith2-Jan-03 17:11
Cory Smith2-Jan-03 17:11 
GeneralRe: The PURE .Net way Pin
mikasa23-Jan-03 5:15
mikasa23-Jan-03 5:15 
GeneralRe: The PURE .Net way Pin
Sameers (theAngrycodeR )23-Jan-03 12:13
Sameers (theAngrycodeR )23-Jan-03 12:13 
GeneralRe: The PURE .Net way Pin
Gnu27-Jan-03 6:13
Gnu27-Jan-03 6:13 
GeneralRe: The PURE .Net way Pin
Member 124044911-Jan-05 3:32
Member 124044911-Jan-05 3:32 
AnswerRe: The PURE .Net way Pin
Wcohen5-Jan-06 6:18
Wcohen5-Jan-06 6:18 

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.