Delphi TSplitter闪烁问题

时间:2013-04-04 21:44:03

标签: delphi flicker vcl-styles

我正在使用启用了VCL样式的Delphi,我想为我的表单更改TSplitter的颜色。我在内插器类中重写TSplitter.Paint以绘制比默认VCL样式cBtnFace颜色更暗的颜色,但是在调整大小时窗体上会出现明显的闪烁。有没有办法消除这种闪烁?

我已经尝试过这些东西来尝试减少闪烁,但没有一个有效:

  1. 禁用VCL样式(TSplitter.StyleElements := [])。

  2. 更改VCL样式位图样式设计器的“分割器”对象元素,但修改此对象元素不会更改分割器的外观。

  3. 尝试处理WM_ERASEBKGND对象上的TControl消息,但我无法在插入器类中调用该过程。

    procedure WMEraseBkgnd(var Msg: TWMEraseBkgnd); message WM_ERASEBKGND;
    ...
    procedure TSplitter.WMEraseBkgnd(var Msg: TWMEraseBkgnd);
    begin
        // this is never invoked by the TSplitter
        Msg.Result := 1;
    end;
    
  4. 有什么其他想法可以消除TSplitter上的闪烁? <{1}}没有DoubleBuffer属性,或者我可以告诉的任何类似的东西。

    更新

    不幸的是,我无法共享代码库,但我可以告诉您,当TSplitter闪烁时,这就是设置应用程序UI的方式:

    TSplitter

    表单顶部还有一个工具栏和一个主菜单,但其余的UI组件都设置为alClient(或OnResized以填充空间)。

    我假设由于BackgroundPanel位于LeftPanel,TForm (DoubleBuffered = False) -> BackgroundPanel (DoubleBuffered = True, ParentBackground = False) -> -> A TGradient, image and label to fill the BackgroundPanel -> LeftPanel (ParentBackground = False`, no flickering) -> -> LeftPanelFrame and frame content (selective double buffering) -> TSplitter -> RightPanel (ParentBackground = False, no flickering) -> -> RightPanelFrame and frame content (selective double buffering) 和RightPanel(即Control,&gt; Send to Back)后面,BackgroundPanel上的TSplitterDoubleBuffered = True会帮助减少/消除前面的即时UI层上任何组件的闪烁(即ParentBackground = False)。但是,情况似乎并非如此。

    也许我会尝试将TSplitter作为LeftPanel,TPanel和RightPanel的父级,并设置其TSplitterDoubleBuffered = True。我将不得不稍后尝试并回来。所以,它看起来像这样:

    ParentBackground = False

    最后,我应该注意,在调整大小时(窗口右侧的黑色轨迹),对TForm进行双重缓冲会大大减慢用户界面,而不是在应用程序未调整大小时执行其他UI操作时。

    更新2

    不幸的是,虽然我上面的方法(创建一个后台父TForm -> BackgroundPanel (DoubleBuffered = True, ParentBackground = False) -> -> A TGradient, image and label to fill the BackgroundPanel -> EncapsulatingPanel (DoubleBuffered = True, ParentBackground = False) -> -> LeftPanel (ParentBackground = False) -> -> -> LeftPanelFrame and frame content -> -> TSplitter -> -> RightPanel (ParentBackground = False) -> -> -> RightPanelFrame and frame content )修复了TPanel上的闪烁,但它也引起了其他奇怪的UI问题,也许其中一些@David Heffernan提到了评论。现在,我刚刚离开了闪烁的问题,因为分割器只有1px宽,只有在宽度+高度调整时闪烁。

1 个答案:

答案 0 :(得分:4)

TSplitter控件可能没有DoubleBuffered属性,但是此属性应该在您遇到闪烁的最上层控件上实现 - 在大多数情况下,表单。只要所有控件的ParentDoubleBuffered仍然默认启用,它们都将获得此更改。

DoubleBuffered并不总能修复闪烁,在某些情况下可能会使事情变得更糟。您可以考虑仅在调整大小时使用DoubleBuffered,然后在调整大小时将其关闭。此属性应仅用于实际调整大小的控件。例如,在调整表单大小时,请在表单上启用DoubleBuffered。但是当仅调整面板内容的大小时,只为该面板(及其所有子控件)启用它。

至于由于此更改导致的应用程序性能下降,您还可以考虑在调整大小时实现一个标志,这将暂停任何可能使其陷入困境的程序执行(重绘的任何内容,如标签,图像等) )。它的自身也可以解决你的问题(实际上可能是第二个答案)。