【发布时间】:2019-09-19 02:36:50
【问题描述】:
我的控件是 TCustomControl 的后代,其中所有内容都使用 GDI+ 在重写的 Paint 方法中绘制。
一切都很好
DoubleBuffered := True;
ParentBackground := False;
然后我在Paint 方法中用
g := TGPGraphics.Create(Canvas.Handle);
g.Clear(MakeColor(70, 70, 70));
现在我想在我不绘画的区域制作透明背景。
所以,我把g.Clear 注释掉了
ParentBackground := True;
在构造函数中。
当运行时主题关闭时,将父控件的DoubleBuffered 设置为True 就足够了,以避免闪烁,但对于运行时主题,这不再有帮助。
以下是TWinControl 代码的摘录,带有导致闪烁的标记行:
procedure TWinControl.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
if StyleServices.Enabled and Assigned(Parent) and (csParentBackground in FControlStyle) then
begin
{ Get the parent to draw its background into the control's background. }
if Parent.DoubleBuffered then
PerformEraseBackground(Self, Message.DC) //It flickers here!!!!!
else
StyleServices.DrawParentBackground(Handle, Message.DC, nil, False);
end
else
begin
{ Only erase background if we're not doublebuffering or painting to memory. }
if not FDoubleBuffered or
{$IF DEFINED(CLR)}
(Message.OriginalMessage.WParam = Message.OriginalMessage.LParam) then
{$ELSE}
(TMessage(Message).wParam = WPARAM(TMessage(Message).lParam)) then
{$ENDIF}
FillRect(Message.DC, ClientRect, FBrush.Handle);
end;
Message.Result := 1;
end;
有什么解决办法吗?
【问题讨论】:
-
为什么将
DoubleBuffered设置为True? -
我认为无需将
DoubleBuffered设置为True就可以解决闪烁问题。这一直是我解决闪烁的 VCL 控件的方法。 -
@DavidHeffernan:但是状态栏和列表视图控件通常需要双缓冲,否则您会得到可怕的视觉伪像(至少在我见过的大多数瑞典 PC 上)。
-
@AndreasRejbrand 列表视图和状态栏确实是规则的例外。
-
所以你可以通过自己处理 WM_ERASEBKGND 来改变行为,不是吗?