一个控件,在按了键盘的delete或del键后自己destory掉procedure TA.keydown(var Key: Word; Shift: TShiftState);
begin
  inherited;
  if (Key = 46) or (key=110) then
  begin
    key := 0;
    Self.Free; 
    Abort;   //没有这句要出错,好象还要处理其他消息,这样做会不会有内存泄露,有没有什么更好的处理办法
  end;
end;

解决方案 »

  1.   

    加Abort可以,这个要看一下TWinControl的代码就知道为什么不加Abort就报错了。
    只能大概解释一下:
    因为在事件中调用Self.Free以后,TWinControl还要要执行一些其它的代码,而这些
    代码会访问到一些TWinControl的对象成员,而你的对象都Free了,这样出错就是必然的了
      

  2.   

    没事不会有内存泄露的!
    更好的方法可以这样:
    procedure TA.keydown(var Key: Word; Shift: TShiftState); 
    begin 
      inherited; 
      if (Key = 46) or (key=110) then 
      begin 
        key := 0; 
        Self.Close;  
        ////Abort;   //没有这句要出错,好象还要处理其他消息,这样做会不会有内存泄露,有没有什么更好的处理办法 
      end; 
    end
    然后在Form.onClose事件里写
    Action := caFree;
    这样就不会出错了
      

  3.   

    谢谢楼上,但如果不Abort的话,KeyDown中就出错了,已经等不到执行Form的OnClose了
      

  4.   

    直接Free不会出错,请看下面的测试代码:type
      TMyCheckBox = class(TCheckBox)
      protected
        procedure KeyDown(var Key: Word; Shift: TShiftState); override;
      end;  TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
        IsCreate: Boolean;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}{ TMyCheckBox }procedure TMyCheckBox.KeyDown(var Key: Word; Shift: TShiftState);
    begin
      inherited;
      if (Key = 46) or (key=110) then
      begin
        key := 0;
        Self.Free;
        Form1.IsCreate := False;
      end;
    end;// 建立自定义控件
    procedure TForm1.Button1Click(Sender: TObject);
    var
      CheckBox: TMyCheckBox;
    begin
      if not IsCreate then
      begin
        CheckBox := TMyCheckBox.Create(Self);
        CheckBox.Parent := Self;
        CheckBox.SetFocus;
        IsCreate := True;
      end;
    end;// 检查窗口拥有的元件数和控件数
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      ShowMessage(IntToStr(ControlCount) + ';' + IntToStr(ComponentCount));
    end;
      

  5.   

    procedure TA.keydown(var Key: Word; Shift: TShiftState);  
    begin  
      inherited;  
      if (Key = 46) or (key=110) then  
      begin  
        key := 0;  
        Self.Close; ///!!是Close不是Self.Free
        ////Abort;   //没有这句要出错,好象还要处理其他消息,这样做会不会有内存泄露,有没有什么更好的处理办法  
      end;  
    end 
      

  6.   

    to  maozefa 阿发伯:
       如果-----------------------------------------
    procedure TForm1.Button1Click(Sender: TObject);
    var
      CheckBox: TMyCheckBox;
    begin
      if not IsCreate then
      begin
        CheckBox := TMyCheckBox.Create(Self);
        CheckBox.Parent := Self;
        CheckBox.SetFocus;
        IsCreate := True;
      end;
    end;
    ----------------------------------的话,那TMyCheckBox就只能创建一个,删除后才能创建第二个了,不符合要求,即使去掉IsCreate := True; 创建多个TMyCheckBox后逐个删除还是会不定时地出错.
      

  7.   

    另外TMyCheckBox在创建的时候还不能确定它是否是放在Form1上,所以不能使用Form1.IsCreate := False;
      

  8.   

    另外TMyCheckBox在创建的时候还不知道它是否是放在Form1上,所以不能使用 Form1.IsCreate := False;
      

  9.   

    感谢两位的答复,to maozefa 阿发伯:
       用你的方法在创建多个对象时,在删除中仍然会不确定地弹出错误.
       看起来象是对象被Free后,消息队列中仍然有消息要处理这个对象导致的错误,有没有较好的方法象很多软件一样,按delete键就将其删除?谢谢!to blazingfire ...该充电了...
       这个对象不是Form类,没有Close方法,而且也不希望在删除它的时候将窗体关闭了,有什么更好的办法吗?谢谢!
      

  10.   

    老问题了,对象能不能释放自身?以前讨论过这个问题,记得结论是任何对象都不能自己释放自己,self.free这种写法是不对的,因为对象本身并不是自己的管理者,lz可以翻翻以前的帖子,有些日子了,我记不太清了。
      

  11.   

    请看Free方法的帮助:
    Warning: Never explicitly free a component within one of its own event handlers or the event handler of a component it owns or contains. For example, don't free a button, or the form that owns the button, in its OnClick event handler.不要试图在控件的事件中释放自身.
    在Button.OnClick中释放Form本来是没事的,但是因为Form释放时会释放它所拥有的所有控件及子控件,把Button也释放了,也违反了这条规则,所以出错.你需要完成的功能完全可以用Close方法做到,记得在OnClose事件中写上Action := caFree;
      

  12.   


    那用FreeAndNil 应该是由系统来释放吧,但是也不行