procedure TForm1.Button2Click(Sender: TObject);

var
l: TLabel;
begin
l:=TLabel.Create(self);
l.Name:='label999';
l.Caption:='test label';
l.Left:=10;
l.Top:=10;
l.Transparent:=True; // 这句会影响自己的客户区在父控件里显示时背景色是否需要重绘
l.Parent:=self;
end;

这里AControl是图形子控件,即上面的l,以下是主要执行步骤(把所有用到的函数主要语句列出来)
1. 执行 SetParent
2. 执行 InsertControl
3. 执行 Insert(AControl) 此处不算插入前和插入后执行的一大堆检查与通知语句
4. 执行 AControl.Invalidate;
5. 执行 TControl.InvalidateControl
6. 执行 InvalidateRect(Parent.Handle, @Rect, False) 刷新父控件的无效区,当Transparent:=True的时候,第三个参数是True则需要重绘背景

总结:
图形控件的显示比较简单,就是计算自己的有效区域后,然后把它的父控件(一定是Win控件)某个区域声明为无效区域。如果是图形控件是透明的,那么还要计算其是否与兄弟图形控件完全重合,重合的话就不用重绘了。不过最重要的是,PaintControls函数里才真正重绘Win控件的所有子图形控件。

问题:其中是否重合的问题还需要仔细研究,为什么只比较一部分兄弟图形控件呢?当某个控件特别大完全遮住了某个控件时,情况又不一样。

procedure TForm1.Button4Click(Sender: TObject);
var
l: TEdit;
begin
l:=TEdit.Create(self);
l.Name:='edit100';
l.Text:='test';
l.Left:=100;
l.Top:=100;
l.Parent:=self;
end;

1. 子控件执行 SetParent(AParent)
2. 父控件执行 InsertControl(Self); 其中Self是子控件
3. 父控件执行 Insert(AControl) 此处不算插入前和插入后执行的一大堆检查与通知语句
4. 父控件执行 UpdateControlState
5. 父控件寻找最高层Parent,执行UpdateShowing
6. 最高层Parent创建句柄后,递归执行UpdateShowing先显示所有子Win控件
7. 发消息 CM_SHOWINGCHANGED 调用API SetWindowPos 显示自己。问题:为什么不需要调用 UpdateWindow
8. 在显示Win控件的过程中,所有图形子控件也被一起显示了。

总结:说到底就是调用API SetWindowPos 显示每一个Win子控件。

问题1:这个只是初次显示,以后的显示,还要查看Invalidate函数,它只是简单发送CM_INVALIDATE消息,最后发现是调用API InvalidateRect声明整个Win控件客户区都无效。
声明无效区域仅仅是声明,真正如何重绘,还要看每个Win控件自己如何响应WM_PAINT消息(少数控件,比如TListBox和TComboBox覆盖这个消息)。
一般情况下还是调用TWinControl.WMPaint,然后调用PaintHandler,它调用BeginPaint PaintWindow PaintControls EndPaint 把所有内容在内存里重绘,最后调用API BitBlt一次性全部贴图。
问题2:如果有重绘消息,会有无数个各自不同的重绘消息发给不同的Win控件(主窗体上的每一个窗口)?

============================================================

另一种写法也可以显示TEdit,但是与TEdit的显示风格不一致:
procedure TForm1.Button1Click(Sender: TObject);
var
l: TEdit;
begin
l:=TEdit.Create(self);
l.Name:='edit100';
l.Text:='test';
l.Left:=100;
l.Top:=100;
l.ParentWindow:=Self.Handle;
l.HandleNeeded;
// SetWindowPos(l.Handle, BitBtn1.Handle, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE + SWP_NOACTIVATE);
end;

测试Parent的Handle,纯正的Windows的Handle,没有经过Delphi的封装:

procedure TForm1.Button3Click(Sender: TObject);
begin
if ParentWindow=0 then ShowMessage('ParentWindow is nil')
else ShowMessage('ParentWindow is not nil');
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
if Edit1.ParentWindow=0 then ShowMessage('ParentWindow is nil')
else ShowMessage('ParentWindow is not nil');
exit;
end;

另外,可以通过VC直接测试SetWindowPos的功能:

void CdsdsDlg::OnBnClickedOk()
{
int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);
int dx = 600;
int dy = 400;
SetWindowPos(&wndTopMost,cx-dx,cy-dy,dx,dy,SWP_SHOWWINDOW); //设置窗口于右下角
}

