Reading Values from the Keyboard

To code the Lunar Lander game, you first need some way to capture keystrokes from the user. You can always use text boxes to read from the user, as you did in Chapter 6, “Creating a Windows Program: The Visual Critter.” However, in a game environment, a text box is distracting. Also, text boxes are generally concerned with entire phrases of text and do not handle special keys such as arrow keys and function keys well. Fortunately, C# provides features that make it easy for your programs to read input directly from the keyboard.

Introducing the Key Reader Program

The form object features three events that can be used to determine which key a user has pressed. The KeyDown event fires whenever a key is being held down. The KeyUp event is triggered when the user releases a key. The KeyPressed event occurs after the key is pressed and released. The keyboard events are used to look at the keyboard in different ways. The Key Reader program shown in Figures 7.2 through 7.4 demonstrates some of these differences between the KeyDown() and KeyPressed() methods. Look at the program first, and I’ll explain why the various responses seem to disagree.

Figure 7.2. When the user presses lowercase a, both events display the value a, but they disagree on capitalization.


Figure 7.3. If the user presses a control key, only the KeyDown event can interpret the value.


Figure 7.4. The KeyDown event can also respond to arrow keys, function keys, and other special keyboard inputs.


Setting Up the Key Reader Program

The setup of the Key Reader program is very straightforward. The visual layout of the program includes three labels. I named two of the labels lblDown and lblPressed. These two labels show information from the KeyDown and KeyPressed events, respectively.

I didn’t rename the third label; instead, I left it as the default name suggested by the Designer (label1). Although renaming is never a bad idea, there are a few objects you don’t need to rename. If you have a label meant entirely for displaying text to the user, if that label will never have any events activated and you will never refer to the label, you don’t need to worry about giving it a name. All these conditions are true for the label that holds the instructions to the user, so I didn’t give it a more explicit name. If you don’t want to worry about these rules, just rename every object in your programs, and you’ll be safe.

There are no other components on the form. I did set one of the form’s properties, however. The KeyPreview property determines whether a form will check keystrokes that are being sent to components on that form. For example, if you have a text box on the form, you might not want to trap for keyboard input when that text box is currently selected. Set KeyPreview to true to ensure that all keyboard presses are sent to the form handlers you will be writing shortly.

Coding the KeyPress Event

The KeyPress event occurs after the user has pressed and released a button on the keyboard. You usually trap for the KeyPress event when you want to know which of the alphanumeric keys was pressed. The KeyPress event is not the default event for the form object, so to write code for it, you need to be sure that the form is visible in the Designer. Then choose the events list (with the lightning icon) in the Properties window. You see a list of properties the form recognizes. The KeyDown, KeyUp, and KeyPress events are listed on this screen. Choose the KeyPress event to code first, because it is the simplest. Here’s the code produced by the Designer:

private void KeyReader_KeyPress(object sender,
          System.Windows.Forms.KeyPressEventArgs e) {
}  // end KeyPress

The KeyReader_KeyPress() method generated by the Designer provides two objects. The first is an object named sender, which refers to the object that triggered the event. Most event handlers have this parameter, although you will not need it the projects for this chapter..

You can use sender if several buttons call the same event handler. Inside that event handler, you can do different things, based on which button called the event.

The other parameter is named e and is extremely useful. The e parameter is an instance of the KeyPressEventArgs class. It stores interesting information about what kind of keyboard event just occurred. Most event handlers pass an object as a parameter. Different kinds of event create different objects, but all of these event parameters are used to provide information about the event. The event objects are usually called e. Often, your event-handling code starts by looking at some parameters of e. Figure 7.5 shows the main help screen for KeyPressEventArgs so you can get a feel for its capability. Of course, you’ll want to look it up in the documentation as you program with it.

Figure 7.5. The KeyPress-EventArgs object has properties and methods describing which key was pressed.


Whenever you are trying to learn about a new kind of event handler, take a careful look at the parameters sent when that event is triggered. You can find these parameters either through the online help or by having the Designer create you an event of whatever type you’re interested in. The parameters are often classes that provide all kinds of useful information about the event.

I wanted to copy the value the user typed to lblPress. The code is simplistic:

private void KeyReader_KeyPress(object sender,
              System.Windows.Forms.KeyPressEventArgs e) {
       lblPress.Text =  "Press: " + Convert.ToString(e.KeyChar);
     }  // End KeyPress

e.KeyChar refers to one of the properties of the KeyPressEventArgs object. The KeyChar property returns the key the user just tried to type. KeyPress events are good at retrieving the same kinds of values you might see in a text box (although one at a time). You cannot use the KeyPress event to look for control keys, arrow keys, or function keys. These keys simply do not trigger the KeyPress event, so you can’t use a KeyPress() method to look for them.

NOTE

IN THE REAL WORLD

