Вопрос к корифеям программирования под Винду Имеется следующая ситуация: Существует простейшее окошко, с обработчиком событий WndProc(), которы по сообщению WM_PAINT обновляет клиентскую часть окна (допустим закрашивает ее в черный цвет), а все остальные сообщения перенаправляет стандартной функции DefWindowProc(). Запускаем все это дело, появляется черное окно. Теперь беру любое другое окошко (калькулятор, или малеьнкое окошко от FlashGet'а, которое всегда висит в углу) и начинаю его услиленно таскать по клиентской области своего окна. И что же я вижу? За этим таскаемым окошком остается белый след, который, естественно, тут же закрашивается черным (WndProc()/WM_PAINT), но сам факт, что система при перетаскивании обьекта по поверхности моего окна, предыдущее положение этого обьекта очищает в белый цвет! T.e. этот белый цвет рисуется не моей WndProc() и не DefWindowProc() Беру для эксперимента любые чужие программы и смотрю, как ведут в таких ситуациях они: * EmuZWin - при таскании поверх клиентской зоны белого следа нет, след есть только при задевании рамки окна (т.е. зоны обновления DefWindowProc()) * VirtualDubMod - след есть * Spectaculator - след есть * Консольное окно - следа нет, даже при задевании рамок окна * MediaPlayerClassic - след есть Кто в курсе? Что это за бадяга? Возможно это зависит от каких либо свойств окна, но каких?
При регистрации класса используй ноль в кисти для фона, или как правильно советует Quantum корректно обрабатывай WM_ERASEBKGND ЗЫ: BeginPain заливает окно кистью из свойств класса и от этого не только следы, но и мерцания наблюдаются
CS_SAVEBITS не используется >> Реакция на него отключена давно. > А зря Почему зря? Кисть при регистрации пробовал абсолютно любую - все равно есть след, либо цветом кисти, либо, если NULL, то белым цветом
Ivan_d Именно поэтому заметен след от таскания. Либо задавайте классу чёрную кисть и уберите обработчик WM_ERASEBKGND, либо в обработчике WM_ERASEBKGND сами заливайте фон чёрным цветом и возвращайте TRUE (кисть класса в данном случае значения не имеет).
Обьясняю подробно суть проблемы: Если отключить всякие реакции WndProc() на сообщения, а так же ничего не передавать функции DefWndowProc(), а на все отвечать return 1, то мы получим следующее: Нетаскаемое (естественно, раз отключена обработка) и не обновляемое окно, но(!), если по поверхности этого окна таскать чужое окошко (например маленькое окно от FlashGet, которое всегда тусуется в углу экрана), то на системной части моего окна это таскаемое окошко будет оставлять свои следы, а на пользовательской части моего окна эти следы будут закрашиваться системой в цвет, определенный в классе моего окна. Если же цвет в классе определен, как NULL, то закрашиваться будет белым цветом. Вопрос - как сделать так, чтобы система НИ ВО ЧТО не закрашивала следы чужих окошек на клиетской части моего окна?
Ivan_d На WM_PAINT нужно отвечать return 0. Это касается и других сообщений, которые нельзя просто игнорировать (поэтому и существует DefWindowProc). Обрабатывать WM_PAINT, где просто вызывать ValidateRect или DefWindowProc и возвращать 0. Также обрабатывать WM_ERASEBKGND - просто возвращать TRUE. Кстати, зачем Вам на клиентской области окна понадобились следы от других окон? Изначально, вроде бы, появления следов необходимо было избежать...
Да, на WM_PAINT я отвечаю нулем. на WM_ERASEBKGND отвечаю 1. Зачем? Обьясняю - пока нет четкого следа на клиентской области окна, это значит, что система его затирает, тратя на это время.
Чтобы не быть голословным, приведу графический пример: Скриншот В данном примере: Рефреш системной части окна отключен (на WM_NCPAINT отвечаю 0) Рефреш клиетской части окна я тоже не делаю На WM_ERASEBKGND отвечаю 1 Как видно из скриншота, на системной части окна остаются следы маленького окошка от FlashGet'a, а на клиетской они же закрашиваются системой в белый цвет. А мне нужно, чтобы система их НЕ ЗАКРАШИВАЛА,а ничего не делала!
Похоже, что в процессе перетаскивания приходит сообщение WM_PRINT - это только гипотеза. Попробуйте отключить и его. И покажите наконец исходник
Попробую завтра может выцепить из исходинка (он огромен) те кусочки, что за это отвечают и запостить сюда. Что же касается всех сообщений, то я их в виде текстовых строк вывожу для отладочных целей в отдельное консольное окошечко. Вот что приходит при перетаскивании: WM_NCPAINT - сейчас ничего не делааю, отвечаю 0 WM_ERASEBKGND - ничего не делаю, отвечаю 1 WM_SYNCPAINT - сейчас ничего не делаю, отвечаю 0 WM_PAINT - сейчас ничего не делаю, отвечаю 0 и такие пакеты, пока таскаю мелкое окошко поверх своего а в спокойном режиме, или когда таскаю не задевая мое окно идет только WM_PAINT, который я посылаю сам, для обновления окна каждый фрейм.
Проблема решилась! Добрый человек подсказал, что нужно кисть указывать не NULL (как указано в доке), a (HBRUSH)GetStockObject(NULL_BRUSH) Всем пасиба!
Ivan_d WM_PAINT - сейчас ничего не делаю, отвечаю 0 Неверно. Если никакого своего кода нет - надо вызывать DefWindowProc(). Если свой код есть - надо его заключать в BeginPaint()/EndPaint(). Также не надо посылать самому WM_PAINT. Если надо немедленно отрисоваться: Код (Text): InvalidateRect (hWnd, NULL, FALSE); UpdateWindow (hWnd); // This will call your WM_PAINT handler
Ivan_d Использование прозрачной кисти просто не оставляет видимых следов рисования, но вовсе не значит, что система не тратит время на заполнение дыр прозрачной кистью.