- •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
Unlike our message for the Open handler, this code makes use of the result returned by the Show method. This result is a DialogResult enumeration that indicates the button pressed. The values in this enumeration are shown in .NET Table 8.2, and correspond to the kinds of buttons typically found in Windows dialogs.
.NET Table 8.2 DialogResult enumeration
The DialogResult enumeration represents a value returned by a dialog box. This class is part of the System.Windows.Forms namespace, and is used with all dialog boxes in Windows Forms. In particular, a DialogResult is returned by the MessageBox.Show method as well as the ShowDialog method in both the Form class and common dialogs derived from the CommonDialog class. This enumeration is also used by the Button class to indicate the result to automatically return from a modal dialog when the button is clicked.
|
Abort |
The dialog return value is Abort. Typically, this means the user |
|
|
clicked an Abort button. |
|
Cancel |
The dialog returns Cancel, typically from a Cancel button. |
|
Ignore |
The dialog returns Ignore, typically from an Ignore button. |
Enumeration |
No |
The dialog returns No, typically from a No button. |
Values |
None |
The dialog returns nothing, indicating that the dialog box is still |
|
||
|
|
running. |
|
OK |
The dialog returns OK, typically from an OK button. |
|
Retry |
The dialog returns Retry, typically from a Retry button. |
|
Yes |
The dialog returns Yes, typically from a Yes button. |
|
|
|
You can compile and run this code if you would like to see the message boxes we created. You can generate an open error easily enough by selecting a file that is not, in fact, an album file. A save error can be generated by attempting to save to a read-only CD, or by filling up a floppy disk and then saving a file to it.
Our last example will generate a message box for closing an existing album.
8.1.4Creating A YesNoCancel dialog
Our final example is the case where an album has changed but is about to be discarded. This can occur when the application is about to exit, when loading a new album with the Open menu item, and when creating a new album with the New menu item.
To handle these situations in a consistent way, we will create a protected method to gracefully close the current album for all three cases using the dialog in figure 8.4. We will call this method CloseCurrentAlbum and have it return a boolean value indicating
whether the album was closed or the user clicked the Cancel button.
Figure 8.4 This dialog is displayed when an album is about to be discarded.
230 |
CHAPTER 8 DIALOG BOXES |
The three buttons in our dialog will correspond to the following behavior in our
CloseCurrentAlbum method:
•Yes will save the album, then close the album and return true.
•No will not save the album, then close the album and return true.
•Cancel will not save or close the album and return false to indicate that the calling operation should be canceled.
To close the album, CloseCurrentAlbum will clear the album and related settings. The following steps create this method:
|
ADD A CLOSECURRENTALBUM METHOD |
|
|
|
|
|
Action |
Result |
|
|
|
1 |
Add the |
protected bool CloseCurrentAlbum() |
|
CloseCurrentAlbum |
{ |
|
|
|
|
method to the |
|
|
MainForm.cs source code |
|
|
window. |
|
|
|
|
2 |
Offer to save the album if it |
if (_bAlbumChanged) |
|
has been modified. |
{ |
|
|
// Offer to save the current album |
|
|
|
3 |
Define an appropriate |
string msg; |
|
message to display. |
if (_album.FileName == null) |
|
Note: We vary the mes- |
msg = "Do you want to save the " |
|
+ "current album?"; |
|
|
sage text depending on |
else |
|
whether the current album |
msg = String.Format("Do you want to " |
|
+ "save your changes to \n{0}?", |
|
|
has a name or not. |
|
|
_album.FileName); |
|
|
|
|
4 |
Display the message box |
DialogResult result |
|
and record the result. |
= MessageBox.Show(this, msg, |
|
|
"Save Current Album?", |
|
|
MessageBoxButtons.YesNoCancel, |
|
|
MessageBoxIcon.Question); |
|
|
|
5 |
Perform the action |
if (result == DialogResult.Yes) |
|
requested by the user. |
menuSave_Click(this,EventArgs.Empty); |
|
|
else if (result == DialogResult.Cancel) |
|
|
{ |
|
|
// Do not close the album |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
6 |
Close the album and return |
// Close the album and return true |
|
true. |
if (_album != null) |
|
Note: This action is only |
_album.Dispose(); |
|
_album = new PhotoAlbum(); |
|
|
performed if the Yes or No |
SetTitleBar(); |
|
button was selected. |
_bAlbumChanged = false; |
|
return true; |
|
|
|
|
|
|
} |
|
|
|
We will use this new method in three different places to ensure that the user has the option of saving any changes he or she might make to the album.
MESSAGE BOXES |
231 |
•In menuNew_Click to save the existing album before a new album is created.
•In menuOpen_Click to save the album before a new album is selected.
•In menuExit_Click to save the album before the application exits.
We will modify the handlers for the New and Open menus here. The Exit menu presents some additional issues, which we will take up in the next section. The following table continues our previous steps.
UPDATE THE HANDLERS FOR THE NEW AND OPEN MENUS
|
Action |
Result |
|
|
|
7 |
Modify the menuNew_Click |
protected void menuNew_Click |
|
method to use the |
(object sender, System.EventArgs e) |
|
CloseCurrentAlbum method. |
{ |
|
if (this.CloseCurrentAlbum() == true) |
|
|
|
|
|
|
{ |
|
|
// Make sure the window is redrawn |
|
|
this.Invalidate(); |
|
|
} |
|
|
} |
|
|
|
8 |
Modify the menuOpen_Click |
protected void menuOpen_Click |
|
method to use the |
(object sender, System.EventArgs e) |
|
CloseCurrentAlbum method. |
{ |
|
// Save the existing album, if necessary |
|
|
|
|
|
Note: The new code here |
if (this.CloseCurrentAlbum() == false) |
|
replaces the previous code in |
{ |
|
// Cancel this operation |
|
|
this method to save the current |
|
|
return; |
|
|
album. The remainder of this |
} |
|
method stays the same. |
OpenFileDialog dlg = new OpenFileDialog(); |
|
|
|
|
|
. . . |
|
|
} |
|
|
|
These changes make our application much more user-friendly by interacting with the user when they are about to discard a modified album.
TRY IT! Before moving on, create a MessageBox dialog in the menuRemove_Click method, where the current photograph is removed without any confirmation by the user. Add a question box here to verify that the user does indeed want to remove the current photo.
Another place where a message box could be used is at the beginning and end of the album. Modify the Next and Previous menus to display an information dialog whenever the user tries to move before the beginning of the album or past the end.1
For the Exit menu, life is not so easy. We will pick up this topic in the next section.
1 The interface designers among us will argue that the Previous and Next commands should be disabled at the beginning and end of the album, respectively. Why allow the user to invoke a menu item that does not work? I would not disagree, and if you prefer this approach, please go right ahead.
232 |
CHAPTER 8 DIALOG BOXES |