我写了程序用来避免子窗体的重复打开,打开某一个窗体是没有问题的。但是当同时打开了2个窗体,再打开那个不在激活状态下的窗体时,原本打开的窗体不会被激活而是重新打开2个相同的子窗体,这是怎么回事啊?!
代码是这样的
Procedure TF_MPSSAEass.OpenMDIWin(Sender:TFormclass);   //避免子窗体重复打开
var
  i:integer;
  Frm:TForm;
begin
  if F_MPSSAEass.MDIChildCount=0 then            //先打开一个子窗体
  begin
    Frm:=Tform(Sender.NewInstance);
    Frm:=Frm.Create(self);
    Frm.Show;
    exit;
  end;
  for i:=0 to F_MPSSAEass.MDIChildCount-1 do   //当已有子窗体打开时判断是否处于最小话或不可见状态
  begin
    if F_MPSSAEass.MDIChildren[i].ClassType=Sender then
    begin
      Frm:=F_MPSSAEass.MDIChildren[i];
      if Frm.WindowState=wsMinimized then
        showwindow(Frm.Handle,sw_shownormal)
      else
        showwindow(Frm.Handle,sw_showna);
      if (not Frm.Visible ) then
        Frm.Visible :=True;
      Frm.BringToFront;
      Frm.SetFocus;
      Frm.WindowState:=wsMaximized;
      exit;
    end;
    Frm:=Tform(Sender.NewInstance);   //如果上面两种状态都不是则创建新窗体
    Frm:=Frm.Create(self);
    Frm.Show;
  end;
end;

解决方案 »

  1.   

    我再解释下哈。比如说有2个子窗体frm1,frm2,用上面的程序打开frm1,再次打开frm1也不会有问题(只会打开一个)。然后frm1不关闭,打开frm2,frm2被打开后是激活状态,frm1就不是激活状态了。这是再打开frm1,将会同时新打开2个frm1窗体,也就是这是实际上已打开了3个frm1窗体了!
      

  2.   

    逻辑有问题,以下代码每个不是Sender:TFormclass实例的都会执行
    Frm:=Tform(Sender.NewInstance);  //如果上面两种状态都不是则创建新窗体 
    Frm:=Frm.Create(self); 
    Frm.Show; 
      

  3.   

     if application.FindComponent('frm1')=nil then
          begin
            application.CreateForm(Tfrm1,frm1);
            frm1.Show;
          end; if application.FindComponent('frm2')=nil then
          begin
            application.CreateForm(Tfrm2,frm2);
            frm2.Show;
          end;这样就行了,共勉
      

  4.   

    谢谢楼上的,我想把它写成通用过程,方便调用
    Procedure TF_MPSSAEass.OpenMDIWin(Sender:TFormclass); 
    var
    Frm:TForm;
    begin
    if application.FindComponent('Frm')=nil then
      begin
        application.CreateForm(TFrm,Frm);  //这里报错
        Frm.Show;
      end;
    end;
      

  5.   

    可以試試openMutex函數,他是一个互斥句柄OpenMutex(
    dwDesiredAccess:DWORD;
    bInheritHandle:Boolean;
    lpName:PChar
    ):THandle;代碼形式如下:var
      Form1: TForm1;
      MutexHandle:Integer;procedure TForm1.Button1Click(Sender: TObject);
    begin
      if OpenMutex(MUTEX_ALL_ACCESS, FALSE, 'RunOnceMutex') <> 0 then
      begin
        Showmessage('this is open');
        exit;
      end;
      MutexHandle:=CreateMutex(nil,true,'RunOnceMutex');  application.CreateForm(Tform2,form2);
      form2.Show;  ReleaseMutex(MutexHandle);
    end;
      

  6.   

    直接用个LIST把你打开的FormName和handle存起来,下次先进去搜FormName,如果有了,就用handle把窗口显示出来但是子窗口关闭的时候要给主窗口发个消息,从List里删除这个窗口
      

  7.   

    //用这个吧!我一直在用的,源于大富翁的代码var
      ZAppName          : array[0..127] of char;
      Hold              : string;
      Found             : HWND;
    procedure TfmMain.FormCreate(Sender: TObject);
    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;
      

  8.   

     if F_MPSSAEass.MDIChildren[i].ClassType is Sender then 能不能可靠我也没试过不过还可以用 if F_MPSSAEass.MDIChildren[i].ClassName = Sender.ClassName then 或创建时设.Tag    用Tag来识别
      

  9.   

    Frm.ShowModal; 就可以搞定了
      

  10.   

    楼上的可以,但是打开frm1后,其他就不能操作了尝试这样写下
    if not assigned(frm1) then
      frm1 := Tfrm1.create(nil);
    frm1.show;
      

  11.   

    procedure  TRootMainForm.OpenForm(FormClass: TFormClass; var fm; AOwner:TComponent);
    var
       i: integer;
       Child:TForm;
     begin
       for i := 0 to Screen.FormCount -1 do
       if Screen.Forms[i].ClassType=FormClass then
       begin
          Child:=TForm(Screen.Forms[i]);
          if Child.WindowState=wsMinimized then
          ShowWindow(Child.handle,SW_SHOWNORMAL)
          else
          ShowWindow(Child.handle,SW_SHOWNA);
          if (not Child.Visible) then Child.Visible:=True;
          Child.BringToFront;
          Child.Setfocus;
          TForm(fm):=Child;
          exit;
       end;
       Child:=TForm(FormClass.NewInstance);
       TForm(fm):=Child;
       Child.Create(AOwner); 
    end;
      

  12.   

    这个我用了N年了。没有大问题。
    有时会有充满的问题。
    用于主窗体打开MDI子窗体。
      

  13.   

    if not assigned(form1) then 
      form1:= Tform1.create(nil); 
      

  14.   

    if not assigned(frm1) and frm1 =nil then 
    begin
       //
    end;
      

  15.   

    这个人说的是对的,不过还要改一改if not assigned(frm1) then 
      frm1 := Tfrm1.create
    else
      frm1.bringtofront; 
    //show的过程包括create和onshow两个事件,bringtofront只会把窗体制前。