前两天编码遇到了要使用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 copyprint?
  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;
//ControlCount属性的读取方法
function TWinControl.GetControlCount: Integer;
beginResult := 0;if FControls <> nil then Inc(Result, FControls.Count);if FWinControls <> nil then Inc(Result, FWinControls.Count);
end;

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

[delphi] view plain copyprint?
  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. end
  9. else
  10. ListAdd(FControls, AControl);//否则添加到FControls列表
  11. end;
  12. end;
procedure TWinControl.Insert(AControl: TControl);
beginif AControl <> nil thenbeginif AControl is TWinControl thenbeginListAdd(FWinControls, AControl);//如果是TWinControl则添加到FWinControls列表...end elseListAdd(FControls, AControl);//否则添加到FControls列表...end;
end;

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

[delphi] view plain copyprint?
  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;
function TWinControl.FindChildControl(const ControlName: string): TControl;
varI: Integer;
beginResult := nil;if FWinControls <> nil thenfor I := 0 to FWinControls.Count - 1 doif CompareText(TWinControl(FWinControls[I]).Name, ControlName) = 0 thenbeginResult := TControl(FWinControls[I]);Exit;end;
end;

测试

整个测试界面

1、Self.FindChildControl(窗体调用)

测试代码:

[delphi] view plain copyprint?
  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;
//FindChildControl查找
procedure TForm1.btn1Click(Sender: TObject);
var
c:TControl;
beginmemo1.Clear;Memo1.Lines.Add('FindChildControl查找'+Edit1.Text+'...');c:=self.FindChildControl(Edit1.Text);//窗体调用if(c=nil)thenMemo1.Lines.Add('未找到!')elsebeginMemo1.Lines.Add('找到!');Memo1.Lines.Add('父控件名称:'+c.Parent.Name);end;
end;

测试结果:

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

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

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

2、Panel1.FindChildControl

测试代码:

[delphi] view plain copyprint?
  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;
//FindChildControl查找——父控件调用
procedure TForm1.btn4Click(Sender: TObject);
var
c:TControl;
beginmemo1.Clear;Memo1.Lines.Add('FindChildControl查找'+Edit1.Text+'...');c:=panel1.FindChildControl(Edit1.Text); //panel1调用if(c=nil)thenMemo1.Lines.Add('未找到!')elsebeginMemo1.Lines.Add('找到!');Memo1.Lines.Add('父控件名称:'+c.Parent.Name);end;
end;

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

3、Self.FindComponent

测试代码:

[delphi] view plain copyprint?
  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;
//FindComponent查找
procedure TForm1.btn2Click(Sender: TObject);
var
c:TComponent;
beginmemo1.Clear;Memo1.Lines.Add('FindComponent查找'+Edit1.Text+'...');c:=self.FindComponent(Edit1.Text);//窗体调用if(c=nil)thenMemo1.Lines.Add('未找到!')elsebeginMemo1.Lines.Add('找到!');Memo1.Lines.Add('拥有者名称:'+c.Owner.Name);end;
end;

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

      

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

  

4、Panel1.FindComponent

测试代码:

[delphi] view plain copyprint?
  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;
procedure TForm1.Button6Click(Sender: TObject);
var
lbl:TLabel;
c:TComponent;
beginlbl:=TLabel.Create(Panel2);//动态创建并指定拥有者lbl.Name:='Label6';memo1.Clear;Memo1.Lines.Add('FindComponent查找Label6...');c:=panel2.FindComponent('Label6');//拥有者调用if(c=nil)thenMemo1.Lines.Add('未找到!')elsebeginMemo1.Lines.Add('找到!');Memo1.Lines.Add('拥有者名称:'+c.Owner.Name);end;{在窗体上显示还需加上以下代码}lbl.Parent:=Panel2;//Parent默认为nil,所以“无显示”lbl.Left:=50; //指定相对Parent的位置lbl.Top:=50;
end;

测试结果:


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

                </div>

转自:https://blog.csdn.net/tht2009/article/details/6954880

