2017-02-09 14 views
3

У меня есть несколько TableLayoutPanels на формах MDI. Каждый макет таблицы имеет несколько элементов управления (включая ObjectListView), и только самый верхний из них установлен на видимый.Черный фон и артефакты на ObjectListView, когда форма получает фокус

Я реализовал решение, данное в этом SO answer, и отлично работает при открытии формы в первый раз, потому что нет мерцания над элементами управления макета при изменении размера.

Я также добавил:

protected override void OnShown(EventArgs e) 
    { 
     base.OnShown(e); 

     foreach (CoTableLayoutPanel tlp in this.Controls) 
     { 
      if (tlp != null) 
      { 
       tlp.BeginUpdate(); 
       tlp.Size = firstLayout.Size; 
       tlp.EndUpdate(); 
      } 
     } 
    } 

я выше, так что при переключении раскладки в виде они уже все правильный размер, и я избегаю дальше мерцает в то время как изменение размера. Это также отлично работает.

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

Если я использую стандарт TableLayoutPanel, управление списком ведет себя так, как ожидалось, т.е. нет артефактов, не отображается черный фон, без изменения размера столбца. Тем не менее, я получаю мерцание назад, когда я открываю форму.

ObjectListView обладает такими свойствами, как Invalidate и Refresh, и я попытался назвать их по OnGotFocus методы формы. Проблема все еще сохраняется.

Это проблема ObjectListView или я могу исправить проблему изнутри производной таблицы?

EDIT

Проблема вызвана этим методом:

protected override CreateParams CreateParams 
{ 
    get 
    { 
     CreateParams cp = base.CreateParams; 
     cp.ExStyle |= WS_EX_COMPOSITED; 
     return cp; 
    } 
} 

Комментируя этот метод сделает ObjectListView работу, как ожидалось, но возвращается мерцающие.

Любое обходное решение для вышеуказанного метода?

ответ

0

То, что выглядит как черный, это только неокрашенный часть окна. Если у вас много элементов управления на форме, тогда их перекраска занимает достаточно времени для создания заметных артефактов. Когда вы используете многоуровневое окно, оно становится черным, если вы используете свойство Opacity или TransparencyKey. Если вы этого не сделаете, артефакт имеет тенденцию быть намного менее нежелательным, потому что неокрашенные части имеют тенденцию быть белыми.

Большинство программистов полагают, что это проблема мерцания, но это не так, и свойство DoubleBuffered не может ее решить. Для подавления это потребует двойной буферизации всех элементов управления, используя тот же буфер. Примерно подход WPF.

Двойная буферизация - все, что делает флаг стиля WS_EX_COMPOSITED. Чисто сделано операционной системой, .NET не участвует. Это ранняя версия Aero, впервые доступная на XP. ОС создает растровое изображение для окна верхнего уровня и сообщает своим элементам управления рисовать в это растровое изображение, а не непосредственно в фреймбуфер видео. Когда картина сделана, она сбивает растровое изображение одним ударом в фреймбуфер. Не делает картину более быстрой, но пользователь воспринимает ее как очень гладкую.Если вы теперь используете свойство DoubleBuffered, вы хотите отключить это.

Я обнаружил технику для Winforms btw, опубликовал ее сначала на форуме на форумах MSDN, уже 10 лет назад. С тех пор он много раз копировался, как лесной пожар. Я не получил много отрицательных отзывов об этом, он решает проблему для подавляющего большинства программистов. Единственным нарушителем спокойствия, о котором я знаю, является TabControl, особенно когда у него слишком много вкладок и отображаются глифы навигации влево/вправо. Его визуальный визуализатор стилей никогда не был проблемой, когда появляются эти глифы, он начинает перекрашивать себя снова и снова. Похоже на очень быстрое мерцание, вы не можете пропустить это. Легко работать.

Поэтому нет, продвигайтесь вперед и используйте мое решение. Это хорошо, и делать это по-другому было бы крайне нетривиально. Вам в принципе придется заново изобрести WPF, чтобы полностью устранить его, используя элементы управления без окон, которые опираются на поверхность родительского окна. VB6 сделал это кстати, одна из причин, почему VB6 UI выглядит так устаревшим. Замена элементов управления кодом может привести вас туда тоже (Label и PictureBox являются особенно расточительными), но это, как правило, занимает много кода, и вы не можете бить 3 строки кода решения :)

+0

Спасибо за объяснение. –