彈出一個非阻塞對話框(在程序關閉後 仍然顯示對話框)

今天有個小需求, 程序要求執行一個檢測操做, 若是檢測失敗的話則彈出信息而且關閉程序html

因爲檢測代碼是封裝到一個獨立進程裏的, 因此直接使用TerminateProcess(GetCurrentProcess, 0);來關閉當前進程java

但是在測試時卻發現, 本來使用MessageBox來彈出消息卻會阻塞結束進程的操做git

通常咱們在系統裏彈出對話框都是調用Windows.MessageBox, 這個方法在通常狀況下, 能夠不阻塞本程序的操做(雖然在代碼層面仍然是阻塞的)github

 

你們能夠用一個小例子試試api

procedure TForm1.Button1Click(Sender: TObject);
begin
  MessageBox(0, '測試內容1', '測試標題', MB_OK);
  MessageBox(0, '測試內容2', '測試標題', MB_OK);
end;

實際狀況執行之後, 點擊按鈕彈出第一個對話框, 這時, 雖然程序界面仍然能夠移動輸入等執行其餘操做, 可是測試內容2卻沒有彈出session

只有吧第一個對話框關閉之後, 第2個對話框才能彈出來函數

因此, 猜想MessageBox的非阻塞只是在內部處理了對當前進程的消息循環, 可是代碼層面並無返回並向後執行, 因此並非真正意義上的非阻塞測試

 

那需求怎麼辦呢.......spa

 

偉大的Google, 碼農們須要你的時候來了(雖然這幾天Google又被偉大的GFW給牆了...不過我們能夠換IP...嘿嘿 你懂的: 啦啦啦)code

終於搜到一個相關的文章, 關於在win7下若是讓一個服務向用戶界面推送消息的問題: 穿透Session0隔離

其中有一個關鍵性函數: WTSSendMessage, 能夠向指定的Session發送消息

既然是想Session發送消息, 那確定是桌面級的, 和應用程序無關了唄, 我們再看看他的定義: WTSSendMessage function

顯然, 最後一個參數是控制是否阻塞等待的, 看來這就是我要的東西了, 立刻寫代碼試試:

補充一下, 不知道爲何 這個自從XP就出現的函數, 直到Delphi XE5都沒有被定義到Windows單元中, 而其餘的2個WTS相關函數卻定義了(也許定義到其餘單元我沒找到?)

複製代碼
const
  WTS_CURRENT_SERVER_HANDLE = 0;

function WTSSendMessage(Server: HWND; SessionId: DWORD; Title: PChar;
  TitleLength: DWORD; AMessage: PChar; MessageLength: DWORD; Style: DWORD;
  Timeout: DWORD; var Response: DWORD; Wait: Boolean): Boolean; stdcall;
  external 'wtsapi32.dll' name 'WTSSendMessageA';

function WTSGetActiveConsoleSessionId: DWORD; stdcall;
  external kernel32 name 'WTSGetActiveConsoleSessionId';


procedure TForm1.Button1Click(Sender: TObject);
var
  nTitle, nMessage: string;
  nResponse: DWORD;
begin
  nTitle := '測試標題';
  nMessage := '測試內容1';
  WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId,
    PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage),
    MB_OK, 0, nResponse, False);
  nMessage := '測試內容2';
  WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId,
    PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage),
    MB_OK, 0, nResponse, False);
end;
複製代碼

執行測試一下, 我擦....竟然仍是必須先吧內容1肯定了之後才能彈出內容2? 難道是我理解錯了不成?

單步跟蹤一下...#^&%^*

不對啊, 彈出了內容1立刻就執行到內容2的代碼了啊, 而後就直接end結束了, 但是爲何只彈出了1個對話框呢?

再補充一下測試

複製代碼
const
  WTS_CURRENT_SERVER_HANDLE = 0;

function WTSSendMessage(Server: HWND; SessionId: DWORD; Title: PChar;
  TitleLength: DWORD; AMessage: PChar; MessageLength: DWORD; Style: DWORD;
  Timeout: DWORD; var Response: DWORD; Wait: Boolean): Boolean; stdcall;
  external 'wtsapi32.dll' name 'WTSSendMessageA';

function WTSGetActiveConsoleSessionId: DWORD; stdcall;
  external kernel32 name 'WTSGetActiveConsoleSessionId';


procedure TForm1.Button1Click(Sender: TObject);
var
  nTitle, nMessage: string;
  nResponse: DWORD;
begin
  nTitle := '測試標題';
  nMessage := '測試內容1';
  WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId,
    PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage),
    MB_OK, 0, nResponse, False);
  nMessage := '測試內容2';
  WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId,
    PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage),
    MB_OK, 0, nResponse, False);
  TerminateProcess(GetCurrentProcess, 0);
end;
複製代碼

看看這樣, 執行結果, 果真 程序關閉了, 可是隻有內容1的對話框, 肯定之後才彈出內容2的

我的猜想, 應該是WTSSendMessage以相似消息隊列方式給Session發對話框消息, 而對於Session的處理, 則必須是阻塞的, 估計是爲了可以讓用戶知道多條消息的前後順序吧

 

無所謂啦, 只要程序不阻塞就行, 搞定....嘿嘿嘿嘿.......

http://www.cnblogs.com/hs-kill/p/3797103.html

相關文章
相關標籤/搜索