TGraphicControl = class(TControl) // 这个类实在是简单,因为所有事情都已经委托给它的父Win控件了,只要管自己即可
private
FCanvas: TCanvas; // 私有内部画板,不用程序员申请就有了
// 注意区别,其实图形控件没有画自己一说(但仍然接受WM_PAINT消息),直接响应消息并绘画即可。
// 其父类已经在VCL体系中搭好了框架绘制当前图形控件,它会调用Paint函数执行程序员的画图动作。
// Graphic控件自绘过程:
// 0. Windows发消息给其父Win控件
// 1. 如果父控件是WinControl,那么流程是:WMPaint, PaintHandler, PaintWindow, PaintWindows,其中最后一个函数PaintWindows会绘制所有图形子控件
// 2. PaintWindows 给所有图形子控件执行 Perform(WM_PAINT, DC, 0) 消息,其中DC是父控件的句柄
// 3. Graphic控件会通过WMPaint函数响应WM_PAINT消息,程序员不必改动这个函数,
// 4. WMPaint函数调用虚函数Paint,程序员改写Paint可被准确应用上而不必对整个VCL框架有任何改动,甚至不用理解这件事情,只需填写Paint函数即可
// 5. 如果父控件是CustomControl,那么会再多绕一道弯:先执行CustomControl的WMPaint,目的是加上自绘状态,再调用WinControl的WMPaint
// 总结:整个过程特简单,就是父控件发来WM_Paint消息,对应的WMPaint函数已经写好,程序员自己填上Paint函数的内容即可
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
protected
procedure Paint; virtual; // 虚函数,空函数。注意一定是要虚函数才符合面向对象的精神,才能正确被调用。
property Canvas: TCanvas read FCanvas;
public
constructor Create(AOwner: TComponent); override; // 简单创建Canvas并连接当前图形控件
destructor Destroy; override; // 销毁内部画板和自己,取消自己的焦点 fixme 图形控件也可以有焦点?
end;

--------------------------------------------------------------------------------------------------

TCustomControl = class(TWinControl) // 这个类的主要框架都在TWinControl里搭好了框架,所以才会出现最简单的三明治风格
private
FCanvas: TCanvas; // 私有内部画板,不用程序员申请就有了
// Custom控件自绘过程:
// 0. Windows发消息给CustomControl控件自己(也是Win控件,具有句柄)
// 1. 响应绘制自己控件的源头,还是从CustomControl控件的WMPaint函数开始
// 2. 三明治风格,加上csCustomPaint自绘风格后,调用父类同名WMPaint函数,这样可以把自己和所有子控件都管起来(有现成的VCL框架代码在其父类中准备好了)
// 3. 父类同名函数根据四种不同情况:双缓冲,DC句柄,子控件数量,自绘标记,分别作出不同的判断后进行绘制
// 4. 先绘制自己,再绘制所有子图形控件(如果有的话)
// 5. 绘制自己的时候,父类的管理函数(一般是PaintHandler)会调用本类的PaintWindow覆盖函数(虚函数)
// PaintWindow又会调用Paint函数,程序员通过改写Paint函数的内容,达到在框架内被自动调用的目的
// 6. 图形子控件的绘制过程是通过父控件给它发送WM_PAINT消息,其中包含了父控件的DC句柄,然后委托给图形子控件自己进行绘制
// 总结1:Custom控件的整个绘制过程道理与Graphic控件非常类似,只是少绕一些弯子(不必通过父控件来重绘)
// WMPaint直接调用本类的Paint函数,而程序员通过改写Paint函数的内容,达到在框架内被自动调用的目的
// 总结2:与直接继承自TWinControl的控件有所区别,后者直接覆盖PaintWindow函数,而不必响应WM_PAINT消息就可以达到被调用的目的了:http://www.cnblogs.com/findumars/p/3931703.html
procedure WMPaint(var Message: TWMPaint); message WM_PAINT; // 加Custom风格后重绘,调用TWinControl.WMPaint函数,因为要重画所有子控件
protected
// 此函数只被PaintHandler调用,后者又会被WMPaint WMPrintClient调用
procedure PaintWindow(DC: HDC); override; // 虚函数,在VCL体系中搭好了框架画自己,它会调用Paint;函数执行程序员的画图动作。
procedure Paint; virtual; // 虚函数,空函数。等待程序员填写画板的真正内容。框架已经由PaintWindow搭好了。
property Canvas: TCanvas read FCanvas;
public
constructor Create(AOwner: TComponent); override; // 创建并设置内部画板
destructor Destroy; override; // 销毁内部画板和自己
end;

