Сегодня разберем очередное украшательство для ваших программ, а именно тень от диалоговых окон. Обычная тень создается штатными средствами системы, но поддерживается только начиная с Windows XP. Для этого требуется, чтобы стиль окна включал в себя флаг CS_DROPSHADOW, и здесь есть одна тонкость: этот флаг нельзя прописать в ресурсах, а надо устанавливать при инициализации диалогового окна. В обработчике инициализации должен быть такой код:
...
; Определить константу CS_DROPSHADOW
CS_DROPSHADOW = 00020000h
; Получить текущее значение стиля окна
invoke GetWindowLong,[hwnddlg],GCL_STYLE
; Добавить к нему атрибут тень
or eax,CS_DROPSHADOW
; Установить новый стиль окна
invoke SetClassLong,[hwnddlg],GCL_STYLE,eax
...
Тут есть плюсы: корректно поддерживаются окна любой нестандартной и сложной формы, а все следующие окна процесса автоматически создаются сразу с тенью. Но есть один странный момент. Несмотря на то, что дочерние окна сперва создаются с корректной тенью, при любом перемещении их над родительским окном тени родительского и дочернего окна сливаются в одну.
Похоже это связано с тем, что родительское окно и все его дочерние окна считаются как один объект. А тень по сути является одним самостоятельным окном, которое и связывается с этим объектом. Для обхода такого недоразумения придется создавать псевдо-дочерние окна, которые находятся на одном уровне иерархии с главным окном. А чтобы они вели себя как дочерние, главное окно надо будет блокировать до их закрытия. Вот фрагмент кода открытия псевдо-дочернего окна сообщения или диалогового окна:
...
; Заблокировать главное окно
invoke EnableWindow,[hwnddlg],FALSE
; Открыть псевдо-дочернее окно с тенью, его родитель по уровню
; иерархии равен родителю главного окна. В результате этого при
; его перемещении над главным окном тень теряться не будет
invoke MessageBox,NULL,szMess,szTitle,MB_OK
; или...
invoke DialogBoxParam,[hInstance],ID_DLG,NULL,DialogProc,0
; Подразумевается, что родительское окно создано с hWndParent = NULL
; Разблокировать главное окно и вернуть на него фокус
invoke EnableWindow,[hwnddlg],TRUE
invoke SetFocus,[hwnddlg]
...
При такой реализации открытия окон поведение тени становится полностью корректным, при любом перемещении окон тень не теряется и не сливается.
В приложении два примера создания окон с тенью. В первом случае создается реальное дочернее окно, а во втором примере - псевдо-дочернее окно с блокировкой главного окна.