参见英文答案 >
How can I make the second instance of my program pass control back to the first instance?1个
See also:
07001
我在启动应用程序之前使用以下代码,以检查是否有另一个实例
它已经开始了:
var _PrevIoUsHandle : THandle; begin _PrevIoUsHandle := FindWindow('TfrmMainForm',nil); if _PrevIoUsHandle <> 0 then begin ShowMessage('Application "" is already running!'); SetForegroundWindow(_PrevIoUsHandle); ShowWindow(_PrevIoUsHandle,SW_SHOW); Application.Terminate; Exit; end; ...
但是,如果它已经启动,我需要显示该应用程序.问题是以这种方式显示最小化按钮不再起作用,当我单击任务栏中的图标时,它“取消最小化”,并且显示的动画就像它被最小化一样.我错过了什么吗?是否有一种适当的方式来激活和显示外部应用程序,同时它被最小化?
解决方法
这是一个完整的项目,它只运行一个应用程序实例,并且应该将已运行的实例窗口带到前面.
您可以下载testing project
或尝试以下代码:
Project1.dpr
program Project1; uses Forms,Windows,Unit1 in 'Unit1.pas' {Form1}; {$R *.res} var Mutex: THandle; const AppID = '{0AEEDBAF-2643-4576-83B1-8C9422726E98}'; begin MessageID := RegisterWindowMessage(AppID); Mutex := CreateMutex(nil,False,AppID); if (Mutex <> 0) and (GetLastError = ERROR_ALREADY_EXISTS) then begin PostMessage(HWND_BROADCAST,MessageID,0); Exit; end; Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1,Form1); Application.Run; end.
Unit1.pas
unit Unit1; interface uses Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,StrUtils,StdCtrls; type TForm1 = class(TForm) private function ForceForegroundWindow(WndHandle: HWND): Boolean; function ForceRestoreWindow(WndHandle: HWND; Immediate: Boolean): Boolean; protected procedure WndProc(var AMessage: TMessage); override; end; var Form1: TForm1; MessageID: UINT; implementation {$R *.dfm} { TForm1 } function TForm1.ForceForegroundWindow(WndHandle: HWND): Boolean; var CurrThreadID: DWORD; ForeThreadID: DWORD; begin Result := True; if (GetForegroundWindow <> WndHandle) then begin CurrThreadID := GetWindowThreadProcessId(WndHandle,nil); ForeThreadID := GetWindowThreadProcessId(GetForegroundWindow,nil); if (ForeThreadID <> CurrThreadID) then begin AttachThreadInput(ForeThreadID,CurrThreadID,True); Result := SetForegroundWindow(WndHandle); AttachThreadInput(ForeThreadID,False); if Result then Result := SetForegroundWindow(WndHandle); end else Result := SetForegroundWindow(WndHandle); end; end; function TForm1.ForceRestoreWindow(WndHandle: HWND; Immediate: Boolean): Boolean; var WindowPlacement: TWindowPlacement; begin Result := False; if Immediate then begin WindowPlacement.length := SizeOf(WindowPlacement); if GetWindowPlacement(WndHandle,@WindowPlacement) then begin if (WindowPlacement.flags and WPF_RESTORETOMAXIMIZED) <> 0 then WindowPlacement.showCmd := SW_MAXIMIZE else WindowPlacement.showCmd := SW_RESTORE; Result := SetWindowPlacement(WndHandle,@WindowPlacement); end; end else Result := SendMessage(WndHandle,WM_SYSCOMMAND,SC_RESTORE,0) = 0; end; procedure TForm1.WndProc(var AMessage: TMessage); begin inherited; if AMessage.Msg = MessageID then begin if IsIconic(Handle) then ForceRestoreWindow(Handle,True); ForceForegroundWindow(Application.Handle); end; end; end.
在OS版本上测试:
> Windows 8.1 64位
> Windows 7 SP1 64位家庭高级版
> Windows XP SP 3 32位专业版
已知问题和限制:
>根本没有考虑MainFormOnTaskbar;此时必须设置为True