-------------------------- 显示隐藏刷新 --------------------------

TControl = class(TComponent)
procedure Show; 调用 Parent.ShowControl(Self);
procedure Refresh; 简单调用虚拟函数 Repaint,自己不直接起作用。名叫Refresh的函数就这里一个,别无分号。
procedure Repaint; virtual; 不透明则GetDC且重画控件,透明就简单Invalidate并Update,复杂。在TWinControl里被覆盖了,因此就算被调用也是对TGraphicControl起作用而已。
procedure Invalidate; virtual; 调用InvalidateControl类函数,后者调用InvalidateRect API函数

procedure Update; virtual; 调用 Parenet.Update,它的Parent是TWinControl,所以这句就是一个呼叫转移作用,并不直接起作用。
procedure WndProc(var Message: TMessage); virtual; 处理完消息一般会Exit,否则只能Dispatch(Message);
function Perform(Msg: Cardinal; WParam: WPARAM; LParam: LPARAM): LRESULT; overload; 根据参数构建TMessage,并调用WindowProc(Message);最后取得返回值
procedure DefaultHandler(var Message); override; 只处理WM_SETTEXT消息,并且不继续传递

TWinControl = class(TControl)

procedure TWinControl.CMInvalidate(var Message: TMessage);
procedure WMPaint(var Message: TWMPaint); message WM_PAINT; 双缓冲则调用 PaintHandler,否则调用BeginPaint,复杂
procedure Repaint; override; 直接调用 Invalidate; Update; 特简单。自定义控件的时候,总要写这句标识无效且立即重画。注意,这里Invalidate也是类函数,不是API

procedure Update; override; 有句柄就立即UpdateWindow(WindowHandle); 这里的UpdateWindow可是真正的API,亮真家伙了,才能真正重画,不再转移呼叫了。

procedure PaintControls(DC: HDC; First: TControl); 重画WinControl所包含的所有子控件(TLabel等) FControls FWinControls ,发送 Perform(WM_PAINT, DC, 0);
procedure PaintHandler(var Message: TWMPaint); 调用BeginPaint或者PaintWindow或者重画FControls 复杂
procedure PaintWindow(DC: HDC); virtual; 构建并发送 WM_PAINT到DefaultHandler里,所以一般得覆盖,否则不起作用(无法调用程序员的Paint代码),但是仍然可以画出默认的程序界面。而且在TCustomControl里也确实被重载了。

procedure WndProc(var Message: TMessage); override;
procedure DefaultHandler(var Message); override; 处理了少部分消息。自己有句柄的话,会调用CallWindowProc(FDefWndProc),否则inherited DefaultHandler(Message);

TGraphicControl = class(TControl)
private
FCanvas: TCanvas; 可以画图了
procedure WMPaint(var Message: TWMPaint); message WM_PAINT; 简单调用 Paint;
protected
procedure Paint; virtual; 空函数,等待重写。比如TLabel的重画,就依赖于 procedure TCustomLabel.Paint; (它的上级TWinControl给它发WM_PAINT后调用它的Paint)。具体过程如下:TLabel的Create函数根据OS版本预先指定FDrawTextProc函数指针(也是指向自定义的类函数)。它的上级TWinControl收到WM_PAINT消息后,会给所有子控件发送WM_PAINT消息(具体过程查看TWinControl.PaintControls函数),此时TLabel会收到一个WM_PAINT消息,执行WMPaint函数,WMPaint会调用Paint虚函数,因此TLabel会调用自己的Paint函数,Paint函数会调用DoDrawText函数,DoDrawText根据不同情况判断Autosize和BiDi等属性做出相应处理后,最后调用FDrawTextProc函数,最后它会调用API函数Windows.DrawTextW,完成绘制。值得注意的是,这个API所用DC是借用父控件的DC。
property Canvas: TCanvas read FCanvas;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;

TCustomControl = class(TWinControl)
private
FCanvas: TCanvas; 可以自绘了
procedure WMPaint(var Message: TWMPaint); message WM_PAINT; 简单调用 inherited
protected
procedure Paint; virtual; 空函数,等待重写
procedure PaintWindow(DC: HDC); override; 简单调用 Paint;
property Canvas: TCanvas read FCanvas;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;

要搞清楚 TWinControl 和 TCustomControl 的区别,就要搞清楚TCustomControl为什么要覆盖 WMPaint。为什么有的控件从TWinControl继承,有的从TCustomControl继承?主要区别在于后者可以自绘,前者不需要。

-------------------------- 从TGraphicControl和TCustomControl开始,自动创建和包含Canvas实体 --------------------------

constructor TGraphicControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCanvas := TControlCanvas.Create;
TControlCanvas(FCanvas).Control := Self;
end;

