You can put some code in the application start section to find whether or not there is another instance of itself is running.1. You can use the findwindow() function.
2. You can detect global atom using globalfindatom(), if find the atom, you do exit the current instance. if not found, use the globaladdatom() to add one.
2. You can detect global atom using globalfindatom(), if find the atom, you do exit the current instance. if not found, use the globaladdatom() to add one.
const
CM_RESTORE = WM_USER + $1000; {自定义的“恢复”消息}
MYAPPNAME = "My Delphi Program";
并在Form的定义的public节中加入
procedure CreateParams(var Params: TCreateParams); override;
Procedure RestoreRequest(var message: TMessage); message CM_RESTORE;
在implementation节中加入
{指定窗口名称}
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.WinClassName := MYAPPNAME;
end;{处理“恢复”消息}
procedure TForm1.RestoreRequest(var message: TMessage);
begin
if IsIconic(Application.Handle) = TRUE then
Application.Restore
else
Application.BringToFront;
end;经过以上修改,程序的主窗口的类名已经被指定了,这是进行判断的基础。一般在程序刚开始运行的时候进行判断,所以还要对DPR文件进行修改。2、对DPR文件的改动在 uses 节中添加 windows、messages这两个单元加入下列语句,注意两个文件中常量CM_RESTORE和MYAPPNAME的定义必须一致
const
CM_RESTORE = WM_USER + $1000; {自定义的“恢复”消息}
MYAPPNAME = "My Delphi Program";
var
RvHandle : hWnd;将下列语句插到程序最前部(在Application.Initialize之前)RvHandle := FindWindow(MYAPPNAME, NIL);
if RvHandle > 0 then
begin
PostMessage(RvHandle, CM_RESTORE, 0, 0);
Exit;
end;
这段程序的意思是如果找到一个类名相同的窗口,则向该窗口发送一个消息,并退出,而本例中原窗口收到该消息后会自动激活或从图标还原,从而达到了避免二次运行且能自动调出前一例程的目的。
我这边有另外一种方法,用的时候,你把该单元放到主窗口单元的Uses部分中即可:
unit MultInst;interface
const
MI_QUERYWINDOWHANDLE= 1;
MI_RESPONDWINDOWHANDLE=2;
MI_ERROR_NONE= 0;
MI_ERROR_FAILSUBCLASS= 1;
MI_CREATINGMUTEX= 2;
UNIQUE_APPSTR='unique application string';
function GetMIError:integer;implementation
uses
Forms,Windows,SysUtils;
var
MessageID:integer;
WProc:TFNWndProc;
MutHandle:THandle;
MIError:integer;function GetMIError:integer;
begin
Result:=MIError;
end;function NewWndProc(Handle:HWND;Msg:integer;WParam,LParam:LongInt):Longint;stdcall;
begin
Result:=0;
if Msg=MessageID then
begin
case WParam of
MI_QUERYWINDOWHANDLE:
begin
if IsIconic(application.Handle) then
begin
Application.MainForm.WindowState:=wsNormal;
Application.Restore;
end;
PostMessage(HWND(LParam),MessageID,MI_QUERYWINDOWHANDLE,Application.MainForm.Handle);
end;
MI_RESPONDWINDOWHANDLE:
begin
SetForeGroundWindow(HWND(LParam));
Application.Terminate;
end;
end;
end
else Result:=CallWindowProc(WProc,Handle,Msg,WParam,LParam);
end;procedure SubClassApplication;
begin
WProc:=TFNWndProc(SetWindowLong(Application.Handle,GWL_WNDProc,Longint(@NewWndProc)));
if WProc=nil then
MIError:=MIError or MI_ERROR_FAILSUBCLASS;
end;procedure DoFirstInstance;
begin
MutHandle:=CreateMutex(nil,false,UNIQUE_APPSTR);
if MutHandle=0 then
MIError:=MIError or MI_CREATINGMUTEX;
end;procedure BroadcastFocusMessage;
var
bs:DWORD;
begin
Application.ShowMainForm:=false;
bs:=BSM_APPLICATIONS;
BroadcastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE,@bs,
MessageID,MI_QUERYWINDOWHANDLE,application.Handle);
end;procedure InitInstance;
begin
SubClassApplication;
MutHandle:=OpenMutex(MUTEX_ALL_ACCESS,false,UNIQUE_APPSTR);
if MutHandle=0 then
DoFirstInstance
else begin
BroadcastFocusMessage;
Application.Terminate;
end;
end;initialization
MessageID:=RegisterWindowMessage(UNIQUE_APPSTR);
InitInstance;
finalization
if WProc<>nil then
SetWindowLong(application.Handle,GWL_WNDPROC,Longint(WProc));
if MutHandle<>0 then
CloseHandle(MutHandle);
end.
实现单实例运行的关键是判断前一实例是否存在,Win3.x中运行的程序能获知前
一实例的句柄,从而可以方便地进行判断,但 Windows 95 是抢先式多任务系统,其
程序的前一实例句柄恒为零,所以只有另寻其他办法。目前最有效的办法是通过查看
是否有相同窗口类名的例程存在来进行判断。下面介绍在Delphi中实现的方法。
1、对主窗口程序的改动:
在主窗口(即程序创建的第一个窗口)中interface节加入
const
CM_RESTORE = WM_USER + $1000; {自定义的“恢复”消息}
MYAPPNAME = "My Delphi Program";
并在Form的定义的public节中加入
procedure CreateParams(var Params: TCreateParams); override;
Procedure RestoreRequest(var message: TMessage); message CM_RESTORE;
在implementation节中加入
{指定窗口名称}
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.WinClassName := MYAPPNAME;
end;
{处理“恢复”消息}
procedure TForm1.RestoreRequest(var message: TMessage);
begin
if IsIconic(Application.Handle) = TRUE then
Application.Restore
else
Application.BringToFront;
end;
经过以上修改,程序的主窗口的类名已经被指定了,这是进行判断的基础。一般在程
序刚开始运行的时候进行判断,所以还要对DPR文件进行修改。
2、对DPR文件的改动
在 uses 节中添加 windows、messages这两个单元加入下列语句,注意两个文件中常
量CM_RESTORE和MYAPPNAME的定义必须一致
const
CM_RESTORE = WM_USER + $1000; {自定义的“恢复”消息}
MYAPPNAME = "My Delphi Program";
var
RvHandle : hWnd;
将下列语句插到程序最前部(在Application.Initialize之前)
RvHandle := FindWindow(MYAPPNAME, NIL);
if RvHandle > 0 then
begin
PostMessage(RvHandle, CM_RESTORE, 0, 0);
Exit;
end;
这段程序的意思是如果找到一个类名相同的窗口,则向该窗口发送一个消息,并退
出,而本例中原窗口收到该消息后会自动激活或从图标还原,从而达到了避免二次运