调整大小时防止 TPaintBox 闪烁

Posted

技术标签:

【中文标题】调整大小时防止 TPaintBox 闪烁【英文标题】:Prevent TPaintBox flicker when resizing 【发布时间】:2021-06-07 12:09:49 【问题描述】:

我有一个带有一些控件的TFrame,还有一个TPanel,它是我绘制视频的TPaintBox 的容器。

当我调整框架大小时,由于臭名昭著的背景擦除,油漆盒上的图像会闪烁。

我搜索了几个小时并尝试了所有方法(将 PaintBox 的 ControlStyle 设置为 csOpaque,将面板的 Brush 设置为 bsClear,将面板更改为双缓冲,将面板的 FullRepaint 设置为 false,等等) 但唯一能解决问题的是在我的框架中拦截 WM_ERASEBKGND 消息:

void __fastcall TFrameSample::WndProc(TMessage &Message)

    if (Message.Msg == WM_ERASEBKGND)
        Message.Result = 1;
    else
        TFrame::WndProc(Message);

但是,这意味着不会重绘任何内容,包括框架的标题栏及其所有控件。

我知道这是一个很常见的问题,有解决办法吗?

【问题讨论】:

禁用样式是否也有同样的问题? 好问题@RemyLebeau。我刚刚对此进行了测试,答案是肯定的。我将在我的 Q 中删除对此的引用。 @RemyLebeau 我一直想知道是否可以只拦截油漆框或其祖先面板的背景擦除?另一个想法是从面板继承并创建一个禁用背景擦除的新面板?不确定这是否有意义.. 您可以在运行时基于每个控件对公共WindowProc 属性进行子类化。或者,您可以派生一个新类并在编译时覆盖虚拟 WndProc() 方法。 哦,刚刚发布了答案,现在看到您的评论。如果您想发布答案,我会删除我的。谢谢! 【参考方案1】:

在 Remy Lebeau 的旧帖子中找到了答案,请参阅 http://www.delphigroups.info/2/81/414040.html

有几种不同的方式来拦截消息 每个控制。派生一个新类只是其中之一。你也可以 子类只是现有对象实例的 WindowProc 属性。 例如:

private
    OldWndMethod: TWndMethod;
    procedure PanelWndProc(var Message: TMessage);
constructor TForm1.Create(AOwner: TComponent);
begin
    inherited Create(AOwner);
    OldWndMethod := Panel1.WindowProc
    Panel1.WindowProc := PanelWndProc;
end;
procedure TForm1.PanelWndProc(var Message: TMessage);
begin
    if Message.Msg = WM_ERASEBKGND then
    begin
        //...
    end else
        OldWndMethod(Message);
end;

【讨论】:

以上是关于调整大小时防止 TPaintBox 闪烁的主要内容,如果未能解决你的问题,请参考以下文章

调整窗口大小时是不是可以完全消除闪烁?

移动/调整窗口大小时闪烁

在自动调整 TextView 大小时输入文本时 UITableView 闪烁/口吃

避免在调整大小时移动其控件的对话框上闪烁

AWT Canvas BufferStrategy 和调整大小闪烁

Qt Quick Window/Frame with Inner Shadow在调整大小时闪烁