
- •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

MAP THE PAGE DOWN AND PAGE UP KEYS TO THE NEXT AND PREVIOUS MENUS
|
Action |
Result |
|
|
|
1 |
In the MainForm.cs source |
protected override void OnKeyDown |
|
window, override the |
(KeyEventArgs e) |
|
OnKeyDown method. |
{ |
|
|
|
|
|
|
2 |
Invoke the Previous menu |
switch (e.KeyCode) |
|
when the Page Up key is |
{ |
|
pressed down. |
case Keys.PageUp: |
|
e.Handled = true; |
|
|
|
|
|
|
menuPrevious.PerformClick(); |
|
|
break; |
|
|
|
3 |
Invoke the Next menu |
case Keys.PageDown: |
|
when the Page Down key |
e.Handled = true; |
|
is pressed down. |
menuNext.PerformClick (); |
|
break; |
|
|
|
|
|
|
|
4 |
Do nothing by default. |
default: // do nothing |
|
|
break; |
|
|
} |
|
|
base.OnKeyDown(e); |
|
|
} |
|
|
|
Run the program to see how this code works. Open an album and make sure all four keys we handled work as expected.
TRY IT! Modify the OnKeyDown method to recognize the Home and End keys as well. Have the Home key display the first photograph in the album, and the End key display the last.
As an alternate approach, modify this method so that Shift+PageDown will display the last photograph, and Shift+PageUp the first photograph in the album. To implement this change, you will need to modify the method to check the Shift property within the PageUp and PageDown case blocks.
That’s probably enough for our quick look at keyboard events. Let’s also take a look at mouse events.
12.2MOUSE EVENTS
The mouse device has gone through its own little evolution since it was invented by Xerox Corporation almost 30 years ago. The number of buttons have varied from one to three, and the shape has evolved from a rather uncomfortable rectangle to the hand-fitting contours found in most modern versions. The mouse wheel is a rather recent addition, permitting automated scrolling from the comfort of your mouse. An even newer addition is a five-button mouse, with the extra buttons intended for backward/forward navigation in applications such as web browsers.
Regardless of the type mouse you own, the possible events in .NET are the same. In chapter 8 we used the MouseMove event to update the PixelDlg form as the
MOUSE EVENTS |
387 |
mouse pointer changed position. In the previous chapter we used the MouseDown event in our MonthCalendar control to pop up a context menu when the user clicked on a date. Here, we look at mouse events in general.
Mouse events are somewhat similar to keyboard events. Mouse buttons go down and up just like keyboard keys, and the events MouseDown and MouseUp occur accordingly. Since the mouse also controls the mouse pointer, there are events related to pointer movement as well. The complete list of mouse events is shown in the following table. These events occur with respect to a specific control.
Mouse events
Event |
Description |
Event Argument |
|
|
|
MouseDown |
Occurs when a mouse button is pressed down while |
MouseEventArgs class |
|
the pointer is over the control. |
|
MouseEnter |
Occurs when the mouse pointer enters the control. |
MouseEventArgs class |
MouseHover |
Occurs when the mouse pointer remains, or hovers, |
MouseEventArgs class |
|
over a control for a configurable amount of time. |
|
MouseLeave |
Occurs when the mouse pointer leaves the control. |
MouseEventArgs class |
MouseMove |
Occurs when the mouse pointer moves over the |
MouseEventArgs class |
|
control. |
|
MouseUp |
Occurs when a mouse button is released while the |
MouseEventArgs class |
|
pointer is over the control. |
|
MouseWheel |
Occurs when the mouse wheel moves while the |
MouseEventArgs class |
|
control has focus. The read-only |
|
|
MouseWheelPresent property in the |
|
|
SystemInformation class indicates whether the |
|
|
operating system believes a mouse wheel is |
|
|
present. |
|
|
|
|
12.2.1THE MOUSEEVENTARGS CLASS
As you can see from the table, all mouse event handlers received an instance of the MouseEventArgs class as their event parameters. A summary of this class appears in
.NET Table 12.3. We will illustrate mouse events a few different ways in this chapter. Our first example will combine the keyboard support we examined in the previous chapter with mouse events.
12.2.2HANDLING MOUSE EVENTS
Since we have seen a couple of mouse events before, let’s make a change that involves both keyboard and mouse events. Keeping with our theme of the Previous and Next menus, let’s modify the mouse button behavior in our Panel control so that the left and right buttons invoke the Previous and Next menus, respectively, when the Ctrl key is pressed.
388 |
CHAPTER 12 A .NET ASSORTMENT |

