Blog. Just Blog

Эффект бегущей строки на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Очередной интересный визуальный эффект для ваших программ - бегущая строка. Обычно подобный эффект используется в различных кейгенах, но вполне может пригодиться и для более мирных приложений. В качестве основы взята ассемблерная библиотека Scroller lib 1.01 от ReWolf / HTBTeam. Изначально она предназначалась для MASM, так что пришлось ее портировать под FASM. В процессе переноса библиотека была немного переработана и дополнена, а также упрощена ее структура и подключение к проектам. Сперва в сегменте данных определяются вспомогательные константы и структура для создания скроллера.
  1. ; Константы, определяющие режим скроллера
  2. SCROLL_START = 0  ; Скроллер запущен
  3. SCROLL_PAUSE = 1  ; Скроллер на паузе
  4. SCROLL_STOP  = 2  ; Скроллер полностью остановлен
  5.  
  6. ; Структура для скроллера
  7. struct SCROLLSTRUCT
  8.         ; Значения заполняются пользователем
  9.         hwDlg      dd ?  ; Хэндл окна для скроллера
  10.         hFont      dd ?  ; Шрифт скроллера
  11.         ddWidth    dd ?  ; Ширина скроллера
  12.         X          dd ?  ; Координата X
  13.         Y          dd ?  ; Координата Y
  14.         lpstrText  dd ?  ; Строка скроллера ASCIIZ
  15.         ddTxtColor dd ?  ; Цвет текста скроллера
  16.         ddBkgColor dd ?  ; Цвет фона скроллера
  17.         ddSpeed    dd ?  ; Скорость движения
  18.         dbMode     db ?  ; Режим скроллера
  19.  
  20.         ; Внутренние переменные
  21.         ddROP      dd ?
  22.         hBkgDC     dd ?
  23.         hTxtBmp    dd ?
  24.         hTmpBmp    dd ?
  25.         hBakTmpBmp dd ?
  26.         hInDC      dd ?
  27.         ddHeight   dd ?
  28.         ddPos      dd ?
  29.         ddTxtWidth dd ?
  30. ends
В структуре два типа переменных - пользовательские и служебные. Пользовательские предназначены для задания координат, цвета и других параметров скроллера, они все обязательны для заполнения. Служебные используются процедурой скроллера и не должны изменяться пользователем.

