
- •brief contents
- •about this book
- •The Windows Forms namespace
- •Part 1: Hello Windows Forms
- •Part 2: Basic Windows Forms
- •Part 3: Advanced Windows Forms
- •Who should read this book?
- •Conventions
- •Action
- •Result
- •Source code downloads
- •Author online
- •acknowledgments
- •about .NET
- •Casting the .NET
- •Windows Forms overview
- •about the cover illustration
- •Hello Windows Forms
- •1.1 Programming in C#
- •1.1.1 Namespaces and classes
- •1.1.2 Constructors and methods
- •1.1.3 C# types
- •1.1.4 The entry point
- •1.1.5 The Application class
- •1.1.6 Program execution
- •1.2 Adding controls
- •1.2.1 Shortcuts and fully qualified names
- •1.2.2 Fields and properties
- •1.2.3 The Controls property
- •1.3 Loading files
- •1.3.1 Events
- •1.3.2 The OpenFileDialog class
- •1.3.3 Bitmap images
- •1.4 Resizing forms
- •1.4.1 Desktop layout properties
- •1.4.2 The Anchor property
- •1.4.3 The Dock property
- •1.5 Recap
- •2.1 Programming with Visual Studio .NET
- •2.1.1 Creating a project
- •Action
- •Result
- •2.1.2 Executing a program
- •Action
- •Result
- •2.1.3 Viewing the source code
- •View the code generated by Visual Studio .NET
- •Action
- •Result
- •2.2 Adding controls
- •2.2.1 The AssemblyInfo file
- •Action
- •Results
- •2.2.2 Renaming a form
- •Action
- •Result
- •2.2.3 The Toolbox window
- •Action
- •Result
- •2.3 Loading files
- •2.3.1 Event handlers in Visual Studio .NET
- •Action
- •Result
- •2.3.2 Exception handling
- •Action
- •Result
- •Action
- •Results and Comments
- •2.4 Resizing forms
- •2.4.1 Assign the Anchor property
- •Action
- •Result
- •2.4.2 Assign the MinimumSize property
- •Action
- •Result
- •2.5 Recap
- •Basic Windows Forms
- •Menus
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •3.3 Click events
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •3.5 Context menus
- •Action
- •Result
- •Action
- •Result
- •3.6 Recap
- •Status bars
- •4.1 The Control class
- •4.2 The StatusBar class
- •Action
- •Result
- •Action
- •Result
- •4.3.1 Adding panels to a status bar
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •4.5 Recap
- •Reusable libraries
- •5.1 C# classes and interfaces
- •5.2 Class libraries
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •5.3 Interfaces revisited
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •5.4 Robustness issues
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Common file dialogs
- •Action
- •Results
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •6.3 Paint events
- •Action
- •Result
- •Action
- •Result
- •6.4 Context menus revisited
- •Action
- •Result
- •Action
- •Result
- •6.5 Files and paths
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •6.6 Save file dialogs
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •6.7 Open file dialogs
- •Action
- •Result
- •Action
- •Result
- •6.8 Recap
- •Drawing and scrolling
- •7.1 Form class hierarchy
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •7.4 Panels
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Dialog boxes
- •8.1 Message boxes
- •Action
- •Result
- •Action
- •Result
- •8.1.4 Creating A YesNoCancel dialog
- •Action
- •Result
- •Action
- •Result
- •8.2 The Form.Close method
- •8.2.1 The relationship between Close and Dispose
- •Action
- •Result
- •8.3 Modal dialog boxes
- •Action
- •Result
- •Action
- •Result
- •8.3.2 Preserving caption values
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Basic controls
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •9.1.2 Creating a derived form
- •Action
- •Result
- •9.2 Labels and text boxes
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •9.3.6 Adding AlbumEditDlg to our main form
- •Action
- •Result
- •Action
- •Result
- •9.4 Recap
- •List controls
- •10.1 List boxes
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •10.2 Multiselection list boxes
- •10.2.1 Enabling multiple selection
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •10.3 Combo boxes
- •Action
- •Result
- •Action
- •Result
- •10.4 Combo box edits
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •10.5 Owner-drawn lists
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •More controls
- •Action
- •Result
- •Action
- •Result
- •11.2 Tab pages
- •Action
- •Result
- •Action
- •Result
- •11.3.1 Dates and times
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •11.5 Recap
- •A .NET assortment
- •12.1 Keyboard events
- •Action
- •Result
- •Action
- •Result
- •12.2 Mouse events
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •12.3 Image buttons
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •12.4 Icons
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •12.5 Recap
- •Toolbars and tips
- •13.1 Toolbars
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •13.4.2 Creating tool tips
- •Action
- •Result
- •Action
- •Result
- •Advanced Windows Forms
- •List views
- •14.2 The ListView class
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •14.2.3 Populating a ListView
- •Action
- •Result
- •Action
- •14.3 ListView columns
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •14.6 Recap
- •Tree views
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •15.3 Dynamic tree nodes
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •15.4 Node selection
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •15.5 Fun with tree views
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Multiple document interfaces
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •16.3 Merged menus
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •16.4 MDI children
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •16.5 MDI child window management
- •Action
- •Result
- •Action
- •Result
- •16.6 Recap
- •Data binding
- •17.1 Data grids
- •Action
- •Result
- •Action
- •Result
- •17.2 Data grid customization
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Odds and ends .NET
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •18.2 Timers
- •Action
- •Result
- •Action
- •Result
- •18.3 Drag and drop
- •Action
- •Result
- •Action
- •Result
- •18.4 ActiveX controls
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •18.5 Recap
- •C# primer
- •A.1 C# programs
- •A.1.1 Assemblies
- •A.1.2 Namespaces
- •A.2 Types
- •A.2.1 Classes
- •A.2.2 Structures
- •A.2.3 Interfaces
- •A.2.4 Enumerations
- •A.2.5 Delegates
- •A.3 Language elements
- •A.3.1 Built-in types
- •A.3.2 Operators
- •A.3.3 Keywords
- •A.4 Special features
- •A.4.1 Exceptions
- •A.4.2 Arrays
- •A.4.3 Main
- •A.4.4 Boxing
- •A.4.5 Documentation
- •.NET namespaces
- •B.1 System.Collections
- •B.2 System.ComponentModel
- •B.3 System.Data
- •B.4 System.Drawing
- •B.5 System.Globalization
- •B.6 System.IO
- •B.7 System.Net
- •B.8 System.Reflection
- •B.9 System.Resources
- •B.10 System.Security
- •B.11 System.Threading
- •B.12 System.Web
- •B.13 System.Windows.Forms
- •B.14 System.XML
- •Visual index
- •C.1 Objects
- •C.2 Marshal by reference objects
- •C.3 Components
- •C.4 Common dialogs
- •C.7 Event data
- •C.8 Enumerations
- •For more information
- •bibliography
- •Symbols
- •Index

