之前在做一個程序只能開一次,再次打開就會提示此軟件已運行。但是我發現會再次點這個程序是因爲它是處於最小化,或者乾脆就是處於托盤狀態,纔會去再次點。但是點擊後知道那個程序已在運行,但是還得再找到那個程序。我就想可不可以提示運行之後就把那個程序顯示出來!不過在之中間我還是發現了兩個問題。
1、如果此軟件沒做什麼事還好,用正常的FindWindow(nil,'此軟件的項目標題') 就可以找到。但是如果這個軟件本身就已有在接收消息,且時刻在處於系統消息,那就會出現找不到該軟件的句柄;或是找到了消息也發過去了,但是該軟件卻沒收到。我就對FindWindow這個函數進行研究了下,發現參數改變下準確率就升高了好多。我是用FindWindow('TMainForm',nil)有該軟件主窗體的類進行查找,成功率就高好多,或者可以把兩者結合起來TFormtdmain('TMainForm','此軟件的項目標題')。我目前的成功率是100%但是沒在高強度情況下進行查找,不敢說完全100%能成功。
2、第二個問題是找到該軟件了,消息也收到了,怎麼讓該軟件從最小化或是托盤中顯示出來,且顯示在最前端。在網上找了說什麼三種方法,且三種方法還各有缺點,還得多種結合才能去掉缺點。看的好像很複雜的樣子,但是我記得我好像有做過這個類似的,找了下就找到了。只要用ShowWindow(Application.Handle,SW_SHOW); Application.Restore; 這兩句就可以很快解決了。
希望能給讀者一點幫助。
以下是我的代碼,以供參考。
//這是在工程文件 program ABTMonitor; 裏進行判斷
var
hMutex: THandle;
h: HWND;
Size: Integer;
CopyDataStruct: TCopyDataStruct;
begin
hMutex := CreateMutex(nil, False, 'ABRMonitorSystem');
if WaitForSingleObject(hMutex, 0) = wait_TimeOut then
begin
application.MessageBox('安貝通視頻監控系統已經運行!','運行',MB_OK+MB_ICONINFORMATION);
h := FindWindow('TMainForm',PChar('安貝通視頻監控系統')); { 按標題查找目標窗口 }
if h > 0 then
begin
Size := 7; { 多出的兩個字節用於後面的 #0 }
CopyDataStruct.lpData := PChar('@Show' + #0); { 要發送的字符串, #0 表示 PChar 結束}
CopyDataStruct.dwData := WM_COPYDATA; { 指定消息類型 }
CopyDataStruct.cbData := Size; { 指定要發送的數據的大小 }
SendMessage(h, WM_COPYDATA, 0, Integer(@CopyDataStruct)); { 發送 }
end;
Exit;
end;
Application.Initialize;
Application.Title :='安貝通視頻監控系統';
Application.CreateForm(TMainForm, MainForm);
Application.CreateForm(TFormshowlabel, Formshowlabel);
Application.Run;
//這是在主窗體unit MainFrm;裏接收消息
procedure TMainForm.Mymessage1(var t: TWmCopyData);
var
CommrevStr: string;
begin
CommrevStr := StrPas(t.CopyDataStruct^.lpData);
if CommrevStr='@Show' then
begin
ShowWindow(Application.Handle,SW_SHOW);
Application.Restore;
exit;
end;
end;