5

我正在使用启用了 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;
    

摆脱闪烁的任何其他想法TSplitter?据我所知,没有 DoubleBuffer 属性TSplitter或类似的东西。

更新

不幸的是,我不能分享代码库,但我可以告诉你,这是在TSplitter闪烁时设置应用程序 UI 的方式:

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)

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

我假设由于 BackgroundPanel 位于 LeftPanel TSplitter、 和 RightPanel 后面(即 Control -> Send to Back),BackgroundPanel 上的DoubleBuffered = TrueParentBackground = False将有助于减少/消除其前面直接 UI 层上任何组件的闪烁(即TSplitter)。但是,情况似乎并非如此。

也许我会尝试将 aTPanel作为 LeftPanel TSplitter、 和 RightPanel 的父级并设置它的DoubleBuffered = Trueand ParentBackground = False。稍后我将不得不尝试并返回。所以,它看起来像这样:

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

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

更新 2

不幸的是,虽然我上面的方法(创建背景父级TPanel)修复了 上的闪烁TSplitter,但它也导致了其他奇怪的 UI 问题,也许@David Heffernan 在评论中提到了其中的一些问题。现在,我刚刚离开了闪烁的问题,因为拆分器只有 1px 宽,并且只有在调整宽度 + 高度时才会闪烁。

4

1 回答 1

4

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

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

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

于 2013-04-04T23:47:48.583 回答