Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> SetWindowRgn()/resize 
V
    Опции темы
Paspartu
Дата 13.7.2008, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



Сделал окно с закругленными углами... Обнавляю регион окна в WM_SIZE, но при изменении размеров (уменьшение за левый бордюр) закругленные углы с правой стороны начинают мерцать точно также как и у стандартных окон XP, но есть приложения где этого не происходит как бороться с этими косяками? Пытаюсь сделать c SelectClipRgn() но без результатно т.к. окно (бордюр) отрисовывается до... (WM_NCPAINT)... Как бороться с этой XXX smile  smile ?
PM MAIL   Вверх
GremlinProg
Дата 13.7.2008, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



мерцание углов происходит потому, что при рисовании используются инструменты для работы  с прямоугольными областями, а не с регионами, это отноcится к InvalidateRect, ValidateRect, так же следует обратить внимание на отсечение дочерних окон из области прорисовки на родителе, т.к. отсекаются так же прямоугольные области. 

для решения проблемы нужно переписывать движок обновлений окна, где использовать InvalidateRgn, ValidateRgn, которым передавать скругленные регионы окон, взамен Begin-EndPrint ну и естественно двойной буфер как на WM_PAINT, так и на WM_NCPAINT.

бордюр отрисовывается до WM_NCPAINT не может, т.к. этот самый бордюр на это сообщение DefWindowProc как раз и рисует.
нарисован он может только в такой схеме:

Код

switch(message){
  case WM_NCPAINT:
    //тут неклиентская область, с бордюром еще не нарисована
    DefWindowProc(...)
    //а тут уже нарисована
    break;
}


общую схему корректного рисования с двойным буфером через WM_PRINT пару лет назад я уже выкладывал, смотри статистику


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Paspartu
Дата 15.7.2008, 01:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



To GremlinProq, спасибо за отклик, очень мало знатоков по этому вопросу…

Просмотрел Ваши, посты… подчеркнул много интересного (WM_PRINT), но в тех приложениях, которые я видел, WM_PRINT не используется… немного опишу, что я делаю…

Хочу сделать свое окно, т.е. окно собственного дизайна, мучался с окнами стиля WS_OWERLAPPED с перерисовкой заголовка и кнопок, но в конечном итоге решил их отрисовывать самостоятельно, т.е. у меня все окно – клиентская часть… но все же решил использовать WM_NCPAINT в нем у меня выводиться только рамка (бордюры и заголовок), а вся скажем так псевдо клиентская область отсекается, и в момент перерисовки у меня бордюр не Invalidate-тится, а сразу переноситься из совместимого контекста на контекст окна… т.к. если  делать Invalidate то получается следующее: к примеру клиентская часть белая а бордюр черный, это в принципе не важно… так вот когда мы уменьшаем окно за левый бордюр – светлая, псевдо клиентская часть залазит на темный правый бордюр, если мы делаем InvalidateRgn  – то все равно возникает мерцание, т.е. на темном бордюре мы видим белые блики при прямом переносе этого незаметно, конечно, возможно, я в корне не прав, и надо делать подобные вещи со стандартной клиентской и неклиентской зоной? Возможно проблема глубже, т.к. я думаю, что если проблема была бы пустяковой то товарищи из Microsoft это бы реализовали… и стандартные окна XP  не имели бы таковых косяков (мерцание скругленных уголков)… их конечно мало заметно, и возможно большинство людей их попросту не замечают… но я хочу в этом досконально разобраться… т.е. почему это происходит и как с этим бороться т.к. есть приложения с окнами у которых закруглены углы, но при изменении размеров все - OK.

PM MAIL   Вверх
GremlinProg
Дата 15.7.2008, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Paspartu @  15.7.2008,  03:30 Найти цитируемый пост)
так вот когда мы уменьшаем окно за левый бордюр – светлая, псевдо клиентская часть залазит на темный правый бордюр, если мы делаем InvalidateRgn  – то все равно возникает мерцание


распространенная прблема копирования клиентской области.

user posted image

