Whileループの中でキーボードから’s’を入力したら、Whileのループを脱出するような処理を行いたいのですが、どのようにしてsが押されたことを確認するのかわかりません。よろしくお願いします。
whileループが回っている間、そのウィンドウはキーボードフォーカスを持っているんでしょうか?
キーボードフォーカスとは何でしょうか?
ちなみにソースはこんな感じにと考えています。
procedure TForm1.Button1Click(Sender: TObject);
begin
while Flag=1 do
begin
if 'sが押されたら' then
Flag:=0;
.
.
.
.
end;
end;
フォーカスを持つとは、アクティブになる(なれる)こと。
キーボード入力をキャッチできるコンポーネントがフォーム上にあると、
典型的にはTEdit, TMemo,
下記コードでは、Button1があると、
キー入力されても捕らえることができない。
そこで、Form1.KeyPreviewプロパティをtrueにして
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
flgS: Boolean;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (Key = Word('S')) or (Key = Word('s')) then
begin
flgS := true;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
i := 0;
while i < $FFFFFFFF do
begin
i := i + 1;
// いっときループを中断して、制御をWindowsに返す
Application.ProcessMessages;
if flgS then
begin
flgS := false;
Showmessage('Break');
Break;
end;
end;
Showmessage('End');
end;
なるほど。
Application.ProcessMessages;
で、どのくらいの間ループは中断されているのでしょうか?
あまり長いと、この部分で制御を行っているので、都合が悪いのですが…
ループ内で、GetASyncKeyStateなどを使って判定すればよろしいかと。
Application.ProcessMessages
が行うことは、当該Applicationがキャッチしたメッセージを、
正確には、Applicationのメッセージキューにあるメッセージを処理することだけです。
処理が終われば、制御はApplicationに返され、ループが再開します。
中断時間は不明ですが、限りなくゼロに近い値です。
これがないと、ループは終了するまで制御を独占します。
キーボードから'S'を入力すると、その旨のメッセージがApplicationに届けられ、
メッセージキューという待合室で処理を待ちます。
しかし、処理がされないので、'S'の入力を契機にループを終了することは不可能となります。
また、ループ中にユーザーがWindowsをシャットダウンしてしまった場合、
「このプログラムから応答がありません」というメッセージを出すだけで、
強制的にこのApplicationも終了させてしまいます。
保存していないデータがあれば、それを保存する機会を与えられることなく失われます。
にしのさん、さどやまさんありがとうございます。
両方とも試してみたところ、どちらもうまくいきました。
これから、ほかの部分を作ってどちらの方法を使うか検討したいと思います。
ありがとうございました。
ツイート | ![]() |