Tip: How to handle startup for Windows Forms apps using the Me.Activated event

Rob Sherratt

Well-known member
Joined
Dec 30, 2012
Messages
64
Location
Corfu. Greece
Programming Experience
10+
Here is another tip which I hope will be helpful to others. If so, please let me know?

I just finished development of a large Windows Forms app using Visual Studio Express 2012 and VB.NET 4.5 under Windows 8.

As everyone knows, when you are developing a Windows Form application, the Visual Studio development environment creates a single default Form1 class which runs no code you write at all unless it is "event driven". You have to use some buttons or other click-event handlers to make your application do anything useful in response to user input. Running code when the Form1 class is instantiated is not documented by Microsoft. It is problematic to try to change the default behaviour from instantiating the Form1 class automatically, because otherwise you have to write extra Forms handling code yourself in a way that is also not well documented by Microsoft.

Because I'm too lazy to research more complex alternatives, the way I initialize my Windows Form app and run startup code without requiring user intervention is the following (simple template shown below):

VB.NET:
Imports System.IO
Imports System.Net
Imports System.Data
Imports System.Threading
Imports System.Globalization
Imports System.Windows.Forms
Imports System.Text.RegularExpressions

Public Class Form1

    ' Global declarations go here, e.g.

    Dim MyDataSet As New DataSet("All Data Tables")
    Dim MyUpperTable As New DataTable("Input Worksheet.csv")
    Dim MyLowerTable As New DataTable("Output Worksheet.csv")
    Dim FormStarted As Boolean = False
    Dim MyApplicationFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
    Const MyAppExceptionText As String = "Something really amazing is about to happen, ..."

Private Sub Do_Initialize(sender As Object, e As EventArgs) Handles Me.Activated

Try
     If Not FormStarted Then
             FormStarted = True
        
         ' Your initialization code goes here, an example shown of making a DataGridView display something useful before
         ' the Windows Form is used by the user.  It will run once only when the Windows Form app starts up
         ' Make sure any DataTables are declared globally as in this example, so you can use them elsewhere.

         MyInputFile = MyApplicationFolder & "\Input Worksheet Default.csv"
         If Not CSV_To_Table(MyInputFile, MyUpperTable, True) Then
                Console.WriteLine("Warning: The .csv file ""Input Worksheet Default.csv"" is missing and has not been displayed.")
                MyDataGridView.DataSource = MyUpperTable
                MyDataGridView.Show()
                Thread.Yield()
          End If
        
      End If ' Not FormStarted
      Exit Sub

     Catch ex As Exception
        Console.Writeline(MyAppExceptionText)
        Console.Writeline(ex.ToString())
        Exit Sub
End Try
End Sub 'Do_initialize

' Button click event handlers etc. go here

End Class 'Form1

The event "Me.Activated" is raised by VB.NET 4.5 automatically whenever the user first runs the forms application. Unfortunately it is also generated whenever a FileDialog box or MessageBox is closed by the user. This can be a real pain since you don't want your "Me.Activated" code to run under those circumstances. Therefore I use the boolean flag "FormStarted" which is Globally declared within the Form1 class, and this ensures the Do_Initialize() code runs once only. You must not use any dialog box that involves user intervention within the Do_initialize "Me.Activated" procedure. You would get input from users following another user event such as a button click.

If you find this useful, please give me a good rating via "rate this thread" ?. I am anxious to get beyond the "Newbie" status on this forum :very_drunk:

Best regards to all,
Rob
 
Last edited:
Form initialization user code is generally done using the default Load event handler (just doubleclick the form to generate handler). Activated event is used for those things that should happen each time form is activated (is focused), and can happen a lot of times during runtime.
It actually starts before that with the class constructor (Sub New), but compiler adds Load event to that as well as its own InitializeComponent method that sets up controls added in designer. You can add a custom constructor too, compiler then inserts a call for InitializeComponent.

