タイムリミット付きの入力待ちをするには?

解決


どんぐり雨  2006-07-19 19:18:34  No: 22681

コンソールアプリケーションで、
タイムリミット付きの入力待ち
の動作をするにはどのようにしたらよいのでしょうか。

1. あ
2. い
3. う
のように選択肢を表示して、
例えば10秒間ユーザーからキー入力がなければ、
デフォルトの動作を実行する。

というようなことをしたいと考えているのですが、
ユーザーからのキー入力待ち(Writeln)、という動作と、
タイマー、という動作の2つを同時に行う方法が、
コンソールアプリケーションなのでどうしたらいいのか、わかりません。
どのような方法があるのでしょうか?


ディオン  2006-07-19 20:25:31  No: 22682

10秒間ループをまわす

StartTime := GetTickCount;
Flag := True;
try
repeat
  StopTime := GetTickCount;
  Application.ProcessMessages;
Until GetTickCount > StartTime + 10000;
Flag := False;


ディオン  2006-07-19 20:26:31  No: 22683

修正・・

StartTime := GetTickCount;
Flag := True;
try
  repeat
    StopTime := GetTickCount;
    Application.ProcessMessages;
  Until GetTickCount > StartTime + 10000;
finally
  Flag := False;
end;


どんぐり雨  2006-07-20 06:16:47  No: 22684

ディオン さんの示した
タイマーのコードはわかっているのですが

ユーザーからのキー入力待ち
Readln

を加えると、
ユーザーからキー入力があるまで、
そこでタイマーが止まってしまうのです


kkk  2006-07-20 13:53:40  No: 22685

>そこでタイマーが止まってしまうのです
タイマーが止まるのではなくて 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文字入力だけならタイマー付でも簡単に作成できそうです。


ディオン  2006-07-21 01:08:04  No: 22686

正確に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.


えーと  2006-07-21 09:04:46  No: 22687

質問の意味をよく考えましょう。

> コンソールアプリケーションで、

ですから、Window がないので TButton とかの VCL は使えませんし、メッセージ
ループもないので Application.ProcessMessages; も無意味です。

kkk さんのレスで解決します。


どんぐり雨  2006-07-23 07:08:18  No: 22688

kkk の紹介していただいたリンク先のコードを参考にして、
GetNumberOfConsoleInputEvents でユーザーからの入力があるかないかを調べて
ある場合のみ ReadConsoleInput で入力を取得しにいく、という方法で、
タイマーのループの流れを止めないで、ユーザーからの入力を調べることができました。

ありがとうございました。


どんぐり雨  2006-07-23 15:28:29  No: 22689

kkk ”さん” です。
呼び捨てにしてしまいました。
すいません。
本当にありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加