前两天编码遇到了要使用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之和。

  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方法来将子控件添加到父容器的上述两个列表。

  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类的组件。

  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 := 0 to FWinControls.Count - 1 do
  8. if CompareText(TWinControl(FWinControls[I]).Name, ControlName) = 0 then
  9. begin
  10. Result := TControl(FWinControls[I]);
  11. Exit;
  12. end;
  13. end;

测试

整个测试界面

1、Self.FindChildControl(窗体调用)

测试代码:

  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

测试代码:

  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

测试代码:

  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

测试代码:

  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从新运行了一次,结果就这样突然都查不到了,真是令人蛋疼。好在最后验证了这个方法的原理及其实现过程。

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

FindChildControl与FindComponent的更多相关文章

  1. 将一个字符串映射为一个Delphi页面控件属性名(通过FindComponent和GetPropInfo找到这个控件指针)

    uses TypInfo; function TForm1.SetControlProp(ComStr, value: string): boolean; var ComName, ComProp: ...

  2. react-native-vector-icons的简单使用,图片,按钮,标签视图,导航条

    ICONS是可以直接使用图片名, 就能加载图片的三方,使用很方便, 你不需要在工程文件夹里塞各种图片, 节省很多空间,下面就来看看怎么使用吧! 1. 首先打开terminal进入到我们的工程文件夹下, ...

  3. Camel运行原理分析

    Camel运行原理分析 以一个简单的例子说明一下camel的运行原理,例子本身很简单,目的就是将一个目录下的文件搬运到另一个文件夹,处理器只是将文件(限于文本文件)的内容打印到控制台,首先代码如下: ...

  4. 有关RAVE报表 - 大富翁论坛20050419

    部分资料来源于RAVE开发人员指南 ravedevguide5 新闻组News.Nevrona.com RAVE的官方主页  www.nevrona.com/rave KeyLife富翁笔记  作者 ...

  5. inno setup介绍及官方网站地址

    使 用 笔 记 1.Inno Setup 是什么?Inno Setup 是一个免费的 Windows 安装程序制作软件.第一次发表是在 1997 年,Inno Setup 今天在功能设置和稳定性上的竞 ...

  6. Delphi 复习代码

    1.取得可文件路径 Path := ExtractFilePath(Application.ExeName); //取得可执行文件路径 TXMLDocument.Create(ExtractFileP ...

  7. Delphi CxGrid 汇总(2)

    17. 怎样设计多表头的cxGrid? 解决:cxGrid可以解决如下的表头: --------------------------------- | 说明1 | 说明2 | ------------ ...

  8. 【笨嘴拙舌WINDOWS】实践检验之按键精灵【Delphi】

    通过记录键盘和鼠标位置和输入信息,然后模拟发送,就能够创建一个按键精灵! 主要代码如下: library KeyBoardHook; { Important note about DLL memory ...

  9. cxGrid使用汇总2

    17. 怎样设计多表头的cxGrid? 解决:cxGrid可以解决如下的表头: --------------------------------- | 说明1 | 说明2 | ------------ ...

随机推荐

  1. 为joomla加入�下拉菜单的方法

    用 Joomla! 建站的大多数站长都须要在站点前台使用下拉菜单(dropdown menu),或者叫弹出菜单(slide menu),由于这样能够在有限的页面空间上公布很多其它的导航菜单,而且能够进 ...

  2. iOSAPP启动时实现加载广告

    现在很多APP在启动的时候都在加载广告,现在也很流行,主要是盈利啊.笔者也做了很多关于广告的事情.现在记录下自己在APP启动的时候,怎么加载广告的. 下面总结下广告加载的三种方式 1.现在很多APP的 ...

  3. 字符相等(E - 暴力求解、DFS)

    判断字符相等 Description Today on a lecture about strings Gerald learned a new definition of string equiva ...

  4. Codeforces Round #315 (Div. 2B) 569B Inventory 贪心

    题目:Click here 题意:给你n,然后n个数,n个数中可能重复,可能不是1到n中的数.然后你用最少的改变数,让这个序列包含1到n所有数,并输出最后的序列. 分析:贪心. #include &l ...

  5. 【linux】 linux gpio操作

    欢迎转载,转载时需保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http:// ...

  6. BZOJ 1042: [HAOI2008]硬币购物( 背包dp + 容斥原理 )

    先按完全背包做一次dp, dp(x)表示x元的东西有多少种方案, 然后再容斥一下. ---------------------------------------------------------- ...

  7. java排序方法中的插入排序方法

    插入排序方法就是:将一个数据插入到已经排好序的有序数据中,从而得到一个新的.个数加一的有序数据. package Array; //插入排序方法 import java.until.Scanner; ...

  8. Codeforces 482 - Diverse Permutation 构造题

    这是一道蛮基础的构造题. - k         +(k - 1)      -(k - 2) 1 + k ,    1 ,         k ,             2,    ....... ...

  9. A*算法的C语言实现

    #include ”stdio.h“ #include “conio.h” #include ”assert.h“ #include “stdlib.h” #define MAPMAXSIZE 100 ...

  10. BIOS和CMOS的联系与区别

    BIOS为何物? BIOS就是(Basic Input/Output System,基本输入/输出系统的缩写)在电脑中起到了最基础的而又最重要的作用.是电脑中最基础的而又最重要的程序.把这一段程序放在 ...