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

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. gitlab 安装遇到 fatal:does not appear to be a git repository fatal: Could not read from remote repository. 问题

    Cloning into 'door_lock_bsp'... git@192.168.1.5's password:  fatal: 'door_lock/door_lock_bsp.git' do ...

  2. AC日记——总分 Score Inflation 洛谷 P2722

    题目背景 学生在我们USACO的竞赛中的得分越多我们越高兴. 我们试着设计我们的竞赛以便人们能尽可能的多得分,这需要你的帮助 题目描述 我们可以从几个种类中选取竞赛的题目,这里的一个"种类& ...

  3. pycharm上传代码到码云错误现象用户密码

    >>出现此时错误说明在pycharm>git登录用户名或密码是错误的(必须填成是自己注册的码云邮箱和密码 不允许出现中文)并且无法在当前修改用户名或密码 >>接下来打开电 ...

  4. 缓存区溢出检测工具BED

    缓存区溢出检测工具BED   缓存区溢出(Buffer Overflow)是一类常见的漏洞,广泛存在于各种操作系统和软件中.利用缓存区溢出漏洞进行攻击,会导致程序运行失败.系统崩溃.渗透测试人员利用这 ...

  5. 1.搭建maven,eclipse创建maven项目

    1.下载maven包,下载地址为:http://maven.apache.org/download.cgi 2.解压zip包 3.eclipse 引入maven: window-Preferences ...

  6. dtrace 网站

    Oracle SQL Tuning and CBO Internals: Based Optimizer with CBO Internals and SQL Tuning Optimization ...

  7. java正则过虑字符

    public static void main(String[] args) { String testrString = "{\"abc\" : \"[123 ...

  8. Lucene 源码分析之倒排索引(一)

    倒排索引是 Lucene 的核心数据结构,该系列文章将从源码层面(源码版本:Lucene-7.3.0)分析.该系列文章将以如下的思路展开. 什么是倒排索引? 如何定位 Lucene 中的倒排索引? 倒 ...

  9. EasyHook库系列使用教程之四钩子的启动与停止

    此文的产生花费了大量时间对EasyHook进行深入了解同一时候參考了大量文档 先来简单比較一下EasyHook与Detour钩取后程序流程 Detours:钩取API函数后.产生两个地址,一个地址相应 ...

  10. C#使用CurrentUICulture切换语言

    1. 创建2个窗口   2. 窗口1属性Localizable设置为True,Language选择英语(美国) 然后把窗口1中控件的Text由中文编辑成英文,Form2一样设置.   此时,Form1 ...