下のような時計を作ったのですが、Microsoft Edgeと起動すると、
終了ボタンが聞きません。
どうしたらいいですか??
よろしくお願いします。
var
Form1: TForm1;
s:string;
STO:integer;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
STO:=1;
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
Edit2.Text:=NowST(s);
Repeat
s:=TimeToStr(Time);
Edit1.Text:=s;
sleep(1000);// 1秒間持ちます。
Application.processMessages;// この文以前の画面制御などの文が実行されるのを待ちま
Until STO=1;
Close;
end;
function TForm1.NowST(s:string):string;
var
st:string;
n:integer;
begin
n:=pos(':',S);
ST:=copy(s,1,n-1); s:=copy(S,n+1,length(s)); n:=pos(':',s);
NowST:=DateToStr(Date);
end;
end.
すみません、Delphiを勉強し始めたばかりに作ったプログラムを修正して作ったので、いらないところが残っていました。
例えば、このプログラムを3つ起動して、起動したばかりを終了させると、終了できますが、起動し順に終了ボタンを押すと、どれも終了できません。
終了できる方法を教えてください。
var
Form1: TForm1;
STO:integer;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
STO:=1;
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
Edit2.Text:=DateToStr(Date); STO:=0;
Repeat
Edit1.Text:=TimeToStr(Time);
sleep(1000);
Application.processMessages;
Until STO=1;
Close;
end;
end.
Deactive になると再度 Active になっても Button は Click できないみたいだね
1) 起動したばかりを終了させると、終了できますが、
2) 起動し順に終了ボタンを押すと、どれも終了できません。
1はフォームが切り替わっていないので Button が有効
2はフォームが切り替わっているので Button が無効
ApplicationEvents の OnActivate を使えば回避できるけど
FormがActiveになるたびにOnActivate が実行されるので
初回のみ実行するように
procedure TForm2.ApplicationEvents1Activate(Sender: TObject);
begin
if STO = 0 then
begin
STO := 1;
Edit2.Text:=DateToStr(Date);
Repeat
Edit1.Text:=TimeToStr(Time);
sleep(100);
Application.ProcessMessages;
Until STO=2;
Close;
end;
end;
間違っていたり、外していたらすいません。
実際の挙動の流れを纏めると、
■最初のアクティブ化
- FormActivate が呼ばれてループに入る。
- このループはメインスレッド上で動いているので、UI スレッドを占有する。
■非アクティブ → 再アクティブ化
- 再度 FormActivate が呼ばれる。
- しかしメインスレッドはすでに最初のループで占有されているため、厳密には「並列」ではなく「イベントキューに積まれて順次処理される」状態になる。
- 見かけ上「二重に実行されている」ように見える。
■ Button1 をクリック
- ProcessMessages の隙間でクリックイベントが処理され、STO := 1 がセットされる。
- これで「最初のループ」は終了し、Close が呼ばれる。
- しかし二回目の FormActivate 呼び出しが残っている
- こちらも同じループに入っているが、STO の値は既に 1 → すぐに Until STO=1 が成立して抜ける。
- ただしその後の Close 呼び出しが再度走ろうとするため、UI が「閉じられない/応答しない」ように見える。
タイマーを使ったほうが良いのかもです。
AAAAAさん、mamさん、ありがとうございました。
Activateの中で色々するのが悪いようですので、
もう一つbuttonをもう一つ増やしました。
procedure TForm1.Button1Click(Sender: TObject);
begin
STO:=1;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Edit2.Text:=DateToStr(Date);
Repeat
Edit1.Text:=TimeToStr(Time);
sleep(1000);// 1秒間持ちます。
Application.processMessages;// この文以前の画面制御などの文が実行されるのを待ちま
Until STO=1;
Close;
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
STO:=0;
end;
| ツイート |
|