Blog. Just Blog

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

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Разберем еще один красивый эффект для ваших приложений - плавное сворачивание и разворачивание окна. Для этого используются те же функции, что и для создания окон нестандартной формы, так как по сути это такая же работа с прямоугольными регионами, но только в цикле с заданными параметрами. Алгоритм простой: прямоугольный регион окна увеличивается от центра до полного размера или уменьшается со всех сторон до центра. Для этого надо сперва надо вычислить шаг, на который будет увеличиваться или уменьшаться горизонтальная и вертикальная координата.
  1.         ; Обработчик инициализации окна
  2.         ...
  3.         ; Получить размер окна
  4.         invoke  GetClientRect,[hwnddlg],coord
  5.  
  6.         ; Вычислить размеры окна для создания основного региона
  7.         mov     eax,[coord.bottom]
  8.         sub     eax,[coord.top]
  9.         mov     [height],eax
  10.  
  11.         mov     eax,[coord.right]
  12.         sub     eax,[coord.left]
  13.         mov     [width],eax
  14.  
  15.         SPEED   = 4     ; Скорость анимации
  16.  
  17.         ; Вычислить коэффициент соотношения сторон в зависимости от
  18.         ; размеров ширины и высоты окна
  19.         cmp     eax,[height]
  20.         ja      @f
  21.  
  22.         ; Высота/ширина
  23.         xor     edx,edx
  24.         mov     eax,[height]
  25.         mov     ecx,[width]
  26.         div     ecx
  27.         shl     eax,SPEED
  28.         mov     [delta_x],(1 shl SPEED) ; Шаг изменения ширины
  29.         mov     [delta_y],eax           ; Шаг изменения высоты
  30.         jmp     @1
  31. @@:
  32.         ; Ширина/высота
  33.         xor     edx,edx
  34.         mov     eax,[width]
  35.         mov     ecx,[height]
  36.         div     ecx
  37.         shl     eax,SPEED
  38.         mov     [delta_x],eax           ; Шаг изменения ширины
  39.         mov     [delta_y],(1 shl SPEED) ; Шаг изменения высоты
  40. @1:
Поскольку коэффициенты получаются целочисленные, то наиболее красивый эффект будет на окнах квадратной формы или на окнах с кратным соотношением размеров сторон.

При плавном разворачивании окна цикл начинается с середины окна. Размер региона по горизонтали и вертикали уменьшается на соответствующий шаг. При достижении края одной из сторон окно полностью перерисовывается. Между итерациями цикла делается небольшая пауза, по опытам вполне достаточно одной миллисекунды. Для увеличения скорости анимации нужно увеличить шаг.
  1.         ; Разворачиваем окно. Для этого установим регион
  2.         ; в цикле от центра до края окна
  3.  
  4.         ; Текущие смещения окна - центр экрана
  5.         mov     eax,[width]
  6.         shr     eax,1
  7.         mov     [cur_x],eax
  8.  
  9.         mov     eax,[height]
  10.         shr     eax,1
  11.         mov     [cur_y],eax
  12.  
  13. loc_loop_show:
  14.         ; Создать главный регион диалогового окна
  15.         invoke  CreateRectRgn,0,0,[width],[height]
  16.         mov     [hRMain],eax
  17.  
  18.         ; Вырезать все окно
  19.         invoke  CreateRectRgn,0,0,[width],[height]
  20.         push    eax
  21.         invoke  CombineRgn,[hRMain],[hRMain],eax,RGN_DIFF
  22.         ; Освободить хэндл и память региона
  23.         invoke  DeleteObject
  24.  
  25.         ; Добавить прямоугольный регион (режим RGN_OR)
  26.         mov     eax,[height]
  27.         sub     eax,[cur_y]
  28.         push    eax
  29.  
  30.         mov     eax,[width]
  31.         sub     eax,[cur_x]
  32.         push    eax
  33.  
  34.         invoke  CreateRectRgn,[cur_x],[cur_y]
  35.         push    eax
  36.         invoke  CombineRgn,[hRMain],[hRMain],eax,RGN_OR
  37.         ; Освободить хэндл и память региона
  38.         invoke  DeleteObject
  39.  
  40.         ; Установить новый регион для окна и перерисовать его
  41.         invoke  SetWindowRgn,[hwnddlg],[hRMain],TRUE
  42.         ; Освободить хэндл и память главного региона
  43.         invoke  DeleteObject,[hRMain]
  44.  
  45.         ; Окно уже показывается?
  46.         invoke  IsWindowVisible,[hwnddlg]
  47.         or      eax,eax
  48.         jnz     @f
  49.         ; Сделать окно видимым
  50.         invoke  ShowWindow,[hwnddlg],SW_SHOW
  51. @@:
  52.         ; Вычесть шаг по вертикали и горизонтали
  53.         mov     eax,[delta_x]
  54.         sub     [cur_x],eax
  55.         mov     eax,[delta_y]
  56.         sub     [cur_y],eax
  57.  
  58.         ; Дошли до края хотя бы по одной координате?
  59.         cmp     [cur_x],0
  60.         jbe     loc_show
  61.  
  62.         cmp     [cur_y],0
  63.         jbe     loc_show
  64.  
  65.         ; Небольшая пауза
  66.         invoke  Sleep,1
  67.         jmp     loc_loop_show
  68. loc_show:
  69.         ; Сбросить регион для окна и перерисовать его
  70.         invoke  SetWindowRgn,[hwnddlg],NULL,TRUE
