Delphi 消息之?dāng)r截篇---攔截系統(tǒng)關(guān)機(jī)、重啟、注銷(xiāo)
最近做的項(xiàng)目中需要攔截系統(tǒng)關(guān)機(jī),因?yàn)槲以贔ormCloseQuery中總是把CanClose設(shè)為False,,不攔截關(guān)機(jī)的話直接導(dǎo)致系統(tǒng)中的關(guān)機(jī)、重啟,、注銷(xiāo)都失效了,!導(dǎo)致用戶不能關(guān)機(jī)!(提示用戶說(shuō)要關(guān)機(jī)的話直接按電源^^)這樣肯定是不行的,!
要完成這個(gè)功能只需要攔截到WM_QUERYENDSESSION消息就萬(wàn)事Ok!
Windows在關(guān)機(jī)的時(shí)候會(huì)想(向)所有頂層窗口廣播一個(gè)消息WM_QUERYENDSESSION,,其lParam參數(shù)可以區(qū)分是關(guān)機(jī)還是注銷(xiāo)用戶(注銷(xiāo)用 戶時(shí)lParam是ENDSESSION_LOGOFF)。然后Windows會(huì)等到所有的應(yīng)用程序都對(duì)這個(gè)消息返回TRUE才會(huì)關(guān)機(jī),,因此,,只要我們的 應(yīng)用程序?qū)@個(gè)消息的處理返回FALSE,Windows就不會(huì)關(guān)機(jī)了,。
這個(gè)消息不能直接讓?xiě)?yīng)用程序退出,,這個(gè)消息主要是詢問(wèn)應(yīng)用程序是否已經(jīng)作好了退出的準(zhǔn)備,當(dāng)所有的應(yīng)用程序都對(duì)這個(gè)消息返回TRUE,系統(tǒng)回(會(huì))注銷(xiāo)或關(guān)機(jī),。如果想退出程序,,請(qǐng)使用WM_CLOSE消息!
關(guān)鍵在于怎么在Delphi下攔截WM_QUERYENDSESSION消息呢,?Delphi也是很強(qiáng)悍的,,當(dāng)然不用直接去SetWindowLong了。
首先介紹一下Delphi中攔截消息的幾種做法
第一種:自定義處理單條消息
- unit Unit2;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs;
- type
- TForm2 = class(TForm)
- procedure FormCreate(Sender: TObject);
- procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
- private
- { Private declarations }
- //直接用 TWMQueryEndSession
- procedure EndMsg(var nMsg: TWMQueryEndSession); Message WM_QUERYENDSESSION;
- //也可以用這種
- //procedure EndMsg(var nMsg: TMessage); Message WM_QUERYENDSESSION;
- public
- { Public declarations }
- end;
- var
- Form2: TForm2;
- implementation
- {$R *.dfm}
- //收到WM_QUERYENDSESSION消息后就會(huì)觸發(fā)這個(gè)過(guò)程
- procedure TForm2.EndMsg(var nMsg: TWMQueryEndSession);
- begin
- //0 可以取消關(guān)機(jī)操作
- nMsg.Result := 1;
- ShowMessage('注銷(xiāo),、重啟,、關(guān)機(jī)');
- end;
- end.
第二種:利用Application.OnMessage處理消息
- unit Unit2;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs;
- type
- TForm2 = class(TForm)
- procedure FormCreate(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- procedure OnMsg(var nMsg: tagMSG; var nHandled: Boolean);
- end;
- var
- Form2: TForm2;
- implementation
- {$R *.dfm}
- //消息處理過(guò)程
- procedure TForm2.OnMsg(var nMsg: tagMSG; var nHandled: Boolean);
- begin
- //處理……
- //這里會(huì)收到各種消息……經(jīng)測(cè)試無(wú)法收到WM_QUERYENDSESSION消息
- end;
- procedure TForm2.FormCreate(Sender: TObject);
- begin
- Application.OnMessage := OnMsg;
- end;
- end.
第三種:自己處理窗口函數(shù),個(gè)人感覺(jué)這是最強(qiáng)大的,,可以攔截一切發(fā)往窗口的消息,!
- unit Unit2;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs;
- type
- TForm2 = class(TForm)
- procedure FormCreate(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- procedure WndProc(var nMsg: TMessage); override;
- end;
- var
- Form2: TForm2;
- implementation
- {$R *.dfm}
- procedure TForm2.WndProc(var nMsg: TMessage);
- begin
- //這里能收到發(fā)往窗口的所有消息
- inherited; // 注意這句不能少
- if nMsg.Msg = WM_QUERYENDSESSION then
- begin
- if nMsg.LParam = 0 then
- ShowMessage('關(guān)機(jī)或重啟')
- else
- ShowMessage('注銷(xiāo)');
- end;
- end;
- end.
經(jīng)過(guò)再次測(cè)試,只有Application.OnMessage不能攔截WM_QUERYENDSESSION消息,!還有,,有時(shí)候Delphi的一些控件也會(huì)導(dǎo)致不能正確攔截。