После инициализации переменных вызывается основная функция скроллера. Обратите внимание, что скроллер должен быть привязан только к существующему и видимому окну, поэтому в функции выполняется проверка существования родительского окна, а само окно принудительно делается видимым. Принцип работы скроллера в том, что из окна считывается фрагмент заданного размера, текст скроллера преобразуется в картинку, а затем в цикле по ней передвигается "кадр" и накладывается на фрагмент из окна.
  1. ;-----------------------------------------------------------------------
  2. ; Процедура инициализации и запуска скроллера
  3. ; by ManHunter / PCL
  4. ; http://www.manhunter.ru
  5. ;
  6. ; Based on Scroller lib v1.01 by ReWolf / HTBTeam
  7. ; http://rewolf.prv.pl
  8. ;
  9. ; Параметры вызова:
  10. ;     lpScrollData - указатель на заполненную структуру SCROLLSTRUCT
  11. ;-----------------------------------------------------------------------
  12. proc    Scroller lpScrollData:DWORD
  13.  
  14.         ; Локальные переменные
  15.         local   sz_x      :DWORD
  16.         local   sz_y      :DWORD
  17.         local   ddLen     :DWORD
  18.         local   hBkgBrush :DWORD
  19.         local   hBkgPen   :DWORD
  20.  
  21.         ; Локальная проекция структуры
  22.         virtual at 0
  23.         scroll SCROLLSTRUCT
  24.         end virtual
  25.  
  26.         ; Сохранить все регистры
  27.         pusha
  28.  
  29.         ; Указатель на структуру SCROLLSTRUCT
  30.         mov     edi,[lpScrollData]
  31.  
  32.         ; Родительское окно существует?
  33.         invoke  IsWindow,[edi+scroll.hwDlg]
  34.         or      eax,eax
  35.         jnz     @f
  36.  
  37.         ; Восстановить все регистры
  38.         popa
  39.         ; EAX = 0, функция завершилась с ошибкой
  40.         xor     eax,eax
  41.         ret
  42. @@:
  43.         ; Сделать окно видимым и обновить его
  44.         invoke  ShowWindow,[edi+scroll.hwDlg],SW_SHOW
  45.         invoke  UpdateWindow,[edi+scroll.hwDlg]
  46.  
  47.         ; Получить контекст устройства окна
  48.         invoke  GetDC,[edi+scroll.hwDlg]
  49.         mov     [edi+scroll.hBkgDC],eax
  50.  
  51.         ; Режим наложения AND
  52.         mov     [edi+scroll.ddROP],SRCAND
  53.  
  54.         ; Стартовая позиция скроллера = 0
  55.         mov     [edi+scroll.ddPos],0
  56.  
  57.         invoke  CreateCompatibleDC,[edi+scroll.hBkgDC]
  58.         mov     [edi+scroll.hInDC],eax
  59.  
  60.         ; Установить шрифт скроллера
  61.         invoke  SelectObject,[edi+scroll.hInDC],[edi+scroll.hFont]
  62.  
  63.         ; Получить длину строки скроллера
  64.         invoke  lstrlen,[edi+scroll.lpstrText]
  65.         mov     [ddLen],eax
  66.  
  67.         lea     eax,[sz_x]
  68.         invoke  GetTextExtentPoint32,[edi+scroll.hInDC],[edi+scroll.lpstrText],\
  69.                 [ddLen],eax
  70.         push    [sz_y]
  71.         pop     [edi+scroll.ddHeight]
  72.         push    [sz_x]
  73.         pop     [edi+scroll.ddTxtWidth]
  74.  
  75.         mov     eax,[edi+scroll.ddWidth]
  76.         shl     eax,1
  77.         add     eax,[edi+scroll.ddTxtWidth]
  78.         invoke  CreateCompatibleBitmap,[edi+scroll.hBkgDC],eax,\
  79.                 [edi+scroll.ddHeight]
  80.         mov     [edi+scroll.hTxtBmp],eax
  81.  
  82.         invoke  SelectObject,[edi+scroll.hInDC],[edi+scroll.hTxtBmp]
  83.         invoke  SetBkMode,[edi+scroll.hInDC],OPAQUE; TRANSPARENT;
  84.         invoke  SetTextColor,[edi+scroll.hInDC],[edi+scroll.ddTxtColor]
  85.         invoke  CreateSolidBrush,[edi+scroll.ddBkgColor]
  86.         mov     [hBkgBrush],eax
  87.  
  88.         invoke  SelectObject,[edi+scroll.hInDC],eax
  89.  
  90.         invoke  CreatePen,PS_SOLID,1,[edi+scroll.ddBkgColor]
  91.         mov     [hBkgPen],eax
  92.  
  93.         invoke  SelectObject,[edi+scroll.hInDC],eax
  94.  
  95.         mov     eax,[edi+scroll.ddWidth]
  96.         shl     eax,1
  97.         add     eax,[edi+scroll.ddTxtWidth]
  98.         invoke  Rectangle,[edi+scroll.hInDC],0,0,eax,[edi+scroll.ddHeight]
  99.  
  100.         invoke  TextOut,[edi+scroll.hInDC],[edi+scroll.ddWidth],0,\
  101.                 [edi+scroll.lpstrText],[ddLen]
  102.  
  103.         invoke  SelectObject,[edi+scroll.hInDC],[hBkgPen]
  104.         invoke  SelectObject,[edi+scroll.hInDC],[hBkgBrush]
  105.  
  106.         invoke  DeleteObject,[hBkgPen]
  107.         invoke  DeleteObject,[hBkgBrush]
  108.  
  109.         invoke  CreateCompatibleBitmap,[edi+scroll.hBkgDC],\
  110.                 [edi+scroll.ddWidth],[edi+scroll.ddHeight]
  111.         mov     [edi+scroll.hBakTmpBmp],eax
  112.  
  113.         invoke  SelectObject,[edi+scroll.hInDC],eax
  114.         invoke  BitBlt,[edi+scroll.hInDC],0,0,[edi+scroll.ddWidth],\
  115.                 [edi+scroll.ddHeight],[edi+scroll.hBkgDC],[edi+scroll.X],\
  116.                 [edi+scroll.Y],SRCCOPY
  117.  
  118.         invoke  SelectObject,[edi+scroll.hInDC],[edi+scroll.hBakTmpBmp]
  119.  
  120.         invoke  CreateCompatibleBitmap,[edi+scroll.hBkgDC],\
  121.                 [edi+scroll.ddWidth],[edi+scroll.ddHeight]
  122.         mov     [edi+scroll.hTmpBmp],eax
  123.  
  124.         ; Запустить основную процедуру скроллера
  125.         xor     eax,eax
  126.         push    eax
  127.         invoke  CreateThread,NULL,NULL,scroll_proc,[lpScrollData],NULL,esp
  128.         pop     eax
  129.  
  130.         ; Обновить родительское окно
  131.         invoke  UpdateWindow,[edi+scroll.hwDlg]
  132.  
  133.         ; Восстановить все регистры
  134.         popa
  135.         ; EAX = 1, функция выполнена успешно
  136.         xor     eax,eax
  137.         inc     eax
  138.  
  139.         ret
  140. endp
