コンソールアプリケーションで、
タイムリミット付きの入力待ち
の動作をするにはどのようにしたらよいのでしょうか。
1. あ
2. い
3. う
のように選択肢を表示して、
例えば10秒間ユーザーからキー入力がなければ、
デフォルトの動作を実行する。
というようなことをしたいと考えているのですが、
ユーザーからのキー入力待ち(Writeln)、という動作と、
タイマー、という動作の2つを同時に行う方法が、
コンソールアプリケーションなのでどうしたらいいのか、わかりません。
どのような方法があるのでしょうか?
10秒間ループをまわす
StartTime := GetTickCount;
Flag := True;
try
repeat
StopTime := GetTickCount;
Application.ProcessMessages;
Until GetTickCount > StartTime + 10000;
Flag := False;
修正・・
StartTime := GetTickCount;
Flag := True;
try
repeat
StopTime := GetTickCount;
Application.ProcessMessages;
Until GetTickCount > StartTime + 10000;
finally
Flag := False;
end;
ディオン さんの示した
タイマーのコードはわかっているのですが
ユーザーからのキー入力待ち
Readln
を加えると、
ユーザーからキー入力があるまで、
そこでタイマーが止まってしまうのです
>そこでタイマーが止まってしまうのです
タイマーが止まるのではなくて Readlnから処理が返らないのでタイマーの処理が出来ないのですよね。
独自にキー入力ルーチンを用意する必要ありでしょう。
http://leed.issp.u-tokyo.ac.jp/~takeuchi/delphi/browse.cgi?index=036751&back=http://leed.issp.u-tokyo.ac.jp/~takeuchi/delphi/article/036/036751.html
を参考に作成してみてはいかがでしょうか?
ただ、上記リンクで紹介されているソフトはバージョンが古くDelphi7ではエラーがでます。
http://www.slis.keio.ac.jp/~anakata/filearea/arc/w32crt03.lzh
を例にとると KeyEvent.xxx というのをすべて Event.KeyEvent.xxx と変更すればOKでした。
KeyPressedとReadkeyを使用すれば1文字入力だけならタイマー付でも簡単に作成できそうです。
正確に10秒をのぞんでいるのなら無理ですが、
Buttonを2つ,Memo,Editを配置して
フォームのプロパティKeyPreview = True にします
Button1を押すと入力した文字はEditBoxにはいります。
EditBoxのTextを処理すれば文字列の判断をして
ループを終了すればよいでしょう。
Button2を押すとキーボードから1文字を入力すると
ループが終了します。
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure Button2Click(Sender: TObject);
private
InputKey: Char;
CloseFlag: Boolean;
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseFlag := True;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
StartTime: DWord;
StopTime: DWord;
begin
Edit1.Text := '';
Edit1.SetFocus;
Memo1.Lines.Text := '1. あ' + #13#10 + '2. い' + #13#10 + '3. う';
StartTime := GetTickCount;
repeat
Application.ProcessMessages;
if Edit1.Text <> '' then break; //または判断処理してループ終了
StopTime := GetTickCount;
Until CloseFlag or (StopTime > StartTime + 10000);
ActiveControl := Nil;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
StartTime: DWord;
StopTime: DWord;
begin
InputKey := #0;
Memo1.Lines.Text := '1. あ' + #13#10 + '2. い' + #13#10 + '3. う';
StartTime := GetTickCount;
repeat
Application.ProcessMessages;
StopTime := GetTickCount;
Until CloseFlag or (InputKey <> #0) or (StopTime > StartTime + 10000);
ActiveControl := Nil;
if InputKey <> #0 then ShowMessage(InputKey);
end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
InputKey := Key;
end;
end.
質問の意味をよく考えましょう。
> コンソールアプリケーションで、
ですから、Window がないので TButton とかの VCL は使えませんし、メッセージ
ループもないので Application.ProcessMessages; も無意味です。
kkk さんのレスで解決します。
kkk の紹介していただいたリンク先のコードを参考にして、
GetNumberOfConsoleInputEvents でユーザーからの入力があるかないかを調べて
ある場合のみ ReadConsoleInput で入力を取得しにいく、という方法で、
タイマーのループの流れを止めないで、ユーザーからの入力を調べることができました。
ありがとうございました。
kkk ”さん” です。
呼び捨てにしてしまいました。
すいません。
本当にありがとうございました。
ツイート | ![]() |