【发布时间】:2013-11-16 16:03:31
【问题描述】:
我在表单上有一些自定义进度条,它们每秒更新/刷新两次,并且它们在闪烁。
TMyProgressBar = class(TCustomControl)
我从TCustomControl 继承了控件,因为我需要Handle 和一些TWinControl 事件。控件(最多 64 个项目)是动态创建的并放在 ScrollBox 上。当进度更新时,我首先致电InvalidateRect。
所有绘画工作(一组矩形、DrawText 等 - 灵感来自 here)在内存 DC 中执行,然后在控件的 DC 上执行BitBlt-ed。无论如何它都在闪烁,似乎组件消失并重新出现。恕我直言,这是由背景擦除引起的。
在this flickering-free drawing advice 中,它被写入以下列方式处理WM_ERASEBKGND:
type
TMyProgressBar = class(TCustomControl)
procedure WMEraseBkGnd(var Message:TMessage); message WM_ERASEBKGND;
procedure TMyProgressBar.WMEraseBkGnd(var Message: TMessage);
begin
Message.Result := 1;
end;
但在另一个组件中,通过 TMS (TAdvProgressBar),Result 被设置为 0 用于相同的消息。
现在the Windows documentation 表示:
如果清除背景,应用程序应该返回非零值; 否则,它应该返回零。
我测试了两种变体(结果 = 0、1),令我惊讶的是,它们都避免了闪烁。
那么现在,我必须在我的 Delphi 代码中添加什么?正确的方法是什么?
【问题讨论】:
-
返回 1,您可能不会受益于将更新区域标记为擦除。
-
这并不是真正的万能药。在
WM_ERASEBACKGROUND中可能确实需要完成一些工作。当然,如果你什么都不画,那么你就不会闪烁。 -
有一个非常棒的自定义
TScrollBox示例,它针对闪烁进行了调整:stackoverflow.com/a/16569324/327083
标签: delphi winapi delphi-7 gdi flicker