Мерцающая проблема Delphi TSplitter

Я использую Delphi со включенными стилями VCL, и я хотел бы изменить цвет TSplitter для моей формы. Я переопределяю TSplitter.Paint в классе Interposer для рисования более темного цвета, чем стили VCL по умолчанию cBtnFace цвет, но при изменении размера на форме заметно мерцание. Есть ли способ убрать это мерцание?

Я пробовал эти вещи, чтобы попытаться уменьшить мерцание, но ничего не получилось:

  1. Отключение стилей VCL (TSplitter.StyleElements := []).

  2. Изменение элемента объекта "Конструктор растрового стиля стилей VCL" для "Splitter", но изменение этого элемента объекта не изменяет внешний вид разделителя.

  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 мерцает:

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)

В верхней части формы также есть панель инструментов и главное меню, но для остальных компонентов пользовательского интерфейса установлено значение alClient (или OnResized для заполнения пространства).

Я предположил, что поскольку BackgroundPanel находится за левой панелью, TSplitterи RightPanel (т. е. Control -> Send to Back), DoubleBuffered = True а также ParentBackground = False на BackgroundPanel поможет уменьшить / убрать мерцание от любых компонентов на непосредственном уровне пользовательского интерфейса перед ним (то есть, TSplitter). Но, похоже, это не так.

Возможно я постараюсь разместить TPanel как родитель LeftPanel, TSplitterи RightPanel и установите его DoubleBuffered = True а также 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 существенно замедляет пользовательский интерфейс при изменении размера (черный след справа от окна), а не при выполнении других действий пользовательского интерфейса, когда приложение не изменяет размер.

ОБНОВЛЕНИЕ 2

К сожалению, пока мой подход выше (создание фонового родителя TPanel) исправлено мерцание на TSplitterЭто также вызвало другие странные проблемы с пользовательским интерфейсом, возможно, некоторые из которых @David Heffernan упоминались в комментариях. Сейчас я только что оставил проблему мерцания, поскольку разделитель имеет ширину всего 1 пиксель и мерцает только при изменении ширины и высоты.

1 ответ

Решение

TSplitter контроль может не иметь DoubleBuffered свойство, но это свойство должно быть реализовано на самом верхнем элементе управления мерцанием - в большинстве случаев - на форме. Пока все элементы управления имеют ParentDoubleBuffered все еще включен по умолчанию, все они также получат это изменение.

DoubleBuffered не всегда устраняет мерцание, а в некоторых ситуациях может усугубить ситуацию. Вы можете рассмотреть только использование DoubleBuffered во время изменения размера, а затем выключите его, когда изменение размера будет сделано. Это свойство должно использоваться только для тех элементов управления, размер которых на самом деле изменяется. Например, при изменении размера формы включите DoubleBuffered на форме. Но при изменении размера только содержимого панели включите его только для этой панели (и всех ее дочерних элементов управления).

Что касается падения производительности вашего приложения из-за этого изменения, вы можете также рассмотреть возможность применения флага при изменении размера, который приостановит выполнение любой программы, которая может привести к ее сбою (что-либо перерисовывает, например, метки, изображения и т. Д.). Это само по себе также может быть решением вашей проблемы (на самом деле может быть вторым ответом).

Другие вопросы по тегам