一个frmMain为MDIForm,一个form1为MDIChild,
点击frmMain上有一个btn1按钮,btn1的单击事中件代码   if Form1=nil then form1:=TForm1.Create(nil);  Form1.Show; 
在form1的close事件中代码 FreeAndNil(form1);
form1上有一个btn1按钮,btn1的单击事中件代码 Self.Close; frmMain具体代码如下procedure TfrmMain.btn1Click(Sender: TObject);
begin
  if Form1=nil then form1:=TForm1.Create(nil);
  Form1.Show;
end;
form1具体代码如下procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FreeAndNil(form1);
end;procedure TForm1.btn1Click(Sender: TObject);
begin
  Self.Close;
end;
 
问题是,如果通过单击Form1窗体右上角自带的关闭按钮来关闭窗体,则不报错。
如果通过单击Form1上的btn1按钮来关闭窗体,则报如下错误
为什么两个关闭方法一个正常一个却报错呢?

解决方案 »

  1.   

    再mdiform 里 调用与销毁是 这样的//主窗体调用
      if not Assigned(FrmOrd) then
      begin
        Application.CreateForm(TFrmOrd, FrmOrd);
        FrmOrd.Show;
      end;//子窗体销毁
    procedure FrmOrd.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Action := caFree;
      FrmOrd:= nil;
    end;
      

  2.   

    试了一下,问题出在TForm1.Create(nil)把它改为TForm1.Create(Application);至于为什么会报错不太清楚,建议楼主用D自带的MDI APP生成一个试一下,在New->Others->Projects里面就有MDI Application,里面在创建MDI Child的时候Owner也是设置为Application。另外个人觉得在Close里面用FreeAndNil(form1);去释放对象的方式感觉不太好,FreeAndNil一般是在外部调用的,很少在类内部使用。
      

  3.   

    请教chinawcs:
    if not Assigned(FrmOrd) then
      begin
        Application.CreateForm(TFrmOrd, FrmOrd);
        FrmOrd.Show;
      end;
    Assigned是什么功能函数呢?
      

  4.   

    Assigned  这个不知道吗  ?相当于nil 判断 
      

  5.   

    关于delphi Assigned 1.根据 Delphi 指令参考手册中说明:
    Assigned 函式在参数不为nil时传回True,表示指针已经指到某个内存地址,这个内存地址可能是一个对象地首地址,也可能在函数或过程中,声明一个指针变量,没有赋值为nil ,无乱的指向某处,这两个种情况,Assigned(指针变量)都不为nil , 函数放回True;而参数为nil时则传回False。
    Assigned 并不是一个真正的函数。技巧:
    用呼叫 Assigned 的方式来取代直接把参数拿来和nil比较,效率会更好。
    2.这个问题要从内存方面来解释
    当你建构一个物件 SomeComponet.Create(Owner);
    系统会有一个指针指向这个对象
    当你解构一个物件 SomeComponet.Free;
    系统会将指针指到的东西杀掉,但是指针还是指在相同的位置
    请注意计算机的资源是有限的,
    所以可能下一步你的程序要跟系统要资源,
    刚才的指针位置,就出现了其它的数据
    If Assigned(SomeComponet) then SomeComponet := nil;
    先检查这个对象有没有在其它地方被设成 nil,
    然后再将它设成 nil 。
    3
    function Assigned(var P): Boolean;DescriptionUse Assigned to determine whether the pointer or procedure referenced by P is nil. P must be a variable reference of a pointer or procedural type. Assigned(P) corresponds to the test P<> nil for a pointer variable, and @P <> nil for a procedural variable.Assigned returns False if P is nil, True otherwise.检查指针指向的参考变量或过程是否为nil每次我通常的处理方法都是:if assigned(frm) then frm.close;   但是当下次调用时就会出错。为什么呢,
    frm.close;frm.free; 只是指定这块内存可以重写,并未释放为NIL 因此当下次调用时,即使frm.free已经
    执行过,assigned(frm)仍为TRUE,再次释放 frm.Close 或者 frm.free 肯定会报错;因为frm.Close或frm.free 是释放对象指针frm 指向的内存空间,在上次已经释放调了,但是 frm 本身并没有 初始化为 nil ,相反它还是指向被释放的内存地址;东西已经没有了,没有地东西去释放,不报错错才怪。正确的处理方法:if assigned(frm) then 
    begin
       frm.close;
       frm:=nil;
    end;或:if assigned(frm) then 
    begin
    frm.close;
    freeandnil(frm);
    end;
      

  6.   

    回复Jekhn:你用的delphi的版本是7.0的么?我将
    if Form1=nil then form1:=TForm1.Create(nil);
    改为
    if Form1=nil then form1:=TForm1.Create(Application);点击Form1的btn1关闭Form1时,仍报错!
      

  7.   

    我是在D7下测试的,要不你把你的工程打包上传到CSDN,可能跟你的某些设置也有关系,或者按照我跟你说的用自带的MDI APP试一下。
      

  8.   

    回复Jekhn:上传到CSDN什么位置呢?
    我上传上,你下载看一看,看在你的机器上是否也报错。
    谢谢!
      

  9.   

    回复Jekhn:
    上传到CSDN什么位置呢?
    我上传后,你下载看一看,看在你的机器上是否报错。
    谢谢!
      

  10.   

    CSDN就可以,在我的社区,我的资源里面,你把积分设置为0就行了,这样下载就不用积分了。
      

  11.   

    现在改成
    if Form1=nil then form1:=TForm1.Create(nil);
    也不报错了估计是delphi生成的exe跟windows的兼容性的问题吧。搞不清了。