在起动后用
findwindow或findwindowex查找自己的类或窗口,
如果已经存在就给它发消息。

解决方案 »

  1.   

    implementation 
    var hnd: THandle;initialization
        hnd := CreateMutex(nil, True, 'irgendwaseinmaliges');
        if GetLastError = ERROR_ALREADY_EXISTS then Halt;finalization
        if hnd <> 0 then CloseHandle(hnd);
    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文件进行修改。begin  Application.Initialize;
      Application.Title := 'xxx管理系统;
      hMutex:=CreateMutex(nil,False,'xxx管理系统');
      Ret:=GetLastError;
      If Ret<>ERROR_ALREADY_EXISTS Then
       Begin
       Application.CreateForm(TajMAIN, ajMAIN);  Application.Run;
       End
      Else
       Application.MessageBox('已经运行!','注意!',MB_OK);
       ReleaseMutex(hMutex);end.
      

  2.   

    implementation 
    var hnd: THandle;initialization
        hnd := CreateMutex(nil, True, 'irgendwaseinmaliges');
        if GetLastError = ERROR_ALREADY_EXISTS then Halt;finalization
        if hnd <> 0 then CloseHandle(hnd);
    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文件进行修改。begin  Application.Initialize;
      Application.Title := 'xxx管理系统;
      hMutex:=CreateMutex(nil,False,'xxx管理系统');
      Ret:=GetLastError;
      If Ret<>ERROR_ALREADY_EXISTS Then
       Begin
       Application.CreateForm(TajMAIN, ajMAIN);  Application.Run;
       End
      Else
       Application.MessageBox('已经运行!','注意!',MB_OK);
       ReleaseMutex(hMutex);end.
      

  3.   

    我用了一种使用原子(atom)+互斥(Mutex)+FindWindow的方法可以是程序只
    运行一次,并且将应用程序调入前台。若您的应用程序注册为缺省打开为某种
    扩展名文件的程序,将打开您所双击的文件,并且前台运行。在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;
      

  4.   

    我这里有个问题了:
       如果用FindWindow这样的API查找到窗体,再用ShowWindow(hWnd,SW_SHOWNORMAL);这个API恢复窗体,此时该窗体就不能最小化了。点标题栏上的最小化按钮无效!这也是大问题