.NET Table 12.3 MouseEventArgs class
The MouseEventArgs class is the event argument class associated with the mouse events. This class represents information about the mouse device and the mouse pointer position when the event occurs. It is part of the System.Windows.Forms namespace, and inherits from the System.EventArgs class.
|
Button |
Gets the MouseButtons enumeration value corresponding to |
|
|
the mouse button pressed by the user. |
|
Clicks |
Gets the number of times the mouse button was pressed and |
|
|
released. Note that the DoubleClick event should normally be |
|
|
used to process double-clicks of the mouse. |
Properties |
Delta |
Gets a signed integer representing the number of detents the |
|
||
|
|
mouse wheel has rotated. A detent is a rotation of the mouse |
|
|
wheel by one notch. |
|
X |
Gets the x-coordinate of the current mouse pointer position. |
|
Y |
Gets the y-coordinate of the current mouse pointer position. |
|
|
|
This requires handling both the KeyDown and KeyUp events to track when the Ctrl key is held down, and the MouseDown event to map a mouse click to the appropriate menu. Once we have done this, we will discover some additional changes that will improve our interface. First, let’s take a look at how to track the Ctrl key.
Set the version number of the MyPhotos application to 12.2.
TRACK WHEN THE CTRL KEY IS HELD DOWN
|
Action |
Result |
|
|
|
1 |
In the MainForm.cs window, create a |
private bool ctrlKeyHeld = false; |
|
boolean field to identify when the Ctrl |
|
|
key is held down. |
|
|
|
|
2 |
Modify the OnKeyDown method to set |
protected override void OnKeyDown |
|
this field to true. |
(KeyEventArgs e) |
|
|
{ |
|
|
switch (e.KeyCode) |
|
|
{ |
|
|
. . . |
|
|
case Keys.ControlKey: |
|
|
ctrlKeyHeld = true; |
|
|
break; |
|
|
. . . |
|
|
} |
|
|
. . . |
|
|
} |
|
|
|
MOUSE EVENTS |
389 |

TRACK WHEN THE CTRL KEY IS HELD DOWN (continued)
|
Action |
Result |
|
|
|
3 |
Override the OnKeyUp method to set |
protected override void OnKeyUp |
|
this field to false. |
(KeyEventArgs e) |
|
|
{ |
|
|
switch (e.KeyCode) |
|
|
{ |
|
|
case Keys.ControlKey: |
|
|
ctrlKeyHeld = false; |
|
|
break; |
|
|
default: // do nothing |
|
|
break; |
|
|
} |
|
|
base.OnKeyUp(e); |
|
|
} |
|
|
|
Note that we use the ControlKey value from the Keys enumeration in our switch statement. There is also a Control value for the Keys enumeration that is used for the Modifiers property of the KeyEventArgs class which will not work here.
With this in place, we can now use the MouseDown event to invoke the Next and Previous menus when the Ctrl key is held. Continuing the previous steps:
MODIFY THE MOUSE BEHAVIOR WHEN THE CTRL KEY IS HELD
|
Action |
Result |
|
|
|
4 |
In the MainForm.cs |
private void pnlPhoto_MouseDown |
|
[Design] window, add a |
(object sender, System.Windows. |
|
MouseDown event handler |
Forms.MouseEventArgs e) |
|
{ |
|
|
for the Panel control. |
|
|
|
|
|
|
|
5 |
If the Ctrl key is currently |
if (ctrlKeyHeld) |
|
held down, see which |
{ |
|
button was pressed. |
switch (e.Button) |
|
{ |
|
|
|
|
|
|
|
6 |
For the left mouse button, |
case MouseButtons.Left: |
|
invoke the Previous menu. |
menuPrevious.PerformClick(); |
|
|
break; |
|
|
|
7 |
For the right mouse button, |
case MouseButtons.Right: |
|
invoke the Next menu. |
menuNext.PerformClick(); |
|
|
break; |
|
|
|
8 |
Do nothing if any other |
default: // do nothing |
|
button is pressed. |
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
This looks good, right? Well, not exactly. If you run the program, you’ll find that this code mostly works as long as you do nothing else while the Ctrl key is pressed. When you press the right mouse button, the next photo is displayed but the context menu also pops up. In addition, if you use a keyboard accelerator such as Ctrl+O, or you
390 |
CHAPTER 12 A .NET ASSORTMENT |