причина в том, что клиентская область при изменении размеров, по-умолчанию, просто сдвигается относительно левого-верхнего угла клиента, к тому же, область не отсекается по габаритам, после копирования рисуется бордер на новом месте, но, клиентская область, к примеру белая, рисуется сразу на девайсе окна, поэтому при смене белого на черное происходит моргание (при уменьшении размеров окна происходит то же самое, но теперь уже часть клиента копируется на место нового бордера и моргание происходит на неклиентской области), с этой проблемой я тоже долго разбирался и нашел довольно простой способ:
Код

case WM_NCCALCSIZE:{
    ::DefWindowProc(...)
    if(!wParam)break;
    NCCALCSIZE_PARAMS&params    = *(NCCALCSIZE_PARAMS*)lParam;
    RECT&src                    = params.rgrc[1];
    RECT&dst                    = params.rgrc[2];
    ::SetRectEmpty(&src);
    ::SetRectEmpty(&dst);
    return WVR_VALIDRECTS;
}

в общем случае достаточно обнулить любой прямоугольник (src или dst), т.к. при их наложении друг на друга получится пустой прямоугольник.

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

подробнее тут: http://msdn.microsoft.com/en-us/library/ms632634(VS.85).aspx

удобство в том, что ничего лишнего выводиться и моргать не будет, неудобство - при любом изменении размеров необходимо перерисовывать клиентскую область, т.е. для эффективной работы нужно максимально разгрузить метод прорисовки окна, либо вместо обнуления прямоугольников, расчитывать точные координаты бордюров и отсекать их из dst или src.

при использовании дочерних окон, такую обработку необходимо проводить у всех участников в Z-порядке, т.к. эффект копирования накладывается с родителя на дочерние окна.

Это сообщение отредактировал(а) GremlinProg - 15.7.2008, 12:51


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 15.7.2008, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



со стилем XP эта проблема решается только частично, к примеру, если немного надвинуть два "братских" окна друг на друга и попытаться сменить размер одного из них с левой или верхней стороны, на клиентской области будет моргать (как бы просвечивать) бордюр второго братского окна, хотя сам он моргать уже не будет, здесь даже WM_PRINT не помогает, что странно, это какая то "вумная" реализация стилей, по видимому, независящая от места их приложения, т.е. вполне возможно, что какая-то часть прорирсовки бордюра XP лежит не в окне, а, например в каком-то IDLE процессе.

Это сообщение отредактировал(а) GremlinProg - 15.7.2008, 11:24


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Paspartu
Дата 15.7.2008, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



Спасибо за информацию, смысл понял, буду пробовать...
PM MAIL   Вверх
Paspartu
Дата 15.7.2008, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



Огромное спасибо! Все получилось! И к вам, будет еще один вопрос, как к специалисту, просмотрел ваши посты, у Вас есть много интересного по контролам, вопрос следующего плана по кнопкам (MAX/MIN/CLOSE) окна…

Учитывая, что  в стандартном окне при resize (к примеру тащим окно за левый бордер (увеличиваем окно)) правый бордер мерцает, а кнопки стоят как вкопанные… в стандартном окне как это реализовано, в том плане куда выводится графика? Явно что не вместе с бордером, т.к. в таком бы случае они мерцали бы вместе с ним… Я делал так:  
 использовал POPUP окно с WS_EX_LAYERED и ставил его в нужную мне позицию, и получается неплохо, в том плане что при прорисовке заголовка не происходит мерцании этих кнопок правда SPY++ видит весь этот конструктор, это раз, а второе, что вроде в VIST – е WS_EX_LAYERED уже не работает… как быть?

PM MAIL   Вверх
GremlinProg
Дата 19.7.2008, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



стандартно, кнопки, как и бордеры рисуются одновременно, но тут нужно понять, с чем в принципе связано "моргание" окна.

Если сколь угодно часто выводить одну и ту же графику в одно и то же место, ничего моргать не будет, не надо заморачиваться на этот план, на этот факт опираются все direct-приложения, в которых важна скорость обновления динамики.

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

Моргание - это движение того самого одного человека, пробивающегося сквозь статическую толпу.

Обычно происходит в двух случаях:

1. закрашивание заднего плана клиента одним цветом (WM_ERASEBKGND), после чего рисование на нем любых деталей другим цветом
2. копирование клиента при изменении размеров(WM_NCCALCSIZE)

