界面透明控件开发

测试环境: 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的内部控制机理还是不是很清楚,只能用时间来处理这个问题。有更好更方便的方法希望能找到。

你可能感兴趣的:(控件开发)