Under Win 6, you can check the value of hPrevInst at startup. If
it is non-zero, then another instance of your application is
running, and you can take steps to abort the current instance.
Under Win32, hPrevInst is always zero and cannot be relied upon.
You should attempt to create a uniquely named mutex. If the
creation fails, then there is another instance running.
The following example attempts to create a named mutex. If the
mutex fails, a unique system wide custom windows message is
registered with the system, and is then broadcast to all top
level windows. The second instance then shuts down. The
previous instance has also registered this unique custom
system wide message, and has trapped the window procedure of
Form to respond to this message. If the message is received,
then Form is restored (if minimized) and then made to be
the top level window. Care is taken in the example to
minimize the effect of Delphi/Borland C++ Builder's hidden
application window, and its effect on the task bar icon for Form .
Example:
{The code for OneInstance.dpr}
program OneInstance;
uses
Windows,
Forms,
Unit in 'Unit .pas' {Form };
{$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(TForm , Form );
Application.Run;
end.
{The code for unit .pas}
unit Unit ;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs;
type
TForm = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form : TForm ;
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 TForm .FormCreate(Sender: TObject);
begin
{Register a custom windows message}
MyMsg := RegisterWindowMessage('MyApp');
{Set form 's windows proc to ours and remember the old window proc}
OldWindowProc := Pointer(SetWindowLong(Form .Handle,
GWL_WNDPROC,
LongInt(@NewWindowProc)));
end;
procedure TForm .FormDestroy(Sender: TObject);
begin
{Set form 's window proc back to it's original procedure}
SetWindowLong(Form .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.
7/ 6/98 4:3 :28 PM