界面透明控件开发

本文详细介绍了在使用Delphi开发环境下,如何在双缓冲技术开启的情况下,实现控件的背景透明效果。通过深入探讨Delphi控件的内部机制,提出了一种简便且有效的方法,即在创建控件时直接复制父级对象的背景,并在Paint事件中进行背景的绘制。这种方法避免了传统方法带来的界面问题,提供了简洁、高效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

测试环境: Win7 + XE2

在开发界面控件中,想加个背景,做的漂亮点。当然会考虑主界面加背景,其他控件设置透明就能所有控件都能正常显示背景。

自己的控件只要在Create时设置,使用背景和设置透明就OK了

ControlStyle := ControlStyle + [csParentBackground] - [csOpaque];

就能正常实现透明化。为了方便观察,把TForm的背景设置为clSkyBlue。

下面是个简单的不透明控件是显示的状态(背景clSkyBlue),TCustomControl,默认会打开ParentColor,所以颜色和Form的相同


 (图1)  未设置透明属性的情况的图片,

 (图2)   增加 csParentBackground 去除 csOpaque 就看不到刚才那块clSkyBlue。具体可以看代码。

最简单控件透明实现完整代码
 1 //MMWIN:CLASSCOPY
 2 unit _MM_Copy_Buffer_;
 3 
 4 interface
 5 
 6 type
 7   TmtTest = class(TCustomControl)
 8   public
 9     constructor Create(AOwner: TComponent); override;
10   end;
11 
12 
13 implementation
14 
15 { TmtTest }
16 constructor TmtTest.Create(AOwner: TComponent);
17 begin
18   inherited;
19   Width := 100;
20   Height := 60;
21   ControlStyle := ControlStyle + [csParentBackground] - [csOpaque];
22 end;
23 
24 end.

 

当然做控件肯定会遇到屏幕刷新闪烁问题,设置 DoubleBuffered := true; 是很容易想到的一个方法。出状况了,如果你打开Form的双缓冲技术。你会发现上面原来能透明的控件无效了。变成和Form相同颜色和(图1)相同。郁闷啊

上面这张图上当打开TForm的双缓冲技术后,出现的结果。标准的TToolbar 和 TMyToolbar 都出现背景为控件的背景,不是Parent的背景。

在网上查了一些,做背景透明的有不少文章,好像都是一样的。

1.在Create中设定ControlStyle :=ControlStyle - [csOpaque];
2. override 它的CreateParams方法, exstyle 里加上WS_EX_TRANSPARENT.
3. 修改它的parent的window style, 去掉WS_CLIPCHILDREN.

4、截获WM_ERASEBKGND, 什么都不做直接返回1.(不搽除背景)

5、大绝招自己画

在用完上面三板斧后,在DoubleBuffered 开启的情况下依然如旧。上面第四部用颜色标出的是,在使用此招时就乱套了,界面面目全非。

鼠标滑过狼藉遍地,由于不擦除背景导致未被处理的背景一并被画出来。

当然了,他还说最终大绝招~~ (=@__@=)! 自己绘制。

 

还是大绝招好用,不用设置任何东西直接O.K.了。


实现方法:直接拷贝Parent对象的背景

IntersectClipRect 这个函数就能解决问题

 1 //MMWIN:CLASSCOPY
 2 unit _MM_Copy_Buffer_;
 3 
 4 interface
 5 
 6 type
 7   TmtTest = class(TCustomControl)
 8   protected
 9     procedure Paint; override;
10   public
11     constructor Create(AOwner: TComponent); override;
12   end;
13 
14 
15 implementation
16 
17 
18 { TmtTest }
19 
20 constructor TmtTest.Create(AOwner: TComponent);
21 begin
22   inherited;
23   Width := 100;
24   Height := 60;
25 end;
26 
27 procedure TmtTest.Paint;
28 var
29   SaveIdx: Integer;
30   DC: HDC;
31   p: TPoint;
32 begin
33   inherited;
34   if Parent = nil then
35     Exit;
36   DC := Canvas.Handle;
37   SaveIdx := SaveDC(DC);
38   GetViewportOrgEx(DC, p);
39   SetViewportOrgEx(DC, p.x - Left, p.y - Top, nil);
40   IntersectClipRect(DC, 0, 0, Parent.ClientWidth, Parent.ClientHeight);
41   Parent.Perform(WM_ERASEBKGND, DC, 0);
42   Parent.Perform(WM_PAINT, DC, 0);
43   RestoreDC(DC, SaveIdx);
44 end;
45 
46 end.


另外VCL的内部控制机理还是不是很清楚,只能用时间来处理这个问题。有更好更方便的方法希望能找到。

转载于:https://www.cnblogs.com/gleam/archive/2012/11/23/2784573.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值