各位大虾好!!!小弟最近在学习的时候发现,在程序动行时动态生成的控件在消毁时有时会弹出系统错误对话框,不知道怎么才可以实现正常消毁动态生成的控件而不会出现系统异常。下面是小弟写的代码,请各位大虾狠P啊!!!谢谢!!!......procedure TForm1.SelfFree(Sender: TOjbect; var Key: Word; TShift: TShiftState);
begin
 if Key=VK_RETURN then
  a.Free;  //这一段小弟认为有错,但不知道该怎么写,痛苦ing啊!!!
end;procedure TForm1.Button1Click(Sender: TOjbect);
var
 a: TEdit;  //这一段是不是不应该放在这里啊,要是放到TForm1的定义行吗,或做成全局变量!??
begin
 a:=TEdit.Create(Self);
 a.Parent:=Self;
 a.OnKeyDown:=SelfFree; 
end;以上代码错误百出,请热心大虾多多指教,小弟走弯路走得实在是太多了,好累啊,呜呜~~~

解决方案 »

  1.   

    procedure TForm1.SelfFree(Sender: TObject; var Key: Word; TShift: TShiftState);
    begin
     if Key=VK_RETURN then
      tedit(sender).Free;  //这一段小弟认为有错,但不知道该怎么写,痛苦ing啊!!!
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    var
     a: TEdit;  //这一段是不是不应该放在这里啊,要是放到TForm1的定义行吗,或做成全局变量!??
    begin
     a:=TEdit.Create(Self);
     a.Parent:=Self;
     a.OnKeyDown:=SelfFree;
    end;
      

  2.   

    var
     a: TEdit;
    procedure TForm1.onkeydown(Sender: TObject; var Key: Word; TShift: TShiftState);
    begin
      if Key=VK_RETURN then
       a.Free;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      a:=TEdit.Create(Self);
      a.Parent:=Self;
      a.OnKeyDown := onkeydown;
    end;
    这样好象就可以,你试一下
      

  3.   

    a: TEdit; //要放到TForm1的定义行procedure TForm1.SelfFree(Sender: TOjbect; var Key: Word; TShift: TShiftState);
    begin
     if Key=VK_RETURN then
      a.Free;  //这句可以不要
    end;procedure TForm1.Button1Click(Sender: TOjbect);
    begin
     a:=TEdit.Create(Self);
     a.Parent:=Self;
     a.OnKeyDown:=SelfFree; 
    end;
      

  4.   

    procedure TForm1.SelfFree(Sender: TObject; var Key: Word; TShift: TShiftState);
    begin
     if Key=VK_RETURN then
      tedit(sender).Free; 
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    begin
     with TEdit.Create(Self) do
    begin
     Parent:=Self;
     OnKeyDown:=SelfFree;
    end;
    end;
      

  5.   

    我上午也写了一个,按道理说不会报错,但报了。
    报错的机率为:40%
    unit Main;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure EditKeyPress(Sender: TObject; var Key: Char);
      private
        { Private declarations }
        iNum: Integer;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
      Randomize;
      with TEdit.Create(Self) do
      begin
        Inc(iNum);
        Name := 'Edit' + IntToStr(iNum);
        Parent := Self;
        Top := Random(200);
        Left := Random(200);
        Text := Name;
        OnKeyPress := EditKeyPress;
      end;
    end;procedure TForm1.EditKeyPress(Sender: TObject; var Key: Char);
    begin
      if (Sender is TEdit) and (Key = #13) then
      begin
        (Sender as TEdit).Free;
      end;
    end;end.
      

  6.   

    本来也是用的KeyDown事件,也会有40%的报错机率。
      

  7.   

    const WM_ReleaseEdit=WM_USER+100;type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        procedure EditKeyPress(Sender: TObject; var Key: Char);
        procedure ReleaseButton(obj: TObject);
        { Private declarations }
      public
        { Public declarations }
        procedure WMReleaseEdit(var Message: TMessage); message WM_ReleaseEdit;
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
    begin
      Randomize;//改在这儿。。免得每次都初始化种子
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      with TEdit.Create(nil) do
      begin
        Parent := Self;
        Top := Random(200);
        Left := Random(200);
        Text := Name;
        OnKeyPress := EditKeyPress;
      end;
    end;procedure TForm1.ReleaseButton(obj:TObject);
    begin
      PostMessage(Handle,WM_ReleaseEdit,Integer(obj),0);
    end;procedure TForm1.EditKeyPress(Sender:TObject;var Key: Char);
    begin
      if (Sender is TEdit) and (Key = #13) then
      begin
        ReleaseButton(Sender);
      end;
    end;procedure TForm1.WMReleaseEdit(var Message: TMessage);
    begin
      if Message.WParam<>0 then
      begin
        TObject(Message.WParam).Free;
      end;
    end;
      

  8.   

    halfdream(哈欠) 
    哇,上星的就是牛啊!
    会用消息,却想不到用消息。
      

  9.   

    非常感谢楼上各位大虾的回复,用tedit(sender).Free; 的方法小弟试过了,这个方法也试过:
    (Sender as TEdit).Free,(从别的地方看来的),但在释放的时候还是会出现警告对话框的,特别是在做组件编写的时候,比如说:TListViewEx=class(TListView)
     a: TEdit;
     procedure DBClick(Sender: TObject);
    end;procedure TListViewEx.DBClick(Sender: TObject);
    begin
     a:=TEdit.Create(Self);
     a.Parent:=Self;  //动态生成TEdit;
    end;但我想动态消毁a的话该怎么办呢!??比如当a接到一个回车键消息时自行消毁。再次感谢楼上各位大虾的回复,谢谢!!!
      

  10.   

    建一个procedure 来销毁
    procedure TForm1.EditFree;
    begin
      a.free
    end当你触发回车时触发他吧。
    再有,如果你的这个控件是在全局用到的话,建议将将申明在TFORM类的private中吧。
      

  11.   

    非常感谢楼上大虾的回复,小弟曾试图用消息的方法来实现,但还是没有办法,还是行不通的,楼上大虾说的建一个procedure来销毁,不知道这个procedure是放在TForm内还是独立成一个procedure啊!!!再次感谢楼上各位大虾的回复,谢谢!!!
      

  12.   

    请使用以下代码试试:unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
        a : TEdit;    //这个变量必须是TForm1类中的全局变量
        procedure EditKeyPress(Sender: TObject; var Key: Char);
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
    begin
      a := nil;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      if a = nil then         //这个判断是为了防止重复创建TEdit对象, 如果有重复创建的情况出现, 则Free时必定会出错
      begin
        a := TEdit.Create(Self);
        a.Parent := Self;
        a.Left := 10;
        a.Top := 10;
        a.OnKeyPress := EditKeyPress;
        a.Visible :=True;
      end;
    end;procedure TForm1.EditKeyPress(Sender: TObject; var Key: Char);
    begin
      if Key = #13 then
      begin
        a.Free;
        a := nil;
      end;
    end;end.
      

  13.   

    请使用以下代码试试:unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
        a : TEdit;    //这个变量必须是TForm1类中的全局变量
        procedure EditKeyPress(Sender: TObject; var Key: Char);
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
    begin
      a := nil;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      if a = nil then         //这个判断是为了防止重复创建TEdit对象, 如果有重复创建的情况出现, 则Free时必定会出错
      begin
        a := TEdit.Create(Self);
        a.Parent := Self;
        a.Left := 10;
        a.Top := 10;
        a.OnKeyPress := EditKeyPress;
        a.Visible :=True;
      end;
    end;procedure TForm1.EditKeyPress(Sender: TObject; var Key: Char);
    begin
      if Key = #13 then
      begin
        a.Free;
        a := nil;
      end;
    end;end.
      

  14.   

    because edit.keypress event 's funtuion pointer is in edit object.
    so you destroy a object in the object's event may be confilcted.
    so you may use timer
    in keypress event
    timer.enabled=true;
    in timer evnet
    timer.enable=false;
    edit.free;
      

  15.   

    procedure TForm1.SelfFree(Sender: TObject; var Key: Word; TShift: TShiftState);
    begin
    if Key=VK_RETURN then
    tedit(sender).Free; //这一段小弟认为有错,但不知道该怎么写,痛苦ing啊!!!
    end;改成:

    procedure TForm1.SelfFree(Sender: TObject; var Key: Word; TShift: TShiftState);
    beginif Key=VK_RETURN then
    begin
    if assigned(a) then
    a.Free; 
    end;
    end;
      

  16.   

    楼主,,我那程序是在g961681(Rabby.W.)基础上修改的,
    测试过可行的,你细心试试就知道的。
    相信g961681(Rabby.W.)也试过的。
    你这程序出错原因其实应该容易解释的。。
    在这样的事件中立即销毁事件所依赖的对象是非常危险的操作.一般应该延后销毁.
    无论是我代码中的POSTMESSAGE,还是搂上所说的使用TIMER事件,都是这样思路.
    这是一个KEYPRESS事件触发的调用序列:
    TWinControl.WMChar(EDIT对象)
    。TWinControl.DoKeyPress(EDIT对象)
    。。TWinControl.KeyPress(EDIT对象)
    TForm1.Edit1KeyPress(FORM1对象) 在这儿一下子把EDIT对象销毁了,
    .......这后序的一些调用便不能完成..