1。动态生成控如何获取句柄?获取的句柄与静态的有什么区别?
2。如何实现让一个动态生成的控件在失去焦点后自动释放?
   我试着把释放的语句写在onexit里但是这样的话程序运行后当动态生成的控件在失去焦点时会内存保存

解决方案 »

  1.   

    http://community.csdn.net/Expert/topic/3402/3402729.xml?temp=.3274042
      

  2.   

    1。动态生成控如何获取句柄?获取的句柄与静态的有什么区别?没有什么区别,一样是取得Handle2。如何实现让一个动态生成的控件在失去焦点后自动释放?
     FreeAndNil还是贴代码好,模糊地说不清了。
      

  3.   

    1。动态生成控如何获取句柄?获取的句柄与静态的有什么区别?没有什么区别,一样是取得Handle,句柄在每次运行将返回不同的值。只要本身具有句柄无论是动态还是静态都可获取。2  比如adotable1
                var adotable1:Tadotable;
                begin
                       adotabl1:=Tadotable1.create(nil);
                       ....                 adotable1.free;
                 end;      //就释放了
      

  4.   

    第二个问题:
    拦截WM_KILLFOCUS消息
    Tmybutton = class(Tbutton)
    public
       procedure killfocus(var msg:Tmessage); message  WM_KILLFOCUS;
    end;
    procedure Tmybutton.killfocus(var msg: Tmessage);
    begin
    self.Free;
    end;procedure TForm1.FormCreate(Sender: TObject);
    var
    aa:Tmybutton ;
    begin
     aa:=Tmybutton.Create(self);
     aa.Parent:=self;
     aa.TabOrder:=0;end;
    在窗体上再放置一个button控件,当动态生成的button aa失去焦点的时候,就free了
      

  5.   

    "我试着把释放的语句写在onexit里但是这样的话程序运行后当动态生成的控件在失去焦点时会内存保存"什么意思???
      

  6.   

    to  CareYouOnly(只在乎你)
    不好意思,打错了,应该时内存报错
      

  7.   

    procedure TEditListBox.ListBoxExit(Sender: TObject);
    begin
      Self.Clear;
      Self.Visible:=False;
      Self.Free;
    end;
    //self是指TEditListBox
    //按F7调试的时候可以看出,就是执行Self.Free时报错
      

  8.   

    to chw_csdn_chw(chw)
    你的代码我试了,第一次free的时候提示:Control‘’ has no parent windows;第二次的free的时候一样出现内存报错
    再帮忙看看吧,谢谢!
      

  9.   

    procedure TForm1.Button1Click(Sender: TObject);
    var
      lbTemp : TListBox;
    begin
      lbTemp := TListBox.Create(Self);
      lbTemp.Parent := Self;
      lbTemp.Height := 200;
      lbTemp.Width := 100;
      lbTemp.OnExit := Self.ListBox1Exit;
      lbTemp.Show;
      lbTemp.BringToFront;
      lbTemp.SetFocus;
    end;procedure TForm1.ListBox1Exit(Sender: TObject);
    begin
      (Sender as TListBox).Free;
    end;我刚试过,没有问题
      

  10.   

    procedure TForm1.Button1Click(Sender: TObject);
    var
      lbTemp : TListBox;
    begin
      lbTemp := TListBox.Create(Self);
      lbTemp.Parent := Self;
      lbTemp.Height := 200;
      lbTemp.Width := 100;
      lbTemp.OnExit := Self.ListBox1Exit;
      lbTemp.Show;
      lbTemp.BringToFront;
      lbTemp.SetFocus;
    end;procedure TForm1.ListBox1Exit(Sender: TObject);
    begin
      (Sender as TListBox).Free;
    end;我刚试过,没有问题
      

  11.   

    各位还是不行执行free后总时提示:提示:Control‘’ has no parent windows;
    大家再帮帮忙,全部代码如下,请大家指教谢谢!
      

  12.   

    unit UnitlistBox;interfaceuses  Windows,  Messages,  Dialogs,  SysUtils,  Classes,  Grids,  Controls,  DB,
      ADODB,  StdCtrls;
    type
      EDLBShow=^TEDLBShow;
      TEDLBShow=record
        ObjectEdit1,ObjectEdit2:TEdit;
        ParentComponent:TWinControl;
        QueryStr:String;
        end;type
      TEditListBox=class(Tlistbox)
        procedure ListBoxKeyPress(Sender: TObject; var Key: Char);
        procedure ListBoxDbClick(Sender: TObject);
        procedure ListBoxExit(Sender: TObject);
      private
        { Private declarations }
        LBShow:TEDLBShow;
        procedure CalPlace(AParent,AObject:TWinControl; ALeft,ATop:Integer);
      public
        { Public declarations }
        procedure killfocus(var msg:Tmessage); message  WM_KILLFOCUS;
        procedure ListBoxShow(ALBShow: TEDLBShow);
        constructor Create(AOwner: TComponent); override;
      end;implementationuses Unit1;{ TEditListBox }
    //利用递归计算动态控件的位置
    procedure TEditListBox.CalPlace(AParent, AObject: TWinControl; ALeft,
      ATop: Integer);
    begin
      if AParent<>AObject then
      begin
        Self.Left:=ALeft+AObject.Left;
        Self.Top:=ATop+AObject.Top;
        CalPlace(AParent,AObject.Parent,Self.Left,Self.Top);
      end else
      begin
        Self.Left:=ALeft+length(LBShow.QueryStr)*10;
        Self.Top:=ATop+10;
      end;
    end;constructor TEditListBox.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      OnKeyPress:=ListBoxKeyPress;
      OnExit:=ListBoxExit;
      OnDblClick:=ListBoxDbClick;
    end;procedure TEditListBox.killfocus(var msg: Tmessage);
    begin
      //Self.Free;   //chw_csdn_chw(chw)的方法^_^
    end;procedure TEditListBox.ListBoxDbClick(Sender: TObject);
    begin
      LBShow.ObjectEdit1.Text:=Trim(copy(Self.Items.Strings[Self.ItemIndex],1,17));
      if LBShow.ObjectEdit2<>nil then
        LBShow.ObjectEdit2.Text:=Trim(copy(Self.Items.Strings[Self.ItemIndex],18,20));
      LBShow.ObjectEdit1.SetFocus;
      LBShow.ObjectEdit1.SelStart:=length(LBShow.ObjectEdit1.Text);
    end;procedure TEditListBox.ListBoxExit(Sender: TObject);
    begin
      Self.Clear;
      Self.Visible:=False; 
      LBShow.ObjectEdit1.SelStart:=length(LBShow.ObjectEdit1.Text);
      LBShow.ObjectEdit1.SetFocus;
      //Self.Free;//加上这句就报错郁闷!!!
    end;procedure TEditListBox.ListBoxKeyPress(Sender: TObject; var Key: Char);
    begin
      if Key=#13 then
      begin
        if Self.ItemIndex=-1 then Exit;
        ListBoxDbClick(Sender);
      end else
        if Key=#27 then
        begin
          ListBoxExit(Sender);
        end;
    end;procedure TEditListBox.ListBoxShow(ALBShow: TedLBShow);
    var
      TempADQ:TADOQuery;
    begin
      LBShow:=ALBShow;
      with Self do
      begin
        Parent:=ALBShow.ParentComponent;
        CalPlace(ALBShow.ParentComponent,ALBShow.ObjectEdit1,0,0);
        if ALBShow.ParentComponent.Width-Left<268 then
          Width:=ALBShow.ParentComponent.Width-Left-10
        else
          Width:=268;
        if ALBShow.ParentComponent.Height-Top<118 then
          Height:=ALBShow.ParentComponent.Height-Top-5
        else
        Style:=lbStandard;
        Visible:=True;
        SetFocus;
      end;
      TempADQ:=TADOQuery.Create(nil);
      TempADQ.Connection:=Form1.ADOConnection1;
      Self.Items.BeginUpdate;
      with TempADQ do
      begin
        SQL.Clear;
        SQL.Add('');//sql语句略去不写,应该不会有问题
        Open;
        First;
        while not eof do
        begin
          Self.Items.Add(Fields.Fields[0].AsString);
          Next;
        end;
      Self.Items.EndUpdate;
      end;
      TempADQ.Free;
    end;end.
      

  13.   

    self.free不能用在OnExit事件了,你看看TListBox的源代码可以知道,Delphi式这样执行OnExit事件的:...//这里还有代码
    if Assigned(FOnExit) then
      FOnExit(self);
    ...//这里还有代码如果你在OnExit事件里加入 ListBox.free那么执行的代码就会变成...
    if Assigned(FOnExit) then
    begin
      ...
      self.free;
      ...
    end;
    ...//注意,这里的代码变成非法了,因为ListBox已经free掉楼上有的朋友说试验成功那是偶然的现象,因为当一个对象释放时,内存虽然被释放了,但系统有时候不会立刻在这段内存里写东西(纯属偶然,有时候内存立刻就会被系统重写了),因而他们的代码就‘成功’的执行了。如果不相信的话可以看看下面的代码:
    var bmp:TBitMap;
    begin
      bmp:=TBitMap.Create;
      bmp.width:=500;
      bmp.free;
      showmessage(IntToStr(bmp.width));//这里bmp明明已经被释放了,但在一般情况下,你依然可以看到bmp.width的值为500,因为储存bmp.width的内存没有立刻被系统重写,里面的数据依然为500。
    end;
      

  14.   

    to CareYouOnly(只在乎你) 
    我认为再onexit里因该是这样的吧
    if Assigned(FOnExit) then
    begin
      ...
      ...
    end;
    self.free;
    不知兄台意见如何?
      

  15.   

    我认为现在单纯的从OnExit里释放控件是可以的,也就是当动态生成的控件失去焦点的时候他会被释放,但是tongg响应OnKeyPess和DbCliick
      

  16.   

    TForm1 = class(TForm)    Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure MyOnexit(Sender:TObject);  //声明一个方法,给listbox的onexit
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      aListBox:TListBox;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
      if not assigned(alistBox) then
      begin
      aListBox:=TListBox.Create(Self); //如果没有创建则创建一个lisbox
      aListBox.Parent:=Form1;
      aListBox.OnExit:=MyOnExit;
      end
      else
        aListBox.show;  //显示  
    end;procedure TForm1.MyOnexit(Sender: TObject);
    begin
      if Sender is TListBox then
        FreeAndNil(TListBox(Sender));  //在onexit里释放,
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      if not Assigned(aListBox) then
        showmessage('I am no free');   //这里没有调用,说明释放了
    end;经过跟踪,发现 FreeAndNil(TListBox(Sender));   根本没起作用,但没出错,也可以让alistbox消失,哈哈,我也搞不清楚了
      

  17.   

    我认为现在单纯的从OnExit里释放控件是可以的,也就是当动态生成的控件失去焦点的时候他会被释放,但是通过响应OnKeyPess和DbCliick再调用OnExit事件时就会不定时的抛出内存错误,各位看看这是为什么,怎样解决?谢谢大家!!!
    代码如下:
    procedure TEditListBox.ListBoxKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      if Key=13 then
      begin
        if Self.ItemIndex=-1 then Exit;
        ListBoxDbClick(Sender);
      end else
        if Key=27 then
        begin
          LBShow.ObjectEdit1.SetFocus;
        end;
    end;procedure TEditListBox.ListBoxDbClick(Sender: TObject);
    begin
      LBShow.ObjectEdit1.Text:=Trim(copy(Self.Items.Strings[Self.ItemIndex],1,17));
      if LBShow.ObjectEdit2<>nil then
        LBShow.ObjectEdit2.Text:=Trim(copy(Self.Items.Strings[Self.ItemIndex],18,20));
      LBShow.ObjectEdit1.SetFocus;
    end;procedure TEditListBox.ListBoxExit(Sender: TObject);
    begin
      Self.Clear;
      Self.Visible:=False;
      LBShow.ObjectEdit1.SelStart:=length(LBShow.ObjectEdit1.Text);
      LBShow.ObjectEdit1.SetFocus;
      //FreeAndNil(Self);
      Self.Free;
    end;
      

  18.   

    procedure TForm1.MyDBClick(Sender: TObject);
    begin
      showmessage('I am clicked');
    end;
    我后来写了个 ondblclick,没出什么错呀
      

  19.   

    不好意思可能我解释的不太清楚,我是说有没有可能在使用KeyUp或DbClick使控件失去焦点,调用OnExit事件,而OnExit事件将控件Free了,从OnExit返回KeyUp或DbClick找不到控件时内存报错可是有时报错有时不报,太郁闷了
    代码如下:
    procedure TEditListBox.ListBoxKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      if Key=13 then  //Enter键入(相当于DbClick)
      begin
        if Self.ItemIndex=-1 then Exit;
        ListBoxDbClick(Sender);
      end else
        if Key=27 then //ESC键入
        begin
          LBShow.ObjectEdit1.SetFocus;//使TEditListBox失去焦点,也就是触发OnExit事件
        end;
    end;procedure TEditListBox.ListBoxDbClick(Sender: TObject);
    begin
      LBShow.ObjectEdit1.SetFocus;//使TEditListBox失去焦点,也就是触发OnExit事件
    end;procedure TEditListBox.ListBoxExit(Sender: TObject);
    begin
      Self.Clear;
      Self.Visible:=False;
      LBShow.ObjectEdit1.SetFocus;
      FreeAndNil(Self);//释放控件
      //Self.Free;)//释放控件
    end;
      

  20.   

    procedure TEditListBox.ListBoxExit(Sender: TObject);
    begin
      Self.Clear;
      Self.Visible:=False;
      LBShow.ObjectEdit1.SetFocus;
      FreeAndNil(Self);//释放控件
      //Self.Free;)//释放控件
    end;错误!不能在OnExit事件里调用self.free,看我上面的帖子。
      

  21.   

    1。动态生成控如何获取句柄?获取的句柄与静态的有什么区别?
    ----以上别人说得很清楚了,Create方法直接就返回句柄,句柄无任何区别。
    2。如何实现让一个动态生成的控件在失去焦点后自动释放?
       我试着把释放的语句写在onexit里但是这样的话程序运行后当动态生成的控件在失去焦点时会内存保存
    --
    如果你弄懂以下三种写法得含义,那么你得问题就解决了。
    var
     test: TTest;
    ...
      test:= TTest.Create(Application);//程序结束时Application对象释放test的内存,你这样干的!你不用写释放内存的代码。
      test:= TTest.Create(nil);//咱自己负责释放内存,必须显式写free来释放,否则
      test:= TTest.Create(Self);//你不用写释放内存的代码,Self就是当前类,类似于c++的this,这个Self,也就是本类(一般都是窗体类)负责释放内存。  我建议这样写:var
    test: TTest
    implementation
    ...
    procedure ..OnEnter();
    begin
      test:= TTest.Create(nil);
    end;procedure ...onexit()
    begin
      test.Free;
      //如果还是不放心可以改写为FreeAndNil(test);
    end;注意:如果释放的不是一个普通的组件,而是一个窗体,那么写成test.Release,而不是test.Free,因为窗体还需要处理自己的消息响应事件,否则可能出错的,这个在Delphi帮助里写的很清楚,Good lick!
      

  22.   

    第一个问题我觉得一样 不过获得句柄的时间不一样而已 一个是在窗口的CREATE里就可以了 一个要在这之后
    第二个问题 如果直接在本控件的事件里释放不是好办法 最好写成标志性变量 然后在监视器里释放掉 因为没有自己释放自己的道理
      

  23.   

    第一个问题不说了。
    第二个,不知道这么写的目的是什么,是研究ONEXIT还是编程需要,如果是研究ONEXIT就不说了。如果是编程需要,那么如果是频繁的创建再释放最好别这样写,把他隐藏掉,需要时候在显示即可;如果真要释放,那么你在窗体的空闲事件里,判断焦点是否在该控件上,如果不在则释放控件,在就不说了。
      

  24.   

    to  man8888(北京男人)
    呵呵,你说的那个好象没用,不是谁释放不释放的问题,
    而是该不该在onexit里释放自己的问题,
    我用你说的方法试过了,也不行,看来真的是楼上说的 在onexit里不能释放自己了,,,想别的方法吧,,
      

  25.   

    真郁闷,一个星星都见不到!!!!
    平时灌水的时候,都是星星,,我要投诉呀!!!!
    代码如下:TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure MyOnexit(Sender:TObject);  //声明一个方法,给listbox的onexit
        procedure Button2Click(Sender: TObject);
        procedure MyDBClick(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      aListBox:TListBox;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
      if not assigned(alistBox) then
      begin
      aListBox:=TListBox.Create(nil); //如果没有创建则创建一个lisbox
      aListBox.Parent:=Form1;
      aListbox.Items.Add('sss');
      aListBox.OnExit:=MyOnExit;
      alistbOx.OnDblClick:=MyDBClick;
      end
      else
        aListBox.show;  //显示
    end;procedure TForm1.MyOnexit(Sender: TObject);
    begin
      if Sender is TListBox then
        FreeAndNil(TListBox(Sender));  //在onexit里释放,
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      if not Assigned(aListBox) then
        showmessage('I am no free');   //这里没有调用,说明释放了
    end;
    procedure TForm1.MyDBClick(Sender: TObject);
    begin
      showmessage('I am clicked');
      Button1.SetFocus;
    end;
      

  26.   

    OK,听大家的意见!不够方法改了一些^_^
    问题解决了,现在只使用一个全局的listbox,不进行动态生成,也就不用释放了
    结贴!
      

  27.   

    晚上再看
    不过这个很简单
    参考TCustomGrid