constructor TCustomControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCanvas := TControlCanvas.Create;
TControlCanvas(FCanvas).Control := Self;
end;

TControl,TWinControl和TGraphicControl的显示函数的更多相关文章

  1. TWinControl与TControl的覆盖函数(TWinControl对TControl的10个消息覆盖函数,17个覆盖函数,私有虚函数仍可多态)

    手工找出来,对比一下,有助于VCL框架的理解.----------------------------------------------------------------------------- ...

  2. TControl的显示函数(5个非虚函数,4个虚函数)和三个例子的执行过程(包括SetParent的例子)

    // 9个显示函数 procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); virtual; // 虚函数,important 根据父控 ...

  3. 如何让vim自动显示函数声明-使用 echofunc.vim插件

    echofunc.vim可以显示函数的declaration, 默认的是针对c/c++, 对于php, 只要 启用了 ctags都可以, 因为echofunc是从tags file中获取数据的... ...

  4. EmWin 文本显示函数

    函数模型----------------------------------- 1:void GUI_DispChar(U16 c):  在当前窗口的当前文本位置处,使用当前字体显示单个字符.  c ...

  5. 如何在gvim中安装autoproto自动显示函数原型

    cankao: http://www.vim.org/scripts/script.php?script_id=1553 注意, 在gvim中执行的命令, :foo和:!foo 的区别, 跟vim一样 ...

  6. ue-edit设置显示函数列表

    UltraEdit的函数列表竟然不显示函数,那这功能要它何用,应该如何才能让函数显示出来呢? 公司编程基本上都在UltraEdit中进行,俺刚来公司还不熟悉,今天装了个UltraEdit,可是看着别人 ...

  7. sublime text 格式化html css 与显示函数列表

    sublime 格式化html css 1.ctrl + shift + p 2.输入install package,选择install package 3.输入:HTML-CSS-JS Pretti ...

  8. LCD浮点数显示函数的探讨

    LCD浮点数显示函数的探讨 原创 2017年12月19日 单片机开放附赠的学习资料里面很少见到显示浮点数的函数,显示浮点数的操作也相当烦坠! 一般转换显示法 拿STM32单片机资源,我们选取ADC采样 ...

  9. matlab中的输出显示函数

    matlab中的输出显示函数 在matlab中使用的显示函数有disp.sprintf.fprintf比较常用.下面来介绍一下他们的用法. 1.disp()函数: disp(x)主要是用来输出变量x的 ...

随机推荐

  1. mysql数据库编码格式

    1.查看数据库编码格式 mysql> show variables like 'character_set_database'; 2.查看数据表的编码格式 mysql> show crea ...

  2. LeetCode OJ-- Spiral Matrix

    https://oj.leetcode.com/problems/spiral-matrix/ 螺旋矩阵,逆着转,输出矩阵中的元素. 在纸上模仿,然后记左上角(l1,l2)右上角(l1,r2),左下角 ...

  3. Ruby自动化测试(操作符的坑)

    事情是这样的: times++ @ddr = DDR::DDR.new() 执行到这里的时候,总是报错:'+@' undefied method.刚开始的时候以为是机器在重启过程中一些不稳定函数调用或 ...

  4. 不要使用 reader.Peek() 去读取每行数据

    1.问题描述 使用SteamRead的Peek()和ReadLine()来读取流中的数据,如果数据行数太多,会读取不完整(后面有些数据就读不出来了). 比如: while (srResponseRea ...

  5. cookies-判断用户是否是第一次进入页面

    在郑州美莱的活动项目中客户当时有提到该需求.尽管最后去掉了该需求,但是还是花了我不少时间研究,因为之前的项目我前端没有用到过cookies,吓死宝宝了 $(document).ready(functi ...

  6. js-html音乐播放

    <img src="images/music.png" id="music" class="rotate"> <audio ...

  7. waypoint+animate元素滚动监听触发插件实现页面动画效果

    最近在做一个官网类型滚动加载动画,使用到waypoint监听事件插件和animate动画样式,两者结合完美实现向下滚动加载动画,但是没有做向上滚动撤消动画,留待以后有空研究 首先来介绍下jquery. ...

  8. gradle_____最后到齐的构建工具

    从今年开始,开始换用gradle 了,个人感觉还好,配置不像maven,一堆xml 文件,一个jar 一行字符,内置的task 和很多.自定义task 也挺简单,比ant简单一些. 简单配置文件示例: ...

  9. Cef应用程序结构

    Application Structure 应用程序结构 Every CEF3 application has the same general structure. Provide an entry ...

  10. abp ueditor 多图以及文件无法上传

    abp .net core使用ueditor遇到的问题:多图和上传文件无法上传,提示“http://请求错误”. 400 bad request解决办法: 因为abp默认启用了ValidateAnti ...