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.
source to share
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
source to share
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 classMyButton
. - The method is
Button_Click
set in your callAddHandler
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.
source to share