Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Системное программирование и WinAPI > Как работает WM_SETTEXT ? |
Автор: mekhanikus 10.5.2009, 15:49 |
Может кому-то вопрос покажется странным, но всетаки. Началось все с того, что я решил сделать subclassing стандартного STATIC'а, написать для него собственный WM_PAINT. Задача была, в общем то, успешно решена. Однако, в процессе тестирования программы выявилась неприятная особенность: в момент раздачи STATIC'ам (их много на форме) значений через WM_SETTEXT, происходит неприятное мерцание этих самых STATIC'ов. Насколько я понял, это происходит потому, что "The DefWindowProc function sets and displays the window text" причем делает это дефолтным шрифтом и цветом, а потом все это заново перерисовывается моим WM_PAINT'ом. Подскажите, как этого можно избежать? Можно ли отучить DefWindowProc перерисовывать текст? Или как самому обработать WM_SETTEXT? |
Автор: andrew_121 10.5.2009, 18:04 |
Это из-за того что тело, вызывающее SendMessage() на ходится не в отдельном потоке. |
Автор: J0ker 10.5.2009, 19:53 |
вам нужно заблокировать WM_ERASEBKGND - это он мерцает |
Автор: mekhanikus 11.5.2009, 07:03 | ||||||
Надо будет покурить в эту сторону.
Представте себе - проблема (для меня ![]() Не смог найти куда засунуть текст, полученый в WM_SETTEXT. Пожалуйста пните в нужном направлении. Добавлено через 12 минут и 46 секунд
Пробовал, не помогает. Причина, имхо, именно в реакции DefWindowProc на WM_SETTEXT. |
Автор: J0ker 11.5.2009, 09:06 | ||
такого попросту быть не может если вы перекрываете отрисовку и блокируете WM_ERACEBKGND то больше никто ничего не рисует если мерцание происходит в момент, когда ваш код перерисовывает контрол, то значит надо рисовать в буфер а потом копировать посредством BitBlt |
Автор: Earnest 11.5.2009, 09:18 |
J0ker, не стоит быть столь категоричным, когда речь идет о старых контролах виндоус. Насчет статика утверждать не берусь, но вот комбобокс точно рисуется не только на WM_PAINT... Из вышесказанного, конечно, не следует, что аффтар все правильно сделал. Но такое вполне может быть (что отрисовка на settext идет не через стандартный WM_PAINT). С другой стороны, если сделать контрол полностью OwnerDraw, то должно помочь - тогда действительно все под контролем. |
Автор: J0ker 11.5.2009, 09:22 | ||
вы неправильно понимаете процесс если что либо меняется для контрола, что требует его перерисовки, то контролу посылается WM_PAINT - если вы его (правильно) перехватили, то больше никто ничего в клиентской области рисовать не будет (за исключением, как я говорил выше, WM_ERACEBKGND) |
Автор: Earnest 11.5.2009, 09:32 | ||
Как уже сказано, это не обязательно так, для некоторых старых контролов. Во всяком случае, комбобоксу не получается кастомизировать отрисовку без полного OwnerDraw, только перехватом WM_PAINT, а они со статиком ровестники, еще из Win 3 приползли, так что там костыль на костыле, и вполне возможна "оптимизация" отрисовки. |
Автор: J0ker 11.5.2009, 09:41 | ||||||||||
стоит все контролы - это обычные окна что значит "рисуется на"??? WM_PAINT - мессадж, дающий команду на перерисовку клиентской области - других нет - все, что рисуется в клиентской области рисуется в ответ на WM_PAINT я так подозреваю, что вы имеете ввиду owner-drawn контролы - но это уже из другой оперы
не может
под контролем родительского окна
это что называется "через <--->" ЗЫЖ я столь категоричен не от упрямства, а от опыта ![]() Добавлено @ 09:43
как уже сказано - получается не поручусь за выпадающий список, но все остальное перерисовывается на ура: http://www.codeproject.com/KB/combobox/ComboBox_appears_flat.aspx?display=Print |
Автор: J0ker 11.5.2009, 09:58 |
да, заыл сказать, что листбокс - разговор отдельный |
Автор: mekhanikus 11.5.2009, 11:08 | ||
Оказывается может. Сначала, чтоб проверить, получился ли у меня сабклассинг, я сделал пустой WM_PAINT, который возвращает 0. (знаю, что это не правильно, но, вопрос не в этом). После запуска программы сабкассированные статики остались пустыми (что и требовалось доказать). Однако, после раздачи значений через WM_SETTTEXT они появились. Добавлено через 8 минут и 32 секунды А кто, всетаки, скажет, где хранится этот самый текст окна (WindowText)? Если б я это узнал, то сам бы обработал WM_SETTEXT, без лишней отрисовки. |
Автор: GremlinProg 11.5.2009, 11:17 | ||||||
а что подозревать, когда Earnest, так и пишет: а выпадающий список не контрол? и почему не поручишься, только что ведь утверждал, что все рисуются только в ответ на WM_PAINT )
это ты зря, бывают моменты, когда отрисовка идет, к примеру при захвате мыши (EDIT, RICHEDIT), т.е. она конечно на WM_PAINT тоже идет, но вот именно при "таскании" курсора по тексту, текущее выделение рисуется "на лету", перерисовка окна тут не происходит, накладно Добавлено через 7 минут и 38 секунд
это черный ящик, и дорога к нему закрыта обрабатывай сам, просто текст храни в своем буфере, чтобы при отрисовке обращаться только к нему |
Автор: J0ker 11.5.2009, 17:23 | ||||
специфическая его часть
потому, что не рабботал с этой частью но не вижу причин, почему она должна быть исключением - так шо 99% - на WM_PAINT или WM_NCPAINT
не вижу противоречия с моим высказыванием |
Автор: GremlinProg 11.5.2009, 19:08 | ||
ну надо же, а я думал это обычный контрол, как и все а это оказывается какой-то хитрый специфический трюк винды не расстраивай меня J0ker, может ты еще будешь настаивать что и меню это не контрол, а какой-то очередной специфический трюк? я совсем тогда разочаруюсь ) тогда и не нужно так категорично настаивать рисовать может кто угодно, где угодно и когда угодно другой вопрос - какие могут быть причины, чтобы не рисовать чего-либо на WM_PAINT ну это уже совсем ни в какие ворота:
от свои слов же не будешь отказываться я просто привел буквально самый очевидный пример, когда WM_PAINT добровольно вообще не посылается в контрол, пока не будет отпущена мышь как же нет противоречий-то? ps: конечно WM_PAINT ни кто ни кому не посылает (он генерируется в момент простоя, когда область перерисовки не пуста), это просто допустимый оборот речи в этом топике для краткости |
Автор: J0ker 11.5.2009, 23:06 | ||||||||||
не все что вы видите на экране явлется окном - возможна отрисовка непосредственно на DC экрана правда? что-то с трудом верится как я казал выше - с вероятностью 99% это окно хотя вам, конечно, виднее ![]()
с какого это перепою?
тем не менее я настаиваю - рисует контрол сам на себе - исключительно собственно я не понимаю к чему вы пытаетесь подкопаться ![]()
вы неправильно ставите вопрос какие могут быть причины, что-бы РИСОВАТЬ что-либо НЕ на WM_PAINT? - вот как раз тут всплывает прцесс выделения текста понимаете, данный вопрос не комутативен зачем??? даже повторю - больше никто ничего в клиентской области рисовать не будет - только и исключительно сам контрол
посылаются другие сообщения, причем самому себе WM_PAINT посылается когда необходимость перерисовки определяется извне, либо самим контролом дабы не дублировать функциональность совершенно очевидно, что при изменении внутреннего состояния контрола никто кроме него самого не может определить необходимость перерисовки Добавлено через 14 минут и 37 секунд
у вас нет доступа к этому буферу сохраняете текст в свой буфер и вызываете InvalidateRect в WM_PAINT рисуете текст из своего буфера |
Автор: GremlinProg 12.5.2009, 01:20 | ||||
вообще-то я и не собирался прикапываться, просто предупредил твою очередную пустую упертость
уже второй раз замечаю за тобой такой явный случай "перевертыша", причем как моих слов, так и своих, не надо использовать этот грязный способ убеждения, просто потому, что неправду видно в контексте и цитатах, а отношение к себе ты уже заведомо испортил, даже если был бы хоть на толику прав выше сказана очевидно совершенно другая мысль
а кто бы с тобой спорил, если бы ты именно на этом настаивал ) а в остальном, можно было не присваивать уже чужую точку зрения, ты же изначально ее и оспаривал странный у тебя однако способ выражать солидарность, всех облил грязью, нехорошо |
Автор: mekhanikus 12.5.2009, 06:32 | ||
Понятно! Всем спасибо! Можно считать вопрос исчерпаным. p.s.Намечается два выхода: забить на мерцание, или создать свой класс окна (может оно и к лучшему? добавится функциональность). |
Автор: GremlinProg 12.5.2009, 10:24 | ||
можно использовать свойства окна для хранения своего буфера:
если от класса STATIC ничего не нужно, то лучше конечно создать свой класс |
Автор: mekhanikus 12.5.2009, 14:04 |
Во как интересно! Хороший примерчик! Распечатал, прибил на стенку - будем изучать. ![]() Респект GremlinProg! |
Автор: mekhanikus 12.5.2009, 14:20 |
А вот пример борьбы с мерцанием от MSDN: http://msdn.microsoft.com/en-us/library/ms969905.aspx Спасибо за ссылку J0ker'у |
Автор: GremlinProg 12.5.2009, 15:28 | ||
там я еще строчку пропустил:
|
Автор: mekhanikus 13.5.2009, 14:52 |
Идея мне понравилась, только как поймать WM_CREATE для STATIC'а в диалоге? Что-то подсказывает мне, что это невозможно. Или я не прав? |
Автор: GremlinProg 13.5.2009, 15:23 |
у тебя же subclassing STATIC'а, как не можешь поймать-то? WM_SETTEXT в любом случае на диалоге ловить бессмысленно, тебе же нужно поймать установку текста в STATIC'е, для этого и нужен subclassing а создание STATIC'a на диалоге можно перехватить с помощью WM_PARENTNOTIFY, но без subclassingа это так же бессмысленно хотя, если будешь делать свой контрол вместо subclassing'а static'a, то все будет намного проще, сам выбирай (я бы STATIC вообще не использовал) |
Автор: mekhanikus 14.5.2009, 03:50 | ||||
Значит так: - в диалоге ловим WM_PARENTNOTIFY; (или для этого надо сабкластить диалог?) - в нем WM_CREATE для STATIC'а; - если наш, то делаем сабклассинг; - в нашей WNDPROC для STATIC'а ловим WM_CREATE; Am I right?
Оставим на десерт. ![]() |
Автор: GremlinProg 14.5.2009, 11:31 | ||
не надо а, ну если так, то WM_PARENTNOTIFY вполне заменяет WM_INITDIALOG нет, WM_CREATE уже не придет, контрол создан, инициализацию всех контролов нужно проводить на WM_INITDIALOG, а сабклассинг следит только за WM_SETTEXT (и желательно WM_GETTEXT), WM_DESTROY и WM_PAINT, если нужно |
Автор: mekhanikus 14.5.2009, 14:07 |
ОК! Будем пробовать. |
Автор: mekhanikus 15.5.2009, 03:08 |
ВАУ! Это действительно работает! ![]() Еще немного напряч мозги, и мне будет нравиться результат. |