Down, Up, Press, Down, Up, Press…
Delphi applications can use two methods for receiving the input from the keyboard. If a user has to type something in an application, the easiest way to receive that input is to use one of the controls that automatically responds to keypresses, such as Edit.
At other times and for more general purposes, however, we can create procedures in a form that handle three events recognized by forms and by any component that accepts keyboard input. We can write event handlers for these events to respond to any key or key combination the user might press at runtime. Those event are:
OnKeyDown – called when any key on the keyboard is pressed.
OnKeyUp – called when any key on the keyboard is released.
OnKeyPress – called when a key corresponding to an ASCII character is pressed.
All the keyboard events have one parameter in common. The Key parameter is the key on the keyboard and is used to pass by reference the value of the pressed key. The Shift parameter (in the OnKeyDown and OnKeyUp procedures) indicates whether the Shift, Alt, or Ctrl keys are combined with the keystroke.
The Sender parameter references the control that was used to call the method.
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState) ; ... procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState) ; ... procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char) ;
Responding when the user presses short-cut or accelerator keys, such as those provided with menu commands, does not require writing event handlers.
Focus is the ability to receive user input through the mouse or keyboard. Only the object that has the focus can receive a keyboard event. Only one component per form can be active, or have the focus, in a running application at any given time.
Some components, such as TImage, TPaintBox, TPanel and TLabel cannot receive focus. In general, components derived from TGraphicControl are unable to receive focus. Additionally, components that are invisible at run time (TTimer) cannot receive focus.
The OnKeyDown and OnKeyUp events provide the lowest level of keyboard response. Both OnKeyDown and OnKeyUp handlers can respond to all keyboard keys, including function keys and keys combined with the Shift, Alt, and Ctrl keys.
The keyboard events are not mutually exclusive. When the user presses a key, both the OnKeyDown and OnKeyPress events are generated, and when the user releases the key, OnKeyUp event is generated. When the user presses one of the keys that OnKeyPress does not detect, only OnKeyDown event occurs, followed by OnKeyUp event.
If you hold down a key, the OnKeyUp event occurs after all the OnKeyDown and OnKeyPress events have occurred.
OnKeyPress returns a different ASCII character for ‘g’ and ‘G,’ but OnKeyDown and OnKeyUp do not make a distinction between uppercase and lowercase alpha keys.
Key and Shift parameters
Since the Key parameter is passed by reference, the event handler can change Key so that the application sees a different key as being involved in the event. This is a way to limit the kinds of characters that the user can input – to prevent users to type alpha keys, for example.
if Key in ['a'..'z'] + ['A'..'Z'] then Key := #0
The above statement checks whether the Key parameter is in the union of two sets: lowercase characters (‘a’..’z’) and uppercase characters (‘A’..’Z’). If so, the statement assigns the character value of zero to Key to prevent any input into the Edit component (for example) when it receives the modified key.
For non-alphanumeric keys, WinAPI virtual key codes can be used to determine the key pressed. Windows defines special constants for each key the user can press. For example, VK_RIGHT is the virtual key code for the Right Arrow key.
To get the key state of some special keys like TAB or PageUp we can use the GetKeyState Windows API call. The key status specifies whether the key is up, down, or toggled (on, off – alternating each time the key is pressed).
if HiWord(GetKeyState(vk_PageUp)) <> 0 then ShowMessage('PageUp - DOWN') else ShowMessage('PageUp - UP') ;
In the OnKeyDown and OnKeyUp events, Key is an unsigned Word value that represents a Windows virtual key. In order to get the character value from Key we use the Chr function. In the OnKeyPress event, Key is a Char value that represents an ASCII character.
Both OnKeyDown and OnKeyUp events use the Shift parameter, of type TShiftState, a set of flags to determine the state of the Alt, Ctrl, and Shift keys when a key is pressed.
For example, when you press Ctrl + A, the following key events are generated:
KeyDown (Ctrl) // ssCtrl KeyDown (Ctrl+A) //ssCtrl + 'A' KeyPress (A) KeyUp (Ctrl+A)
KeyPreview -> Redirecting Keyboard Events to The Form
To trap keystrokes at the form level instead of passing them to the form’s components, set the form’s KeyPreview property to True (using the Object Inspector). The component still sees the event, but the form has an opportunity to handle it first – to allow or disallow some keys to be pressed, for example.
Suppose you have several Edit components on a form and the Form.OnKeyPress procedure looks like:
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char) ; begin if Key in ['0'..'9'] then Key := #0 end;
If one of the Edit components has the Focus and KeyPreview property of a form is False, this code will not execute – in other words if the user presses the ‘5’ key the ‘5’ character will appear in the focused Edit component.
However if the KeyPreview is set to True than the form’s OnKeyPress event is executed before the Edit component sees the key that is pressed. Again if the user has pressed the ‘5’ key, the if assigns the character value of zero to Key to prevent numerical input into the Edit component.
Be sure to visit all the links in the “Suggested Reading” box!