psilogic: (Default)
[personal profile] psilogic
Я по ходу дела много раз сталкивался с задачей отрисовки окон без мелькания при перемещении/скрытии/появлении.

Специально подчеркну: речь не идет об устранении мелькания при отрисовке вообще, и про технологию double buffer я, естественно, знаю. Речь идет об устранении мелькания при массовом изменении расположения и видимости окон.

Обычно это относится к child-окнам в пределах одного parent-окна. Например, есть закладка (в Tab Control), на которой десяток кнопок, edit-box-ов и тому подобного, и есть другая закладка, тоже насыщенная небольшими окнами. И вот между этими закладками мы быстро переключаемся (скажем, зажав Ctrl-Tab). Другой вариант: в верхней части диалога имеется combo-box, при прокрутке которого (стрелками или колесом мыши) меняется нижняя часть диалога: какие-то кнопки исчезают, какие-то появляются, какие-то смещаются или увеличиваются в размерах.

При этом возникают разные, иногда достаточно раздражающие эффекты мелькания.

В Windows имеется механизм BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos, который работает, но не всегда так хорошо, как хотелось бы.

Мне интересно, какие методы используют (если вообще используют) по этому поводу френды-коллеги. Возможно, есть какие-то хорошие методы, о которых я не знаю. Я в конце-концов дошел до создания собственного алгоритма, который жестко минимизирует всяческую перерисовку, и тем самым устраняет мелькание. Алгоритм работает хорошо, но получился достаточно нетривиальным, поэтому мне интересно насчет других подходов.

Date: 2010-09-14 07:10 pm (UTC)
From: [identity profile] yogsagot.livejournal.com
В дотнете у контрола есть замечательные методы - SuspendLayout и ResumeLayout. Смысл в том, что после вызова SuspendLayout никакие изменения в контролах на форме не отображаются до тех пор, пока не будет вызван ResumeLayout и все изменения разом не вступят в силу.

Хотя, готов поспорить, у тебя не дотнет. =)

Date: 2010-09-14 07:29 pm (UTC)
From: [identity profile] psilogic.livejournal.com
Действительно, у меня не дотнет :) Упомянутые *DeferWindowPos работают приблизительно по тому же принципу: по "BeginDefer..." избегают отображения, собственно DeferWindowPos накапливает изменения, а по "EndDefer..." изменения вступают в силу. Проблема в том, как именно "вступают в силу" изменения. Например, в процессе "вступления в силу" выполняется стирание прямоугольника, который был ранее занят окном, даже если этот прямоугольник теперь занят другим окном. Сначала появляется пустой прямоугольник (цветом фона родительского окна), потом поверх него - новое окно. Если цвет фона родительского окна отличается от того цвета, который используется в большей части старого и нового окна, тогда - упс, цвета на значительной площади быстро сменяются, возникает то самое мелькание.

Date: 2010-09-16 09:51 pm (UTC)
From: [identity profile] snusmumrikkk.livejournal.com
Попробуй поиграться с WS_CLIPSIBLINGS и WS_CLIPCHILDRED. По идее, они одлжны помочь избежать отрисовки несколько раз. Кроме того, можно еще попробовать художественно обрабатывать WM_ERASEBKGND (но, кажется, еще есть стили, которые благотворно влияют на его дефолтную обработку).
Page generated Sep. 10th, 2025 01:06 am
Powered by Dreamwidth Studios