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

Сегодня разберем очередное украшательство для ваших программ, а именно тень от диалоговых окон. Обычная тень создается штатными средствами системы, но поддерживается только начиная с 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]  
        ...

При такой реализации открытия окон поведение тени становится полностью корректным, при любом перемещении окон тень не теряется и не сливается.

В приложении два примера создания окон с тенью. В первом случае создается реальное дочернее окно, а во втором примере - псевдо-дочернее окно с блокировкой главного окна.
Теги:
окно
Добавлено: 10 Апреля 2018 20:45:37 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...