FindChildControl与FindComponent(动态创建的控件要通过Owner.FindComponent去找该控件)相关推荐

  1. qt 控件坐标系_Qt中,如何找准控件坐标

    代码如下: void TestWidget::on_pushButton123_clicked() { QPoint p = ui.pushButton123->pos();//获得pushBu ...

  2. asp.net 包含动态创建控件的容器如果要切换显示/隐藏不要用 Visible 属性

    asp.net 包含动态创建控件的容器如果要切换显示/隐藏不要用 Visible 属性 就是不用 XXX.Visible = false;  // true 因为这样该容器及其子控件会彻底的从页面上消 ...

  3. [原]动态创建Web控件制做计算器

    最近参加了Web基础开发的培训,收获不少,做了一个练习,在后台动态创建控件制作了一个简单功能的计算器.程序中控件创建好以后,往往不能放在想要的位置,前台的布局非常麻烦,我用Table.TableRow ...

  4. 在.NET上如何根据字符串动态创建控件

    在.Net上用字符串动态创建控件是通过反射来实现. 首先,利用System.Type.GetType方法,获得字符串中指定的控件的类型实例. 这里需要注意这个字符串的语法,根据msdn的解释: 按名称 ...

  5. WPF 中动态创建和删除控件

    WPF 中动态创建和删除控件 原文:WPF 中动态创建和删除控件 动态创建控件 1.容器控件.RegisterName("Name",要注册的控件)   //注册控件 2.容器控件 ...

  6. MFC小程序003------MFC使用WebBrowser组件,在对话框中创建滚动视图,动态创建一个静态文本控件并设置鼠标单击的消息响应...

    MFC小程序截图: 一.在MFC中简单使用WebBrowser的ActiveX插件的方法: 见博文:  http://blog.csdn.net/supermanking/article/detail ...

  7. 动态创建asp.net控件之我见

    最近考虑将之前用delphi设计的开发框架思路在asp.net上实现,其中有一项功能时动态生成录入界面,这在form开发程序中比较简单只要设置好动态生成的控件的所有者(owner),及位置还有相关事件 ...

  8. MFC动态创建控件并响应事件代码实现过程

    MFC动态创建控件以及响应动态创建的控件的事件的实现方法如下. 1.创建对象     用new进行动态创建一个对象.然后调用Create函数创建窗口,在函数的父窗口参数中传入this或者用AfxGet ...

  9. MFC中动态创建控件以及事件响应实现方法

    本文实例讲述了MFC中动态创建控件以及事件响应实现方法,分享给大家供大家参考.具体实现方法如下: 动态控件是指在需要时由Create()创建的控件,这与预先在对话框中放置的控件是不同的. 一.创建动态 ...

最新文章

  1. AMD and CMD are dead之js模块化黑魔法
  2. 如何成为一名专家级的开发人员
  3. linux安装VScode
  4. 13攻击行为是天生的
  5. 微信小程序:一起玩连线,一个算法来搞定
  6. 学习mfc的一些方法
  7. ORAN专题系列-5:5G O-RAN 一体式小基站硬件白盒化的参考架构
  8. 2021 年产品沉思录精选集 PDF 下载及卷首语合集:像农夫一样耕耘和等待
  9. 技术负责人如何带领好团队
  10. PTC Onshape 的两个核心弱点
  11. 华为网络设备-DHCP基础配置实验
  12. day 26 学习Linux-01天
  13. linux网页版控制台,linux Web控制台
  14. P5385 [Cnoi2019]须臾幻境(LCT+主席树,思维题)
  15. 基督-神[上帝]的道,真理的本真归回
  16. String转JSONObject,JSONObject转JSONArray,JSONArray数组转换成JSON字符串
  17. 图像传感器binning_CMOS图像传感器调试问题汇总
  18. 发送广播失败 Parcelable encountered IOException writing serializable object (name =xxxx).
  19. php统计邮件打开率,监控 Amazon SES 电子邮件的打开率、点击率和退回率
  20. 国内十大开源linux社区

热门文章

  1. 运维跟开发一定有仇么?
  2. 编程之美——数字哑谜
  3. 随想录(程序调试与dll注入)
  4. python文字转图片_python-将文本文件转换为图形
  5. mysql 主从 均衡_Mysql主从复制
  6. 4乘4方格走的路线_国庆自驾游,4条成都出发沿途美景大汇合自驾游路线推荐
  7. 已知原函数和导函数的关系_原函数与导函数的关系
  8. SQLi LABS Less-18
  9. Python简洁的出入库系统(模块化)
  10. REMIX 本地环境搭建指南