我想让我的应用程序只允许一次
请问怎么做啊
还有就是 如果我有父窗体和子窗体
父窗体的button1  事件如下:
Form2:=TForm2.create(self);
我按了button几次,它就创建了几个form2
我想做的是
如果form2 已经创建了就不创建了
直接show就可以了

解决方案 »

  1.   

    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;
    这段程序的意思是如果找到一个类名相同的窗口,则向该窗口发送一个消息,并退出,而本例中原窗口收到该消息后会自动激活或从图标还原,从而达到了避免二次运行且能自动调出前一例程的目的。
     
    检测程序是否运行 
      在某些情况下,我们编写的应用程序同时只能有一个实例在内存中运行,例如服务器程序、需要独占某设备的程序,甚至我们仅仅是让程序同时只有一个实例运行(如UltraEdit就是这样做的,让你不能同时运行多个UltraEdit)。要实现此功能,需要在程序中加一点判断的代码,在Windows 95或Win32环境下的Delphi版本中实现的程序如下:
    按Ctrl+F12键,选择Project1,加入下列语句
    program Project1;
    uses
    windows, {加入该句才能调用函数}
    Forms,
    Unit1 in 'Unit1.pas'{Form1};
    {$R *.RES}
    const classname='TForm1'; {声明为主窗体的类名}
    var handle:integer; {变量}
    begin
    {-----------------主要为该判断部分----------------------}
    handle:=findwindow(classname,nil);{查找是否有此类的窗体}
    if handle<>0 then {不为0则程序已运行}
    begin
    messagebox(0,'该程序已经有一个在运行中!','运行',0);{提示程序已运行}
    halt; {退出程序}
    end;
    {------------------------------------------------------}
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
    end.
      

  2.   

    if not Assigned(Form2) then
    Form2:=TForm2.create(self);
    Form2.show;这样就OK啦
      

  3.   

    只运行一次
    begin
      CreateMutex(nil, True, 'hlyy');
      if GetLastError = ERROR_ALREADY_EXISTS then
        begin
          MessageBox(0, '某某系统已经运行了', '运行错误!',
            MB_ICONERROR);
          Halt;
        end;
    引用windows单元
      

  4.   

    这样
    if Not assigned(frmChild) then
      frmChild:=TfrmChild.create(Self);
    try
      frmChild.ShowModel;
    finally
      frmChild.free;
      frmChild:=Nil;
    end;
    已经创建的就不会再创建,只能Show出来
      

  5.   

    var h:integer;
    begin
      H :=FindWindow('TForm1', nil);
      if H=0 then
      begin
       Application.Initialize;
       Application.CreateForm(TForm1, Form1);
       Application.Run;
      end
      else
      begin
      showmessage('程序已经启动');
      SetActiveWindow(H);
      end;
    用这段试试
      

  6.   

    只能用一次的话:写注册表、INI都可以,不过……
      

  7.   

    通过互斥操作,避免同时产生两个执行程序的实例
    program programname;
    {$R *.res}
    uses
    ......
    var
      hMutex: THandle;
    begin
      hMutex:= CreateMutex(nil, true, PChar(ExtractFileName(Application.ExeName)));
      if GetLastError = ERROR_ALREADY_EXISTS then
      begin
        ReleaseMutex(hMutex);
        Halt;
      end;
      Application.Initialize;
      .....
      Application.Run;
    end.
      

  8.   

    unit Unit1;interface
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;Const
        CM_Restore=WM_User+$1000;{自定义的"恢复"消息}
        MyAppName='MyDelphiProgram';
    type
      TForm1 = class(TForm)
      private
        { Private declarations }
      public
        Procedure CreateParams(var Params:TCreateParams);override;
        Procedure RestoreRequest(var message:TMessage);message CM_Restore;
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}{指定窗口名称}
    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;end.
      

  9.   

    program programname;
    {$R *.res}
    uses
    ......
    var
      hMutex: THandle;
    begin
      hMutex:= CreateMutex(nil, true, PChar(ExtractFileName(Application.ExeName)));
      if GetLastError = ERROR_ALREADY_EXISTS then
      begin
        ReleaseMutex(hMutex);
        Halt;
      end;
      Application.Initialize;
      .....
      Application.Run;
    end.
      

  10.   

    这个问题已经出现过很多次了,一共有几种办法,建立互斥变量(也就是临界资源),还有就是窗体枚举判断,最妥当的是用map
      

  11.   

    if not Assigned(Form2) then
    Form2:=TForm2.create(self);
    Form2.show;
      

  12.   

    Form2 := TForm2.Create(Self);
    if Form2 <> nilthen
      Form2.show
    else
      Exit;
      

  13.   

    错了,应该是这样:
    if  Form2 = nil then  Form2 := TForm2.Create(Self)else
      
      Form2.Show;
      

  14.   


    工程文件实现的话如下:program Project1;uses
      Windows,
      Messages,
      Forms,
      Unit1 in 'Unit1.pas' {Form1};{$R *.RES}var
      AppWnd, MainWnd: HWND;  I: Integer;
      ParamString: string;  CopyDataStruct: TCopyDataStruct;
    begin  AppWnd := FindWindow('TApplication', 'This is my project title');
      if AppWnd <> 0 then
      begin 
        if IsIconic(AppWnd) then 
          ShowWindow(AppWnd, SW_RESTORE)
        else 
          SetForegroundWindow(AppWnd);
        Exit;
      end;  Application.Initialize;
      Application.Title := 'This is my project title';
      Application.CreateForm(TForm1, Form1);
      Application.Run;
      

  15.   

    in delphi menu project  option item set the form2 >> active(auto make); in button event you use form2.show
      

  16.   

    最简单解决方法:
    procedure tform1.button1click;
    begin
        form2.free;
        application.creatform(tform2,form2);
        form2.show; 
    end;
      

  17.   

    对于第一个问题,大家都说得很明白了。第二个问题,用Singleton解决:
    在interface 下,implementation上声明一个公用方法:  function Execute: TForm2;implementationvar
      frm: TForm2 = nil;function Execute: TForm2;
    begin
      if frm = nil then
        frm := TForm2.Create(Application);
      Result := frm; 
    end;当然,不要忘记:
    procedure TForm2.FormDestroy(Sender: TObject);
    begin
      FreeAndNil(frm);
    end;
      

  18.   

    if Not assigned(form2) then
      frmChild:=TfrmChild.create(TForm2,Form2);
    try
      Form2.ShowModel;
    finally
      Form2.free;
      Form2:=Nil;
    end;
      

  19.   

    把下面的代码存为MultInst.pas,然后在工程中加入它就可以了
    注意:把STR_UNIQUE设置为你的字符串,可以生成一个GUDI,每个软件使用不同的GUID就不会有错//==============================================================================
    // Unit Name: MultInst
    // Author   : ysai
    // Date     : 2003-05-20
    // Purpose  : 解决应用程序多实例问题
    // History  :
    //==============================================================================//==============================================================================
    // 工作流程
    // 程序运行先取代原有向所有消息处理过程,然后广播一个消息.
    // 如果有其它实例运行,收到广播消息会回发消息给发送程序,并传回它自己的句柄
    // 发送程序接收到此消息,激活收到消息的程序,然后关闭自己
    //==============================================================================
    unit MultInst;interfaceuses
      Windows ,Messages, SysUtils, Classes, Forms;implementationconst
      STR_UNIQUE    = '{1E1084F3-A7FA-49B0-BEF4-CBF1F5451962}';
      MI_ADDMESSAGE = 0;  //新增一条消息
      MI_ACTIVEAPP  = 1;  //激活应用程序
      MI_GETHANDLE  = 2;  //取得句柄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: //激活应用程序
            if lParam<>0 then
            begin
              //收到消息的激活前一个实例
              //为什么要在另一个程序中激活?
              //因为在同一个进程中SetForegroundWindow并不能把窗体提到最前
              if IsIconic(lParam) then
                OpenIcon(lParam);
              ShowWindow(lParam,SW_SHOW);
              SetForegroundWindow(lParam);
              //终止本实例
              Application.Terminate;
            end;
          MI_GETHANDLE: //取得程序句柄
            begin
              PostMessage(HWND(lParam), iMessageID, MI_ACTIVEAPP,
                Screen.ActiveForm.Handle);
            end;
        end;
      end
      else
        Result := CallWindowProc(OldWProc, Handle, Msg, wParam, lParam);
    end;procedure InitInstance;
    begin
      //取代应用程序的消息处理
      OldWProc    := TFNWndProc(SetWindowLong(Application.Handle, GWL_WNDPROC,
        Longint(@NewWndProc)));  //打开互斥对象
      MutHandle := OpenMutex(MUTEX_ALL_ACCESS, False, STR_UNIQUE);
      if MutHandle = 0 then
      begin
        //建立互斥对象
        MutHandle := CreateMutex(nil, False, STR_UNIQUE);
      end
      else begin
        Application.ShowMainForm  :=  False;
        //已经有程序实例,广播消息取得实例句柄
        BSMRecipients := BSM_APPLICATIONS;
        BroadCastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE,
            @BSMRecipients, iMessageID, MI_GETHANDLE,Application.Handle);
      end;
    end;initialization
      //注册消息
      iMessageID  := RegisterWindowMessage(STR_UNIQUE);
      InitInstance;finalization
      //还原消息处理过程
      if OldWProc <> Nil then
        SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(OldWProc));  //关闭互斥对象
      if MutHandle <> 0 then CloseHandle(MutHandle);end.
      

  20.   

    上面是转贴!
    我试了,只要把代码贴进去就ok!
    就能限制程序只运行一次.
    至于第二个问题简单.
    if not Assigned(Form2) Form2 := TForm2.Create(Application);
    Form2.Show;
    然后在Form2.CloseQuery中加
    Form2 := nil;