Вопрос

Итак, в моем приложении есть куча WinAPI и несколько пользовательских элементов управления.Ура...

Теперь, как правило, они просто тихо перерисовывают себя для анимации, изменения состояния и так далее....и все это прекрасно работает.

Но у меня есть метод класса Window, который называется fix().Это вызывается всякий раз, когда необходимо обновить все окно целиком.Это изменяет размер элементов управления и делает окно недействительным.

Когда это происходит, прорисовывается фон, затем элемент управления tab, затем все остальные сверху.Это вызывает очень раздражающее мигание, особенно при изменении размера окна (из-за постоянных вызовов функции fix()).

То, что я пробовал:

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

Итак:Мне нужна техника / метод / что угодно, что позволило бы мне дважды буферизировать окно целиком.Я подумал, что самостоятельная обработка сообщения WM_PAINT может быть решением, но я не знаю, с чего начать.У меня ужасное предчувствие, что это даже невозможно...

Пожалуйста, помогите, это критическая проблема.Я испытаю большое облегчение, когда эта глупая маленькая проблема будет устранена.

Это было полезно?

Решение

Именно в это время кто-то осознал всю глубину пренебрежения Microsoft к местным разработчикам.На самом деле можно было бы начать питать параноидальный бред о том, что Microsoft намеренно нарушила native painting, чтобы заставить native-разработчиков перейти на WPF.

Во-первых, рассмотрим WS_EX_COMPOSITED. WS_EX_COMPOSITED кажется, это mustard : - в нем говорится, что он применяет botton для верхнего порядка рисования для дочерних элементов управления, и в основном сообщения WM_PAINT обрабатываются пакетно.В нем говорится, что он был добавлен в Windows 2000 (5.0) и, несколькими строками ниже, что он не работает с включенной композицией рабочего стола.т. е.Он перестает работать начиная с Windows Vista (6.0), если только aero glass не отключен, а кто собирается это делать?

Затем есть два возможных "взлома", чтобы попытаться заставить работать рисование без мерцания:

  • Во-первых, вам нужно минимизировать количество перекраски. WS_EX_CLIPCHILDREN | WS_EX_CLIPSIBLINGS необходимы для того, чтобы какая-либо конкретная область окна была окрашена только один раз. BeginDeferWindowPos также необходимо выполнять пакетные операции изменения размера, чтобы гарантировать, что переходных состояний, когда одно окно перекрывает другое, не происходит (т. е.когда размер окна A был изменен, а размер окна B - нет).

Конечно, когда вы пытаетесь нарисовать диалоговое окно с оболочкой, или использовать групповые поля, или элементы управления вкладками, или любое количество других ограничений, WS_EX_CLIPSIBLINGS это просто неуместно.

  • WM_SETREDRAW это волшебное послание.Нет API для доступа к этой функциональности: WM_SETREDRAW обрабатывается непосредственно DefWindowProc, чтобы по существу пометить окно как скрытое на время действия.После WM_SETREDRAW, FALSE отправляется, вызовы GetDC / GetDCEx / GetWindowDC и т.д. С использованием дескриптора родительского окна (и всех его дочерних элементов) вернут DC, который не будет отображаться на экране.Это дает вам возможность выполнять всевозможные действия с дочерними окнами, когда вы закончите отправлять WM_SETREDRAW,TRUE, (а затем перекрасьте окно вручную).Все дочерние окна, конечно, будут раскрашиваться в свое время и после того, как родительское окно удалит фон, поэтому WM_SETREDRAW не является панацеей.

После взлома WS_EX_COMPOSITED, В .NET's WinForms и WPF переписали элементы управления с нуля, чтобы не использовать собственные элементы управления, чтобы они могли там работать с буферизованным рисованием.И альфа-поддержка тоже.

Другие советы

Хм. Перед тем, как люди спешите и закрывают эту тему как дубликат, я бы лучше упомяну, что ваша проблема не является двойной буферией как SE, но мерцает при изменении контроля на репозиции, для которой «ручной» двойной буферизацией является лишь одним из нескольких решений.

Это может быть так, например, BeginDeferWindowPos & Друзья могут исправить мерцание.

Отказ от ответственности: когда-то я знал почти все детали API Win16, но прошло несколько лет с тех пор, как я занимался программированием AP-LEVEL.

Ура и hth.,

- Альф.

Без кода я вряд ли представляю, какова фактическая ситуация ... но вы можете попробовать обрабатывать wm_erasebkgnd, вернуть true, когда вы получили их, чтобы пропустить стирание.

Ручка WM_ERASEBKGND для вашего окна и в реализации, исключите прямолинейные элементы управления каждому ребенку, а затем заполните оставший trueАнкет Сделайте то же самое для всех других управления дочерним делом, которые, в свою очередь, содержит другие элементы управления, такие как управление вкладками в вашем случае.

Видеть здесь Для примера с использованием MFC.

В .net есть ControlStyle.AllPaintingInWmPaint Это должно быть установлено в каждом окне контейнера (так что главное окно и вкладки). Я не мог найти эквивалент Winapi. Но что это делает, так это перемещать картину фона с wm_erasebkgnd в wm_paint. Это также вычитает область контроля ребенка из родителей, чтобы избежать мерцания, возможно, вам нужно сделать это вручную.

Я удивлен ws_ex_composited, не помогает. Это должно работать, если вы установите это в окне верхнего уровня и не вызовут RedRawWindow на подзаконных элементах.

Также обязательно проверьте и без DWM / Aero. Вы можете получить разные результаты.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top