Разберем еще один красивый эффект для ваших приложений - плавное сворачивание и разворачивание окна. Для этого используются те же функции, что и для
создания окон нестандартной формы, так как по сути это такая же работа с прямоугольными регионами, но только в цикле с заданными параметрами. Алгоритм простой: прямоугольный регион окна увеличивается от центра до полного размера или уменьшается со всех сторон до центра. Для этого надо сперва надо вычислить шаг, на который будет увеличиваться или уменьшаться горизонтальная и вертикальная координата.
; Обработчик инициализации окна
...
; Получить размер окна
invoke GetClientRect,[hwnddlg],coord
; Вычислить размеры окна для создания основного региона
mov eax,[coord.bottom]
sub eax,[coord.top]
mov [height],eax
mov eax,[coord.right]
sub eax,[coord.left]
mov [width],eax
SPEED = 4 ; Скорость анимации
; Вычислить коэффициент соотношения сторон в зависимости от
; размеров ширины и высоты окна
cmp eax,[height]
ja @f
; Высота/ширина
xor edx,edx
mov eax,[height]
mov ecx,[width]
div ecx
shl eax,SPEED
mov [delta_x],(1 shl SPEED) ; Шаг изменения ширины
mov [delta_y],eax ; Шаг изменения высоты
jmp @1
@@:
; Ширина/высота
xor edx,edx
mov eax,[width]
mov ecx,[height]
div ecx
shl eax,SPEED
mov [delta_x],eax ; Шаг изменения ширины
mov [delta_y],(1 shl SPEED) ; Шаг изменения высоты
@1:
Поскольку коэффициенты получаются целочисленные, то наиболее красивый эффект будет на окнах квадратной формы или на окнах с кратным соотношением размеров сторон.
При плавном разворачивании окна цикл начинается с середины окна. Размер региона по горизонтали и вертикали уменьшается на соответствующий шаг. При достижении края одной из сторон окно полностью перерисовывается. Между итерациями цикла делается небольшая пауза, по опытам вполне достаточно одной миллисекунды. Для увеличения скорости анимации нужно увеличить шаг.
; Разворачиваем окно. Для этого установим регион
; в цикле от центра до края окна
; Текущие смещения окна - центр экрана
mov eax,[width]
shr eax,1
mov [cur_x],eax
mov eax,[height]
shr eax,1
mov [cur_y],eax
loc_loop_show:
; Создать главный регион диалогового окна
invoke CreateRectRgn,0,0,[width],[height]
mov [hRMain],eax
; Вырезать все окно
invoke CreateRectRgn,0,0,[width],[height]
push eax
invoke CombineRgn,[hRMain],[hRMain],eax,RGN_DIFF
; Освободить хэндл и память региона
invoke DeleteObject
; Добавить прямоугольный регион (режим RGN_OR)
mov eax,[height]
sub eax,[cur_y]
push eax
mov eax,[width]
sub eax,[cur_x]
push eax
invoke CreateRectRgn,[cur_x],[cur_y]
push eax
invoke CombineRgn,[hRMain],[hRMain],eax,RGN_OR
; Освободить хэндл и память региона
invoke DeleteObject
; Установить новый регион для окна и перерисовать его
invoke SetWindowRgn,[hwnddlg],[hRMain],TRUE
; Освободить хэндл и память главного региона
invoke DeleteObject,[hRMain]
; Окно уже показывается?
invoke IsWindowVisible,[hwnddlg]
or eax,eax
jnz @f
; Сделать окно видимым
invoke ShowWindow,[hwnddlg],SW_SHOW
@@:
; Вычесть шаг по вертикали и горизонтали
mov eax,[delta_x]
sub [cur_x],eax
mov eax,[delta_y]
sub [cur_y],eax
; Дошли до края хотя бы по одной координате?
cmp [cur_x],0
jbe loc_show
cmp [cur_y],0
jbe loc_show
; Небольшая пауза
invoke Sleep,1
jmp loc_loop_show
loc_show:
; Сбросить регион для окна и перерисовать его
invoke SetWindowRgn,[hwnddlg],NULL,TRUE
При сворачивании цикл идет в обратном направлении - от края окна до центра по всем координатам. При достижении центра окна по горизонтали или вертикали окно закрывается.
; Сворачиваем окно. Для этого установим регион
; в цикле от края до центра окна
; Текущие смещения окна
mov [cur_x],0
mov [cur_y],0
loc_loop_close:
; Создать главный регион диалогового окна
invoke CreateRectRgn,0,0,[width],[height]
mov [hRMain],eax
; Вырезать все окно
invoke CreateRectRgn,0,0,[width],[height]
push eax
invoke CombineRgn,[hRMain],[hRMain],eax,RGN_DIFF
; Освободить хэндл и память региона
invoke DeleteObject
; Добавить прямоугольный регион (режим RGN_OR)
mov eax,[height]
sub eax,[cur_y]
push eax
mov eax,[width]
sub eax,[cur_x]
push eax
invoke CreateRectRgn,[cur_x],[cur_y]
push eax
invoke CombineRgn,[hRMain],[hRMain],eax,RGN_OR
; Освободить хэндл и память региона
invoke DeleteObject
; Установить новый регион для окна и перерисовать его
invoke SetWindowRgn,[hwnddlg],[hRMain],TRUE
; Освободить хэндл и память главного региона
invoke DeleteObject,[hRMain]
; Добавить шаг по горизонтали и вертикали
mov eax,[delta_x]
add [cur_x],eax
mov eax,[delta_y]
add [cur_y],eax
; Дошли до центра окна по какой-нибудь координате?
mov eax,[width]
shr eax,1
cmp [cur_x],eax
ja loc_close
mov eax,[height]
shr eax,1
cmp [cur_y],eax
ja loc_close
; Небольшая пауза
invoke Sleep,1
jmp loc_loop_close
loc_close:
; Закрыть окно
В приложении пример программы, при запуске которой главное окно появляется с эффектом разворачивания, а при выходе так же плавно сворачивается.