After all the advice about long, descriptive variable names, you might wonder why a variable as important as the KeyPressEventArgs has a name like e. I can’t be sure what was happening in Redmond, Washington, when the C# developers were planning their language, but this is one of several areas where C# looks suspiciously like another language, called Java. Most event handlers in Java pass an event object named e (for event). In C#, it isn’t called an event object, but the variable is used in exactly the same way and is still named e. Certainly, the key people involved in the development of C# were aware of Java, and most were probably fluent in the language. It’s not surprising that many of Java’s best ideas found their way into C#–but maybe I’m being cynical. Maybe e is shorthand for KeyPressEventArgs.

The KeyPress event is great when you want to watch what the user is typing. For example, you might have a text box where you want the user to enter only numbers. You can use the KeyPress() method to check each key as it is pressed and ensure that it is a number. The Backspace key, arrow keys, Alt key, Ctrl key, and Shift key should operate normally in these situations, without triggering the KeyPress event.

The e.KeyChar property returns a variable of the char type, described briefly in Chapter 2, “Branching and Operators: The Math Game.” A char contains only one letter. chars aren’t very useful on their own, so usually you convert them to strings before you do anything else with them. I did so in this case, with your old friend the convert object. I then added the value from the key press to the appropriate label’s text property.

Coding the KeyDown Event

Having three events for handling keyboard input might seem redundant. However, KeyDown and KeyUp act differently than KeyPressed and are used in different circumstances. KeyDown is activated whenever a key is held down. If the key is held down for a long time, the event is called continuously. The KeyUp event is triggered whenever the user releases the key. The KeyDown event is very useful for game programming because it can be triggered continuously and can trap for any key on the keyboard, including the function keys and arrow keys. In addition to the differences in timing, the KeyDown and KeyUp keys are different from KeyPress because they are more closely mapped to the hardware than the KeyPress event. The KeyPress event is used to determine what the user intended to type. KeyUp and KeyDown can determine exactly what key is being held down at any one time. This is a subtle but powerful difference. Look at the template code provided for the KeyDown event:

private void KeyReader_KeyDown(object sender,
        System.Windows.Forms.KeyEventArgs e) {
} // end KeyDown

You might miss something important (I did, on the first attempt). KeyDown looks much like KeyPressed, and both have a parameter named e. The es are not exactly the same. The e in KeyDown is an instance of the KeyEventArgs object, which is a different beast than the KeyPressedEventArgs object. As you can see from Figure 7.6, the KeyEventArgs object is the more powerful of the two objects and sports interesting properties.

Figure 7.6. The KeyEventArgs object has a longer list of features than KeyPressedEvents.


The code in KeyDown is much like that in KeyPressed, but I took advantage of the more powerful event argument object in KeyDown. KeyEventArgs does not have a KeyChar property. Instead, it returns an integer code named KeyValue. This code describes which key on the keyboard was pressed and also stores, in a special binary structure, information about which modifier keys (the keys that are meant to be pressed with another key, such as Shift, Ctrl, and Alt) are also pressed down. Getting meaningful information out of the KeyValue property can be very ugly, but KeyEventArgs comes with some other, more friendly properties that make it much easier. KeyCode describes which key was pressed, and the Control, Alt, and Shift properties return true or false values describing whether the indicated modifier is currently pressed. Generally, you check the KeyCode property to determine which key was pressed.

NOTE

IN THE REAL WORLD

The KeyPressed event handler is most useful in game situations, where it is usually used to trap for arrow keys and function keys. The KeyUp and KeyDown event handlers are useful when you want to check for control or alt sequences in your programs. I once wrote a paint program that allowed the user to change colors with a control key (control-B turned the pen blue, for example) My KeyUp event first checked whether the control key was currently being held down. If so, it checked whether KeyCode corresponded to the B key. If so, it turned the pen blue.

Determining Which Key Was Pressed

The KeyCode returns a special value that relates to the hardware location of whatever key the user pressed. For example, on many keyboards (but not all) the left arrow key might be mapped as key number 123. This information isn’t that useful to a programmer, who wants to know whether the user hit the left arrow. .NET provides a special set of values with names, called an enumeration, so that you don’t have to remember which particular number is associated with each key. Instead, you find the appropriate name from the list of names that pops up when you try to complete the code. All the key codes are stored in an enumeration named Keys. The KeyCode() method returns a value of the Keys enumeration, and you can compare it to other values from the enumeration. For an example, look at the code I added to the KeyDown event for the Key Reader program:

private void KeyReader_KeyDown(object sender,
        System.Windows.Forms.KeyEventArgs e) {
      lblDown.Text = "Down: " +
          Convert.ToString(e.KeyCode);
      if (e.KeyCode == Keys.ShiftKey){
        MessageBox.Show("That is one shifty character");
      } // end if
    } // end KeyDown

The first thing you might notice is that I sent the value of e.KeyCode to lblDown, much as I did in KeyDown. The if statement compares the value of e.KeyCode to the Shift keys, which are represented in the Keys enumeration as Keys.ShiftKey.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.3.175