1
votes

I use readkey command twice. It works fine on the first time but refuses to work in the second one. I'd like that program waits for my key press but the program ends itself.

code:

program window1;

uses crt;

var x,y:integer;

begin

clrscr;
window(1,1,80,25);
readkey;

//writting just window borders
for x:=1 to 80 do
 for y:=1 to 25 do
 begin
   if (x >= 2) and (x <= 79) and
      (y >= 2) and (y <= 24) then
     continue
   else
     begin
       gotoxy(x,y);
       write('*');
     end;
 end;

gotoxy(2,23);
write('inside window press any key to exit...');
readkey;
//readln;

end.

I've pressed the up arrow key.

1
When you say "refuses to work" what exactly do you mean, e.g. that the window closes before you have a chance to press a key, or that windows stays on-screen and doesn't close, as it should, the second time you press a key? I tried your program in Lazarus, the IDE for Free Pascal and it works fine: it clears the screen and waits for me to press a key, then it draws your window, write the 'Inside window ...' message and waits until I press a key and then it closes, so it works fine for me. - MartynA
This: that the window closes before you have a chance to press a key. The program finishes its execution after running with Ctrl+F9 and back to the FPC editor. I'm coding using FPC from CMD (of windows 10) as administrator. - jeremy
Which button(s) do you press first (in response to the first ReadKey)? Have you read the description about ReadKey in the documentation? - Tom Brunberg
I've pressed the up arrow key. - jeremy

1 Answers

1
votes

I've pressed the up arrow key

Some keys on a keyboard generates what is called extended keys. The arrow keys (among others) are such keys. They return two characters, not one. The first character is ASCII 0 and the second is the scan code of the pressed key.

For ReadKey it is documented:

ReadKey reads 1 key from the keyboard buffer, and returns this. If an extended or function key has been pressed, then the zero ASCII code is returned. You can then read the scan code of the key with a second ReadKey call.

I could add to that, that ReadKey waits for input if the keyboard buffer is empty (but only if it is empty).

Therefore, when your program calls ReadKey for the first time, and you hit the "up arrow key", two bytes are put into the buffer, $00 and $48. The first one ($00) is returned to your code, and the scan code for the up arrow remains in the input buffer. When you then later call ReadKey a second time it receives the scan code from the buffer and continues immediately without stopping for input.

You can deal with this in one of two ways:

1.Write a procedure, say WaitForAnyKey that deals with the extended keys:

procedure WaitForAnyKey;
var
  c: char;
begin
  c:=ReadKey;
  if c=#0 then
    c:=ReadKey;
end;

and you call it instead of calling ReadKey directly.

2.Write a procedure that waits for, and accepts a specific key only:

procedure WaitForCR; // wait for CR, Carriage Return (Enter)
const
  CR=#13;
var
  c: Char;
begin
  repeat
    c:=ReadKey;
  until c=CR;
end

and you call it instead of calling ReadKey directly.