在窗体上放一个pageControl然后在窗体上放置一个button,每点击一次button就多出现一个tabsheet,每tabsheet上有一个按钮与状态条,点击tabsheet上的按钮后释放当前的tabsheet,但是在释放的时候出错了
窗体上按钮的代码
var
  mytab:TTabSheet;
  myStatus:TstatusBar;
  mybutton:Tbutton;
begin
  mytab:=TTabSheet.Create(self);
  mytab.PageControl:=PageControl1;
  myStatus:=TstatusBar.Create(mytab);
  myStatus.Parent:=mytab;
  mybutton:=TButton.Create(mytab);
  mybutton.Parent:=mytab;
  mybutton.OnClick:=self.on_the_click;
end;self.on_the_click的代码
Procedure TForm1.on_the_click(Sender:TObject);
var
  aparent:TTabSheet;
begin
  try
    aParent:=TTabSheet((Sender as TButton).Parent);
    aparent.Free;//这时的parent的却是tabsheet,但是释放以后却出错,
   // 报错access viloation at *************
    // 而我自己的异常却没有捕获到,这是怎么回事情呢?
  except
     ShowMessage('error');
  end;
end;

解决方案 »

  1.   

    重新描述一下上面的话哈
    :
    在窗体上放一个pageControl,然后在pageControl外的窗体上放置一个button,每点击一次button,在pageControl上就多出现一个tabsheet,每tabsheet上有一个按钮与状态条,点击tabsheet上的按钮后释放当前的tabsheet,但是在释放的时候出错了
    窗体上按钮的代码
    var
      mytab:TTabSheet;
      myStatus:TstatusBar;
      mybutton:Tbutton;
    begin
      mytab:=TTabSheet.Create(self);
      mytab.PageControl:=PageControl1;
      myStatus:=TstatusBar.Create(mytab);
      myStatus.Parent:=mytab;
      mybutton:=TButton.Create(mytab);
      mybutton.Parent:=mytab;
      mybutton.OnClick:=self.on_the_click;
    end;self.on_the_click的代码
    Procedure TForm1.on_the_click(Sender:TObject);
    var
      aparent:TTabSheet;
    begin
      try
        aParent:=TTabSheet((Sender as TButton).Parent);
        aparent.Free;//这时的parent的却是tabsheet,但是释放以后却出错,
       // 报错access viloation at *************
        // 而我自己的异常却没有捕获到,这是怎么回事情呢?
      except
         ShowMessage('error');
      end;
    end;
      

  2.   

    你释放掉TTabSheet的时候,也就是同时也要释放TabSheet上的BUTTON。。
    而这个BUTTON则是你事件的载体BUTTON释放时,事件并没有执行完成。。这时出异常是显然的。
    FREE改成Release试试。。
      

  3.   

    halfdream(哈欠)
       象你那样说得话,就是在一个form上放一个button,然后把button的代码写成form1.free
    那么 也就是同时也要释放form1上的BUTTON。而这个BUTTON则是我事件的载体BUTTON释放时,事件并没有执行完成。。也应该发出异常了?
      

  4.   

    mybutton:=TButton.Create(mytab);修改成mybutton:=TButton.Create(self);试试看Owner通常都是所在的Form或者nil。
      

  5.   

    To: BlueTrees(蜗牛)
    改成mybutton:=TButton.Create(self);以后还是报错的,奇怪啊!
      

  6.   

    跟踪了半天源代码,很奇怪,在设计器中放置的按钮就可以在自己的事件中释放自己,动态创建的就要报错!然后检查原因,发现Click以后,消息队列中还有残留的关于这个按钮的事件,就是WM_LBUTTONUP事件,真奇怪,窗口句柄已经Destroy了,居然消息循环还能Dispatch这个消息到原来窗口的WndProc中去,这个不知道是Windows的什么毛病。然后在处理这个WM_LBUTTONUP消息的过程中,引发了错误,因为在这个处理中使用了实例的私有成员,而这个实例已经Destroy了,然后.......深入研究为什么设计器中放置的不会产生错误,明天继续。这个问题可真奇怪。
      

  7.   

    修改成Procedure TForm1.on_the_click(Sender:TObject);
    var
      aparent:TTabSheet;
    begin
      try
        aParent:=TTabSheet((Sender as TButton).Parent);
        TButton(Sender).ControlStyle:=TButton(Sender).ControlStyle+[csNoStdEvents];
        aParent.Free;//这时的parent的却是tabsheet,但是释放以后却出错,
       // 报错access viloation at *************
        // 而我自己的异常却没有捕获到,这是怎么回事情呢?
      except
         ShowMessage('error');
      end;
    end;就不会出错了,这样做就是屏蔽掉后面剩下的一个事件处理,让她不处理了。
    这真是奇怪透顶了,后来追踪发现,好像不是Windows残余的消息,但不是windows残余消息,那么又是从哪里来的呢?莫名其妙的。
      

  8.   

    弄了一下,发现如果在ObjectInspector中关联按钮的Click事件,就没有问题。如果在程序中用语句给Button的OnClick赋值,那么即使是在Delphi中放置按钮也会出错。我想也许就是这里的问题吧,但是原因我没弄清楚,呵呵。高人指点。
      

  9.   

    奇怪,怎么我的DELPHI8中没有TTabSheet控件?郁闷中
      

  10.   

    奇怪,怎么我的DELPHI8中没有TTabSheet控件?郁闷中。。
    --------------------------------------------------
    TTabSheet是在TPageConotrol放置之后,右键new添加的。
      

  11.   

    我记得看过一本书上介绍过,好像动态产生的VCL控件,调用Free的时候并没有把窗口的句柄destroy,所以会发生错误,但是如果button的parent是form的时候,当他释放form(如果form是主窗口)那么整个程序
    terminate了,所以,这时候button的句柄也就释放了,不会有错。
    解决办法好像是要调用destory...忘了,现在书不在手边,看了直后在说。
      

  12.   

    //利用PostMessage函数跳出堆栈后再释放,参考如下代码
    const
      MY_DELETETABSHEET = WM_USER + 10;type
      TForm1 = class(TForm)
        Button1: TButton;
        PageControl1: TPageControl;
        procedure Button1Click(Sender: TObject);
      private
        procedure on_the_click(Sender: TObject);
        procedure DeleteTabSheet(var Msg: TMessage); message MY_DELETETABSHEET;
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    var
      myTab: TTabSheet;
      myStatus: TStatusBar;
      myButton: TButton;
    begin
      myTab := TTabSheet.Create(Self);
      myTab.PageControl := PageControl1;
      myStatus := TStatusBar.Create(myTab);
      myStatus.Parent := myTab;
      myButton := TButton.Create(myTab);
      myButton.Parent := mytab;
      myButton.OnClick := on_the_click;
    end;procedure TForm1.DeleteTabSheet(var Msg: TMessage);
    begin
      if Msg.WParam <> 0 then TTabSheet(Msg.WParam).Free;
    end;procedure TForm1.on_the_click(Sender: TObject);
    begin
      PostMessage(Handle, MY_DELETETABSHEET, Integer(TButton(Sender).Parent), 0);
    end;
      

  13.   

    TO: zswang(伴水清清)(专家门诊清洁工) 
    麻烦你能否详细解释一下你的意思呢?
    还有就是PostMessage(Handle, MY_DELETETABSHEET, Integer(TButton(Sender).Parent), 0);
    这句代码的handle具体是谁的handle呢?
      

  14.   

    procedure DeleteTabSheet(var Msg: TMessage); message MY_DELETETABSHEET;
    谁执行消息函数,就是谁的句柄这个两个写法没区别
    Self.Handle
    Handle
      

  15.   

    在一个对象的事件中释放对象本身,真的要注意,这样的程序不能写。伴水的方法是后置释放,通过消息,然后从Tbutton的事件中退出来,然后再通过消息循环,Dispatch到Form的消息处理方法中释放Button。呵呵。绝大多数时候,对象释放后不会马上回收内存,那么在对象事件处理完成返回后,可能对象有自己的收尾代码,这些代码可能会访问对象实例的私有数据,这时候理论上对象实例已经不存在了,应该引发访问异常,但是,因为内存还没有被回收,所以访问不会引发违规。但是我始终不明白,为什么窗口句柄都释放了,为什么还会有系统消息通过消息循环Dispatch到原来窗口关联的WndProc上去,我跟踪了很久,就是搞不明白,根本没理由接受消息的。窗口句柄释放了,难道发送给这个窗口的消息还可以通过DispatchMessage发送到这个窗口过程去?Windows的什么毛病?
      

  16.   

    procedure TForm1.Button1Click(Sender: TObject);
    var
      mytab:TTabSheet;
      myStatus:TstatusBar;
      mybutton:Tbutton;
    begin
      mytab:=TTabSheet.Create(self);
      mytab.PageControl:=PageControl1;
      myStatus:=TstatusBar.Create(mytab);
      myStatus.Parent:=mytab;
      mybutton:=TButton.Create(mytab);
      mybutton.Parent:=mytab;
      mybutton.OnClick:=self.on_the_click;
    end;Procedure TForm1.on_the_click(Sender:TObject);
    var
      aparent:TTabSheet;
    begin
      try
        aParent:=TTabSheet((Sender as TButton).Parent);
        (Sender as TButton).Parent := nil; //加上这句也可以正常
        aparent.Free;
      except
        ShowMessage('error');
      end;
    end;//我实在不太愿意化太多时间想道理,那着代码改改测测出来就成了
      

  17.   

    谢谢个位高手 另有一问
    如果报错access viloation at address 00000000. read of address 00000000.
    可能是什么问题呢?
      

  18.   

    如果报错access viloation at address 00000000. read of address 00000000.
    可能是什么问题呢?访问空指针
    变量没有初始化
    指针已经被释放
    ……