zoukankan      html  css  js  c++  java
  • FindChildControl与FindComponent

    http://blog.csdn.net/tht2009/article/details/6954880 

    前两天编码遇到了要使用FindChildControl方法获取指定名称的TSpeedButton按钮,结果折腾了半天就是没得结果(基础不扎实,呵呵),于是赶紧搜索了下,补习关于这两个方法的用法。

           TWinControl类的FindChildControl方法在FWinControls中查找返回指定名称的可视且有窗体的组件(继承自TWinControl类)。该方法可以确定当前控件是否含有(contain)指定名称的继承自TWinControl类的子控件,其结果与指定要查找的控件的Parent属性有关。如果未找到返回nil(NULL),该方法只查找当前控件的直接子控件,不会迭代查找子控件的子控件。

           TComponent类的FindComponent方法在FComponents中查找返回指定名称的组件。该方法可以确定当前组件是否拥有(Own)指定名称的组件,其结果与指定查找的组件在创建时指定的Owner属性有关。窗体设计器上的创建的组件其拥有者为窗体,所以一般使用Self.FindComponent调用这个方法。该方法参数不区分大小写。

           Parent属性是指定控件的父容器,控件只能在父容器范围内显示和移动。Owner属性是指定组件的所有者,它负责组件的创建和释放。在窗体编辑器中添加组件,则默认地将Owner属性设置为所属的窗体,所以用窗体的FindComponent肯定可以找到。如果动态创建组件,那么必须指定其Owner和Parent,才可以调用相应方法找得到。而且,如果你放上去的是TWinControl的继承类,那么用FindChildControl就可以找到,否则就找不到。

           FindComponent非常简单,下面重点说说FindChildControl这令人纠结的方法【注1】。      

           这里先要了解下面几个基类:

           1、TComponent  所有组件基类

           2、TControl         运行时可视组件(TWinControl和TGraphicControl的基类)

           3、TWinControl  可视且有窗体的组件的基类

           TWincontrol就是Windows控件库的基类,从TWinControl继承下来的控件,都是具备有控件句柄的,也就是在Windows内部具备有唯一标记,能动态索引找到的。

           Delphi使用两个列表来维护控件的子控件:FWinControls和FControls。前者保存有句柄的控件,即继承自TWinControl的控件;后者保存无句柄的控件,一般继承自TGraphicControl的控件。所以控件的ControlCount属性值为FWinControls.Count与FControls.Count之和。

    [delphi] view plain copy
     
     print?
    1. //ControlCount属性的读取方法  
    2. function TWinControl.GetControlCount: Integer;  
    3. begin  
    4.   Result := 0;  
    5.   if FControls <> nil then Inc(Result, FControls.Count);  
    6.   if FWinControls <> nil then Inc(Result, FWinControls.Count);  
    7. end;  

           在创建子控件时会调用Insert方法来将子控件添加到父容器的上述两个列表。

    [delphi] view plain copy
     
     print?
    1. procedure TWinControl.Insert(AControl: TControl);  
    2. begin  
    3.   if AControl <> nil then  
    4.   begin  
    5.     if AControl is TWinControl then  
    6.     begin  
    7.       ListAdd(FWinControls, AControl);//如果是TWinControl则添加到FWinControls列表  
    8.       ...  
    9.     end   
    10.     else  
    11.       ListAdd(FControls, AControl);//否则添加到FControls列表  
    12.     ...  
    13.   end;  
    14. end;  

          下面再来看看FindChildControl的实现代码,可以看到FindChildControl只查找了FWinControls列表,这就是上面所说的它只查找可视且有窗体的组件,即继承自TWinControl类的组件。

    [delphi] view plain copy
     
     print?
    1. function TWinControl.FindChildControl(const ControlName: string): TControl;  
    2. var  
    3.   I: Integer;  
    4. begin  
    5.   Result := nil;  
    6.   if FWinControls <> nil then  
    7.     for I := to FWinControls.Count - do  
    8.       if CompareText(TWinControl(FWinControls[I]).Name, ControlName) = then  
    9.       begin  
    10.         Result := TControl(FWinControls[I]);  
    11.         Exit;  
    12.       end;  
    13. end;  

                       测试

        整个测试界面

    1、Self.FindChildControl(窗体调用)     

         测试代码:

    [delphi] view plain copy
     
     print?
    1. //FindChildControl查找  
    2. procedure TForm1.btn1Click(Sender: TObject);  
    3. var  
    4. c:TControl;  
    5. begin  
    6.   memo1.Clear;  
    7.   Memo1.Lines.Add('FindChildControl查找'+Edit1.Text+'...');  
    8.   c:=self.FindChildControl(Edit1.Text);//窗体调用  
    9.   if(c=nil)then  
    10.   Memo1.Lines.Add('未找到!')  
    11.   else  
    12.   begin  
    13.     Memo1.Lines.Add('找到!');  
    14.     Memo1.Lines.Add('父控件名称:'+c.Parent.Name);  
    15.   end;  
    16. end;  

          测试结果:

    (1)查找Button1(继承自TWinControl)

    (2)查找Label1(继承自TGraphicControl)

             

    (3)查找Button11(父容器为Panel1)

    2、Panel1.FindChildControl

          测试代码:

    [delphi] view plain copy
     
     print?
    1. //FindChildControl查找——父控件调用  
    2. procedure TForm1.btn4Click(Sender: TObject);  
    3. var  
    4. c:TControl;  
    5. begin  
    6.   memo1.Clear;  
    7.   Memo1.Lines.Add('FindChildControl查找'+Edit1.Text+'...');  
    8.   c:=panel1.FindChildControl(Edit1.Text); //panel1调用  
    9.   if(c=nil)then  
    10.   Memo1.Lines.Add('未找到!')  
    11.   else  
    12.   begin  
    13.     Memo1.Lines.Add('找到!');  
    14.     Memo1.Lines.Add('父控件名称:'+c.Parent.Name);  
    15.   end;  
    16. end;  

         测试结果:查找Button11(父容器为Panel1)

         

    3、Self.FindComponent

         测试代码:

    [delphi] view plain copy
     
     print?
    1. //FindComponent查找  
    2. procedure TForm1.btn2Click(Sender: TObject);  
    3. var  
    4. c:TComponent;  
    5. begin  
    6.   memo1.Clear;  
    7.   Memo1.Lines.Add('FindComponent查找'+Edit1.Text+'...');  
    8.   c:=self.FindComponent(Edit1.Text);//窗体调用  
    9.   if(c=nil)then  
    10.   Memo1.Lines.Add('未找到!')  
    11.   else  
    12.   begin  
    13.     Memo1.Lines.Add('找到!');  
    14.     Memo1.Lines.Add('拥有者名称:'+c.Owner.Name);  
    15.   end;  
    16. end;  

          测试结果
    (1)查找Button1(父容器为Form1)、Button11(父容器为Panel1)

          

    (2)查找Label1(继承TCustomLabel→TGraphicControl)、SpeedButton1(继承TGraphicControl)、Timer1(继承TComponent)

      

    4、Panel1.FindComponent

         测试代码:

    [delphi] view plain copy
     
     print?
    1. procedure TForm1.Button6Click(Sender: TObject);  
    2. var  
    3. lbl:TLabel;  
    4. c:TComponent;  
    5. begin  
    6.   lbl:=TLabel.Create(Panel2);//动态创建并指定拥有者  
    7.   lbl.Name:='Label6';  
    8.   memo1.Clear;  
    9.   Memo1.Lines.Add('FindComponent查找Label6...');  
    10.   c:=panel2.FindComponent('Label6');//拥有者调用  
    11.   if(c=nil)then  
    12.   Memo1.Lines.Add('未找到!')  
    13.   else  
    14.   begin  
    15.     Memo1.Lines.Add('找到!');  
    16.     Memo1.Lines.Add('拥有者名称:'+c.Owner.Name);  
    17.   end;  
    18.   {在窗体上显示还需加上以下代码}  
    19.   lbl.Parent:=Panel2;//Parent默认为nil,所以“无显示”  
    20.   lbl.Left:=50; //指定相对Parent的位置  
    21.   lbl.Top:=50;  
    22. end;  

        测试结果:


     


     注1:纠结倒不是因为这个方法本身,而是一开始我就写了这个demo来测试这个方法的使用及其结果,当时也没注意TLabel不是继承自TWinControl(呵呵,平时都不怎么关注这些,自然以为这些普通控件都继承自TWinControl),结果估计是编译器出问题了,用Self.FindChildControl可以查询到Label1,用Panel1.FindChildControl也可以查询到Label(之前都是测试Label的),但就是在TabSheet.FindChildControl里不能查到相应Label,而且编译器也不能在FindChildControl里设断点,后来在网上看到说要将编译器的一个开关打开,但执行的结果还是一样。第二天,无意中看到TLabel不是继承自TWinControl,这就令人郁闷了,怎么之前能查询到呢?马上打开demo从新运行了一次,结果就这样突然都查不到了,真是令人蛋疼。好在最后验证了这个方法的原理及其实现过程。

    delphi lazarus opengl 网页操作自动化, 图像分析破解,游戏开发
  • 相关阅读:
    读財报:交易额增长111%的京东,为毛还是亏?
    HDU 1548 A strange lift 搜索
    linux两台server远程copy文件
    Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离具体解释
    js事件防止冒泡
    LeetCode Rotate Array
    ARM架构授权和IP核授权有什么不一样啊?
    Linux系统结构 详解
    mount -o
    ARM开发板系统移植-----u-boot的编译
  • 原文地址:https://www.cnblogs.com/delphi-xe5/p/6414614.html
Copyright © 2011-2022 走看看