Всплывающее окно - удобный способ информировать о том, что ваша программа выполнила какое-то действие, не требующее немедленного вмешательства пользователя, но достаточно важное, чтобы он об этом узнал. Это может быть сообщение о завершении закачки файла, получении нового письма, завершении длительных вычислений и т.п. Красивый эффект получается, когда информационное окно плавно выезжает из-под таскбара. Простого перемещения окна тут будет недостаточно, так как придется учитывать положение таскбара и всяких других панелей, которые резервируют под себя часть рабочего стола. Поэтому надо сперва получить размер видимой области экрана с учетом различных панелей инструментов и размеры самого всплывающего окна. Затем окно перемещается по одному пикселу в нужном направлении с учетом положения панелей, а размер его видимой части увеличивается на один пиксел в противоположную сторону. Это делается при помощи функции
MoveWindow. Лучше всего сам эффект всплытия реализовать на стадии инициализации окна по сообщению WM_INITDIALOG, но в этом случае придется принудительно показывать окно функцией
ShowWindow и обновлять его содержимое функцией
UpdateWindow после каждого сдвига. Рекомендуются стили окна без заголовка и поверх всех окон, как сделано в прилагаемом примере. Атрибут прозрачности для всплывающих окон лучше не использовать, так как при анимации появляются заметные искажения.
; Сегмент данных
section '.data' data readable writeable
coord RECT ; Размеры окна
screen RECT ; Размеры экрана
; Сегмент кода
section '.code' code readable executable
...
; Обработчик сообщения WM_INITDIALOG
wminitdialog:
; Получить размер рабочей области экрана
invoke SystemParametersInfo,SPI_GETWORKAREA,NULL,screen,FALSE
; Получить размер окна
invoke GetClientRect,[hwnddlg],coord
; Вычислить отступ от правой границы экрана
mov eax,[screen.right]
sub eax,[coord.right]
dec eax
mov [screen.right],eax
; Высота окна
mov ecx,[coord.bottom]
; Цикл всплытия окна
@@:
; Сохранить значение счетчика
push ecx
; Заполняем стек для MoveWindow
push TRUE
mov eax,[coord.bottom]
sub eax,ecx
push eax
push [coord.right]
mov ecx,[screen.bottom]
sub ecx,eax
push ecx
invoke MoveWindow,[hwnddlg],[screen.right]
; Так как сейчас только инициализация, то придется принудительно
; показать окно и обновить его содержимое
invoke ShowWindow,[hwnddlg], SW_SHOW
invoke UpdateWindow,[hwnddlg]
; Небольшая пауза
invoke Sleep,2
; Восстановить счетчик
pop ecx
loop @b
...
После полного появления окна нужно решить, каким образом будет выполняться его дальнейшая обработка. Окно можно убрать по таймеру через несколько секунд, скрыть по клику мышкой на нем или подождать другого события, например, нажатия на какую-нибудь кнопку. В любом случае окно можно или просто закрыть, или убрать его с таким же эффектом, только направление движения будет противоположным. Код плавного скрытия всплывающего окна приведен ниже. Подразумевается, что все используемые структуры с размерами после его открытия остались неизменными.
...
; Высота окна
mov ecx,[coord.bottom]
; Цикл закрытия окна
@@:
; Сохранить значение счетчика
push ecx
; Заполняем стек для MoveWindow
push TRUE
push ecx
push [coord.right]
mov eax,[screen.bottom]
sub eax,ecx
push eax
invoke MoveWindow,[hwnddlg],[screen.right]
; Обновить содержимое окна
invoke UpdateWindow,[hwnddlg]
; Небольшая пауза
invoke Sleep,2
; Восстановить счетчик
pop ecx
loop @b
...
В приложении пример программы, показывающей вcплывающее окно в правом нижнем углу экрана. Окно автоматически спрячется по таймеру через 10 секунд или по клику мышкой (обрабатывается сообщение WM_LBUTTONDOWN). Код можно легко доработать, например, чтобы окно выдвигалось справа, а убиралось вниз.