TGraphicControl和TCustomControl自绘过程的理论解释的更多相关文章

  1. 《Android内核剖析》读书笔记 第13章 View工作原理【View重绘过程】

    计算视图大小的过程(Measure) 视图大小,准确的来说应该是指视图的布局大小:我们在layout.xml中为每个UI控件设置的layout_width/layout_height两个属性被用来设置 ...

  2. [Android FrameWork 6.0源码学习] View的重绘过程

    View绘制的三部曲,  测量,布局,绘画今天我们分析测量过程 view的测量是从ViewRootImpl发起的,View需要重绘,都是发送请求给ViewRootImpl,然后他组织重绘在重绘的过程中 ...

  3. IP地址,子网掩码、默认网关,DNS理论解释

    在网上发现的这篇文章写的非常好,有理论有示例. (一)  问题解析 001.   问:  IP地址,子网掩码,默认网关,DNS服务器,有什么区别呀?我知道没有IP地址就不能上网,我也知道没设DNS就不 ...

  4. Linux 启动过程的详细解释

    对于无论什么系统, 但无法打开电源这么简单的事, 很多事情将在几秒钟内几秒钟或几十本短时间内发生, 了解这一过程将是完整的引导解决问题的任何或提高开机速度的前提. 下一个, 我们会专门寻找Linux程 ...

  5. VxWorks启动过程的详细解释(上)

    vxworks有三个图像: VxWorks Image有三种类型的文件 Loadable Images:由Boot-ROM引导通过网口或串口下载到RAM ROM-based Images(压缩/没有压 ...

  6. java继承子类实例化过程(细节解释)

    1 package face_08; 2 class Fu{ 3 Fu(){ 4 super(); 5 show(); 6 return; 7 } 8 void show() { 9 System.o ...

  7. ANDROID定义自己的看法——onMeasure,MeasureSpec源代码 过程 思考具体解释

    一个简短的引论: 在他们的定义view什么时候,其实很easy,只需要知道3: 1.測量--onMeasure():决定View的大小 2.布局--onLayout():决定View在ViewGrou ...

  8. 机器学习-LDA主题模型笔记

    LDA常见的应用方向: 信息提取和搜索(语义分析):文档分类/聚类.文章摘要.社区挖掘:基于内容的图像聚类.目标识别(以及其他计算机视觉应用):生物信息数据的应用; 对于朴素贝叶斯模型来说,可以胜任许 ...

  9. 浏览器渲染详细过程:重绘、重排和 composite 只是冰山一角

    https://juejin.im/entry/590801780ce46300617c89b8 渲染 这张很经典的图许多人都看过,其中的概念大家应该都很熟悉,也就是这么几个步骤:js修改dom结构或 ...

随机推荐

  1. Masonry基础API

    Masonry基础API mas_makeConstraints()    添加约束 mas_remakeConstraints()  移除之前的约束,重新添加新的约束 mas_updateConst ...

  2. if语句,while语句,do whlie语句,循环语句

    总结: 1.定义数组并赋值: var arr=[1,2,3,4]; 2.通过下标访问数组: var str=arr[0]; 3.自定义数组 var arr=new Array(); 4.数组的赋值 a ...

  3. Oracle RAC 后台进程

    LMS  - Gobal         全局缓存服务进程 LMD  - Global Enqueue Service Daemon 全局查询服务守护进程 LMON -  全局服务器监控进程 LCK0 ...

  4. 了解固态硬盘SSD,竟然如此简单!小白也能懂!

    https://www.youtube.com/watch?v=alb6-zp52mA

  5. UVA - 1619 Feel Good(扫描法)

    题目: 思路: 预处理出a[i]在哪个范围区间内是最小的,然后直接遍历a数组求答案就可以了. 这个预处理的技巧巧妙的用了之前的处理结果.(大佬tql) 代码: #include <bits/st ...

  6. python list排序(正倒)以及获取重复数据

    mylist = [2,2,2,2,5,5,7,2,2,3,3,3,3] #<class 'list'>: [2, 2, 2, 2, 5, 5, 7, 2, 2, 3, 3, 3, 3] ...

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

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

  8. [bzoj4567][Scoi2016][背单词] (贪心+trie树)

    Description Lweb 面对如山的英语单词,陷入了深深的沉思,“我怎么样才能快点学完,然后去玩三国杀呢?”.这时候睿智 的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计 ...

  9. [模拟赛FJOI Easy Round #2][T1 sign] (模拟+求字符串重复字串)

    [题目描述] 小Z在无意中发现了一个神奇的OJ,这个OJ有一个神奇的功能:每日签到,并且会通过某种玄学的算法计算出今日的运势.在多次试验之后,小Z发现自己的运势按照一定的周期循环,现在他找到了你,请通 ...

  10. saltstack(六) saltstack Job管理

    一,简介 Jid: job id 格式为%Y%m%d%H%M%S%f master在下发指令消息时,会附带上产生的jid,minion在接收到指令开始执行时,会在本地的cachedir(默认是/var ...