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;

最新文章

  1. angularjs 1 开发简单案例(包含common.js,service.js,controller.js,page)
  2. IO模型
  3. ajax传递array参数
  4. iOS中修改头部tabBarButton 默认按钮的颜色和默认字体颜色
  5. JS数组添加字典的方法
  6. ubuntu下samba服务器的安装与配置
  7. UVALive 6577 Binary Tree 二叉树的LRU串
  8. 支付宝C# RSA签名 报系统找不到指定的文件问题解决
  9. Mac环境下svn的使用(转载)
  10. 阿里云Ubuntu服务器安装java环境
  11. 如何判断 Android 应用的 Apk 签名是否一致?
  12. 李洪强iOS开发之-环信02.2_环信官网下载环信 SDK
  13. 关键字explicit
  14. Swift - 内存泄露原因(循环强引用)及解决办法
  15. php 下载文件的头信息 Determine Content Type
  16. PageRank算法实现
  17. js原型继承四步曲
  18. C# 切换到二级域名,使用Cookie
  19. mybatis框架下物理分页的实现(整个工程采用的是springmvc、spring、mybatis框架,数据库是mysql数据库)
  20. C# 项目迁移 Microsoft.VisualStudio.Tools.Office.BuildTasks 生成解决方法报错:请确认 <UsingTask> 声明正确,该程序集及其所有依赖项都可用

热门文章

  1. Computed Properties vs Property Requirements - protocol
  2. UI设计四要素
  3. Exceptions & Errors - 异常与错误
  4. sharepoint services
  5. ORACLE索引介绍和使用
  6. jsp中的basePath,获取应用的路径
  7. C++ 迭代器运算符 箭头运算符->
  8. Vijos P1334 NASA的食物计划
  9. redis+php+mysql处理高并发实例
  10. PAT 1133 Splitting A Linked List