кнопки - это неклиентская область, поэтому при закраске заднего плана (WM_ERASEBKGND), они не перекрашиваются, т.е. смены цветов не происходит, это будет происходить только при изменении размеров родительского окна, например в MDI-приложениях и то, только если в MDI не отсекать дочерние окна полностью (обычно отсекается только клиентская часть дочерних окон), поэтому в обычных popup или overlaped окнах при закраске заднего плана эти кнопки не моргают.

кнопки располагаются либо в правом, либо в левом верхних углах окна, но всегда ЗА клиентской областью, причем за её верхней границей. Т.к. выравнивание клиента по-умолчанию происходит по левому-верхнему углу, ни каких "наездов" клиента на левый или верхний бордюр не бывает, поэтому "копирование клиента" не влияет на "моргание" кнопок (на рисунке только один из четырех случаев "наезда", если построить все случаи, можно в этом визуально убедиться)

PS: на рисунке не очень четко видно красный, красный пункитрный прямоугольник стал темно-коричневым, при увеличении нужно внимательно смотреть на его левую границу, это как раз граница "наезда", который составляет 4 пиксела, т.е. это как раз размер бордера окна и не более.

на счет прозрачных окон - не совсем понял, опиши пожалуйста подробнее


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Paspartu
Дата 30.7.2008, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



Спасибо за информацию…  вообще очень мало информации про прорисовке стандартных окон… можно даже сказать что ее нет…  кроме PAINT  и NCPAINT  smile  дело в том что изначально я делал свои окна на основе стандартных, перекрашивая неклиентскую зону, но возникло много нюансов с прорисовкой… поэтому решил отказаться от этой затеи и начал делать окна на основе стандартных убирая заголовок, правда иногда все таки синяя часть (стандартная тема XP) заголовка окна все равно проскакивает, при MIN/MAX окна, но это я так понимаю проблема не только у меня, т.к. в довольно таки дорогих программных продуктах, та же беда при изменении размеров все OK, но при MIN/MAX/RESTORE окна проскакивает стандартная голубая полоска XP… которая меня раздражала, пришлось скажем так убрать эту мультипликацию и делать все моментально т.е. окно при MAX… сразу становиться MAX… т.е. нет плавного перехода… так же и при сворачивании…  Хотя у меня нормальное окно не получилось т.к. стандартные окна зависят от системной метрики (заголовок бордюры и т.д.)… пришлось все делать индивидуально, поэтому у меня как таковой неклиенткой зоны нет… система воспринимает весь размер моего HANDMADE окна как клиенский…  поэтому NCPAINT я вообще не обрабатываю, вернее его можно обрабатывать… только смысл? поэтому пришлось сделать псевдо клиентскую часть – подвешивать дочернее окно, т.е. получается следующие… я так предполагаю  smile т.к. у моего окна стиль WS_CLIPCHILDREN то соответсвенно при WM_PAINT будет происходить прорисовка той части которая не закрыта дочерним окном псевдоклиентской зоны, вот там и отображаются мой заголовок, кнопки, бордюры и т.д.
а по поводу WS_EX_LAYERED окна… я изначально делал  глупо… я делал окно POPUP, и системные кнопки рисовал внем, а потом подвешивал его к правому верхнему углу основного окна… вот и получался такой конструктор… сейчас вывожу все вместе…  правда остались вопросы... я сделал меню… не овнер драв а свое собственное… и для красивости добавил тень… все то же  окно со стилем WS_EX_LAYERED, с DIB секцией… можно задовать оттенок и т.д. которое подвешивается к основному окну где отображены пункты меню и прочая графика, также поступил и с HANDMADE Tooltip  smile , но я так понимаю, что в VIST-е это уже работать не будет т.к. там не поддерживаются окна со стилем WS_EX_LAYERED, возможно я не прав… у меня нет возможности это проверить… вот…

PM MAIL   Вверх
GremlinProg
Дата 31.7.2008, 20:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



информации по рисованию и правда не много, но не потому что её нет, а потому что её много быть и не должно (причем 99% из неё всегда можно найти в MSDN), потому что Microsoft не покорила бы мир слишком сложным GUI. 