При сворачивании цикл идет в обратном направлении - от края окна до центра по всем координатам. При достижении центра окна по горизонтали или вертикали окно закрывается.
  1.         ; Сворачиваем окно. Для этого установим регион
  2.         ; в цикле от края до центра окна
  3.  
  4.         ; Текущие смещения окна
  5.         mov     [cur_x],0
  6.         mov     [cur_y],0
  7. loc_loop_close:
  8.         ; Создать главный регион диалогового окна
  9.         invoke  CreateRectRgn,0,0,[width],[height]
  10.         mov     [hRMain],eax
  11.  
  12.         ; Вырезать все окно
  13.         invoke  CreateRectRgn,0,0,[width],[height]
  14.         push    eax
  15.         invoke  CombineRgn,[hRMain],[hRMain],eax,RGN_DIFF
  16.         ; Освободить хэндл и память региона
  17.         invoke  DeleteObject
  18.  
  19.         ; Добавить прямоугольный регион (режим RGN_OR)
  20.         mov     eax,[height]
  21.         sub     eax,[cur_y]
  22.         push    eax
  23.  
  24.         mov     eax,[width]
  25.         sub     eax,[cur_x]
  26.         push    eax
  27.  
  28.         invoke  CreateRectRgn,[cur_x],[cur_y]
  29.         push    eax
  30.         invoke  CombineRgn,[hRMain],[hRMain],eax,RGN_OR
  31.         ; Освободить хэндл и память региона
  32.         invoke  DeleteObject
  33.  
  34.         ; Установить новый регион для окна и перерисовать его
  35.         invoke  SetWindowRgn,[hwnddlg],[hRMain],TRUE
  36.         ; Освободить хэндл и память главного региона
  37.         invoke  DeleteObject,[hRMain]
  38.  
  39.         ; Добавить шаг по горизонтали и вертикали
  40.         mov     eax,[delta_x]
  41.         add     [cur_x],eax
  42.         mov     eax,[delta_y]
  43.         add     [cur_y],eax
  44.  
  45.         ; Дошли до центра окна по какой-нибудь координате?
  46.         mov     eax,[width]
  47.         shr     eax,1
  48.         cmp     [cur_x],eax
  49.         ja      loc_close
  50.  
  51.         mov     eax,[height]
  52.         shr     eax,1
  53.         cmp     [cur_y],eax
  54.         ja      loc_close
  55.  
  56.         ; Небольшая пауза
  57.         invoke  Sleep,1
  58.         jmp     loc_loop_close
  59. loc_close:
  60.         ; Закрыть окно
В приложении пример программы, при запуске которой главное окно появляется с эффектом разворачивания, а при выходе так же плавно сворачивается.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Zoom.Window.Demo.zip (3,378 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 6380 | Комментариев: 6

Метки: Assembler, окна
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
NT_Header (06.04.2012 в 22:23):
Очень круто!
некто (12.03.2012 в 15:57):
А у меня не поехала
Андрей (14.02.2011 в 00:18):
Если программист в девять утра уже на работе, значит он там же и ночевал -это не просто истина - это какая-то закономерность или напасть!
Alex81524 (23.12.2010 в 09:45):
Программа не просто шикарная. Эффект оригинальный, а автор - почти гений :)
ManHunter (10.12.2010 в 23:04):
Это не наш метод :) Это ж Ассемблер!
zummenix (10.12.2010 в 19:26):
А ещё можно использовать стандартную анимацию виндовса :)

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0068 сек.) / Память: 4.5 Mb
Наверх