the ASCII codes in this tutorial will work with borland kylix, but virtual-key codes will not
We've already covered keyboard control with DelphiX, but you're probably thinking, 'Shouldn't there be a way to do this without DelphiX?'. Well there is, and it's pretty simple too.
Depending on what you're wanting to do, we have two options. The first would be to use ASCII codes and the second would be to make use of Delphi's VK_... command. The later of the two will not work in Kylix as it is specific to the Windows operating system. Still, let's discuss both of these options.
ASCII
For every single key on the keyboard, including control keys, and
also lower and uppercase letters, an ASCII code exists. We can use this
fact to allow our program to check to see if a particular key has been
pressed. Obviously we need to know the ASCII code for the key we're
looking to check for, but never fear for below you will find a list that
shows just that. I've included most keys that you'll need, and its decimal
value.
Key |
Decimal Value |
Key |
Decimal Value |
A |
65 |
Numpad + |
107 |
If there is something that is not listed here that you would want to use you can actually find out its ASCII value by simply creating a new application and putting the following code in your OnKeyDown procedure:
ShowMessage(VarToStr(Key));
This will have the effect of bringing up a window telling you the ASCII value of the key you just pressed. Simple.
Anyway, getting back to the task at hand, if you've been following the DelphiX tutorials you've already come across one of these ASCII codes in tutorial three on animation. There we used one of these codes to allow us to quit our application as soon as the user pressed Esc. The code for this looked like that shown below.
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if key = 27 then close;
end;
Here we used the FormKeyDown procedure which allowed us to take the ASCII code number of the Esc key (27), and close our program when the key is pressed. However if you recall, earlier I said that every key on the keyboard has an ASCII code. While this is true, in Delphi an OnKeyDown procedure will not distinguish between upper and lower case letters, instead always returning the number for the upper case letter. If you want to be able to tell the difference between a user pressing say a 'A' and an 'a' then you need to use the OnKeyPress event. The disadvantage of using an OnKeyPress event is that it cannot check to see if other keys are being pressed at the same time (such as the Shift or Ctrl key), and only one event is processed on every press of a key. Also, if we don't use OnKeyPress, we can process both an OnKeyDown and OnKeyUp event so that we can make something different happen when the user lets go of the key.
The way we tell if a key is being pressed is also different between the OnKeyPress event and an OnKeyDown/Up event. Say we wanted to have our sprite moving left when the user holds down the 'a' key and right when the user holds down the 'd' key, we'd do the following with an OnKeyPress event:
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = 'a' then Sprite.Left := Sprite.Left - 1;
if Key = 'd' then Sprite.Left := Sprite.Left + 1;
end;
You can see that we've actually specified the letter which we want to check for here, not its ASCII code. If the user had left Caps Lock on then this procedure would not do anything as the Key value being returned would be 'A' not 'a' and 'D' not 'd'. With the OnKeyDown event, we refer to a key by its ASCII code as follows:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if key = 65 then Image1.Left := Image1.Left - 1;
if key = 68 then Image1.Left := Image1.Left + 1;}
end;
For most of you, the OnKeyDown and OnKeyUp events are the best to go for as it is not usually desirable to check for upper or lowercase letters, but the ability to check for multiple keys being pressed at the same time, is.
So you can see that handling keyboard events is very simple, as long as you have an ASCII code to hand. It is however often easier to remember the VK_ commands which we'll discuss next.
Virtual Key-Codes (VK)
With this command we can check for a wide variety of keys being
pressed. For example, we can check if the left arrow key has being
pressed by adapting our OnKeyDown procedure to look like the following.
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = vk_left then Image1.Left := Image1.Left - 1;
end;
Far simpler to remember I'm sure you'll agree, but if you're a Kylix user you'll have to stick to the ASCII codes. We are limited in what we can do here though because Delphi only lets us use certain control keys, not any alphabetical, numerical or other character keys, except for the ones on the numpad. The online 'help' that comes with Delphi only tells you about a few of the supported VK commands namely, VK_UP, DOWN, LEFT, RIGHT, INSERT, DELETE, HOME, END, NEXT and PRIOR. Most of these are self-explanatory in their description, but NEXT and PRIOR are less so. PRIOR refers to the 'Page Up' key, and NEXT the 'Page Down' key. So what are the others you can use? Well, the list is fairly extensive as you can see below. I've included the ones we've already mentioned, for completeness. You should find all the keys you might want (and a few you probably won't) below. The Windows SDK help shows you all these and a few more, but many are not actually supported by Delphi.
VK_UP |
Up Arrow Key |
Maybe you'll finally find a good use for the Scroll Lock Key! It should be noted that you can't use these VK combinations with the OnKeyPress event.
Before I finish, you'll find that the source code for this tutorial is a version of the last tutorial's code which allows us to now control our pacman sprite with the keys. All we've done here is take the StartX := StartX + 1; line out of our OnTimer procedure and placed it in an OnKeyDown procedure like that shown below.
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = 37 then StartX := StartX - 1; // Left
if Key = 38 then StartY := StartY - 1; // Up
if Key = 39 then StartX := StartX + 1; // Right
if Key = 40 then StartY := StartY + 1; // Down
end;
Simple. Now you're in control. It can jerk a bit, but putting the interval of the TTimer down to about 1 will help a little. We'll come up with a better way of doing things in the tutorial after next. I've used the ASCII codes of the arrow keys instead of the VK commands so that the code works with both Kylix and Delphi, but it's up to you what you use if you're using just Delphi. So that about raps it up really. As always, if you have any questions, please e-mail me or leave a message on the board.
