关于DoubleBuffer
.NET可能有一个同名同功能的组件,但Delphi是从头开始实现DoubleBuffer,我认为.NET也是这样做的。在实现过程中没有使用窗口样式位。
DoubleBuffer和Glass Aero
很简单:不要为位于Glass上的控件设置DoubleBuffer。要使DoubleBuffering起作用,必须能够初始化“缓冲区”-但对于Glass,应该用什么来初始化它?Windows标准控件(包括TButton)不需要DoubleBuffering。对于需要透明表面和双缓冲类似行为的新控件,可以使用分层窗口API。
让控件在Glass上工作
步骤1:
TForm1 = class(TForm)
...
protected
procedure CreateWindowHandle(const Params: TCreateParams); override;
...
end;
procedure TForm15.CreateWindowHandle(const Params: TCreateParams);
begin
inherited;
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
SetLayeredWindowAttributes(Handle, RGB(60, 60, 60), 0, LWA_COLORKEY);
end;
第二步,这应该是您的表单的OnPaint处理程序:
procedure TForm15.FormPaint(Sender: TObject);
var rClientRect:TRect;
begin
if GlassFrame.Enabled then
begin
rClientRect := ClientRect;
Canvas.Brush.Color := RGB(60, 60, 60);
Canvas.Brush.Style := bsSolid;
Canvas.FillRect(rClientRect);
if not GlassFrame.SheetOfGlass then
begin
rClientRect.Top := rClientRect.Top + GlassFrame.Top;
rClientRect.Left := rClientRect.Left + GlassFrame.Left;
rClientRect.Right := rClientRect.Right - GlassFrame.Right;
rClientRect.Bottom := rClientRect.Bottom - GlassFrame.Bottom;
Canvas.Brush.Color := clBtnFace;
Canvas.FillRect(rClientRect);
end;
end;
end;
步骤 3:设置GlassFrame.Enabled = True; 设置所有其他玻璃属性,在表单上添加控件,无论您喜欢它们放在哪里。可能在Glass上或任何其他地方。确保控件没有"DoubleBuffered = True"。就这样,享受吧。我已经测试了TButton、TCkBox和TEdit。
...编辑...
不幸的是,使用此方法,“Glass”被视为100%透明的表面,但它并不是-它看起来像玻璃,但它不像玻璃一样运作。100%透明度的问题在于,如果您单击该透明区域,则单击会传递到窗口后面的窗口。很可怕。
在撰写本文时,我相信没有API可以更改原始玻璃的默认黑色关键颜色(Google可以找到无数博客和论坛帖子,介绍如何对坐落在玻璃上的控件进行自定义绘制,并且在MSDN上的DWM函数列表中没有更改它的函数)。如果不更改默认的黑色,大多数控件无法正确呈现,因为它们使用clWindowText编写文本,而clWindowText是黑色的。几个论坛上提出的一个建议技巧是使用SetLayeredWindowAttributes API更改透明颜色。它很有效!一旦完成了这个过程,控件上的黑色文本就会显示出来,但不幸的是,玻璃不再是玻璃,玻璃看起来像玻璃,但行为像100%透明度。这基本上使此解决方案无效,并显示了Microsoft的双重标准:原始的BLACK并不表现得像100%透明度,但如果我们将其更改为更好的东西,则会表现得像100%透明度。
在我看来,在Glass上使用自定义控件的普遍想法是错误的。这可能是唯一可行的方法,但它是错误的,因为我们应该使用跨平台一致的控件:建议使用自定义控件会打开不一致、类似Winamp的应用程序的大门,在这些应用程序中,每个用户都必须重新创建满足其艺术想法的轮子。即使开发人员成功地复制了任何给定的Windows控件并让其在Glass上运行,"修复"也只是暂时的,需要为下一个Windows版本重新创建。更不用说可能需要为现有版本的Windows创建多个变体。
另一个解决方案是使用UpdateLayeredWindow的图层窗口。但是由于很多原因,这是个痛苦的事情。
对我来说这是条死路。但我会将此问题标记为"收藏",如果有更好的解决方案出现,我想知道。
TMemo
仍然无法正常工作(至少不是没有双缓冲!),但这只是一个小问题,因为TMemo
的特性集合只是TRichEdit
特性的子集, 而TRichEdit
可以 正常工作。 - Andreas RejbrandTLabel
和TStaticText
都看起来很糟糕。更糟糕的是,窗体似乎无法被点击! - Andreas Rejbrand