unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1: TForm1;
  Mark:Boolean=True;
implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
  while Mark do
  begin
    Application.ProcessMessages;
  end;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
  Mark:=False;
end;end.开始运行后,点击button1后,在不点button2前,窗体不能正常关闭,但是最小最大化都可以,这是为什么呢?

解决方案 »

  1.   


      while Mark and not Application.Terminated do
        Application.ProcessMessages;这样就可以了
      

  2.   

    點擊關閉按鈕,會產生WM_Close,而這個消息是非隊列消息;Application.ProcessMessages并不會處理到。
    正是由于這段
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      while Mark do
      begin
        Application.ProcessMessages;
      end;
    end;
    使得程序一直專注于處理隊列消息,沒有機會處理非隊列消息。
    應該這么寫點擊關閉按鈕,會產生WM_Close,而這個消息是非隊列消息;Application.ProcessMessages并不會處理到。
    正是由于這段
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      while Mark do
      begin
        Application.HandleMessage;
      end;
    end;
      

  3.   

      while Mark do
      begin
        Application.ProcessMessages;
      end;
    这是个死循环呀
      

  4.   

    HandleMessage我试过了,窗口还是不能正常关闭。。但是我不知道为什么。。我用的是delphi 7
      

  5.   

    問題確實比較奇怪  while Mark and not Application.Terminated do
        Application.ProcessMessages;若是正常流程,Application.Terminated標志被改變,應該會收到WM_quit
    嘗試在onmessage攔截WM_Quit并未發現有此消息。
      

  6.   

    抱歉,在OnMessage是攔截不到的WM_QUIT,因為沒有把它傳進去...
      

  7.   

    應該可以得出以下結論:
    1、程序收到了WM_Quit,但這個消息并不是由我們的程序發出的,而是系統給的;
    2、WM_Quit只是一個退出消息循環的條件,所以我們判斷App.Terminated有效果;
    3、根據你原先的寫法,即使WM_QUIT收到了,但并不會結束程序——參考App.ProcessMessage;
    4、循環被打破後,窗體就有機會處理WM_CLOSE了;關于第一點,從程序和VCL源碼看,并沒有顯式地PostQuitMessage或直接發送WM_QUIT,所以推斷是系統發出的
      

  8.   

    谢版主!
    但是我感觉WM_CLOSE应该先与WM_QUIT消息啊,一般点击关闭按钮WM_CLOSE,WM_DESTORY,WM_QUIT。
    但是既然WM_CLOSE是不进队消息,那么在没有处理WM_CLOSE时,系统会直接发送WM_QUIT吗
      

  9.   

    看了一下源碼,并且驗證了一下消息處理方式,前面有幾個結論要修正:
    1、即使一直ProcessMessages處理隊列消息,但只要有非隊列消息產生給窗體,OS借助中斷機制,直接調用窗口過程,傳遞消息;所以WM_Close還是會被處理。查看Form.CLose,由于你的Form1是MainForm,所以會調用App.Terminate——>PostQuitMessage——>處理Application.Terminated標志。倘若你在開另外一個窗體,然后這樣寫程序,就沒這么幸運可以關閉程序了。
    2、HandleMessage只是在消息隊列沒有消息時,掛起線程而已,所以對你的問題也沒幫助;
      

  10.   

    暈,今天咋回事,老出錯...
    若再開一個窗體,程序這樣寫的話,可以正常關閉才對,因為WM_Close能被處理.....
      

  11.   

    并非消息不入队列,而是processmessages做了特殊判断,基本上是WM_QUIT时,只改变FTerminate
    if Msg.Message <> WM_QUIT then
          begin
            
          end
          else
          begin
      {$IF DEFINED(CLR)}
            if Assigned(FOnShutDown) then FOnShutDown(self);
            DoneApplication;
      {$IFEND}
            FTerminate := True;
          end;
        end;