Вспомогательная функция скроллера запускается в отдельном потоке, управляется только через поле dbMode структуры SCROLLSTRUCT соответствующего скроллера. Пример смотрите в прилагаемом исходнике. При полной остановке скроллера поток завершается и скроллер становится недоступным для управления.
  1. ;-----------------------------------------------------------------------
  2. ; Вспомогательная функция скроллера, напрямую не вызывается
  3. ;-----------------------------------------------------------------------
  4. proc scroll_proc lpScrollData:DWORD
  5.  
  6.         ; Локальная проекция структуры
  7.         virtual at 0
  8.         pscroll SCROLLSTRUCT
  9.         end virtual
  10.  
  11.         ; Указатель на структуру SCROLLSTRUCT
  12.         mov     edi,[lpScrollData]
  13. .scroll_loop:
  14.         ; Проверить режим скроллера
  15.         cmp     [edi+pscroll.dbMode],SCROLL_STOP
  16.         ; Выход
  17.         je      .scroll_exit
  18.  
  19.         ; Если скроллер только создан, то отрисовать его
  20.         cmp     [edi+pscroll.ddPos],1
  21.         jbe     @f
  22.  
  23.         ; Выдержать паузу согласно заданной скорости
  24.         invoke  Sleep,[edi+pscroll.ddSpeed]
  25.         ; Скроллер приостановлен?
  26.         cmp     [edi+pscroll.dbMode],SCROLL_PAUSE
  27.         je      .scroll_loop
  28. @@:
  29.         mov     ebx,[edi+pscroll.ddTxtWidth]
  30.         add     ebx,[edi+pscroll.ddWidth]
  31.         cmp     ebx,[edi+pscroll.ddPos]
  32.         jne     @f
  33.         mov     [edi+pscroll.ddPos],0
  34. @@:
  35.         invoke  CreateCompatibleDC,[edi+pscroll.hInDC]
  36.         mov     esi,eax
  37.         invoke  SelectObject,eax,[edi+pscroll.hBakTmpBmp]
  38.         invoke  SelectObject,[edi+pscroll.hInDC],[edi+pscroll.hTmpBmp]
  39.         invoke  BitBlt,[edi+pscroll.hInDC],0,0,[edi+pscroll.ddWidth],\
  40.                 [edi+pscroll.ddHeight],esi,0,0,SRCCOPY
  41.         invoke  SelectObject,esi,[edi+pscroll.hTxtBmp]
  42.         invoke  BitBlt,[edi+pscroll.hInDC],0,0,[edi+pscroll.ddWidth],\
  43.                 [edi+pscroll.ddHeight],esi,[edi+pscroll.ddPos],\
  44.                 0,[edi+pscroll.ddROP]
  45.         invoke  BitBlt,[edi+pscroll.hBkgDC],[edi+pscroll.X],\
  46.                 [edi+pscroll.Y],[edi+pscroll.ddWidth],[edi+pscroll.ddHeight],\
  47.                 [edi+pscroll.hInDC],0,0,SRCCOPY
  48.         invoke  DeleteDC,esi
  49.  
  50.         inc     [edi+pscroll.ddPos]
  51.         jmp     .scroll_loop
  52. .scroll_exit:
  53.         ret
  54. endp
В приложении пример программы с двумя независимыми скроллерами, по нажатию кнопки Pause они останавливаются, при повторном нажатии запускаются снова.

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

Scroller.Demo.zip (4,797 bytes)


Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 5649 | Комментариев: 5

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

Комментарии

Отзывы посетителей сайта о статье
ManHunter (20.12.2009 в 02:02):
Неплохая, но тоже заточена под MASM
Vovka (19.12.2009 в 23:44):
Не плохая либа есть от diablo2oo2
http://diablo2oo2.di.funpic.de...scroller.rar
Isaev (16.12.2009 в 00:15):
станет совсем прикольный компонент ;)
ManHunter (15.12.2009 в 21:18):
Пока не знаю, не пробовал. Но думаю, что смогу.
Isaev (15.12.2009 в 21:08):
приятно двигается
а можешь добавить расплывчатый эффект в по границам строки?
чтобы выезжала и исчезала как будто из тумана (просто градациями яркости)

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

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

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