gpt4 book ai didi

delphi - 如何处理WM_ERASEBKGND以避免闪烁?

转载 作者:行者123 更新时间:2023-12-03 14:43:21 26 4
gpt4 key购买 nike

我在表单上有一些自定义进度条,每秒更新/刷新两次并且它们闪烁。

TMyProgressBar = class(TCustomControl)

我从 TCustomControl 继承了该控件,因为我需要 Handle 和一些 TWinControl 事件。控件(最多 64 个项目)是动态创建的并放置在 ScrollBox 上。当进度更新时,我首先调用 InvalidateRect

所有绘制工作(一组矩形、DrawText 等 - 灵感来自 here)都在内存 DC 中执行,然后在控件的直流。无论如何,它都会闪烁,似乎组件消失并重新出现。恕我直言,这是由背景删除引起的。

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状态:

An application should return nonzero if it erases the background; otherwise, it should return zero.

我测试了两种变体(结果 = 0, 1),令我惊讶的是,两种变体都避免了闪烁。

那么现在,我必须在 Delphi 代码中放入什么?正确的做法是什么?

最佳答案

没关系。重要的是,只要你不调用inherited,默认窗口过程就不会删除背景。由于您要绘制控件的整个表面,因此不需要默认处理。

当您返回“0”或“1”(而不是“0”)时,发生的变化是,当调用 BeginPaint 时,系统会设置相应的 PAINTSTRUCT 。当返回“0”时,它被设置为“True”,表示在绘制过程中必须删除背景。对于“1”,设置为“False”,表示不需要删除。 BeginPaintTWinControl.PaintHandler 中调用。没有人检查过fErase是什么,VCL只使用BeginPaint返回的设备上下文,所以你返回的内容没有任何区别。

尽管如此,我还是会返回“1”,从概念上暗示删除已经完成。

关于delphi - 如何处理WM_ERASEBKGND以避免闪烁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19794785/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com