![]() |
Модераторы: feodorv, GremlinProg, xvr, Fixin |
![]() ![]() ![]() |
|
Paspartu |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 67 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
Сделал окно с закругленными углами... Обнавляю регион окна в WM_SIZE, но при изменении размеров (уменьшение за левый бордюр) закругленные углы с правой стороны начинают мерцать точно также как и у стандартных окон XP, но есть приложения где этого не происходит как бороться с этими косяками? Пытаюсь сделать c SelectClipRgn() но без результатно т.к. окно (бордюр) отрисовывается до... (WM_NCPAINT)... Как бороться с этой XXX
![]() ![]() |
|||
|
||||
GremlinProg |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
мерцание углов происходит потому, что при рисовании используются инструменты для работы с прямоугольными областями, а не с регионами, это отноcится к InvalidateRect, ValidateRect, так же следует обратить внимание на отсечение дочерних окон из области прорисовки на родителе, т.к. отсекаются так же прямоугольные области.
для решения проблемы нужно переписывать движок обновлений окна, где использовать InvalidateRgn, ValidateRgn, которым передавать скругленные регионы окон, взамен Begin-EndPrint ну и естественно двойной буфер как на WM_PAINT, так и на WM_NCPAINT. бордюр отрисовывается до WM_NCPAINT не может, т.к. этот самый бордюр на это сообщение DefWindowProc как раз и рисует. нарисован он может только в такой схеме:
общую схему корректного рисования с двойным буфером через WM_PRINT пару лет назад я уже выкладывал, смотри статистику -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
Paspartu |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 67 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
To GremlinProq, спасибо за отклик, очень мало знатоков по этому вопросу…
Просмотрел Ваши, посты… подчеркнул много интересного (WM_PRINT), но в тех приложениях, которые я видел, WM_PRINT не используется… немного опишу, что я делаю… Хочу сделать свое окно, т.е. окно собственного дизайна, мучался с окнами стиля WS_OWERLAPPED с перерисовкой заголовка и кнопок, но в конечном итоге решил их отрисовывать самостоятельно, т.е. у меня все окно – клиентская часть… но все же решил использовать WM_NCPAINT в нем у меня выводиться только рамка (бордюры и заголовок), а вся скажем так псевдо клиентская область отсекается, и в момент перерисовки у меня бордюр не Invalidate-тится, а сразу переноситься из совместимого контекста на контекст окна… т.к. если делать Invalidate то получается следующее: к примеру клиентская часть белая а бордюр черный, это в принципе не важно… так вот когда мы уменьшаем окно за левый бордюр – светлая, псевдо клиентская часть залазит на темный правый бордюр, если мы делаем InvalidateRgn – то все равно возникает мерцание, т.е. на темном бордюре мы видим белые блики при прямом переносе этого незаметно, конечно, возможно, я в корне не прав, и надо делать подобные вещи со стандартной клиентской и неклиентской зоной? Возможно проблема глубже, т.к. я думаю, что если проблема была бы пустяковой то товарищи из Microsoft это бы реализовали… и стандартные окна XP не имели бы таковых косяков (мерцание скругленных уголков)… их конечно мало заметно, и возможно большинство людей их попросту не замечают… но я хочу в этом досконально разобраться… т.е. почему это происходит и как с этим бороться т.к. есть приложения с окнами у которых закруглены углы, но при изменении размеров все - OK. |
|||
|
||||
GremlinProg |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
распространенная прблема копирования клиентской области. ![]() причина в том, что клиентская область при изменении размеров, по-умолчанию, просто сдвигается относительно левого-верхнего угла клиента, к тому же, область не отсекается по габаритам, после копирования рисуется бордер на новом месте, но, клиентская область, к примеру белая, рисуется сразу на девайсе окна, поэтому при смене белого на черное происходит моргание (при уменьшении размеров окна происходит то же самое, но теперь уже часть клиента копируется на место нового бордера и моргание происходит на неклиентской области), с этой проблемой я тоже долго разбирался и нашел довольно простой способ:
в общем случае достаточно обнулить любой прямоугольник (src или dst), т.к. при их наложении друг на друга получится пустой прямоугольник. что это дает? при возврате такого ответа на WM_NCCALCSIZE система копирует на девайс область, полученную при пересечении двух прямоугольников, поэтому, если какой-нибудь из них занулять, система не будет копировать на девайс ничего. подробнее тут: http://msdn.microsoft.com/en-us/library/ms632634(VS.85).aspx удобство в том, что ничего лишнего выводиться и моргать не будет, неудобство - при любом изменении размеров необходимо перерисовывать клиентскую область, т.е. для эффективной работы нужно максимально разгрузить метод прорисовки окна, либо вместо обнуления прямоугольников, расчитывать точные координаты бордюров и отсекать их из dst или src. при использовании дочерних окон, такую обработку необходимо проводить у всех участников в Z-порядке, т.к. эффект копирования накладывается с родителя на дочерние окна. Это сообщение отредактировал(а) GremlinProg - 15.7.2008, 12:51 -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
GremlinProg |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
со стилем XP эта проблема решается только частично, к примеру, если немного надвинуть два "братских" окна друг на друга и попытаться сменить размер одного из них с левой или верхней стороны, на клиентской области будет моргать (как бы просвечивать) бордюр второго братского окна, хотя сам он моргать уже не будет, здесь даже WM_PRINT не помогает, что странно, это какая то "вумная" реализация стилей, по видимому, независящая от места их приложения, т.е. вполне возможно, что какая-то часть прорирсовки бордюра XP лежит не в окне, а, например в каком-то IDLE процессе.
Это сообщение отредактировал(а) GremlinProg - 15.7.2008, 11:24 -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
Paspartu |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 67 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
Спасибо за информацию, смысл понял, буду пробовать...
|
|||
|
||||
Paspartu |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 67 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
Огромное спасибо! Все получилось! И к вам, будет еще один вопрос, как к специалисту, просмотрел ваши посты, у Вас есть много интересного по контролам, вопрос следующего плана по кнопкам (MAX/MIN/CLOSE) окна…
Учитывая, что в стандартном окне при resize (к примеру тащим окно за левый бордер (увеличиваем окно)) правый бордер мерцает, а кнопки стоят как вкопанные… в стандартном окне как это реализовано, в том плане куда выводится графика? Явно что не вместе с бордером, т.к. в таком бы случае они мерцали бы вместе с ним… Я делал так: использовал POPUP окно с WS_EX_LAYERED и ставил его в нужную мне позицию, и получается неплохо, в том плане что при прорисовке заголовка не происходит мерцании этих кнопок правда SPY++ видит весь этот конструктор, это раз, а второе, что вроде в VIST – е WS_EX_LAYERED уже не работает… как быть? |
|||
|
||||
GremlinProg |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
стандартно, кнопки, как и бордеры рисуются одновременно, но тут нужно понять, с чем в принципе связано "моргание" окна.
Если сколь угодно часто выводить одну и ту же графику в одно и то же место, ничего моргать не будет, не надо заморачиваться на этот план, на этот факт опираются все direct-приложения, в которых важна скорость обновления динамики. Моргание - это смена графики (смена цветов, смена картинки), на фоне статического изображения: если смотреть на толпую бегущих с одной скоростью людей, мы ни кого в ней не выделим отдельно, но если толпа людей стоит на месте и только один человек будет бежать в этой толпе, мы его выделим сразу. В обоих случаях было движение и только во втором это движение было заметным. Моргание - это движение того самого одного человека, пробивающегося сквозь статическую толпу. Обычно происходит в двух случаях: 1. закрашивание заднего плана клиента одним цветом (WM_ERASEBKGND), после чего рисование на нем любых деталей другим цветом 2. копирование клиента при изменении размеров(WM_NCCALCSIZE) кнопки - это неклиентская область, поэтому при закраске заднего плана (WM_ERASEBKGND), они не перекрашиваются, т.е. смены цветов не происходит, это будет происходить только при изменении размеров родительского окна, например в MDI-приложениях и то, только если в MDI не отсекать дочерние окна полностью (обычно отсекается только клиентская часть дочерних окон), поэтому в обычных popup или overlaped окнах при закраске заднего плана эти кнопки не моргают. кнопки располагаются либо в правом, либо в левом верхних углах окна, но всегда ЗА клиентской областью, причем за её верхней границей. Т.к. выравнивание клиента по-умолчанию происходит по левому-верхнему углу, ни каких "наездов" клиента на левый или верхний бордюр не бывает, поэтому "копирование клиента" не влияет на "моргание" кнопок (на рисунке только один из четырех случаев "наезда", если построить все случаи, можно в этом визуально убедиться) PS: на рисунке не очень четко видно красный, красный пункитрный прямоугольник стал темно-коричневым, при увеличении нужно внимательно смотреть на его левую границу, это как раз граница "наезда", который составляет 4 пиксела, т.е. это как раз размер бордера окна и не более. на счет прозрачных окон - не совсем понял, опиши пожалуйста подробнее -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
Paspartu |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 67 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
Спасибо за информацию… вообще очень мало информации про прорисовке стандартных окон… можно даже сказать что ее нет… кроме PAINT и NCPAINT
![]() ![]() а по поводу WS_EX_LAYERED окна… я изначально делал глупо… я делал окно POPUP, и системные кнопки рисовал внем, а потом подвешивал его к правому верхнему углу основного окна… вот и получался такой конструктор… сейчас вывожу все вместе… правда остались вопросы... я сделал меню… не овнер драв а свое собственное… и для красивости добавил тень… все то же окно со стилем WS_EX_LAYERED, с DIB секцией… можно задовать оттенок и т.д. которое подвешивается к основному окну где отображены пункты меню и прочая графика, также поступил и с HANDMADE Tooltip ![]() |
|||
|
||||
GremlinProg |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
информации по рисованию и правда не много, но не потому что её нет, а потому что её много быть и не должно (причем 99% из неё всегда можно найти в MSDN), потому что Microsoft не покорила бы мир слишком сложным GUI.
это не проблема прорисовки окон. непосредственно, перед максимизацией, минимизацией и восстановлением окна система посылает ему сообщение WM_SYSCOMMAND (внимательно читаем секцию Remarks), в котором передает в wParam статус операции SC_MAXIMIZE, SC_MINIMIZE, SC_RESTORE, в зависимости от произошедшего события. на сколько я помню, если в ответ на это сообщение вызывается DefWindowProc, то она вызывает DrawAnimatedRects, которое как раз и производит "плавное" сворачивание, разворачивание или восстановление окна, используя параметры позиционирования окна (WINDOWPLACEMENT, параметры можно получить, используя метод GetWindowPlacement) по-умолчанию, этот метод вызывается с флагом IDANI_CAPTION, из-за которого заголовок окна и проявляется, даже если в стилях не установлен WS_CAPTION это встроенное поведение окна, которое можно свегда переопределить, как обычно, просто заблокировав DefWindowProc. если хочется оставить эффект, но убрать заголовок, можно вручную повторить вызов DrawAnimatedRects, передав ей желаемые параметры. PS: абсолютно любое окно можно реализовать, не используя дополнительных заплаток(окон) и платформо-зависимых ресурсов, для этого нужно просто внимательно читать документацию MSDN и ), конечно работать. -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
Paspartu |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 67 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
Спасибо! Буду дерзать!
|
|||
|
||||
vaddsm |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 128 Регистрация: 30.6.2007 Репутация: нет Всего: нет |
Ооого как я вовремя заглянул в этот раздел, я тут очень схожую тему открыл, прошу помочь!
http://forum.vingrad.ru/forum/topic-222898...y1598510/0.html Это сообщение отредактировал(а) vaddsm - 2.8.2008, 00:11 |
|||
|
||||
vaddsm |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 128 Регистрация: 30.6.2007 Репутация: нет Всего: нет |
Возможно этот вопрос стиля написания, но все же я его задам
Разве не проще и понятнее писать так: case WM_NCCALCSIZE: { ::DefWindowProc(...) if(!wParam)break; NCCALCSIZE_PARAMS *params = (NCCALCSIZE_PARAMS*) lParam; ::SetRectEmpty(¶ms->rgrc[1]); ::SetRectEmpty(¶ms->rgrc[2]); return WVR_VALIDRECTS; } ??? P.S. простите за оффтоп. Это сообщение отредактировал(а) vaddsm - 4.8.2008, 10:47 |
|||
|
||||
GremlinProg |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
vaddsm,
когда речь идет о символьной нагрузке (число символов на лексему), то твой вариант в этом случае длиннее, и требует больше времени на расшифровку кода когда речь идет о нагрузке на компилятор, & и * в этом случае равнозначны в целом, простота и читабельность - это дело вкуса программиста и его представлении о таких качествах PS: стиль и качество письма в этой ветке форума не обсуждается -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
vaddsm |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 128 Регистрация: 30.6.2007 Репутация: нет Всего: нет |
GremlinProg, спасибо что ответил! Ты прав, действительно, если исходить из понимания краткости лексических конструкций твой пример кода выглядит нагляднее. +1. В копилку моему опыту, спасибо! Соглашаюсь, но не во всем. Мнения, к сожалению, своего я здесь выражать полностью не буду, в силу того, что беседа за рамками темы. Отмечу лишь, что фраза NCCALCSIZE_PARAMS¶ms = *(NCCALCSIZE_PARAMS*)lParam; раза в 2 проигрывает обозначенным тобою критерием вот этой NCCALCSIZE_PARAMS *params = (NCCALCSIZE_PARAMS*) lParam; Был бы рад поговорить и дальше на эту тему, но где найти подходящий раздел??
![]() Это сообщение отредактировал(а) vaddsm - 4.8.2008, 20:15 |
|||
|
||||
![]() ![]() ![]() |
Правила форума "C/C++: Системное программирование и WinAPI" | |
|
На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы . Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |