TControl的显示函数(5个非虚函数,4个虚函数)和三个例子的执行过程(包括SetParent的例子)
// 9个显示函数
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); virtual; // 虚函数,important 根据父控件
// 手法:固定不变的模式,或者简单调用,或者简单设置标志位,就不是虚函数。
procedure Show; // 设置自己和所有祖先的visible标识
procedure Hide; // 简单设置visible标识,与祖先无关
procedure Refresh; // 简单调用Repaint虚函数,但Refresh本身不是虚函数。一般应该使用它,因为可以获得更多的无关性。
procedure SendToBack;
procedure BringToFront; // 图形控件也要用此能力啊,所以在TControl就已经定义了
// 这三个函数,被TWinControl覆盖。即使使用,也是被inherited使用。
// 而图形控件都没有覆盖着三个函数,因此会经常用到它们。摆明了就是给图形控件用的。
// fixme 有空试试把它们都放到图形控件里去
procedure Repaint; virtual; // 虚函数,取得父控件的DC,重画父控件的所有子控件。被TWinControl覆盖。
procedure Invalidate; virtual; // 虚函数,调用非虚函数类函数InvalideControl,把自己需要重画的部分算清楚。被TWinControl覆盖。
{ 递归调用Parent的update,否则什么都不做。意思是,自己更新了,那么父控件也要更新。}
procedure Update; virtual; // 虚函数,通知父控件自己更新了。而父控件的Update是可以被改写的,这样就达到了目的。被TWinControl覆盖。
{
看一下VCL的源码,就不难发现了。
Paint是TCustomForm的Protected方法,实际就是调用OnPaint事件。
Invalidate是TWinControl的方法,主要是发送一个CM_INVALIDATE消息,对控件的值作有效性判断。
Update(其实)也是TWinControl的方法,是通过调用Win32API函数重画窗口。
Repaint是TControl的虚方法,在TWinControl中override,程序只有2行,就是(1)Invalidate;(2)Update
Refresh是TControl的方法,程序只有1句:Repaint.
所以ReFresh和RePaint对于TWinControl的子类来说是等价的(除非又重载过),但是应该说Refresh是更规范的用法。
至于Invalidate的Update一般是没有单独使用的必要的。
}
function TControl.GetDeviceContext(var WindowHandle: HWnd): HDC;
begin
if Parent = nil then
raise EInvalidOperation.CreateFmt(SParentRequired, [Name]);
Result := Parent.GetDeviceContext(WindowHandle);
SetViewportOrgEx(Result, Left, Top, nil);
IntersectClipRect(Result, , , Width, Height);
end; procedure TControl.InvalidateControl(IsVisible, IsOpaque: Boolean);
var
Rect: TRect; function BackgroundClipped: Boolean;
var
R: TRect;
List: TList;
I: Integer;
C: TControl;
begin
Result := True;
List := FParent.FControls;
I := List.IndexOf(Self);
while I > do
begin
Dec(I);
C := List[I];
with C do
if C.Visible and (csOpaque in ControlStyle) then
begin
IntersectRect(R, Rect, BoundsRect);
if EqualRect(R, Rect) then Exit;
end;
end;
Result := False;
end; begin
if (IsVisible or (csDesigning in ComponentState) and
not (csNoDesignVisible in ControlStyle)) and (Parent <> nil) and
Parent.HandleAllocated then
begin
Rect := BoundsRect;
InvalidateRect(Parent.Handle, @Rect, not (IsOpaque or
(csOpaque in Parent.ControlStyle) or BackgroundClipped));
end;
end; procedure TControl.Invalidate;
begin
InvalidateControl(Visible, csOpaque in ControlStyle);
end; procedure TControl.Hide;
begin
Visible := False;
end; procedure TControl.Show;
begin
if Parent <> nil then Parent.ShowControl(Self);
if not (csDesigning in ComponentState) or
(csNoDesignVisible in ControlStyle) then Visible := True;
end; procedure TControl.Update;
begin
if Parent <> nil then Parent.Update; // 图形控件没法刷新自己,让父控件去刷新
end; procedure TControl.Refresh;
begin
Repaint;
end; procedure TControl.Repaint;
var
DC: HDC;
begin
if (Visible or (csDesigning in ComponentState) and
not (csNoDesignVisible in ControlStyle)) and (Parent <> nil) and
Parent.HandleAllocated then
if csOpaque in ControlStyle then
begin
DC := GetDC(Parent.Handle);
try
IntersectClipRect(DC, Left, Top, Left + Width, Top + Height);
Parent.PaintControls(DC, Self);
finally
ReleaseDC(Parent.Handle, DC);
end;
end else
begin
Invalidate;
Update;
end;
end;
PaintControls的意思是,重绘所有图形子控件
--------------------------------------------------------------------------------
例子1:可以看到Image1.的绘制过程
image1.Refresh;
例子2:
Image1.Hide;
例子3:
var
Image2 : TImage;
begin
Image2 := TImage.Create(self);
Image2.Left := 100;
Image2.Top := 50;
Image2.Picture.LoadFromFile('c:\pic.jpg');
Image2.Parent := Form1;
end;
TControl的显示函数(5个非虚函数,4个虚函数)和三个例子的执行过程(包括SetParent的例子)的更多相关文章
- C++ - 虚基类、虚函数与纯虚函数
虚基类 在说明其作用前先看一段代码 class A{public: int iValue;}; class B:public A{public: void bPrintf(){ ...
- 基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------> 可以返回派生类对象的引用或指针
您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. ...
- 阻塞、非阻塞的概念和select函数的阻塞功能
其它文档: http://www.cnitblog.com/zouzheng/archive/2010/11/25/71711.html (1)阻塞block 所谓阻塞方式block,顾名思义 ...
- [C++基础]C++中静态成员函数如何访问非静态成员
#include <iostream> /* 静态成员函数只能访问静态数据成员.静态成员函数和类以外的函数和数据,不能访问非静态数据成员,但静态成员函数或静态数据成员可由任意访问许可的函数 ...
- C++函数中那些不可以被声明为虚函数的函数
转自C++函数中那些不可以被声明为虚函数的函数 常见的不不能声明为虚函数的有:普通函数(非成员函数):静态成员函数:内联成员函数:构造函数:友元函数. 1.为什么C++不支持普通函数为虚函数? 普通函 ...
- C++静态成员函数不能调用非静态成员变量
其实我们从直观上可以很好的理解静态成员函数不能调用非静态成员变量这句话因为无论是静态成员函数还是静态成员变量,它们 都是在类的范畴之类的,及在类的整个生存周期里始终只能存在一份.然而非静态成员变量和非 ...
- 在Word2010文档中显示域代码而非域值
当Word2010文档中含有域内容时,默认情况下显示域值,这样可以使插入的域内容清晰明了.用户可以根据需要选择显示域代码或显示域值,操作步骤如下所述: 步骤/方法 第1步,打开Word2010文档窗口 ...
- C++ virtual函数重写,在继承的时候没有在函数前写virtual关键字也依然是虚函数吗?
比如: class Base { Base() {}; ~Base() {}; virtual void Init(); }; class Derived:public Base { virtual ...
- Docker-machine创建虚机时停在虚机启动的提示上,并且创建的虚机显示Ip Not found
Docker-machine创建虚机时停在虚机启动的提示上,并且创建的虚机用docker-machine ls 列出来的时候显示Ip Not found, 是什么原因那? [答案] 看这个帖子: ht ...
随机推荐
- ReentrantLock与synchronized的差别
总的来说,lock更加灵活. 主要同样点:Lock能完毕synchronized所实现的全部功能 不同: 1.ReentrantLock功能性方面更全面,比方时间锁等候,可中断锁等候,锁投票等,因此更 ...
- Qt 学习之路 :使用 QJson 处理 JSON
XML 曾经是各种应用的配置和传输的首选方式.但是现在 XML 遇到了一个强劲的对手:JSON.我们可以在 这里 看到有关 JSON 的语法.总体来说,JSON 的数据比 XML 更紧凑,在传输效率上 ...
- myeclipse一些技巧
ctrl+h-----------------查找字符串 ctrl+A 全选→ctrl+shift+f 代码格式化,排版 ctrl+shift+O 自动引用
- [转] 使用git自动部署简单网站
要做什么 假设你有一个博客,有一台网站服务器(或者很多台作负载均衡的服务器),当你的博客要升级时,你可能要在你自己的电脑上写好代码(可能包括本地调试好),然后提交到git(或svn),然后在每个服务器 ...
- iOS 延迟执行代码
//延迟执行 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)( * NSEC_PER_SEC)),dispatch_get_main ...
- 【转】iOS-Core-Animation-Advanced-Techniques(二)
原文: http://www.cocoachina.com/ios/20150104/10816.html 视觉效果和变换 (四)视觉效果 嗯,园和椭圆还不错,但如果是带圆角的矩形呢? 我们现在能做到 ...
- iOS 集成支付宝遇到的问题(续)
调起支付宝进行支付时提示private key is null ,碰到这个问题有两种解决方案 第一种. 将私钥转成PKCS8替换一下原私钥即可 1.生成私钥pem, 执行命令openssl genr ...
- 设置tabbar的角标与第三方库Masonry的基本使用
// 设置tabbar的角标 [[[[[self tabBarController] viewControllers] objectAtIndex: 0] tabBarItem] setBadgeVa ...
- hdoj 1251 字典树
代码: #include <stdio.h>#define MAX 26 typedef struct TrieNode{ int nCount; struct ...
- Android的进程和线程(转)
进程和线程 当一个应用程序第一次启动的时候,Android会启动一个Linux进程和一个主线程(即UI线程:主要负责处理用户的按键事件.触屏事件及屏幕绘图事件等).默认情况下,所有该程序的组件都将在该 ...