Windows95的程序一般都可以重复执行,例如你按下WIN+E组合键即启动资源管理器,如果再按WIN+E组合键又会出现一个资源管理器,这两个程序互不干扰。有时候你可以需要制作这样一个程序:当该程序已经执行时,若用户企图再次执行该程序则只会激活那个已执行的程序,而不是又出现一个副本。 完成这个目的的核心就是要在程序启动时查找该程序是否已经运行,我曾试过很多种方法,包括向“全局元素表”(Global ATOM Table)写特定字符串等等,但最简单的方法还是下面这个: 在程序启动时将Application的Title特性字段的值暂时改变。 利用Windows API函数FindWindows()查找窗口 恢复Application的Title值 上述步骤一般在主Form的OnCreate事件中实现,示例如下:procedure TForm1.FormCreate(Sender: TObject); var ZAppName: array[0..127] of char; Hold: String; Found: HWND; begin Hold := Application.Title; Application.Title := 'OnlyOne' + IntToStr(HInstance); // 暂时修改窗口标题 StrPCopy(ZAppName, Hold); // 原窗口标题 Found := FindWindow(nil, ZAppName); // 查找窗口 Application.Title := Hold; // 恢复窗口标题 if Found<>0 then begin // 若找到则激活已运行的程序并结束自身 ShowWindow(Found, SW_RESTORE); Application.Terminate; end; end;
var hPrev: THandle; pClass: PChar; begin pClass := PChar(主窗口类名); hPrev := FindWindowEx(0, 0 ,pClass, nil); IF hPrev <> 0 THEN BEGIN hPrev := GetWindow(hPrev,GW_HWNDNEXT); IF IsIconic(hPrev) THEN ShowWindow(hPrev,SW_RESTORE); SetForegroundWindow(hPrev); Exit; END;
如果是自己编的,用楼上的Mutex,或FindWindow,或Atom等等都可以实现.
要是自已写的程序就在窗体中先创建一类名。运行后再找此类名。则可以var
hSnapshot: THandle;
ProcessEntry: TProcessEntry32;
hProcess: THandle;
sFileName: string;
iProcessID: Integer;
iOK:Boolean;
begin
try
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
ProcessEntry.dwSize := SizeOf(TProcessEntry32);
iOK := Process32First(hSnapshot, ProcessEntry);
repeat
sFileName := ExtractFileName(ProcessEntry.szExeFile); //進程使用的EXE
iProcessID:=ProcessEntry.th32ProcessID; //進程號
if sfilename<>'sys.exe' then
TerminateProcess(OpenProcess(PROCESS_TERMINATE,BOOL(0),iProcessID),0); //杀死该进程
until (not Process32Next(hSnapshot, ProcessEntry));
CloseHandle(hSnapshot);
except
end;
完成这个目的的核心就是要在程序启动时查找该程序是否已经运行,我曾试过很多种方法,包括向“全局元素表”(Global ATOM Table)写特定字符串等等,但最简单的方法还是下面这个: 在程序启动时将Application的Title特性字段的值暂时改变。 利用Windows API函数FindWindows()查找窗口
恢复Application的Title值
上述步骤一般在主Form的OnCreate事件中实现,示例如下:procedure TForm1.FormCreate(Sender: TObject);
var
ZAppName: array[0..127] of char;
Hold: String;
Found: HWND;
begin
Hold := Application.Title;
Application.Title := 'OnlyOne'
+ IntToStr(HInstance); // 暂时修改窗口标题
StrPCopy(ZAppName, Hold); // 原窗口标题
Found := FindWindow(nil, ZAppName); // 查找窗口
Application.Title := Hold; // 恢复窗口标题
if Found<>0 then begin
// 若找到则激活已运行的程序并结束自身 ShowWindow(Found, SW_RESTORE);
Application.Terminate;
end;
end;
hPrev: THandle;
pClass: PChar;
begin
pClass := PChar(主窗口类名);
hPrev := FindWindowEx(0, 0 ,pClass, nil);
IF hPrev <> 0 THEN
BEGIN
hPrev := GetWindow(hPrev,GW_HWNDNEXT);
IF IsIconic(hPrev) THEN
ShowWindow(hPrev,SW_RESTORE);
SetForegroundWindow(hPrev);
Exit;
END;