I have done things similar to this a few times before:
First declare a few global variables:
var
hIn: THandle;
hTimer: THandle;
threadID: cardinal;
TimeoutAt: TDateTime;
WaitingForReturn: boolean = false;
TimerThreadTerminated: boolean = false;
Second, add functions
function TimerThread(Parameter: pointer): integer;
var
IR: TInputRecord;
amt: cardinal;
begin
result := 0;
IR.EventType := KEY_EVENT;
IR.Event.KeyEvent.bKeyDown := true;
IR.Event.KeyEvent.wVirtualKeyCode := VK_RETURN;
while not TimerThreadTerminated do
begin
if WaitingForReturn and (Now >= TimeoutAt) then
WriteConsoleInput(hIn, IR, 1, amt);
sleep(500);
end;
end;
procedure StartTimerThread;
begin
hTimer := BeginThread(nil, 0, TimerThread, nil, 0, threadID);
end;
procedure EndTimerThread;
begin
TimerThreadTerminated := true;
WaitForSingleObject(hTimer, 1000);
CloseHandle(hTimer);
end;
procedure TimeoutWait(const Time: cardinal);
var
IR: TInputRecord;
nEvents: cardinal;
begin
TimeOutAt := IncSecond(Now, Time);
WaitingForReturn := true;
while ReadConsoleInput(hIn, IR, 1, nEvents) do
if (IR.EventType = KEY_EVENT) and
(TKeyEventRecord(IR.Event).wVirtualKeyCode = VK_RETURN)
and (TKeyEventRecord(IR.Event).bKeyDown) then
begin
WaitingForReturn := false;
break;
end;
end;
Now you can use TimeoutWait
to wait for Return, but no longer than a given number of seconds. But you have to set hIn
and call StartTimerThread
before you make use of this function:
begin
hIn := GetStdHandle(STD_INPUT_HANDLE);
StartTimerThread;
Writeln('A');
TimeoutWait(5);
Writeln('B');
TimeoutWait(5);
Writeln('C');
TimeoutWait(5);
EndTimerThread;
end.
You can get rid of StartTimerThread
, especially if you start one thread per call, but it might be more tricky to call TimeoutWait
several times in a row then.