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

12.1KEYBOARD EVENTS
We looked briefly at keyboard events in chapter 9 while discussing the TextBox class. There we used the KeyPress event to limit what characters could appear in a text box control. In this section we look more generically at keyboard events, and use them in our application to provide some quick shortcuts for the user.
There are three distinct events that occur whenever a key is pressed and released. Note that we did not say whenever a character is pressed and released. A character may involve multiple key presses. For example, the letter ‘A’ requires the use of the Shift key and the A key, typically abbreviated as Shift+A (of course, this is not true if the Caps Lock key is pressed, but you understand).
The three keyboard events are summarized in the following table. These events occur for a control in the order shown in the table whenever the control has the focus.
Keyboard events
Event |
Description |
Event Argument |
|
|
|
KeyDown |
Occurs when a key on the keyboard is pressed |
KeyEventArgs class |
|
down. |
|
KeyPress |
Occurs when a character is pressed on the |
KeyPressEventArgs class |
|
keyboard, and again each time the character is |
|
|
repeated while it continues to be pressed. |
|
KeyUp |
Occurs when a key on the keyboard is released. |
KeyEventArgs class |
|
|
|
12.1.1HANDLING THE KEYPRESS EVENT
The KeyPress event is used for generic handling of keyboard characters. Event handlers of this type receive an instance of the KeyPressEventArgs class as its event parameter. See .NET Table 12.1 for an overview of this class.
.NET Table 12.1 KeyPressEventArgs class
The KeyPressEventArgs class is the event argument class associated with the KeyPress event. This class represents the keyboard character pressed by the user. It is part of the System.Windows.Forms namespace, and inherits from the System.EventArgs class.
Handled
Public Properties
KeyChar
Gets or sets whether the keyboard character was handled. If true, then the control will not receive the character.
Gets the char value corresponding to the keyboard character pressed.
It is important to realize that this event, as well as the KeyDown and KeyUp events, is received by the control that currently has the focus. In particular, they are not normally received by parent controls such as Panel and Form objects that contain the control. Normally this is a good thing. The per-character behavior is defined by each control, with no need for parental involvement. For example, if you are handling the
384 |
CHAPTER 12 A .NET ASSORTMENT |

KeyPress event to force a text box to contain only integer values, you do not want to spend precious operating system cycles percolating this event up through the set of containing objects for the text box. A parent control such as a Panel or GroupBox will only receive a keyboard event if it specifically has the focus.
This presents a slight problem for subclasses of the ContainerControl object, and in particular the Form object. As you may recall, a ContainerControl object manages the focus for the contained controls, and does not receive the focus directly. There are plenty of situations where you would like to initiate an action from the keyboard regardless of the current control.
The good folks at Microsoft created the KeyPreview property in the Form class for just this purpose. When this property is set to true, the Form object will receive all keyboard events before they are passed to the current control. If the event handler sets the Handled property to true, then the current control will not receive the keyboard key or corresponding character.
Let’s create an example of this in our MyPhotos program by handling the plus ‘+’ and minus ‘–’ characters. The plus character will display the next photograph in the album, while the minus will display the previous photograph. We would like these to occur at the Form level, and not just in our Panel object where the image is displayed. The following table presents the steps required for this change.
Set the version number of the MyPhotos application to 12.1.
MAP THE PLUS AND MINUS KEYS TO THE NEXT AND PREVIOUS MENUS
|
Action |
Result |
|
|
|
1 |
In the MainForm.cs [Design] window, |
|
|
modify the KeyPreview property for the |
|
|
MainForm object to be true. |
|
|
|
|
2 |
Override the protected OnKeyPress |
protected override void OnKeyPress |
|
method in the MainForm.cs source file. |
(KeyPressEventArgs e) |
|
|
{ |
|
|
|
3 |
When a plus sign ‘+’ is pressed, invoke |
switch (e.KeyChar) |
|
the Next menu handler. |
{ |
|
|
case '+': |
|
|
e.Handled = true; |
|
|
menuNext.PerformClick(); |
|
|
break; |
|
|
|
4 |
When a minus sign ‘-’ is pressed, invoke |
case '-': |
|
the Previous menu handler. |
e.Handled = true; |
|
|
menuPrevious.PerformClick(); |
|
|
break; |
|
|
|
5 |
For all other characters, do nothing. This |
default: // do nothing |
|
permits the character to be sent to child |
break; |
|
controls. |
} |
|
|
|
|
|
|
6 |
Don’t forget to call the base class at the |
base.OnKeyPress(e); |
|
end of the method. |
} |
|
|
|
KEYBOARD EVENTS |
385 |

We could have used an if statement in this code, especially with only two items to check. Since we may add behavior for additional characters in the future, a switch statement seems like a good idea. Note how we used the MenuItem.PerformClick method to simulate a user click of the appropriate menu. We could have called the Click event handler directly, of course, but this solution is a bit more elegant.
It should be noted here that not all characters are received by the KeyPress and other keyboard events. Depending on the control, some characters may be preprocessed and unavailable by default in this event. The protected IsInputKey and IsInputChar methods can be used to determine whether a specific character is preprocessed in a derived control.
Let’s move on to the KeyDown and KeyUp events.
12.1.2HANDLING OTHER KEYBOARD EVENTS
The KeyDown and KeyUp events are useful to fine-tune an application’s behavior as keyboard keys are pressed and released, and for handling noncharacter keys such as the function or arrow keys. Handlers for these events receive an instance of the
KeyEventArgs class as their event parameter. This class is summarized in .NET Table 12.2.
.NET Table 12.2 KeyEventArgs class
The KeyEventArgs class is the event argument class associated with the KeyDown and KeyUp events. This class represents the keyboard key pressed down or released by the user. It is part of the System.Windows.Forms namespace, and inherits from the System.EventArgs class.
|
Alt |
Gets whether the Alt key was pressed. |
|
Control |
Gets whether the Ctrl key was pressed. |
|
Handled |
Gets or sets whether the event was handled. |
|
KeyCode |
Gets the specific keyboard key pressed as a value in the Keys |
|
|
enumeration. |
Public |
KeyData |
Gets the combination of keyboard keys pressed at the same |
Properties |
|
time using the Keys enumeration values. |
|
KeyValue |
Gets the int character value corresponding to the keyboard |
|
|
combination. |
|
Modifiers |
Gets the combination of modifier keys pressed or released |
|
|
using the Keys enumeration values. This is a combination of the |
|
|
Ctrl, Shift, and Alt values, or None if no keys were pressed. |
|
Shift |
Gets whether the Shift key was pressed. |
|
|
|
We will demonstrate the use of the KeyEventArgs class by setting the Page Up and Page Down keys to invoke the Previous and Next menus, respectively. We will use the KeyDown event for this purpose. We have already set the KeyPreview property to receive keyboard events in our Form, so all we have to do is override the OnKeyDown method here.
386 |
CHAPTER 12 A .NET ASSORTMENT |