Ultimately all the GUI tools produce code and that is what you must understand. The following discussion highlights those aspects of the code that you need to know. The Container class declaration (see Listing 6.2) exists solely to support the IDE. As shown in Listing 6.1, a Windows Forms application will run fine without it. Listing 6.2 Container Declaration (Wizard.cs)private System.ComponentModel.Container components = null; The constructor (see Listing 6.3) starts off with a simple, but important, call to InitializeComponent. This is the method where all the changes to the form's visual appearance are placed. Any code you add to the constructor needs to go after the call to InitializeComponent, where the form will be initialized and safe to work with. Any GUI changes before InitializeComponent would be rendered useless if something inside InitializeComponent modified the same GUI objects. Listing 6.3 A Windows Forms Constructor (Wizard.cs)public WinForm() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } The InitializeComponent method (see Listing 6.4) is enclosed in region/endregion preprocessing directives. They are called preprocessor directives, in the tradition of C and C++, although C# does not have a preprocessor. They can be used in any code to help organize it in the designer. The code folding tree on the left will collapse entire regions, leaving only the additional code on the #region line displayed. Listing 6.4 The InitializeComponent Method (Wizard.cs)#region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.Size = new System.Drawing.Size(300,300); this.Text = "WinForm"; } #endregion If you recall from Listing 6.1, the Text property was in the constructor. With the IDE, these changes are added to the InitializeComponent method. Generally, you shouldn't modify the code in this method because it is generated by the designer. Doing so has the potential to break the interactivity between code and designer components. It is important to look in this method to find out and understand what the designer is doing for you. We would all like to believe that our tools will take care of everything for us. However, the reality is that all software has bugs, so having to go in and fix a problem in InitializeComponent is a rare but necessary evil. Another important method, generated by the wizard, is Dispose (see Listing 6.5). The purpose of this method is to implement the Dispose pattern, which is the proper way to release unmanaged resources. In Windows programming, numerous unmanaged resources must be released when no longer needed. Failure to dispose of these resources can bring an application to a screeching halt. Therefore, knowing and learning the Dispose pattern is important, especially for Windows Forms. Listing 6.5 The Dispose Method (Wizard.cs)protected override void Dispose (bool disposing) { if (disposing) { if (components != null) { components.Dispose(); } } base.Dispose(disposing); } Another important piece of code, which I conveniently left out of Listing 6.1, is the STAThread attribute (see Listing 6.6) on the Main method. The STAThread attribute enables an application to run in Single Threaded Apartment (STA) when communicating with COM objects. Because all VBA and ActiveX components are STA, the STAThread attribute is a good default. The alternative of leaving it out causes the application to run as Multi-Threaded Apartment (MTA), which could cause problems unless you understand COM and know what you are doing. Listing 6.6 The STAThread Attribute (Wizard.cs)[STAThread] static void Main() { Application.Run(new WinForm()); }
|