As you start coding more advanced programs, you will realize that you can get a lot more done by adding code to the classes in the .NET Framework rather than coding everything yourself. One technique is to replace what .NET does with your own code by using the Overrides qualifier. But you have to be careful. This example shows what can happen and a "best practices" way to use a Try block to be more careful.
To start the example, let's first add an event Sub to display a property. The MouseMove event is a great, high visibility example. The code to display the X and Y location is pretty simple. To see this in action, start a Windows Application and add a single Label component. Then add this code:
Public Class Form1
Private Sub Form1_MouseMove( _
ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles Me.MouseMove
Label1.Text = _
"X Mouse Location: " & e.X.ToString & vbCrLf & _
"Y Mouse Location: " & e.Y.ToString
End Sub
End Class
This gives you a nice little display of the mouse location on the form. So far, so good. But now you decide that you want to also change the mouse cursor icon when the mouse gets close to either side or display a third icon as a default otherwise. One way to do this is to add an Overrides Sub into the Form1 class.
Protected Overrides Sub OnMouseMove( _
ByVal e As System.Windows.Forms.MouseEventArgs)
Cursor.Current = Cursors.NoMove2D
If e.X > Me.Width - 50 Then
Cursor.Current = Cursors.PanEast
Exit Sub
ElseIf e.X < 50 Then
Cursor.Current = Cursors.PanWest
Exit Sub
End If
End Sub
This works great too ... except ... we lost the display of the location! Why did that happen?
The reason is that Overrides replaces the .NET method with your code. The main function of the .NET method is to call any other delegate procedures -- such as the event procedure you coded to display the mouse location.
To solve this problem, you need to call the same method explicitly for the method that is overridden. In general, if you fail to do this, results are unpredictable. In our case, the only result is that the event subroutine we coded earlier isn't called.
The method that we replaced is OnMouseMove. The statement we need to add is:
MyBase.OnMouseMove(e)
So lets add that statement to the subroutine at the very end.
Protected Overrides Sub OnMouseMove( _
ByVal e As System.Windows.Forms.MouseEventArgs)
Cursor.Current = Cursors.NoMove2D
If e.X > Me.Width - 50 Then
Cursor.Current = Cursors.PanEast
Exit Sub
ElseIf e.X < 50 Then
Cursor.Current = Cursors.PanWest
Exit Sub
End If
MyBase.OnMouseMove(e) ' <- New Statement Added
End Sub
(And ... before you write that email ... I know about the other ways that this problem could also be avoided. This is an example.)
Well ... This is an improvement! But the location updating stops at both sides. That's because the Exit Sub statements prevent MyBase.OnMouseMove(e) from being executed. A simple mistake, but one that is very easy to make in the longer and more complex coding you'll find in real-world systems. You could add MyBase.OnMouseMove(e) into all the branches of the If statement structure. Or you could use a Try block.
Protected Overrides Sub OnMouseMove( _
ByVal e As System.Windows.Forms.MouseEventArgs)
Cursor.Current = Cursors.NoMove2D
Try
If e.X > Me.Width - 50 Then
Cursor.Current = Cursors.PanEast
Exit Sub
ElseIf e.X < 50 Then
Cursor.Current = Cursors.PanWest
Exit Sub
End If
Finally
MyBase.OnMouseMove(e)
End Try
End Sub
In this case, the Finally block makes sure that the MyBase.OnMouseMove(e) statement is always executed. Try blocks aren't just for error processing!
