Delphi控件的透明与不透明(要挨个解释一下原因),对InvalidateControl的关键理解
2015-08-25 04:25
429 查看
procedure TForm1.Button3Click(Sender: TObject);
begin
if (csOpaque in ControlStyle) then ShowMessage('不透明')
else ShowMessage('透明') // Form透明
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
if (csOpaque in Panel1.ControlStyle) then ShowMessage('不透明') // Panel不透明
else ShowMessage('透明')
end;
if (csOpaque in Button1.ControlStyle) then ShowMessage('不透明')
else ShowMessage('透明') // Button透明
if (csOpaque in label1.ControlStyle) then ShowMessage('不透明') // Label不透明
else ShowMessage('透明')
if (csOpaque in image1.ControlStyle) then ShowMessage('不透明')
else ShowMessage('透明') // image1没有内容的时候,就是透明;有内容的时候,就是不透明
if (csOpaque in bitbtn1.ControlStyle) then ShowMessage('不透明')
else ShowMessage('透明') // bitbtn1有没有内容都是透明
http://bbs.2ccc.com/topic.asp?topicid=461248
---------------------------------------------------------------
对InvalidateControl的关键理解:
1.它是TControl的非虚函数,虽然它可以被TWinControl调用,但是根据VCL的其它代码,充分证明它实际上只能被图形子控件所使用:
2. 它的实际内容:
关键在于最后一个参数,三个条件之一成立,结果就是false,就不需要重绘背景了。这三个条件分别是:
1. 自身不透明(比如自身是Panel,或者自身是默认状态的标签),那么在自己的区域坐标内,自己可以随意重绘,而整个父控件的大背景不用变化。这个最容易理解。
2. 父控件不透明(比如父控件是Panel),那么父控件的背景不用看别的控件脸色,子控件在上面无论怎么自绘,也不需要改变父控件的背景。这个也能理解。
3. 兄弟控件的矩形区域与自己完全相同(也就是当前控件的区域坐标,与另一个z轴比它低、且不透明的兄弟控件的区域坐标完全一致,此时bChipped=true,此时当前控件的背景色要看这个兄弟控件的颜色即可,与父控件的颜色完全无关了)。这个也好理解,当前控件怎么自绘,都不影响和不需要父控件的背景。
但是,如果透明标签放在Form上,那么IsOpaque=false, bParentOpaque=false, bChipped=false,那么此时就会重绘整个句柄的区域,而不仅仅是指定的部分。
If the bErase parameter is TRUE for any part of the update region, the background is erased in the entire region, not just in the specified part.
begin
if (csOpaque in ControlStyle) then ShowMessage('不透明')
else ShowMessage('透明') // Form透明
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
if (csOpaque in Panel1.ControlStyle) then ShowMessage('不透明') // Panel不透明
else ShowMessage('透明')
end;
if (csOpaque in Button1.ControlStyle) then ShowMessage('不透明')
else ShowMessage('透明') // Button透明
if (csOpaque in label1.ControlStyle) then ShowMessage('不透明') // Label不透明
else ShowMessage('透明')
if (csOpaque in image1.ControlStyle) then ShowMessage('不透明')
else ShowMessage('透明') // image1没有内容的时候,就是透明;有内容的时候,就是不透明
if (csOpaque in bitbtn1.ControlStyle) then ShowMessage('不透明')
else ShowMessage('透明') // bitbtn1有没有内容都是透明
http://bbs.2ccc.com/topic.asp?topicid=461248
---------------------------------------------------------------
对InvalidateControl的关键理解:
1.它是TControl的非虚函数,虽然它可以被TWinControl调用,但是根据VCL的其它代码,充分证明它实际上只能被图形子控件所使用:
procedure TWinControl.RemoveControl(AControl: TControl); begin Perform(CM_CONTROLCHANGE, Integer(AControl), Integer(False)); // 通知父控件 if AControl is TWinControl then with TWinControl(AControl) do begin RemoveFocus(True); // 类函数 DestroyHandle; // important5 销毁它和它所有的子控件 end else if HandleAllocated then AControl.InvalidateControl(AControl.Visible, False); // important5 让图形控件消失使用这种手法 Remove(AControl); // 类函数 Perform(CM_CONTROLLISTCHANGE, Integer(AControl), Integer(False)); // 通知父控件 Realign; end; procedure TControl.DoDock(NewDockSite: TWinControl; var ARect: TRect); begin { Erase TControls before UpdateboundsRect modifies position } if not (Self is TWinControl) then InvalidateControl(Visible, False); if Parent <> NewDockSite then UpdateBoundsRect(ARect) // 类函数 else BoundsRect := ARect; // 类属性 if (NewDockSite = nil) or (NewDockSite = NullDockSite) then Parent := nil; end;
2. 它的实际内容:
procedure TControl.InvalidateControl(IsVisible, IsOpaque: Boolean); var bParentOpaque: Boolean; bChlipped: Boolean; Rect: TRect; begin if (IsVisible or (csDesigning in ComponentState) and not (csNoDesignVisible in ControlStyle)) and (Parent <> nil) and Parent.HandleAllocated then begin Rect := BoundsRect; // 类函数,简单计算(根据控件的长宽高)标签的坐标以及尺寸 bParentOpaque := csOpaque in Parent.ControlStyle; // Form默认透明(csOpaque不在风格里)。但是父控件不一定是Form,不要思维僵化在这里。 bChlipped:=BackgroundClipped; // 实验说明后两个一般情况下都是False // 第三个参数为False,则保持背景不变。Not作用符以后,有三者条件之一成立即可,就会保持背景不变。 // IsOpaque表示TControl自己不透明,完全遮住了父控件相应的区域,当然不用重绘背景 // bParentOpaque表示父控件自己就是不透明的,现有的背景已经足够(不需要更新父父控件的背景),那么无论TControl子控件怎么办自绘,都不需要更新背景。 // bChlipped 重合了 // 反过来说,自己透明(而且有可能是从不透明变成透明),这时当然要重绘背景。因为原来那部分背景根本就没有绘制。 // 父控件透明,也可以从不透明变成透明,这时也要背景重绘。fixme 如果父控件一直是透明的呢,那么每次绘制都要求父父控件背景重绘,因为父父控件的状态也有可能在改变。 // fixme 有空仔细研究背景消息 才能深刻理解 InvalidateRect(Parent.Handle, @Rect, not (IsOpaque or bParentOpaque or bChlipped)); // API end; end;
关键在于最后一个参数,三个条件之一成立,结果就是false,就不需要重绘背景了。这三个条件分别是:
1. 自身不透明(比如自身是Panel,或者自身是默认状态的标签),那么在自己的区域坐标内,自己可以随意重绘,而整个父控件的大背景不用变化。这个最容易理解。
2. 父控件不透明(比如父控件是Panel),那么父控件的背景不用看别的控件脸色,子控件在上面无论怎么自绘,也不需要改变父控件的背景。这个也能理解。
3. 兄弟控件的矩形区域与自己完全相同(也就是当前控件的区域坐标,与另一个z轴比它低、且不透明的兄弟控件的区域坐标完全一致,此时bChipped=true,此时当前控件的背景色要看这个兄弟控件的颜色即可,与父控件的颜色完全无关了)。这个也好理解,当前控件怎么自绘,都不影响和不需要父控件的背景。
但是,如果透明标签放在Form上,那么IsOpaque=false, bParentOpaque=false, bChipped=false,那么此时就会重绘整个句柄的区域,而不仅仅是指定的部分。
If the bErase parameter is TRUE for any part of the update region, the background is erased in the entire region, not just in the specified part.
相关文章推荐
- 百度输入提示 Delphi 实现
- Delphi中对BCD码的直接支持 (转)
- Delphi源码分析之System.DateUtils Start/End functions
- Delphi7 第三方控件1stClass4000的TfcImageBtn按钮控件动态加载jpg图片例子
- Delphi中常用的各个关键字名称及用法
- DelPhi 动态给ComBoBox赋值,从ComBoBox中取值
- Delphi2010中DataSnap技术网摘
- 关于win7 下delphi7出现重新注册,无法打开的故障解决办法
- 解决EditorLineEnds.ttr被锁定导致Delphi2006-2010无法启动的问题
- delphi发送html带附件邮件
- Delphi中处理URL编码解码
- UPX 0.89.6 - 1.02 / 1.05 - 2.90 (Delphi) stub -> Markus & Laszlo 手动脱壳
- UPX 0.89.6 - 1.02 / 1.05 - 2.90 (Delphi) stub -> Markus & Laszlo 手动脱壳
- Delphi XE8 手动配置Android开发环境JDK,Android SDK,NDK
- 获取Delphi所有类的类信息
- Delphi重载,覆盖,多态
- Delphi 的各种错误信息(中英文)
- delphi XML 原来可以玩接口
- Delphi文件映射
- Delphi中ADO异步执行方式