Цитата

в довольно таки дорогих программных продуктах, та же беда при изменении размеров все OK, но при MIN/MAX/RESTORE окна проскакивает стандартная голубая полоска XP… которая меня раздражала

это не проблема прорисовки окон.

непосредственно, перед максимизацией, минимизацией и восстановлением окна система посылает ему сообщение WM_SYSCOMMAND (внимательно читаем секцию Remarks), в котором передает в wParam статус операции SC_MAXIMIZE, SC_MINIMIZE, SC_RESTORE, в зависимости от произошедшего события.

на сколько я помню, если в ответ на это сообщение вызывается DefWindowProc, то она вызывает DrawAnimatedRects, которое как раз и производит "плавное" сворачивание, разворачивание или восстановление окна, используя параметры позиционирования окна (WINDOWPLACEMENT, параметры можно получить, используя метод GetWindowPlacement)

по-умолчанию, этот метод вызывается с флагом IDANI_CAPTION, из-за которого заголовок окна и проявляется, даже если в стилях не установлен WS_CAPTION

это встроенное поведение окна, которое можно свегда переопределить, как обычно, просто заблокировав DefWindowProc.

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

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




--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Paspartu
Дата 1.8.2008, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



Спасибо! Буду дерзать!
PM MAIL   Вверх
vaddsm
Дата 2.8.2008, 00:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Ооого как я вовремя заглянул в этот раздел, я тут очень схожую тему открыл, прошу помочь!

http://forum.vingrad.ru/forum/topic-222898...y1598510/0.html

Это сообщение отредактировал(а) vaddsm - 2.8.2008, 00:11
PM MAIL   Вверх
vaddsm
Дата 4.8.2008, 06:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Возможно этот вопрос стиля написания, но все же я его задам

Цитата


GremlinProg:

case WM_NCCALCSIZE:{
    ::DefWindowProc(...)
    if(!wParam)break;
    NCCALCSIZE_PARAMS&params    = *(NCCALCSIZE_PARAMS*)lParam;
    RECT&src                    = params.rgrc[1];
    RECT&dst                    = params.rgrc[2];
    ::SetRectEmpty(&src);
    ::SetRectEmpty(&dst);
    return WVR_VALIDRECTS;

}



Разве не проще и понятнее писать так:

case WM_NCCALCSIZE:
{
    ::DefWindowProc(...)

    if(!wParam)break;

    NCCALCSIZE_PARAMS *params    = (NCCALCSIZE_PARAMS*) lParam;
    ::SetRectEmpty(&params->rgrc[1]);
    ::SetRectEmpty(&params->rgrc[2]);

    return WVR_VALIDRECTS;

}

???

P.S. простите за оффтоп.


Это сообщение отредактировал(а) vaddsm - 4.8.2008, 10:47
PM MAIL   Вверх
GremlinProg
Дата 4.8.2008, 11:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



vaddsm,

когда речь идет о символьной нагрузке (число символов на лексему), то твой вариант в этом случае длиннее, и требует больше времени на расшифровку кода
когда речь идет о нагрузке на компилятор, & и * в этом случае равнозначны

в целом, простота и читабельность - это дело вкуса программиста и его представлении о таких качествах

PS: стиль и качество письма в этой ветке форума не обсуждается


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
vaddsm
Дата 4.8.2008, 20:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



GremlinProg, спасибо что ответил! Ты прав, действительно, если исходить из понимания краткости лексических конструкций твой пример кода выглядит нагляднее. +1. В копилку моему опыту, спасибо! Соглашаюсь, но не во всем. Мнения, к сожалению, своего я здесь выражать полностью не буду, в силу того, что беседа за рамками темы. Отмечу лишь, что фраза NCCALCSIZE_PARAMS&params    = *(NCCALCSIZE_PARAMS*)lParam; раза в 2 проигрывает обозначенным тобою критерием вот этой  NCCALCSIZE_PARAMS *params    = (NCCALCSIZE_PARAMS*) lParam; Был бы рад поговорить и дальше на эту тему, но где найти подходящий раздел??  smile 

Это сообщение отредактировал(а) vaddsm - 4.8.2008, 20:15
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1038 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.