Blog. Just Blog

Создание диалоговых окон с тенью

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Сегодня разберем очередное украшательство для ваших программ, а именно тень от диалоговых окон. Обычная тень создается штатными средствами системы, но поддерживается только начиная с Windows XP. Для этого требуется, чтобы стиль окна включал в себя флаг CS_DROPSHADOW, и здесь есть одна тонкость: этот флаг нельзя прописать в ресурсах, а надо устанавливать при инициализации диалогового окна. В обработчике инициализации должен быть такой код:
  1.         ...
  2.         ; Определить константу CS_DROPSHADOW
  3.         CS_DROPSHADOW = 00020000h
  4.         ; Получить текущее значение стиля окна
  5.         invoke  GetWindowLong,[hwnddlg],GCL_STYLE
  6.         ; Добавить к нему атрибут тень
  7.         or      eax,CS_DROPSHADOW
  8.         ; Установить новый стиль окна
  9.         invoke  SetClassLong,[hwnddlg],GCL_STYLE,eax   
  10.         ...
Тут есть плюсы: корректно поддерживаются окна любой нестандартной и сложной формы, а все следующие окна процесса автоматически создаются сразу с тенью. Но есть один странный момент. Несмотря на то, что дочерние окна сперва создаются с корректной тенью, при любом перемещении их над родительским окном тени родительского и дочернего окна сливаются в одну. Пример такого нездорового явления природы показан на скриншоте.

При наложении окон тень теряется
При наложении окон тень теряется

Похоже это связано с тем, что родительское окно и все его дочерние окна считаются как один объект. А тень по сути является одним самостоятельным окном, которое и связывается с этим объектом. Для обхода такого недоразумения придется создавать псевдо-дочерние окна, которые находятся на одном уровне иерархии с главным окном. А чтобы они вели себя как дочерние, главное окно надо будет блокировать до их закрытия. Вот фрагмент кода открытия псевдо-дочернего окна сообщения или диалогового окна:
  1.         ...
  2.         ; Заблокировать главное окно
  3.         invoke  EnableWindow,[hwnddlg],FALSE
  4.  
  5.         ; Открыть псевдо-дочернее окно с тенью, его родитель по уровню
  6.         ; иерархии равен родителю главного окна. В результате этого при
  7.         ; его перемещении над главным окном тень теряться не будет
  8.         invoke  MessageBox,NULL,szMess,szTitle,MB_OK
  9.         ; или...
  10.         invoke  DialogBoxParam,[hInstance],ID_DLG,NULL,DialogProc,0
  11.         ; Подразумевается, что родительское окно создано с hWndParent = NULL
  12.  
  13.         ; Разблокировать главное окно и вернуть на него фокус
  14.         invoke  EnableWindow,[hwnddlg],TRUE
  15.         invoke  SetFocus,[hwnddlg]  
  16.         ...
При такой реализации открытия окон поведение тени становится полностью корректным, при любом перемещении окон тень не теряется и не сливается. Это хорошо видно на следующем скриншоте.

При наложении окон тень сохраняется
При наложении окон тень сохраняется

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

Примеры программ с исходными текстами (FASM)Примеры программ с исходными текстами (FASM)

Window.with.Shadow.Demo.zip (4,499 bytes)


Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 4910 | Комментариев: 1

Метки: Assembler, окна
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
UA-rxt (29.12.2012 в 15:13):
Шикарная и проста в использовании вещь.
Достаточно времени провел пока нашел решение: устранить эту "недорисовку" тени поверх родительского окна. Как же не в тему "не дорисовывается-то", а.
Спасибо за пост, именно он указал решение и направление.

Возможно пригодится одно из решений:
Установить поверх всех остальных, как говорится, сделать поплавком)).
invoke SetWindowPos, [ChildWnd], HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or
          SWP_NOSIZE or SWP_NOACTIVATE
или
FormStyle = fsStayOnTop (Delphi)

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2017
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.06 сек. / MySQL: 2 (0.0028 сек.) / Память: 4.5 Mb
Наверх