3.11. Control When Your Application Shuts Down
In Visual Studio 2005, a new "Shutdown mode" option lets you control when your application should end. You can wrap up as soon as the main window is closed (the window that's designated as the startup object), or you can wait until all the application windows are closed. And if neither of these choices offers what you want, you can take complete control with the Application class.
Note: In . NET 2.0, it's easier than ever to specify when your Windows application should call it quits.
3.11.1. How do I do that?
In Visual Studio, double-click the My Project item in the Solution Explorer. A tabbed window with application settings will appear, as shown in Figure 3-11. Click the Application tab, and look at the Windows Application Properties section at the bottom of the tab.
Figure 3-11. Application settings in Visual Studio 2005
You have two out-of-the-box choices for the "Shutdown mode" box:
If neither of these options is suitable, you can take matters into your own hands. First, select the "Startup with custom Sub Main" checkbox. Now, you need to add a subroutine named Main( ) to your application. You can place this subroutine in an existing form or class, as long as you make sure to add the Shared accessibility keyword. Here's an example:
Public Class MyForm Public Shared Sub Main ' (Startup code goes here.) End Sub End Class
Shared methods are always available, even if there isn't a live instance of the containing class. For example, if you add a Main( ) method to a form, the .NET runtime can call your Main( ) method even though there isn't a form object.
Another choice is to add the Main( ) method to a module. In a module, every method, function, property, and variable acts as though it's shared, so you won't need to add the Shared keyword. Here's an example:
Public Module MyModule Public Sub Main ' (Startup code goes here.) End Sub End Module
Whatever you choose, make sure the class or module that contains the Main( ) method is selected in the "Startup object" box.
Note: Using a module is a great choice if you have extensive initialization to perform, because it separates your startup code from your form code.
When you use a Main( ) method to start your application, the application only runs as long as the Main( ) method is active. As soon as Main( ) ends, your application finishes. Here's an example of a prematurely terminated application:
Public Sub Main ' Show one form modelessly (without blocking the code). Form1.Show( ) ' Show another form modelessly (at the same time as the first). Form2.Show( ) ' After this line, the Main method ends, the application shuts ' itself down, and both windows close (after only being open a ' for a few milliseconds of screen time). End Sub
And here's the correct code that shows two windows in sequence:
Public Sub Main ' Show one form modally (code stops until the window is closed). Form1.ShowDialog( ) ' After the first window is closed, show the second modally. Form2.ShowDialog( ) ' Now the application ends. End Sub
In some cases, you might want to start your application with a Main( ) method to perform some basic initialization and show a few forms. Then, you might want to wait until all the forms are closed before the application ends. This pattern is easy to implement, provided you use the Application class. The basic idea is to call Application.Run( ) to keep your application alive indefinitely, and call Application.Exit( ) at some later point to end it. Here's how you could start the application with two visible windows:
Public Sub Main ' Show two forms modelessly (and at the same time). Form1.Show( ) Form2.Show( ) ' Keep the application going until you say otherwise. Application.Run( ) End Sub
To specify that the application should end when either window closes, use this code in the Form.Unload event handler of both forms:
Private Sub Form1_FormClosed(ByVal sender As Object, _ ByVal e As FormClosedEventArgs) Handles Me.FormClosed Application.Exit( ) End Sub
3.11.2. What about...
...cleaning up when the application calls it quits? When your application ends you might want to release unmanaged resources, delete temporary files, or save some final settings. The Application class provides a solution with its ApplicationExit event. All you need to do is attach the event to a suitable event handler in the Main( ) method. Here's an example that uses a method named Shutdown( ):
Note: The ApplicationExit Event always fires (and the code in an event handler for it always runs), even if the application has been derailed by an unhandled exception.
AddHandler Application.ApplicationExit, AddressOf Shutdown
And here's the Shutdown( ) method that runs automatically just before the application ends:
Public Sub Shutdown(ByVal sender As Object, ByVal e As EventArgs) MessageBox.Show("Cleaning up.") End Sub
3.11.3. Where can I learn more?
For more information, refer to the Application class in the MSDN class library reference (it's in the System.Windows.Forms namespace).
Tip: This lab uses the Application class from the System.Windows.Forms namespace. This item is similar to, but different from, the My.Application object. Technically, the My.Application object is a dynamically created class (generated by Visual Studio and hidden from view), which inherits from WindowsFormsApplicationBase. Overall, the My.Application object usually acts as a slightly simplified version of the System.Windows.Forms.Application class. This allows .NET to offer one class to programmers who want simplicity, and another to those who want the full set of features. In other words, .NET lets VBers have their cake and eat it too (but only by creating two different cakes).