For startup initialization for application that is not specific to a form instance there is the application Startup event.

As for documentation, there is a lot of that available through VS and MSDN :)
 
Hi John,

Thanks for your reply and for your expertise. I have switched to use the MyBase.Load event, it is much better since it avoids the "false calls" I was getting with Me.Activated. I'd be grateful for an MSDN link that covers the topic of Forms startup handling. I tried without success to find information. I am unsure what you mean by:

It actually starts before that with the class constructor (Sub New), but compiler adds Load event to that as well as its own InitializeComponent method that sets up controls added in designer. You can add a custom constructor too, compiler then inserts a call for InitializeComponent.

Can you tell me how to find out more about this, e.g. to see the generated Sub New class constructor, and InitializeComponent method within VS 2012? Is it intended that developers should modify these or are they part of the Windows Forms auto-generated code that should not be modified by the programmer?

Also do you have any suggestion of a better way to "package" Global declarations such as shared DataTables, and shared Const strings used everywhere in Subs and Functions within Class Form1 etc?

Thanks,
Rob
 
I'd be grateful for an MSDN link that covers the topic of Forms startup handling. I tried without success to find information.
You could start by looking up the Form class and check out its events. You may also notice most is inherited from Control class, so this is common knowledge for all controls.
to see the generated Sub New class constructor
That can only be done with a decompiler like Reflector after assembly has been compiled, I was just telling you how that relates to the constructing, initializing and loading of the form.
and InitializeComponent method
In Solution Explorer 'show all files', expand the class and open its .designer.vb file.
Is it intended that developers should modify these or are they part of the Windows Forms auto-generated code that should not be modified by the programmer?
You must not change generated code files. A custom constructor is something you add in user code area.
"package" Global declarations such as shared DataTables, and shared Const strings used everywhere
Put global stuff in modules. (and don't forget global is opposite of object-oriented)
 
If you want to do something specifically-related to form initialisation, do it in the constructor. If you want to do some setup for a form that is not specifically related to form initialisation then do it in the Load event handler. If you want to do something in a form immediately after the form has been displayed for the first time then do it in the Shown event handler. If you want to do something when the app starts up but not specifically related to the startup form then do it in the Startup event of the application.
 
@JohnH@ and @jmcihinney@

Thank you both for your expert and most helpful replies. Turns out my "Tip" is not actually that useful at all :disgust: Is there any editing in my OP that I should now do to "set the record straight" ? e.g. shall I turn it into a Question instead of a tip etc?

Thanks to you JohnH, I've now adopted the use of the Mybase.Load event for my Windows Form application "startup" - whose initialization I needed to do after the form and main objects from Form Designer have been instantiated.

Now, I am sorry if the following questions reveal more stupidity on my part, but I will ask anyway.

The MyDataGridView, MyListBox and MyTextBox objects created in Forms Designer are "global" and visible to all my Subs and Functions. How is this "Global" instantiation performed by the IDE-generated code, and how are the objects "shared"? Where is this documented/ explained (URL references please?). Can I instantiate MyDataTable objects and also Const values in a similar "approved" way so they are available to all my Subs and Functions? Can I generate my own "Includes" class library for this sort of stuff, and if so, how do I generate and save the necessary "Includes" files? What is the "correct" way to do this in a Windows Forms environment? Could you show me a code snippet example where you have instantiated a MyDataTable like this in a Class library so it is accessible anywhere in the Form1 Class just by using an "Includes" statement in the header?

I can post this set of questions in a new thread if you prefer. Let me know where on the forum might be more appropriate?

Best regards,
Rob
 
The MyDataGridView, MyListBox and MyTextBox objects created in Forms Designer are "global" and visible to all my Subs and Functions.
That's not what I put in the term 'global', but have you had time to look at the generated code for a form yet? To not 'get lost' in much generated code just add a new form and drop a button or something on it, then review the code. It is quite simple actually, they are variables declared outside any method.
 
Back
Top