終了する方法を教えてください。

解決


AS  2025-12-09 18:06:34  No: 152206

下のような時計を作ったのですが、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.


AS  2025-12-10 17:42:26  No: 152207

すみません、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.


AAAAA  2025-12-10 19:02:38  No: 152208

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;


mam  2025-12-12 13:08:25  No: 152209

間違っていたり、外していたらすいません。

実際の挙動の流れを纏めると、
■最初のアクティブ化
- FormActivate が呼ばれてループに入る。
- このループはメインスレッド上で動いているので、UI スレッドを占有する。
■非アクティブ → 再アクティブ化
- 再度 FormActivate が呼ばれる。
- しかしメインスレッドはすでに最初のループで占有されているため、厳密には「並列」ではなく「イベントキューに積まれて順次処理される」状態になる。
- 見かけ上「二重に実行されている」ように見える。
■ Button1 をクリック
- ProcessMessages の隙間でクリックイベントが処理され、STO := 1 がセットされる。
- これで「最初のループ」は終了し、Close が呼ばれる。
- しかし二回目の FormActivate 呼び出しが残っている
- こちらも同じループに入っているが、STO の値は既に 1 → すぐに Until STO=1 が成立して抜ける。
- ただしその後の Close 呼び出しが再度走ろうとするため、UI が「閉じられない/応答しない」ように見える。


タイマーを使ったほうが良いのかもです。


AS  2025-12-22 16:05:53  No: 152213

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;


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

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







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