VB.Net Inheritance Override

I'm new to VB.Net (I'm on foxpro background) and for the past two weeks I've had my head in a book trying to get started with some of the basics.

I am trying to master class inheritance and I hope this is not an overly difficult question.

I created a class and compiled it as a DLL. It just allows me to place the button on the form. I just want to capture the Click event that I was able to do, but would like to override the legacy code rather than have it like the fire that seems to be happening at the moment.

My understanding is that I could just double-click the control and type the code directly into the "MyButton1 click" event, but want to catch it programmatically through the handler instead.

I thought it would just be using the overridable / overrides options.

Here's the code in my class:

Imports System.Windows.Forms
Imports System.Drawing

Public Class MyButton

    Inherits Windows.Forms.Button

    Sub New()

    End Sub

    Protected Overridable Sub MyButton_Click(sender As Object, e As System.EventArgs) Handles Me.Click

        MsgBox("Base Click")

    End Sub

End Class

      

Then I put a button on my form and name it MyButton1 and in the load event:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    AddHandler MyButton1.Click, AddressOf Button_Click

End Sub

Private Sub Button_Click()
    MsgBox("Actual Click")
End Sub

      

The problem is both events fire and I want the option to override / disable the underlying event.

I thought I could just add the "overrides" keyword to the Button_Click routine, namely:

Private Sub Overrides Button_Click()

      

but I am getting the error Sub Button_Click () cannot be declared as "overrides" because it does not override sub in the base class

So, to clarify - at the moment my code fires both events, so I get two messages. I want to disable / suppress a base class event.

Any help would be much appreciated.

+3


source to share


2 answers


I thought it would just be a use case for overridable / overrides options.

The main problem here is when you are trying to push the square snap into the round hole.

To override something, you need to have inheritance. The derived class overrides what has been inherited from the base class. For example, if you inherited from your class MyButton to create a new type of button named MyButtonDerived, you can do this as expected:

Public Class MyButton
    Inherits Windows.Forms.Button

    Protected Overridable Sub MyButton_Click(sender As Object, e As System.EventArgs) Handles Me.Click
        MsgBox("Base Click")
    End Sub

End Class

Public Class MyButtonDerived
    Inherits MyButton

    Protected Overrides Sub MyButton_Click(sender As Object, e As EventArgs)
        ' We don't call the base method...
        ' MyBase.MyButton_Click(sender, e) 

        ' ... and instead do something else:
        MsgBox("Derived Click")
    End Sub

End Class

      

In contrast, when you placed the MyButton on the form, as in the original problem description, inheritance did not happen. Instead, you've set up "object composition"; the form contains an instance of a button (not derived from it). While it may be possible to change what happens when the button is clicked from within the form itself, this is not a case that can be solved with OOP, inheritance and overriding.



If the MyButton was not designed so that the end user can suppress its basic functionality, your options are limited in how you can use it. Here's an example of what it might look like if MyButton was designed to allow the end user to suppress the base click functionality:

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        MyButton1.SuppressDefaultClick = True
    End Sub

    Private Sub MyButton1_Click(sender As Object, e As EventArgs) Handles MyButton1.Click
        MsgBox("Form Click Code")
    End Sub

End Class

Public Class MyButton
    Inherits Windows.Forms.Button

    Private _suppress As Boolean = False
    Public Property SuppressDefaultClick As Boolean
        Get
            Return _suppress
        End Get
        Set(value As Boolean)
            _suppress = value
        End Set
    End Property

    Protected Overridable Sub MyButton_Click(sender As Object, e As System.EventArgs) Handles Me.Click
        If Not SuppressDefaultClick Then
            MsgBox("Base Click")
        End If
    End Sub

End Class

      

If MyButton has not included a way to suppress the built-in click handler as described above, you will have to resort to other means to solve your problem. In this case, you would have to prevent the button from receiving a message that the left mouse button was pressed and instead implement your own procedure. This approach will be considered a hack because you are working around limiting something and not using it the way it was originally intended. Here's one hack that could be implemented:

Public Class Form1

    Private WithEvents TMBC As TrapMyButtonClick

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        TMBC = New TrapMyButtonClick(Me.MyButton1)
    End Sub

    Private Sub TMBC_Click(sender As MyButton) Handles TMBC.Click
        MsgBox("Form Click Code")
    End Sub

    Private Class TrapMyButtonClick
        Inherits NativeWindow

        Private _mb As MyButton

        Private Const WM_LBUTTONDOWN As Integer = &H201

        Public Event Click(ByVal sender As MyButton)

        Public Sub New(ByVal mb As MyButton)
            If Not IsNothing(mb) AndAlso mb.IsHandleCreated Then
                _mb = mb
                Me.AssignHandle(mb.Handle)
            End If
        End Sub

        Protected Overrides Sub WndProc(ByRef m As Message)
            Select Case m.Msg
                Case WM_LBUTTONDOWN
                    RaiseEvent Click(Me._mb) ' raise our custom even that the form has subscribed to
                    Exit Sub ' Suppress default behavior

            End Select
            MyBase.WndProc(m)
        End Sub

    End Class

End Class

Public Class MyButton
    Inherits Windows.Forms.Button

    Protected Overridable Sub MyButton_Click(sender As Object, e As System.EventArgs) Handles Me.Click
        MsgBox("Base Click")
    End Sub

End Class

      

+3


source


You are getting 2 messages because you have set up 2 different event handlers for the event Click

:

  • The method MyButton_Click

    defined in your class MyButton

    .
  • The method is Button_Click

    set in your call AddHandler

    on the form.

As noted in the comment above, you need to override Button.OnClick

method
in your class MyButton

instead of creating a new method



Imports System.Windows.Forms
Imports System.Drawing

Public Class MyButton
    Inherits Windows.Forms.Button

    Sub New()
    End Sub

    ' Override the OnClick event defined in "Button" class.
    Protected Overrides Sub OnClick(e As System.EventArgs)
        ' Call the Click event from "Button" class.
        MyBase.OnClick(e)

        ' Some custom events.
        MsgBox("MyButton Click")
    End Sub

End Class

      

It can be a good exercise to set breakpoints in methods Button_Click

and MyButton.OnClick

so you can see exactly how the stack is created.

+1


source







All Articles