В моем приложении я постоянно перехожу от одного элемента управления к другому. Я создал нет. пользовательских элементов управления, но во время навигации мои элементы управления мерцают. обновление занимает 1-2 секунды. Я пытался установить это
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
or
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
но это не помогло ... Каждый элемент управления имеет одинаковое фоновое изображение с разными элементами управления. Итак, какое решение для этого ..
Спасибо.
c#
winforms
user-controls
flicker
Ройсон
источник
источник
UpdateStyles
после установки этих? Это плохо задокументировано, но иногда может быть необходимо.Ответы:
Это не тот вид мерцания, который может решить двойная буферизация. Ни BeginUpdate, ни SuspendLayout. У вас слишком много элементов управления, BackgroundImage может сделать его намного хуже.
Он запускается, когда UserControl рисует себя. Он рисует BackgroundImage, оставляя дыры там, где находятся окна дочерних элементов управления. Затем каждый дочерний элемент управления получает сообщение, которое нужно нарисовать, и они заполняют пустоту содержимым своего окна. Когда у вас много элементов управления, эти дыры какое-то время видны пользователю. Обычно они белые, плохо контрастирующие с BackgroundImage в темноте. Или они могут быть черными, если для формы установлено свойство Opacity или TransparencyKey, что плохо контрастирует практически с чем угодно.
Это довольно фундаментальное ограничение Windows Forms, оно связано с тем, как Windows отображает окна. Исправлено WPF, кстати, он не использует окна для дочерних элементов управления. Вам нужна двойная буферизация всей формы, включая дочерние элементы управления. Это возможно, проверьте мой код в этой ветке для решения. Однако у него есть побочные эффекты и на самом деле скорость рисования не увеличивается. Код прост, вставьте его в свою форму (не в пользовательский элемент управления):
Есть много вещей, которые вы можете сделать, чтобы улучшить скорость рисования до такой степени, что мерцание больше не будет заметно. Начните с решения BackgroundImage. Они могут быть очень дорогими, если исходное изображение велико и его нужно уменьшить, чтобы он соответствовал элементу управления. Измените свойство BackgroundImageLayout на «Плитка». Если это дает заметное ускорение, вернитесь в свою программу рисования и измените размер изображения, чтобы оно лучше соответствовало типичному размеру элемента управления. Или напишите код в методе UC OnResize (), чтобы создать копию изображения нужного размера, чтобы его не приходилось изменять каждый раз при перерисовке элемента управления. Используйте для этой копии формат пикселей Format32bppPArgb, он отображается примерно в 10 раз быстрее, чем любой другой формат пикселей.
Следующее, что вы можете сделать, это сделать так, чтобы дыры не были настолько заметными и плохо контрастировали с изображением. Вы можете отключить флаг стиля WS_CLIPCHILDREN для UC, флаг, который предотвращает рисование UC в области, где находятся дочерние элементы управления. Вставьте этот код в код UserControl:
Дочерние элементы управления теперь будут рисовать себя поверх фонового изображения. Вы все еще можете видеть, как они рисуют себя один за другим, но уродливая промежуточная белая или черная дыра не будет видна.
И последнее, но не менее важное: сокращение количества дочерних элементов управления всегда является хорошим подходом к решению проблем с медленным рисованием. Переопределите событие OnPaint () UC и нарисуйте то, что теперь отображается в дочернем элементе. Особый ярлык и PictureBox очень расточительны. Удобно указывать и щелкать, но их легкая альтернатива (рисование строки или изображения) требует только одной строки кода в вашем методе OnPaint ().
источник
Это реальная проблема, и ответ, который дал Ханс Пассан, отлично подходит для предотвращения мерцания. Однако, как он упомянул, есть побочные эффекты, и они могут быть уродливыми (уродливым UI). Как указано, «Вы можете отключить
WS_CLIPCHILDREN
флаг стиля для UC», но это отключает его только для UC. Компоненты в основной форме все еще имеют проблемы.Например, полоса прокрутки панели не отрисовывается, потому что технически она находится в дочерней области. Однако дочерний компонент не рисует полосу прокрутки, поэтому он не отображается до тех пор, пока не будет наведен указатель мыши (или его не вызовет другое событие).
Также не работают анимированные значки (изменение значков в цикле ожидания). Удаление значков на a
tabPage.ImageKey
не изменяет размер / перекрашивает другие tabPages соответствующим образом.Итак, я искал способ отключить
WS_CLIPCHILDREN
начальную отрисовку, чтобы моя форма загружалась красиво окрашенной, или, еще лучше, включала ее только при изменении размера моей формы с большим количеством компонентов.Уловка состоит в том, чтобы заставить приложение вызывать
CreateParams
желаемыйWS_EX_COMPOSITED/WS_CLIPCHILDREN
стиль. Я нашел здесь взлом ( https://web.archive.org/web/20161026205944/http://www.angryhacker.com/blog/archive/2010/07/21/how-to-get-rid-of- flicker-on-windows-forms-applications.aspx ), и он отлично работает. Спасибо AngryHacker!Я помещаю
TurnOnFormLevelDoubleBuffering()
вызов вResizeBegin
событиеTurnOffFormLevelDoubleBuffering()
формы и вызываю событие ResizeEnd формы (или просто оставляю егоWS_CLIPCHILDREN
после того, как оно изначально будет правильно отрисовано).источник
Если вы выполняете какую-либо пользовательскую отрисовку в элементе управления (т.е. переопределяете OnPaint), вы можете попробовать двойную буферизацию самостоятельно.
И аннулируйте свой контроль с помощью свойства
NeedRepaint
В противном случае приведенный выше ответ с SuspendLayout и ResumeLayout, вероятно, вам нужен.
источник
if (image != null) image.Dispose();
раньшеimage = new Bitmap...
Попробуйте методы BeginUpdate / EndUpdate ИЛИ SuspendLayout / ResumeLayout. См. Ниже
Как исправить проблемы с мерцанием вложенных элементов управления winform
Мерцание во время обновления элементов управления в WinForms (например, DataGridView)
источник
В основной форме или пользовательском элементе управления, где находится фоновое изображение, установите для
BackgroundImageLayout
свойства значениеCenter
илиStretch
. Вы заметите большую разницу, когда пользовательский элемент управления выполняет рендеринг.источник
Я попытался добавить это в качестве комментария, но у меня недостаточно очков. Это единственное, что когда-либо помогало моим мерцаниям, большое спасибо Гансу за его пост. Для всех, кто использует C ++ Builder, как я, вот перевод
Добавьте объявление CreateParams в файл .h основной формы вашего приложения, например
и добавьте это в свой файл .cpp
источник
Поместите приведенный ниже код в свой конструктор или событие OnLoad, и если вы используете какой-то настраиваемый пользовательский элемент управления, имеющий подэлементы управления, вам необходимо убедиться, что эти настраиваемые элементы управления также имеют двойную буферизацию (хотя в документации MS говорится по умолчанию установлено значение true).
Если вы создаете настраиваемый элемент управления, вы можете добавить этот флаг в свой ctor:
При желании вы можете использовать этот код в своей форме / элементе управления:
Мы перебираем все элементы управления в форме / элементе управления и
DoubleBuffered
получаем доступ к их свойству, а затем меняем его на true, чтобы сделать каждый элемент управления в форме двойной буферизацией. Причина, по которой мы делаем здесь отражение, заключается в том, что представьте, что у вас есть элемент управления, у которого есть дочерние элементы управления, которые недоступны, таким образом, даже если они являются частными элементами управления, мы все равно изменим их свойство на true.Более подробную информацию о технике двойной буферизации можно найти здесь .
Есть еще одно свойство, которое я обычно переопределяю для решения этой проблемы:
WS_EX_COMPOSITED
- Закрашивает всех потомков окна в порядке отрисовки снизу вверх с использованием двойной буферизации.Вы можете найти больше этих флагов стиля здесь .
Надеюсь, это поможет!
источник
Просто добавлю к ответу Ганса:
(Версия TL; DR: прозрачность тяжелее, чем вы думаете, везде используйте только сплошные цвета)
Если WS_EX_COMPOSITED, DoubleBuffered и WS_CLIPCHILDREN не устранили ваше мерцание (для меня WS_CLIPCHILDREN сделал это еще хуже), попробуйте следующее: просмотрите ВСЕ элементы управления и весь ваш код, и везде, где у вас есть прозрачность или полупрозрачность для BackColor, ForeColor или любой другой цвет, просто удалите его, используйте только сплошные цвета. В большинстве случаев, когда вы думаете, что вам просто нужно использовать прозрачность, вы этого не делаете. Измените дизайн кода и элементов управления и используйте сплошные цвета. У меня было ужасное, ужасное мерцание, и программа работала медленно. Когда я удалил прозрачность, она значительно ускорилась, и мерцания нет.
РЕДАКТИРОВАТЬ: Чтобы добавить дальше, я только что обнаружил, что WS_EX_COMPOSITED не обязательно должен быть для всего окна, его можно применять только к определенным элементам управления! Это избавило меня от многих проблем. Просто создайте настраиваемый элемент управления, унаследованный от любого элемента управления, который вам нужен, и вставьте уже опубликованное переопределение для WS_EX_COMPOSITED. Таким образом, вы получите двойной буфер низкого уровня только для этого элемента управления, избегая неприятных побочных эффектов в остальной части приложения!
источник
Я знаю, что этот вопрос очень старый, но хочу поделиться своим опытом по нему.
У меня было много проблем с
Tabcontrol
мерцанием в форме с переопределениемOnPaint
и / илиOnPaintBackGround
в Windows 8 с использованием .NET 4.0.Только думаю , что работал было НЕ ИСПОЛЬЗОВАТЬ на
Graphics.DrawImage
метод вOnPaint
переопределениях, другими словами, когда ничья была сделана непосредственно к видеокарте , предоставленнойPaintEventArgs
, даже картина все прямоугольник, мерцающем исчез. Но при вызовеDrawImage
метода, даже при рисовании обрезанного Bitmap (созданного для двойной буферизации), появляется мерцание.Надеюсь, поможет!
источник
Я объединил это фликкер исправить и этот шрифт исправить , то я должен был добавить немного мой собственный код , чтобы запустить таймер на краске Аннулируйте TabControl , когда он идет закадровый и обратно, и т.д ..
Все трое делают это:
Я не создатель, но насколько я понимаю, растровое изображение выполняет все обходы ошибок.
Это была единственная вещь, которая окончательно решила для меня мерцание TabControl (с иконками).
разница видео результат: vanilla tabcontrol vs tabcontrolex
http://gfycat.com/FineGlitteringDeermouse
пс. вам нужно будет установить HotTrack = true, потому что это тоже исправляет эту ошибку
источник
Вы пробовали
Control.DoubleBuffered
недвижимость?Также это и это может помочь.
источник
Нет необходимости в двойной буферизации и тому подобном, ребята ...
Простое решение ...
Если вы используете интерфейс MDI, просто вставьте приведенный ниже код в основную форму. Это уберет все мерцание со страниц. Однако некоторые страницы, которым требуется больше времени для загрузки, будут отображаться через 1 или 2 секунды. Но это лучше, чем показывать мерцающую страницу, на которой каждый элемент появляется один за другим.
Это единственное лучшее решение для всего приложения. Смотрите код для ввода в основную форму:
источник