TRY IT! Compile and run the application to see the menus in action. Notice how the shortcut for the Load menu is displayed within the menu. Try setting the ShowShortcut property for this menu to false in order to prevent this shortcut from appearing on the menu. Note that the keyboard shortcut still works, the user is just not told about it in the menu bar.
Sit back for a moment and think about what we have done here. If you have used Visual C++ with MFC, you should realize that the secret macros and magic interface files required by this environment are gone. In their place are well-designed objects that can quickly and easily be used to create arbitrarily complex menu structures.
If you have been following the examples with Visual Studio .NET, also realize that you have not written any code thus far. This will change when we add event handlers for our menus in the next section.
3.3CLICK EVENTS
Of course, a menu is not very useful if you can’t make it do something. In this section we’ll define some event handlers for our menus and examine how event handlers work in more detail than we covered in chapter 2. This section builds on the MyPhotos version 3.2 project constructed in section 3.2, or available on the book’s web site.
Events for Windows Forms controls can be added from the Windows Forms Designer window, or in the Properties window. We will discuss each method separately.
3.3.1ADDING HANDLERS VIA THE DESIGNER WINDOW
As you might guess, Visual Studio adds a Click event handler whenever you doubleclick a menu control in the Windows Forms Designer. We already saw this behavior for buttons in chapter 2. Let’s use this feature to add a handler to the Load menu here.
Set the version number of the application to 3.3.
ADD CLICK HANDLER FOR THE LOAD MENU
|
Action |
Result |
|
|
|
1 |
Display the MainForm.cs |
|
|
[Design] window. |
|
|
|
|
2 |
Add a Click handler for |
A new event handler for the Load menu is added and the |
|
the Load menu |
cursor is placed in the MainForm.cs code window within the |
|
How-to |
newly added handler. |
|
|
|
|
a. Click on the File menu. |
protected void menuLoad_Click(object sender, |
|
b. Double-click on the Load |
System.EventArgs e) |
|
{ |
|
|
menu. |
} |
|
Note: This double-click |
The new handler is also registered as a Click handler for the |
|
Load menu in the InitializeComponent method. |
|
|
method only works for the |
|
|
|
|
|
Click event. We will see |
menuLoad.Click += new System.EventHandler |
|
how to add events more |
(this.menuLoad_Click); |
|
|
|
|
generally in the next section. |
|
|
|
|
CLICK EVENTS |
85 |

