之前在做一个程序只能开一次,再次打开就会提示此软件已运行。但是我发现会再次点这个程序是因为它是处于最小化,或者干脆就是处于托盘状态,才会去再次点。但是点击后知道那个程序已在运行,但是还得再找到那个程序。我就想可不可以提示运行之后就把那个程序显示出来!不过在之中间我还是发现了两个问题。
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;