Эффект плавного открытия окна

Разберем еще один красивый эффект для ваших приложений - плавное сворачивание и разворачивание окна. Для этого используются те же функции, что и для создания окон нестандартной формы, так как по сути это такая же работа с прямоугольными регионами, но только в цикле с заданными параметрами. Алгоритм простой: прямоугольный регион окна увеличивается от центра до полного размера или уменьшается со всех сторон до центра. Для этого надо сперва надо вычислить шаг, на который будет увеличиваться или уменьшаться горизонтальная и вертикальная координата.
        ; Обработчик инициализации окна
        ...
        ; Получить размер окна
        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:
        ; Закрыть окно

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