ADD CLICK HANDLER FOR THE LOAD MENU (continued)
3 |
Copy the code from the |
This code is identical to the code used with our Load button in |
|
now defunct btnLoad_ |
chapter 2; it is just invoked via a menu rather than a button. |
|
Click into our new |
protected void menuLoad_Click |
|
method and delete the old |
|
|
(object sender, System.EventArgs e) |
|
|
method. |
{ |
|
Note: Unless you removed |
OpenFileDialog dlg = new OpenFileDialog(); |
|
dlg.Title = "Load Photo"; |
|
|
it, the code for |
|
|
btnLoad_Click should |
dlg.Filter = "jpg files (*.jpg)" |
|
+ "|*.jpg|All files (*.*)|*.*"; |
|
|
still be present in your |
|
|
|
|
|
code. After copying this |
if (dlg.ShowDialog() == DialogResult.OK) |
|
code, remove the method. |
{ |
|
|
try |
|
|
{ |
|
|
pbxPhoto.Image = new |
|
|
Bitmap(dlg.OpenFile()); |
|
|
} |
|
|
catch (Exception ex) |
|
|
{ |
|
|
MessageBox.Show( |
|
|
"Unable to load file: " |
|
|
+ ex.Message); |
|
|
} |
|
|
} |
|
|
dlg.Dispose(); |
|
|
} |
|
|
|
Since this code matches the handler we discussed in chapter 2 for the Load button, we will not discuss it again.
Compile the application to verify that the Load menu now works as expected. You should be able to load a new image using the menu bar via the mouse, using the access keys Alt+F and then Alt+L, or using the keyboard shortcut Ctrl+L.
3.3.2ADDING HANDLERS VIA THE PROPERTIES WINDOW
Double-clicking our controls in Visual Studio is fine when we wish to add a Click event handler for a menu item. What about other types of events? The .NET classes provide a rich set of events for everything from keyboard presses and mouse clicks to redrawing a control. To support these and other events, Visual Studio provides a more generic way to add an event handler than the double-click we have used thus far.
This is done using the Properties window. We have seen how this window provides the list of properties associated with a specific control. It also provides the list of events for each control and allows new event handlers to be added. Figure 3.6 shows the relevant elements of the Properties window. Note the small toolbar buttons between the object dropdown and the list of object members. The Properties button is the default and displays a list of properties for the current object. If you click the Events button, this window displays a list of events. The events for the menuExit object are shown in the figure.
86 |
CHAPTER 3 MENUS |

