- •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
16.3MERGED MENUS
By definition, an MDI application permits multiple windows to be displayed. Each child window may be the same or different, and each may display different information about one or more objects. It would be nice if the menu items for the application could be customized depending on which child window is displayed. Exactly how to do this is the subject of this section.
As an example, consider a car-buying application that permits users to search for, display, and purchase used cars. As an MDI application, this might display a photograph of the car in one window, standard features and warranty information in another window, and optional packages and pricing information in a third window. Clearly the set of menus and the contents of each menu should differ depending on which style window is currently active. For instance, menus for the photograph window might permit different colors to be viewed or different parts of the vehicle to be shown. These concepts make no sense for the other windows, and should not be accessible when these windows are active.
While our application is not quite so ambitious, we do have the problem of our File menu, since both the ParentForm and the MainForm class contain this item. Once we make the two File menus merge, we also have to deal with the contents of these menus, to ensure the items appear in an appropriate order.
The Menu class provides a MergeMenu method for merging two menus together. This method accepts a Menu object and merges it with the calling Menu object. The MenuItem class provides additional overrides of this method to merge MenuItem objects and to copy a menu item so that it may be merged with other menus. This latter method has the advantage of not affecting the existing MenuItem object.
In MDI applications, an MDI container form automatically merges the menu for the active child form with the MainMenu object stored in its Menu property. The Form.MergedMenu property contains the result of this merge, and can be used to access or modify the merged menu directly. The Form.Menu property always contains the original menu assigned to the form.
Since this merging occurs automatically for MDI applications, this section will focus on how menus are merged together, and make the appropriate changes in our MDI application to merge the two File menus together. First we will discuss the various ways to merge two menus, followed by the mechanism for establishing the order of merged menu items.
16.3.1ASSIGNING MERGE TYPES
As mentioned at the start of this chapter, the MenuItem class contains two properties
that control exactly how two menus are merged together. This section will discuss the MergeType property that controls how the menus are merged. Later we will look at the MergeOrder property that controls the final position of a merged item.
MERGED MENUS |
535 |
The MergeType property gets or sets a MenuMerge enumeration value specifying how this menu should be merged with other menus. An overview of this enumeration appears in .NET Table 16.1. The default setting for the MergeType property is MenuMerge.Add. This default adds each item separately, and is the cause of the two File menus in our current application.
.NET Table 16.1 MenuMerge enumeration
The MenuMerge enumeration specifies various types of behavior for a MenuItem object when it is merged with another menu. This enumeration is used by the MergeType property in the MenuItem class, and is part of the System.Windows.Forms namespace.
Enumeration
Values
Add |
The item is added to the collection of MenuItem |
|
objects in the merged menu. |
MergeItems |
All MenuItem objects contained by the item are |
|
merged with those contained by the menu at the |
|
same position in the merged menu. |
Remove |
The item is not included in the merged menu. |
Replace |
The item replaces an existing MenuItem object |
|
at the same position in the merged menu. |
|
|
This explains why our existing application has two File menus. Since the MergeType property defaults to Add, the menus are simply added to the collection separately.
We can fix this by modifying the MergeType property for these menus.
Set the version number of the MyPhotos application to 16.3.
MERGE THE PARENT AND CHILD FILE MENUS
|
Action |
Result |
|
|
|
1 |
In the MainForm.cs [Design] |
The two File menus in the parent and child form will now |
|
window, set the MergeType |
merge into a single menu in the application, the result of |
|
property of the File menu item |
which is shown in this graphic. The menu items exhibit |
|
to MergeItems. |
the default merge behavior, which is Add. |
|
|
|
2 |
Similarly, set the MergeType |
|
|
property to MergeItems for the |
|
|
File menu in the ParentForm.cs |
|
|
[Design] window. |
|
|
Note: The MergeType property |
|
|
must be set for both File menu |
|
|
objects to merge the two |
|
|
menus together. |
|
|
|
|
Compile and run the application, and open a client form in the parent window to see the merged menu as shown in the table. The two menus are merged, but their contents
536 |
CHAPTER 16 MULTIPLE DOCUMENT INTERFACES |
are not exactly in an acceptable order. This is because each of the MenuItem objects within their respective File menus use the default MergeType property, which is Add. As a result, each menu item is simply added to the end of the list. The items from the parent form appear first, followed by the items from the child form.
We can fix this, of course, but first a brief aside.
TRY IT! Modify the MergeType property for either File menu so that one menu uses the MergeItems member value and the other the Add value. Run the application to verify that the menus no longer merge.
Also rename the File menu in the ParentForm class to use the name “Fickle.” Run the application and see which name is shown in the application. You will find that the name in the MDI child is preferred over the name in the parent. This is a consequence of how the menus are merged, and can be utilized to rename a menu in the parent form when a specific kind of child is displayed.
Back in our application, we have two problems with the merged File menu. The first is that we have two versions of the New and Exit menus, and the second is that the order of the merged menu is a bit of a mess.
We will address these two problems together as part of a discussion on the MergeOrder property.
16.3.2ASSIGNING MERGE ORDER
So far we have merged our two File menus into a single menu. The next step is to clean up the contents of this menu. This involves setting the appropriate MergeType for each menu, and using the MergeOrder property to establish the order of these items within the merged menu. The MergeOrder property contains the zero-based position where the menu should appear within the merged menu. If multiple items are assigned the same order, they appear one after another in the merged menu. This
is the case in our existing code, where all menus in the File menu use the default MergeOrder value of zero.
Before we start making changes to our existing menus, let’s step back and consider what a reasonable File menu should contain for our MDI application. Such a menu is described by the following table, which shows the menu name, its position, a short description, and some implementation notes.
Contents of the merged File menu in our MDI application
Menu name |
Position |
Description |
Implementation Notes |
|
|
|
|
New |
0 |
Opens a new album in a new MDI |
Same as existing New menu in the |
|
|
child window. |
ParentForm class. |
Open |
1 |
Opens an existing album file in a |
This should be processed by the |
|
|
new MDI child window. |
ParentForm class in order to create |
|
|
|
the new child window. |
|
|
|
|
MERGED MENUS |
537 |
Contents of the merged File menu in our MDI application |
(continued) |
|||
|
|
|
|
|
Menu name |
Position |
Description |
|
Implementation Notes |
|
|
|
|
|
Close |
2 |
Closes the active MDI child |
|
Similar to the Exit menu in the |
|
|
window. |
|
MainForm class. |
separator |
3 |
|
|
|
Save |
4 |
Saves the album in the active MDI |
|
Same as existing Save menu in the |
|
|
child window. |
|
MainForm class |
Save As |
5 |
Saves the album in the active MDI |
|
Same as existing Save As menu in |
|
|
child window under a new name. |
|
the MainForm class. |
separator |
6 |
|
|
|
Exit |
7 |
Closes all child windows as well as |
|
Same as existing Exit menu in the |
|
|
the MDI container form. |
|
ParentForm class. |
|
|
|
|
|
This details how the merged menu should look. There is still the question of the menu structure in the ParentForm and MainForm classes. Based on the previous table, we can establish how the File menu should appear for each Form class. The following table details the contents of each menu, and describes its behavior in the merged menu object.
Individual File menu for our MDI parent and child classes
Class |
Menu |
Implementation notes |
|
|
|
|
|
|
New |
This menu should behave as it already does, and replace the New menu |
|
|
|
in the child form. |
|
ParentForm |
Open |
This is a new menu to open an existing album in a new window. |
|
separator |
This menu should not exist when the menus are merged. |
||
|
|||
|
Exit |
This menu should behave as it already does, and appear at position 7 |
|
|
|
when the menus are merged. |
|
|
|
|
|
|
New |
Should not be present in the merged menu for our MDI application. |
|
|
Open |
Should not be present in the merged menu. |
|
|
separator |
Should become the first separator at position 3 in the merged menu. |
|
MainForm |
Save |
As currently exists, at position 4 in the merged menu. |
|
|
Save As |
As currently exists, at position 5 in the merged menu. |
|
|
separator |
Should become the second separator at position 6 in the merged menu. |
|
|
Exit |
Should become the Close menu at position 2 in the merged menu. |
|
|
|
|
We are now ready to update our menus based on these tables. Our first change will simply update the menus so that they appear as described within the application.
538 |
CHAPTER 16 MULTIPLE DOCUMENT INTERFACES |