Как не допустить запуск второй копии программы XIII
Своим опытом делится Олег Кулабухов: Самый простой, но немного некорректный способ - найти заголовок окна по FindWindow() и выполнять какие-либо действия в зависимости от того, есть ли такое окно или нет. Второй выриант - через определение мутексов. Если определить мутекс не удастся - всем окнам передается системное сообщение.
Нижеприведенный пример проверяет наличие окна, если таковое имеется - делает его видимым (если оно минимизировано). Впрочем - дольше объяснять, смотрите сами.
{The code for OneInstance.dpr}
program OneInstance;
uses Windows, Forms, Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
begin {Attempt to create a named mutex} CreateMutex(nil, false, 'MyApp'); {if it failed then there is another instance} if GetLastError = ERROR_ALREADY_EXISTS then begin {Send all windows our custom message - only our other} {instance will recognise it, and restore itself} SendMessage(HWND_BROADCAST, RegisterWindowMessage('MyApp'), 0, 0); {Lets quit} Halt(0); end; Application.Initialize; {Tell Delphi to un-hide it's hidden application window} {This allows our instance to have a icon on the task bar} Application.ShowMainForm := true; ShowWindow(Application.Handle, SW_RESTORE); Application.CreateForm(TForm1, Form1); Application.Run; end.
type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.DFM}
var OldWindowProc : Pointer; {Variable for the old windows proc} MyMsg : DWord; {custom systemwide message}
function NewWindowProc(WindowHandle : hWnd; TheMessage : LongInt; ParamW : LongInt; ParamL : LongInt) : LongInt stdcall; begin if TheMessage = MyMsg then begin {Tell the application to restore, let it restore the form} SendMessage(Application.handle, WM_SYSCOMMAND, SC_RESTORE, 0); SetForegroundWindow(Application.Handle); {We handled the message - we are done} Result := 0; exit; end; {Call the original winproc} Result := CallWindowProc(OldWindowProc, WindowHandle, TheMessage, ParamW, ParamL); end;
procedure TForm1.FormCreate(Sender: TObject); begin {Register a custom windows message} MyMsg := RegisterWindowMessage('MyApp'); {Set form1's windows proc to ours and remember the old window proc} OldWindowProc := Pointer(SetWindowLong(Form1.Handle, GWL_WNDPROC, LongInt(@NewWindowProc))); end;
procedure TForm1.FormDestroy(Sender: TObject); begin {Set form1's window proc back to it's original procedure} SetWindowLong(Form1.Handle, GWL_WNDPROC, LongInt(OldWindowProc)); end;
begin {Tell Delphi to hide it's hidden application window for now to avoid} {a "flash" on the taskbar if we halt due to another instance} ShowWindow(Application.Handle, SW_HIDE); end.