- •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
The new menu structure for the MyPhotos application
Menu Bar |
Menu Item |
Shortcut |
Description |
|
|
|
|
|
|
|
File |
Ctrl+N |
Create a new photo album (the existing album is saved if |
|
|
|
|
necessary). |
|
|
Open |
Ctrl+O |
Open an existing photo album file. |
|
File |
Save |
Ctrl+S |
Save the current album. |
|
|
Save As |
|
Save the current album in a new file. |
|
|
Exit |
|
Exit the application. It should offer to save the current album |
|
|
|
|
if any changes have been made. |
|
|
|
|
|
|
Edit |
Add |
Ctrl+A |
Add one or more photos to the album. |
|
Remove |
Ctrl+R |
Remove the displayed photo from the album. |
||
|
||||
|
|
|
|
|
|
Image |
|
We will leave this menu as already implemented. This |
|
|
|
|
contains a submenu indicating how the image should be |
|
View |
|
|
displayed. |
|
|
|
|
||
|
Next |
Ctrl+Shift+N |
Display the next image in the album, if any. |
|
|
Previous |
Ctrl+Shift+P |
Display the previous image in the album, if any. |
|
|
|
|
|
It is tempting to use our own terminology and establish our own conventions here. For example, why not use an “Album” main menu instead of the File menu, or have Ctrl+N as the shortcut for View-Next rather than File-New. The short answer: don’t do it. Computer users appreciate familiarity and resist change (so do most consumers and small children, but I digress). The File menu is standard in most Windows applications, and Ctrl+N is used for creating a new object (be it a document in Microsoft Word, or an image in Adobe PhotoDeluxe). Unless you are intending your application to be somewhat contrary, use existing standards where possible.
So even though Ctrl+N and Ctrl+P would make nice shortcuts for Next and Previous, we will stick with Ctrl+N for New and save Ctrl+P for when we add printing in part 3 of the book. We have already looked at menus in chapter 3, so this section will remove the existing Load menu and add our new menu structure.
Set the version number of the MyPhotos application to 6.1.
REMOVE THE LOAD MENU
|
Action |
Results |
|
|
|
1 |
In the MainForm.cs [Designer] |
The menu and its properties are removed from the |
|
window, remove the Load menu |
program. |
|
from the File menu. |
Note: The menuLoad_Click method remains in |
|
How-to |
|
|
the source file. We will make use of this code |
|
|
a. Right-click the menu item. |
when we handle the Add menu later in this chapter. |
|
b. Select Delete. |
|
|
Alternately |
|
|
Click the menu item and press the |
|
|
Delete key. |
|
|
|
|
DESIGN ISSUES |
163 |
The creation of our menu requires the procedures we saw in chapter 3. The following table creates and positions the new menu items required in our application. The subsequent sections will look at the required event handlers for these menu items.
CREATE OUR NEW MENU
|
|
|
|
|
Action |
|
|
|
|
Result |
|
|
|
|
|
|
|
|
|
|
|
||
2 |
Create the new File menu structure, as shown in the |
The new settings appear in the |
|||||||||
|
following table. |
|
|
|
|
|
|
|
window and are reflected in the |
||
|
|
|
|
|
Settings |
|
|
|
|
MainForm.cs file. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MenuItem |
|
Property |
|
Value |
|
||||
|
|
New |
|
(Name) |
|
menuNew |
|
||||
|
|
|
|
|
Shortcut |
|
CtrlN |
|
|||
|
|
|
|
|
Text |
|
&New |
|
|||
|
|
Open |
|
(Name) |
|
menuOpen |
|
||||
|
|
|
|
|
Shortcut |
|
CtrlO |
|
|||
|
|
|
|
|
Text |
|
&Open… |
|
|||
|
|
separator |
|
|
|
|
|
|
|
|
|
|
|
Save |
|
(Name) |
|
menuSave |
|
||||
|
|
|
|
|
Shortcut |
|
CtrlS |
|
|||
|
|
|
|
|
Text |
|
&Save |
|
|||
|
|
Save As |
|
(Name) |
|
menuSaveAs |
|
||||
|
|
|
|
|
Text |
|
Save &As... |
|
|||
|
|
separator |
|
|
|
|
|
|
|
|
|
|
|
Exit |
|
as before |
|
|
|
|
|
||
|
Note: Recall that a menu separator is added by creat- |
|
|||||||||
|
ing a MenuItem with the Text property set to a single |
|
|||||||||
|
dash ‘-‘. |
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
||
3 |
Define a new Edit menu between the existing File and |
Note: This space intention- |
|||||||||
|
View menus. |
|
|
|
|
|
|
|
ally left blank. |
||
|
How to |
|
|
|
|
|
|
|
|
||
|
a. Click the “Type Here” entry on the menu bar, to the |
|
|||||||||
|
right of the existing View menu. |
|
|||||||||
|
b. Enter the name “&Edit” in this space and press |
|
|||||||||
|
Enter. |
|
|
|
|
|
|
|
|
||
|
c. Using the mouse, click on the new Edit menu and |
|
|||||||||
|
drag it left to appear between the File and View |
|
|||||||||
|
menus. |
|
|
|
|
|
|
|
|
||
|
|
|
|
|
Settings |
|
|
||||
|
|
|
|
Property |
|
Value |
|
||||
|
|
|
|
(Name) |
|
menuEdit |
|
||||
|
|
|
|
|
Text |
|
&Edit |
|
|||
|
Note: If you are not using Visual Studio, create the new |
|
|||||||||
|
menu manually, and set the Index property for each of |
|
|||||||||
|
the File, Edit, and View menus to 0, 1, and 2 respectively. |
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
164 |
CHAPTER 6 COMMON FILE DIALOGS |
CREATE OUR NEW MENU (continued)
|
|
|
|
|
Action |
|
|
|
Result |
|
|
|
|
|
|
|
|
|
|
|
|
4 |
Add the dropdown menu for the Edit menu. |
|
||||||||
|
|
|
|
|
Settings |
|
|
|
|
|
|
|
|
MenuItem |
Property |
Value |
|
||||
|
|
|
Add |
(Name) |
menuAdd |
|
||||
|
|
|
|
|
Shortcut |
CtrlA |
|
|||
|
|
|
|
|
Text |
&Add |
|
|||
|
|
|
Remove |
(Name) |
menuRemove |
|
||||
|
|
|
|
|
Shortcut |
CtrlR |
|
|||
|
|
|
|
|
Text |
&Remove |
|
|||
|
|
|
|
|
|
|
|
|
|
|
5 |
Create the View menu structure: |
|
|
|
|
|||||
|
|
|
|
|
Settings |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
MenuItem |
|
Property |
|
Value |
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Image |
|
as before |
|
|
|
|
|
|
|
|
separator |
|
|
|
|
|
|
|
|
|
|
Next |
|
(Name) |
|
menuNext |
|
||
|
|
|
|
|
Shortcut |
|
CtrlShiftN |
|
||
|
|
|
|
|
Text |
|
&Next |
|
||
|
|
|
Previous |
|
(Name) |
|
menuPrevious |
|
||
|
|
|
|
|
Shortcut |
|
CtrlShiftP |
|
||
|
|
|
|
|
Text |
|
&Previous |
|
||
|
|
|
|
|
|
|
|
|
|
|
The source code generated here does not use anything we have not already seen and discussed in chapter 3, so we will move right along and start processing our new menus.
6.1.2ADDING CLASS VARIABLES
Before we can implement any event handlers for our menus, and in particular before
we can open and save album files, we must have a PhotoAlbum at our disposal in the MainForm class. In chapter 5 we added a reference to the MyPhotoAlbum library in the MyPhotos project, so this library is already available to our application.
Here we will add some protected variables to hold the displayed album and whether the user has made any changes to this album.
|
|
CREATE SOME CLASS VARIABLES |
|
|
|
|
|
|
Action |
|
Result |
|
|
|
|
1 |
At the top of the |
|
using Manning.MyPhotoAlbum; |
|
MainForm.cs file, indicate |
|
Note: Since we already reference the library (remember, |
|
that we are using the |
|
|
|
|
no header files required), we could write the fully quali- |
|
|
MyPhotoAlbum |
|
|
|
|
fied name every time we reference an object from the |
|
|
namespace. |
|
|
|
|
library. Typing Manning.MyPhotoAlbum.PhotoAlbum |
|
|
|
|
|
|
|
|
repeatedly is not my idea of fun, so adding a using direc- |
|
|
|
tive here makes sense. |
|
|
|
|
DESIGN ISSUES |
165 |
CREATE SOME CLASS VARIABLES (continued)
|
Action |
Result |
|
|
|
2 |
Within the MainForm class, |
protected PhotoAlbum _album; |
|
add a protected album |
|
|
variable _album. |
|
|
|
|
3 |
Add a protected boolean |
protected bool _bAlbumChanged = false; |
|
called _bAlbumChanged to |
Note: This will be useful when deciding whether to save |
|
track when an album is |
|
|
an existing album before loading a new one or closing the |
|
|
modified. |
|
|
application. If no changes have occurred, then we will |
|
|
|
|
|
|
know to not save the album. |
|
|
|
4 |
Create an empty album at |
public MainForm() |
|
the end of the MainForm |
{ |
|
constructor. |
. . . |
|
_album = new PhotoAlbum(); |
|
|
|
|
|
|
} |
|
|
|
These variables are required to implement all of our new menu items in this chapter. With these in place, it is time to do just that.
6.2MULTIPLE FILE SELECTION
Now that we have an album in our MainForm class, albeit an empty one, we can add photos to it. In previous chapters, we allowed the user to read in a single photo, first using a button and later with a menu item. In our new structure, this has been replaced by the ability to add multiple photos to the album or remove the current photo from the album. Since this code builds on our original Load handler, it is a good place to begin.
As you would expect, we will provide Click handlers for both the Add and Remove items. The Add menu should allow one or more photos to be selected and added to the album, while the Remove menu should delete the currently displayed photo from the album. The Add menu will use the Multiselect property of the OpenFileDialog class, and is where our catchy section title comes from.
6.2.1ADDING IMAGES TO AN ALBUM
In chapter 3, the Click handler for the Load menu permitted a single file to be selected using the OpenFileDialog class. This made sense when only a single image was managed by the application. In this chapter, the idea of an album permits multiple images to be present at the same time. As a result, our user should also be able to load multiple images at once. This is again done using the OpenFileDialog class, so the code for this handler will be similar to the Click event handler for the
Load menu from chapter 3. The Multiselect property is provided by the OpenFileDialog class to indicate whether multiple files can be selected in the dialog. This and other members specific to this class are summarized in .NET Table 6.1.
166 |
CHAPTER 6 COMMON FILE DIALOGS |