procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2 := TForm2.Create(nil);
end;procedure TForm1.Button2Click(Sender: TObject);
begin
  Form2.Show;
end;procedure TForm1.Button3Click(Sender: TObject);
begin
  Form2.Free;
end;procedure TForm1.Button4Click(Sender: TObject);
begin
  if Assigned(Form2) then ShowMessage('OK') else ShowMessage('NOT');
end;
如何在按BUTTON2之前知道FORM2已经创建并且是一个有效的对象?(注意:如何判断是一个有效的对象?)

解决方案 »

  1.   

     if form2<>nil then
     begin
      有效
     end;
      

  2.   

    if Form2 <> nil then
      Form2.show
      

  3.   

    是否创建就是上面有的:Assigned(Form2)判断是一个有效的对象?请问“有效的对象”是指怎样“有效”呢
      

  4.   


    简单的说有效对象是指可以正常使用的。首先Form2没有被Create的时候,Assigned(Form2)是False,当然Form2肯定是无效的。这个没有问题,然后我们Form2 := TForm2.Create 创建了一个实例,此时我们Assigned(Form2)是True,答案也是肯定的。此时我们可以执行Form2.Free将Form2释放后,这个时候再用Assigned(Form2)来判断是否是有效的对象就不行了。这个就是我说的是否有效了。
      

  5.   

    楼主问题提得好。这个问题我也研究过。一直没结果。以下思路的方向有问题,并不能从根本上解决问题。但还是贴出来。
    implementation
    uses Unit2;
    {$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
      Form2 := TForm2.Create(Application);{注意这里加了Owner为Application}
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      Form2.Show;
    end;procedure TForm1.Button3Click(Sender: TObject);
    begin
      Form2.Free;
    end;procedure TForm1.Button4Click(Sender: TObject);
    begin
      if Assigned(Form2) and (Application.FindComponent('Form2') <> nil) then
        ShowMessage('OK') else ShowMessage('NOT');
    end;
    再就是尽量使用FreeAndNil()释放对象,就可以避免用Assigned()检查失败了
      

  6.   

    TO: lihuasoft恩,这个也是困扰我的一个问题。呵呵。我有一个项目是MDI模式的,MainForm为EXE,ChildForm为DLL方式的。ChildForm创建后可以传递给MainForm,但是ChildForm一旦caFree后,MainForm就无法跟踪他了。我目前做法是关闭时通过给mainForm发送一条消息来跟踪。所以才会提问,看有没有什么好的方法来得知对象是否有效。
      

  7.   

    Assigned仅能判断对象引用是否为Nil,达不到对对象实体的检测!
    而平时我们仅用Free来释放对象,这样仅释放堆上的对象实体,而对栈上的对象引用没做任何操作!
    所以在释放对象时,需要FreeAndNil
      

  8.   


    我有一个项目是MDI模式的,MainForm为EXE,ChildForm为DLL方式的。ChildForm创建后可以传递给MainForm,但是ChildForm一旦caFree后,MainForm就无法跟踪他了。我目前做法是关闭时通过给mainForm发送一条消息来跟踪。所以才会提问,看有没有什么好的方法来得知对象是否有效。也就是说有2个指向一个实例(通过指针赋值的)。一个指针在exe里(Ptr1),一个指针在dll里(Ptr2),通过dll里窗体执行caFree来释放并关闭ChildForm(Ptr2),可以设置FreeAndNil(Ptr2)随便你怎么处理,但是exe里(Ptr1)的指针还是有所指向的。这样就导致exe和dll之间的管理、控制关系的脱节。
      

  9.   


    我有一个项目是MDI模式的,MainForm为EXE,ChildForm为DLL方式的。ChildForm创建后可以传递给MainForm,但是ChildForm一旦caFree后,MainForm就无法跟踪他了。我目前做法是关闭时通过给mainForm发送一条消息来跟踪。所以才会提问,看有没有什么好的方法来得知对象是否有效。 也就是说有2个指向一个实例(通过指针赋值的)。一个指针在exe里(Ptr1),一个指针在dll里(Ptr2),通过dll里窗体执行caFree来释放并关闭ChildForm(Ptr2),可以设置FreeAndNil(Ptr2)随便你怎么处理,但是exe里(Ptr1)的指针还是有所指向的。这样就导致exe和dll之间的管理、控制关系的脱节。
      

  10.   

    function IsVCLObj(const objptr : Pointer) : Boolean;
    var classPtr, tmpptr: Pointer;
    begin
      Result := False;
      if objptr = nil then Exit;  classPtr := PPointer(objptr)^;
      while (classPtr <> nil) and (classPtr <> TObject) do
      begin
        tmpptr := Pointer(Integer(classPtr) + vmtParent);
        if IsBadReadPtr(tmpptr, Sizeof(Pointer)) or
           IsBadReadPtr(PPointer(tmpptr)^, Sizeof(Pointer)) then
           break;
        classPtr := PPointer(PPointer(tmpptr)^)^;
      end;
      Result := classPtr = TObject;
    end;
      

  11.   

    if Assigned(Form2) then ShowMessage('OK') else ShowMessage('NOT');
      

  12.   

    既然你用2个指针指向MDI,在释放MDI时,肯定要多维护一个指针!
      

  13.   

    思路的问题,原则上应该是由谁创建就要由谁释放。
    如果窗体对象是在DLL中的导出函数创建的,那么就由DLL中导出一个释放窗体的函数,那么需要释放的时候,就由EXE调用这个导出函数来释放窗体对象,顺便把EXE中的窗体对象指针置为nil。
    如果窗体对象是由DLL中的导出类在EXE中创建的,那么就直接在EXE中释放掉,顺便把EXE中的窗体对象指针置为nil。
      

  14.   


    有想过应该可以通过VMT来解决这个我问题,但是思想还没有成熟。多谢coffeemay的代码。上面的对话已经说明了不能简单的用Assigned来判断对象是否有效。上面我也给出了我的维护方法了,我在考虑有没有更好的方法来解决。原则是原则,具体的程序千变万化的。如果由DLL中导出释放函数,那必然是由EXE来调用的。我现在的问题是DLL自己把自己关闭了,EXE是处于被动的。所以无法跟踪DLL的真正状态了。
      

  15.   

    使用 freeandnil(Form2); 释放