|
Improvements to prevent multiple application instances from appearing at the same time
//==================================================== ==============================
// Unit Name: MultInst
// Purpose: Solve the problem of multi-instance application
// History:
//==================================================== ==============================
//==================================================== ==============================
// work process
// The program runs first to replace the original message processing process, and then broadcast a message.
// If there are other instances running, the broadcast message will be sent back to the sending program, and its own handle will be returned
// The sending program receives this message, activates the program that received the message, and then closes itself
//==================================================== ==============================
unit MultInst;
interface
uses
Windows, Messages, SysUtils, Classes, Forms;
implementation
const
STR_UNIQUE ='{2BE6D96E-827F-4BF9-B33E-8740412CDE96}';
MI_ACTIVEAPP = 1; //Activate the application
MI_GETHANDLE = 2; //Get handle
var
iMessageID: Integer;
OldWProc: TFNWndProc;
MutHandle: THandle;
BSMRecipients: DWORD;
function NewWndProc(Handle: HWND; Msg: Integer; wParam, lParam: Longint):
Longint; stdcall;
begin
Result := 0;
if Msg = iMessageID then
begin
case wParam of
MI_ACTIVEAPP: //Activate the application
if lParam<>0 then
begin
//Activate the previous instance of the received message
//Why activate in another program?
//Because SetForegroundWindow does not bring the form to the front in the same process
if IsIconic(lParam) then
OpenIcon(lParam)
else
SetForegroundWindow(lParam);
//Terminate this instance
Application.Terminate;
end;
MI_GETHANDLE: //Get the program handle
begin
PostMessage(HWND(lParam), iMessageID, MI_ACTIVEAPP,
Application.Handle);
end;
end;
end
else
Result := CallWindowProc(OldWProc, Handle, Msg, wParam, lParam);
end;
procedure InitInstance;
begin
//Replace the application's message processing
OldWProc := TFNWndProc(SetWindowLong(Application.Handle, GWL_WNDPROC,
Longint(@NewWndProc)));
//Open the mutex object
MutHandle := OpenMutex(MUTEX_ALL_ACCESS, False, STR_UNIQUE);
if MutHandle = 0 then
begin
//Create a mutex object
MutHandle := CreateMutex(nil, False, STR_UNIQUE);
end
else begin
Application.ShowMainForm := False;
//There is already a program instance, the broadcast message gets the instance handle
BSMRecipients := BSM_APPLICATIONS;
BroadCastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE,
@BSMRecipients, iMessageID, MI_GETHANDLE, Application.Handle);
end;
end;
initialization
//Registration message
iMessageID := RegisterWindowMessage(STR_UNIQUE);
InitInstance;
finalization
//Restore message processing
if OldWProc <> Nil then
SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(OldWProc));
//Close the mutex object
if MutHandle <> 0 then CloseHandle(MutHandle);
end.
//The method of use is very simple, just add this unit to the project. |
|