TLabel和TEdit的初次显示过程的更多相关文章

  1. TEdit的创建与显示过程

    -------------------------- 分析TEdit的创建与显示过程 --------------------------TCustomEdit = class(TWinControl ...

  2. 使用javascript生成的植物显示过程特效

    查看效果:http://keleyi.com/keleyi/phtml/html5/33.htm .NET版本:http://keleyi.com/a/bjac/66mql4bc.htm 完整HTML ...

  3. Activtiy完全解析(三、View的显示过程measure、layout、draw)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/52840065 本文出自:[openXu的博客]   在Activity完全解析的第一篇文章A ...

  4. 浅谈移动端 View 的显示过程

    作者:个推安卓开发工程师 一七 随着科技的发展,各种移动端早已成为人们日常生活中不可或缺的部分,人们使用移动端产品工作.社交.娱乐……移动端界面的流畅性已经成为影响用户体验的重要因素之一.那么你是否思 ...

  5. JQuery实现密码有短暂的显示过程和实现 input hint效果

    目录: 一.实现目的 二.问题思考 三.解决办法 1.输入用户名 2.输入密码短暂显示 一.实现目的 这几天做项目的时候,客户要求在文本框输入密码的时候,要求密码有短暂的显示过程,如下图: 二.问题思 ...

  6. Android 启动、绘制、显示过程

    Activity 启动过程: startActivity()-> Instrumentation.execStartActivity()-> Binder->ActivityMana ...

  7. 修改u-boot的开机logo及显示过程【转】

    本文转载自;http://blog.csdn.net/voice_shen/article/details/6789424 [ u-boot: Git://git.denx.de/u-boot.git ...

  8. Delphi: TLabel设置EllipsisPosition属性用...显示过长文本时,以Hint显示其全文本

    仍然是处理多语言中碰到问题. Delphi自2006版以后,TLabel有了EllipsisPosition属性,当长文本超过其大小时,显示以...,如下图: 这样虽然解决显示问题,但很显然,不知道. ...

  9. Oracle-一张表中增加计算某列值重复的次数列,并且把表中其他列也显示出来,或者在显示过程中做一些过滤

    总结: 1.计算某列值(数值or字符串)重复的次数 select 列1,count( 列1 or *) count1  from table1 group by 列1 输出的表为:第一列是保留唯一值的 ...

随机推荐

  1. day21-1 类的继承

    目录 类的继承 什么是继承 为什么用继承 对象的继承 继承与抽象 继承的应用 对象属性查找顺序 类的继承 什么是继承 继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承) ...

  2. /etc/updatedb.conf配置文件

    [root@localhost ~]# vi /etc/updatedb.conf PRUNE_BIND_MOUNTS = "yes" PRUNEFS = "9p afs ...

  3. checkbox prop无效问题

    因为bootstrap插件问题,需要先获取input的上级元素,然后添加checked $("input[name='checkInput']").parent().addClas ...

  4. linux shell脚本学习笔记一

    一.文件比较运算符-e filename 如果 filename存在,则为真 [ -e /var/log/syslog ]-d filename 如果 filename为目录,则为真 [ -d /tm ...

  5. P1091 合唱队形题解(洛谷,动态规划LIS,单调队列)

    先上题目 P1091 合唱队形(点击打开题目) 题目解读: 1.由T1​<...<Ti​和Ti​>Ti+1​>…>TK​可以看出这题涉及最长上升子序列和最长下降子序列 2 ...

  6. web视频播放插件:Video For Everybody

    相比其它的web视频播放插件(video.js , jwplayer等)来说,Video For Everybody(极力推荐)是一款更好的视频播放插件,无需任何下载,支持html5以及flash播放 ...

  7. LINUX-网络 - (以太网和WIFI无线)

    ifconfig eth0 显示一个以太网卡的配置 ifup eth0 启用一个 'eth0' 网络设备 ifdown eth0 禁用一个 'eth0' 网络设备 ifconfig eth0 192. ...

  8. String类的转换功能

    /* * String类的转换功能 * char[] toCharArray():把字符串转换为字符数组 * String toLowerCase():把字符串转换为小写字符串 * String to ...

  9. EF中避免查询重复执行的手段

    由于ef有lazyload机制,编写的查询语句往往都没有立即执行,当你轮训结果集的时候才会将查询翻译成database端的sql语句,执行sql将结果返回到方法中.但是,下次再使用前面的结果集的时候, ...

  10. Oracle 关于几个随机函数sys_guid、dbms_random.random、dbms_random.value(取随机的结果集)

    sys_guid():SYS_GUID (),是Oracle 8i 后提供的函数.SYS_GUID产生并返回一个全球唯一的标识符(原始值)由16个字节组成.更适合多个数据库数据集成时使用(--源自百度 ...