TGraphicControl和TCustomControl自绘过程的理论解释
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自绘过程的理论解释的更多相关文章
- 《Android内核剖析》读书笔记 第13章 View工作原理【View重绘过程】
计算视图大小的过程(Measure) 视图大小,准确的来说应该是指视图的布局大小:我们在layout.xml中为每个UI控件设置的layout_width/layout_height两个属性被用来设置 ...
- [Android FrameWork 6.0源码学习] View的重绘过程
View绘制的三部曲, 测量,布局,绘画今天我们分析测量过程 view的测量是从ViewRootImpl发起的,View需要重绘,都是发送请求给ViewRootImpl,然后他组织重绘在重绘的过程中 ...
- IP地址,子网掩码、默认网关,DNS理论解释
在网上发现的这篇文章写的非常好,有理论有示例. (一) 问题解析 001. 问: IP地址,子网掩码,默认网关,DNS服务器,有什么区别呀?我知道没有IP地址就不能上网,我也知道没设DNS就不 ...
- Linux 启动过程的详细解释
对于无论什么系统, 但无法打开电源这么简单的事, 很多事情将在几秒钟内几秒钟或几十本短时间内发生, 了解这一过程将是完整的引导解决问题的任何或提高开机速度的前提. 下一个, 我们会专门寻找Linux程 ...
- VxWorks启动过程的详细解释(上)
vxworks有三个图像: VxWorks Image有三种类型的文件 Loadable Images:由Boot-ROM引导通过网口或串口下载到RAM ROM-based Images(压缩/没有压 ...
- java继承子类实例化过程(细节解释)
1 package face_08; 2 class Fu{ 3 Fu(){ 4 super(); 5 show(); 6 return; 7 } 8 void show() { 9 System.o ...
- ANDROID定义自己的看法——onMeasure,MeasureSpec源代码 过程 思考具体解释
一个简短的引论: 在他们的定义view什么时候,其实很easy,只需要知道3: 1.測量--onMeasure():决定View的大小 2.布局--onLayout():决定View在ViewGrou ...
- 机器学习-LDA主题模型笔记
LDA常见的应用方向: 信息提取和搜索(语义分析):文档分类/聚类.文章摘要.社区挖掘:基于内容的图像聚类.目标识别(以及其他计算机视觉应用):生物信息数据的应用; 对于朴素贝叶斯模型来说,可以胜任许 ...
- 浏览器渲染详细过程:重绘、重排和 composite 只是冰山一角
https://juejin.im/entry/590801780ce46300617c89b8 渲染 这张很经典的图许多人都看过,其中的概念大家应该都很熟悉,也就是这么几个步骤:js修改dom结构或 ...
随机推荐
- Linux 软件编译、安装、删除
本文学习内容 手动安装软件 手动安装下载源码的软件 源码编译3步骤 deb包-包依赖管理 dekg -l 查看所以安装deb的包 apt-get仓库安装(自动处理依赖问题) 640?wx_fmt=gi ...
- SpringMVC-Mybatis整合和注解开发
SpringMVC-Mybatis整合和注解开发SpringMVC-Mybatis整合整合的思路在mybatis和spring整合的基础上 添加springmvc.spring要管理springmvc ...
- jsp中的basePath,获取应用的路径
1 2 3 4 5 String path = request.getContextPath(); String basePath = request.getScheme()+": ...
- angularJs 解析factory、service、provider
了解angular js factory可以认为是设计模式中的工厂方法,就是你提供一个方法,该方法返回一个对象的实例:对于angularJs的factory,就是先定义一个对象,给这个对象添加属性和方 ...
- [USACO06JAN] 冗余路径 Redundant Paths
题目描述 In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1. ...
- #if 0的意义和好处
在调试中经常遇到,写好的程序,需要调试相反的两方面,如:有两款单片机的程序,分别对应着不同的硬件引脚,我们把代码都写上了,但是不能同时让他们起效,通常的办法是/**/屏蔽一些段落,但是调试起来很麻烦. ...
- Spring security 5 Authorize Configuration
1. Spring Security 核心请求,认证配置类 WebSecurityConfigurerAdapter protected void configure(HttpSecurity htt ...
- EF中避免查询重复执行的手段
由于ef有lazyload机制,编写的查询语句往往都没有立即执行,当你轮训结果集的时候才会将查询翻译成database端的sql语句,执行sql将结果返回到方法中.但是,下次再使用前面的结果集的时候, ...
- 【Codeforces 1019A】Elections
[链接] 我是链接,点我呀:) [题意] 每个人都有自己喜欢的队员 但是如果贿赂他们可以让他们更改自己喜欢的队员 问你最少要花多少钱贿赂队员才能让1号队员严格有最多的人喜欢? [题解] 除了1号之外, ...
- mongodb local数据库的空间初始化好大啊!
新建立了一个replicat set,登录到primary里,show dbs一看吓一跳 local数据库竟然占用了80多G的空间 [root@wxlab31 bin]# ./mongo --host ...