bDisplay by Category:
The available settings are displayed by category.
c Display Alphabetically: b c |
d |
e |
|
The available settings are |
|
displayed alphabetically. |
|
dProperties Button:
Click to display the available properties for this object.
eEvents button:
Click to display the available events for this object.
fObject Drop-Down:
The object whose settings are displayed.
g Description Pane: g
Shows an explanation of the currently selected item.
f
Figure 3.6
The Properties window displays both the properties and events for the controls on the form.
As you can see in the figure, our menuExit object supports five different events. These correspond to the events for the MenuItem class shown in .NET Table 3.3 on page 82. To the right of these events, the registered event handlers are displayed, with a menuExit_Click method shown as the handler for the Click event. To add a specific type of event, you simply need to double-click the entry in this window. We will illustrate this by defining a Click event handler for the Exit menu.
ADD CLICK HANDLER FOR THE EXIT MENU
|
Action |
Result |
|
|
|
1 |
Display the Properties |
The available properties for the menuExit object are shown. |
|
window for the Exit menu. |
|
|
|
|
2 |
Click the Events button in |
The events for the menuExit object are displayed. |
|
the Properties toolbar. |
|
|
|
|
3 |
Double-click on the Click |
A menuExit_Click handler is added to the menuExit |
|
item listed in the window. |
object. The new method is registered and defined in the |
|
|
InitializeComponent method, and the cursor is located |
|
|
within this new method. |
|
|
protected void menuExit_Click |
|
|
(object sender, System.EventArgs e) |
|
|
{ |
|
|
|
4 |
Call the Form.Close |
this.Close(); |
|
method within this handler. |
} |
|
|
Note: Note how the code for this event handler is split |
|
|
across steps 3 and 4 of this table. We will do this |
|
|
throughout the book as a convenient way to discuss dif- |
|
|
ferent sections of code for a single member of a class. |
|
|
|
CLICK EVENTS |
87 |
The Form.Close method is used to exit the application. This method closes the associated form, or the entire application if the form was the startup form for the application.
As you may have noticed in chapter 1, the Application class provides an Exit method that we could use instead here. This call forces all message loops started by Application.Run methods to exit, and closes any forms associated with them as well.
In our existing code, either method would close the application. As we will see in chapter 9, however, the Close method ensures that all nonmemory resources associated with a form are disposed, and invokes the Form.Closing event to permit additional processing as required. As a result, use of the Close method is normally preferred in an Exit menu rather than the Application.Exit method.
TRY IT! Once again, compile and run the code to verify that the Load and Exit menus now work. If you feel like experimenting, modify the Enabled and Visible properties for the Exit menu to see how they change the behavior of this menu.
Our handling of the File menu is now complete. Next we will handle the items in the View menu.
3.4POPUP EVENTS AND SHARED HANDLERS
The File menu is fairly straightforward as menus go. There is a Load item, a separator, and an Exit item. Each menu item raises a Click event when pressed, and the associated event handler performs the appropriate operations. Our View menu will handle things a little differently. This menu contains a single Image menu, which in turn points to a submenu with two entries. When a MenuItem object contains a nonempty collection in its MenuItems property, the Click event for that menu is not raised. This makes sense, as the submenu automatically pops up when the parent menu is clicked, making a Click event a bit extraneous.
This is the case for the File and View menus on the menu bar. These menus never raise a Click event. The same applies to the Image menu, since it is the parent of the
MenuItem objects menuStretch and menuActual. Rather than Click events, menus such as the Image menu raise a Popup event just before their submenu is displayed. This permits an event handler to modify the contents or appearance of the submenu as dictated by the application. An example of this type of handler can be found in the Windows operating system. Display the My Computer window and look at the File menu. The contents of the File menu changes depending on what type of file is currently selected.
In .NET, Popup events can be associated with any MenuItem or ContextMenu object that contains a collection of MenuItem objects in their MenuItems property.
In this section we will use a Popup event associated with the Image menu to control how our two submenu items appear when displayed. Before we do this, we will need a Click event handler for our submenu items.
88 |
CHAPTER 3 MENUS |