- •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
Once this is done, we will look at implementing any changes required to support these menus.
The following table details the steps required:
ASSIGN THE TYPE AND ORDER FOR OUR FILE MENUS
|
|
|
|
Action |
|
|
|
|
Result |
||
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
In the ParentForm.cs [Design] |
|
||||||||
|
|
window, add an Open menu to the |
|
||||||||
|
|
File menu just after the existing New |
|
||||||||
|
|
menu. |
|
|
|
|
|
|
|
|
|
|
|
|
|
Settings |
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Property |
|
|
Value |
|
||||
|
|
|
(Name) |
|
menuOpen |
|
|||||
|
|
|
Shortcut |
|
|
CtrlO |
|
||||
|
|
|
Text |
|
|
&Open |
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
Update the merge settings for the |
|
||||||||
|
|
items in the File menu. |
|
|
|
|
|
||||
|
|
|
|
Settings |
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|||
|
|
|
Menu |
MergeType |
MergeOrder |
|
|||||
|
|
|
New |
Replace |
|
0 |
|
|
|
|
|
|
|
|
Open |
Replace |
|
1 |
|
|
|
|
|
|
|
separator |
Remove |
|
0 |
|
|
|
|
||
|
|
|
Exit |
Add |
|
7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
|
In the File menu for the MainForm.cs |
|
||||||||
|
|
[Design] window, update the merge |
|
||||||||
|
|
settings for the items in this menu. |
|
||||||||
|
|
|
|
Settings |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
Menu |
MergeType |
|
MergeOrder |
|
||||
|
|
|
New |
Remove |
|
0 |
|
|
|
|
|
|
|
|
Open |
Remove |
|
1 |
|
|
|
|
|
|
|
separator |
Add |
|
3 |
|
|
|
|
||
|
|
|
Save |
Add |
|
4 |
|
|
|
|
|
|
|
Save As |
Add |
|
5 |
|
|
|
|
||
|
|
separator |
Add |
|
6 |
|
|
|
|
||
|
|
|
Exit |
Add |
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The key points here are the fact that the New and Open menus in the ParentForm class replace those in the MainForm class, and the merge order for each menu must match the desired position we discussed earlier. One other interesting point is the reuse of the Exit menu in the MainForm class for the Close menu in the merged menu. This makes sense, although we still need to rename the menu text to read
MERGED MENUS |
539 |
“Close” rather than “Exit.” We will do this in a way that continues to preserve the SDI application from part 2.
CHANGE THE EXIT MENU TEXT WHEN RUNNING AS AN MDI CHILD FORM
|
Action |
Result |
|
|
|
4 |
Override the OnLoad method in |
protected override void OnLoad(EventArgs e) |
|
the MainForm.cs code window. |
{ |
|
|
|
5 |
If the form is an MDI child |
if (IsMdiChild) |
|
window, then modify the Exit |
menuExit.Text = "&Close"; |
|
menu to appear as a Close |
base.OnLoad(e); |
|
menu. |
|
|
} |
|
|
How-to |
|
|
Use the IsMdiChild property. |
|
|
|
|
This change ensures that the Exit menu displays “Close” when the MainForm object is created as an MDI child window. Otherwise, the default setting of “Exit” will be used.
Compile and run the application to verify that our changes produce the appropriate menu structure. Create a new MDI child window and display the File menu. Your application should appear as in figure 16.5. Note how all the menus are now in the desired order, including the separator menus. Also note that the Exit menu from the MainForm class is reincarnated as the Close menu in the MDI application.
Figure 16.5 The merged File menu here gives no indication that different menu items are processed in different classes.
540 |
CHAPTER 16 MULTIPLE DOCUMENT INTERFACES |
Of course, the Open menu is not yet implemented for our ParentForm class. Also note that the Toolbar control in our child window still provides access to the now hidden New and Open menus in the MainForm class.
We will deal with our toolbar shortly. First, let’s discuss our new Open menu.
16.3.3OPENING A CHILD FORM
The Open menu in the parent form should work much like the now hidden Open
menu for the MainForm class. The handler for this menu should display an OpenFileDialog and create a new child window containing the selected album. To create the MainForm instance, we will create a new constructor that accepts an album file name with which to initialize the window.
The code required here is nothing new to us, so let’s get to it.
IMPLEMENT HANDLER FOR OPEN MENU IN PARENT FORM
|
ACTION |
RESULT |
|
|
|
1 |
Add a using statement for |
using Manning.MyPhotoAlbum; |
|
our library at the start of |
|
|
the ParentForm.cs code |
|
|
window. |
|
|
|
|
2 |
Add a Click handler for |
private void menuOpen_Click |
|
the Open menu in the |
(object sender, System.EventArgs e) |
|
ParentForm.cs [Design] |
{ |
|
|
|
|
window. |
|
|
|
|
3 |
Implement this handler to |
// Allow user to select a new album |
|
display an OpenFile- |
using (OpenFileDialog dlg = new OpenFileDialog()) |
|
Dialog instance from |
{ |
|
dlg.Title = "Open Album"; |
|
|
which to select an album. |
|
|
dlg.Filter = "abm files (*.abm)|" |
|
|
|
+ "*.abm|All files (*.*)|*.*"; |
|
|
dlg.InitialDirectory = PhotoAlbum.DefaultDir; |
|
|
dlg.RestoreDirectory = true; |
|
|
if (dlg.ShowDialog() == DialogResult.OK) |
|
|
{ |
|
|
|
4 |
If an album is selected, try |
try |
|
to open the file in a new |
{ |
|
window. |
// Open new child window for the album |
|
MainForm form = new MainForm(dlg.FileName); |
|
|
|
|
|
How-to |
form.MdiParent = this; |
|
Use a not-yet-implemented |
form.Show(); |
|
} |
|
|
constructor that accepts an |
|
|
|
|
|
album file. |
|
|
|
|
MERGED MENUS |
541 |
IMPLEMENT HANDLER FOR OPEN MENU IN PARENT FORM (continued)
|
ACTION |
RESULT |
|
|
|
5 |
If an error occurs creating |
catch (Exception ex) |
|
the child window, display |
{ |
|
an error message to the |
MessageBox.Show(this, |
|
"Unable to open file " + dlg.FileName |
|
|
user. |
|
|
+ "\n (" + ex.Message + ")", |
|
|
|
"Open Album Error", |
|
|
MessageBoxButtons.OK, |
|
|
MessageBoxIcon.Error); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
The code displays an open file dialog and creates a child window using the selected album file. This code requires a new constructor for the MainForm class, namely one that accepts the file name of a photo album.
In this new constructor, we would like to make use of the constructor code already present in the existing constructor. We can do this in C# by simply invoking the default constructor with the this keyword. The following table illustrates this syntax, and the changes required for our new constructor.
CREATE A MAINFORM CONSTRUCTOR THAT ACCEPTS AN ALBUM FILE
Action |
Result |
6In the MainForm.cs file, create a public MainForm(string albumFile) new constructor that accepts
the name of an album file.
7 |
Invoke the default constructor |
: this() |
|
within our new constructor. |
{ |
|
|
|
8 |
Within the constructor, create a |
_album = new PhotoAlbum(); |
|
PhotoAlbum for the given file. |
_album.Open(albumFile); |
|
Note: If a file cannot be opened |
SetTitleBar(); |
|
} |
|
|
as an album, this will throw an |
|
|
exception. |
|
These changes permit the ParentForm class to create a new child window containing an open album. Compile and run the application to verify that this works as expected. The File menu from our two classes is now fully merged, and all menus are fully implemented.
As can be seen from this discussion, the ability to merge menus provides a powerful mechanism for controlling the menu bar in MDI applications. They permit the exact placement of menu items, and control over which class, the parent or child, will process each item. While we only merged a single menu here, you may find in your
542 |
CHAPTER 16 MULTIPLE DOCUMENT INTERFACES |