请问如何令所写的程序不能同时打开两个?(100分)

  • 主题发起人 主题发起人 Lonelysword
  • 开始时间 开始时间
L

Lonelysword

Unregistered / Unconfirmed
GUEST, unregistred user!
请问如何令所写的程序不能同时打开两个?
 
修改一下你的dpr文件:
var li:longint;
begin
li:=FindWindow ('TfrmWinPopup', Nil);
^^^^^^^^^^^^改成你的主窗口的类名
if li<>0 then
begin
halt(0);
end;
Application.Initialize;
Application.CreateForm(TfrmWinPopup, frmWinPopup);
Application.run;
end.
 
下面是你要的答案
program Project1;

uses
Forms,windows,
Unit1 in 'Unit1.pas' {Form1};

var hw:hwnd;

{$R *.RES}
begin
Application.Initialize;
application.title:='test';
hw:=createmutex(nil,false,'test');
if getlasterror<>error_already_exists then
begin
Application.CreateForm(TForm1, Form1);
Application.Run;
end;
end.
 
cakk的不好,要是两个FORM同名怎么办?我的FORM1可是很多的呀
 
1.用查找窗口名称,就像cakk说的那样,是曹晓刚在我初学Delphi时告诉我的,
不过我嫌不好,从来没用过,理由同CJ所说;
2.用查找类名称,具体函数记不得了,是Delphi中的,每个应用程序中的类名很
少重复,这样做可以满足大部分情况,不过也不好;
3.用信号灯,我一般用CreateSemaphore(不记得这个API是不是这样写了),标准
的Win32 API,价格便宜量又足,我一直用他;
4.应用程序启动时发一条自定义消息,里面的para是启动时的时间,接受到消息后
判断一下启动时间,就可以判别了;
5.用内存文件,可以多个程序公用一块内存区域,具体做法好像在机工的那本高级
编程里面有讲,用来传递数据不错,用来做判断是否有多个程序启动有点小题大做。

还有两、三个方法记不清了,原来我总结了一大堆,瞅准机会在草晓刚面前抖了一把。 :-)

很久没有用Delphi编过程序了,本来想现编几个例子,无奈手头的机器只有32M内存,
我还开了大概有30多个Netscape窗口,也罢也罢,过几天我把Delphi摸熟了,再写例子吧!
 
最好的方法使用阻塞,
当然用finfwindowsclass 或 findwindow也可以

var
hMutex : Thandle;
WaitResult : word;
BroadcastList : DWORD;
begin
MessageID := RegisterWindowMessage('Check For Choice Previous Inst');

hMutex := createMutex(nil,false,pchar('App_Choice'));
WaitResult := WaitForSingleObject(hMutex,10);
if ( waitResult = WAIT_TIMEOUT ) then

begin
BroadcastList := BSM_APPLICATIONS;
BroadcastSystemMessage(
BSF_POSTMESSAGE,@BroadcastList,MessageID,0,0);
end
else
begin
{ do the normal stuff}
Application.Title := 'Choice Organics Purchase & Sales System';
Application.CreateForm(TMainForm, MainForm);
Application.Run;
ReleaseMutex(hMutex);
end;
CloseHandle(hMutex);
end.

This goes in the MainForm

procedure Tmainform.OnAppMessage(var Msg : TMsg Var Handled : Boolean);
begin
{ If it's the special message then focus on this window}
if Msg.Message = MessageID then // if we get the broadcast message from an
another instance of this app that is trying to start up
begin
show;
WindowState := wsMaximized;
BringToFront;
SetFocus;
Handled := true;
end;
end;

//And this goes in the TMainForm.FormCreate

Application.OnMessage:= OnAppMessage;

阻塞的方法最安全,最保险.
^0^
 
netredfox的方法似乎很麻烦.

第二个解答,我在补充一点.
application.title:='test'; //test可以自己定义名称
这种方法我在程序中用过多次,一点问题都没有!!
 
to sunstone:
互斥对象用起来是很麻烦,不过不容易出错.:-)
 
其实随便用一个就行, 只要别起太雷同的名字就行:-)
 
>>cakk的不好,要是两个FORM同名怎么办?我的FORM1可是很多的呀
起一个不容易重复的名字就可以了.就象sunstone说的:
>>>application.title:='test'; //test可以自己定义名称

原理是一样的.
 
真是各有千秋,象这样讨论老问题才不觉得乏味.
 
在深度历险里有这样的控件,我自己也改写过一个。
 
我用了一种使用原子(atom)+互斥(Mutex)+FindWindow的方法可以是程序只
运行一次,并且将应用程序调入前台。若您的应用程序注册为缺省打开为某种
扩展名文件的程序,将打开您所双击的文件,并且前台运行。
在我的一个MDI程序下通过了。

在dpr文件中:
var
hMutex : Thandle;
WaitResult : word;
Mf : DWORD;
S:String;
begin
hMutex := createMutex(nil,false,pchar(utCommon.SysName));
WaitResult := WaitForSingleObject(hMutex,10);
if ( waitResult = WAIT_TIMEOUT ) then
begin
S:=ParamStr(1);//实际上是您所双击的文件名(含路径)
Mf:=FindWindow('TMainForm', ‘主窗口的Caption');
if (Mf<>0) and (GlobalFindAtom(PChar(S))=0) then
begin
SendMessage(Mf, WM_User+1, GlobalAddAtom(PChar(S)), Length(S)+1);
WaitForSingleObject(hMutex,10);
end;
SetForegroundWindow (Mf);
end
else
begin
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
ReleaseMutex(hMutex);
end;
CloseHandle(hMutex); // close the mutex handle
end.

主窗口:
procedure TMainForm.WndProc(var Message: TMessage);
begin
if Message.Msg=WM_User+1 then
begin
FillChar(OpenFileName, Sizeof(OpenFileName),0);
GlobalGetAtomName(Message.WParam, @OpenFileName, Message.LParam);
Show;
WindowState := wsMaximized;
Application.BringToFront;
OpenTest(OpenFileName); //打开一个子窗口显示文件
GlobalDeleteAtom(Message.WParam);
end
else
Inherited WndProc(Message);
end;
 
多人接受答案了。
 
后退
顶部