I'm using a TopMost Form that when its Shown it just waits for the OnMouseDown to select an area on the screen and on the OnMouseUp event I close the Form, then my intention is to return a Rectangle that contains the selected area after the OnMouseUp event ...when the Form closes using a ShowDialog call.
Something like this:
Dim Rect As Rectangle = MyForm.ShowDialog
So I've thinked that overriding/replacing properly the ShowDialog function to return other DataType could be the most efficient way, but I didn't know how to done it properly, I need a code-example.
PS: I think this way is better than adding hardcoded methods to reproduce the same function, but I'm open to other alternatives.
No, you can't do this. When you override a method in a derived class, you cannot change the type of value it returns. In more technical terms, you cannot change the signature of the method as defined in the base class.
What you can do is return a more specific derived type, but that won't help in this case. You can't inherit from DialogResult
and it wouldn't serve any purpose even if you could.
The other thing you can do is overload a method. I have done this with the ShowDialog
method before. In a derived class, I added an additional overload that accepted one or more parameters, which the dialog then used to initialize itself before displaying. That can be a pretty slick design—I certainly thought so at the time—but it's not without its compromises. But that is not what you're asking here.
Anyway, even if you could change the return type of the ShowDialog
method, it would be a bad idea to do it. I can think of two good reasons off the top of my head, and one bonus reason:
You cannot determine how the user closed the dialog. The standard dialog is going to have a confirm ("OK"/"Yes") button and a cancel ("Cancel"/"Close"/"No") button. You only want to do the action if the user pressed the confirm button. If they pressed the cancel button, you want to bail out.
If you return a different type from ShowDialog
, you'll need to figure out a way of signaling whether the dialog was canceled. What are you going to return as the rectangle (or whatever) if the dialog was canceled?
You'd end up doing some nonsense like returning a Nullable<Rectangle>
, and you're no better off than where you started.
If you use it like the sample code shown in the question, you'll forget to call the Dispose
method on your dialog form and leak resources.
This is an important one that lots of WinForms programmers forget. When you close a normal, non-modal form, the Dispose
method is called automatically. But it is not called automatically for modal dialogs, shown using the ShowDialog
method. In that case, you have to call Dispose
yourself manually. (Why, you might ask? Simple, because after the dialog is closed, you almost always want to read values from its properties, which you can't do if it has been disposed.)
So the standard idiom for showing a modal dialog is this one; I highly encourage you to use it:
Using myDialog As New MyDialogForm
If (myDialog.ShowDialog() = DialogResult.OK)
' Do whatever it is you want to do, including
' reading the values of properties of myDialog.
'
' For example:
Dim rect As Rectangle = myDialog.SelectedRectangle
' ...
End If
End Using
With the Using
statement, you don't have to call the Dispose
method yourself, it gets handled automatically, even if an exception is thrown. This is nothing unusual and should not be unexpected. Using
statements are how you deal with any resource that implements IDisposable
. Modal dialogs are no exception.
It is a non-standard idiom, highly likely to confuse future maintenance programmers. People expect it to return a DialogResult
value. Even if you don't care about other people, if you are anything like me, when you return to look at code you've written 3 months from now, it might as well have been the first time you've ever seen it.
TL;DR: No, just add a regular old property to the derived Form class you're showing as a modal dialog.