Blog. Just Blog

Быстрый поиск

Введите фрагмент названия статьи для поиска

Подсказки (tooltips) в диалоговых окнах

16.09.2009 | Категория: Образ мышления: Assembler | Автор: ManHunter
Еще один способ придать вашим программам профессиональный вид - использование всплывающих подсказок (tooltips), которые появляются при наведении курсора мыши на какой-нибудь элемент диалогового окна. Готовые примеры на FASM или слишком громоздкие, или недостаточно гибкие, поэтому пришлось придумывать что-то свое. Причем с самого начала поставил себе задачу сделать функции работы с подсказками как можно более универсальными, чтобы в дальнейшем их можно было легко использовать в других проектах.

В сегменте данных определим все необходимые константы, переменные и структуры. Большая часть этих данных в FASM по умолчанию отсутствует, так что пришлось штудировать MSDN и другие источники и описывать их самостоятельно.
  1. ; Сегмент данных
  2. section '.data' data readable writeable  
  3.  
  4. hwndTip         dd ?    ; Хэндл окна подсказки
  5. TTipFlag        dd ?    ; Флаг активности подсказки
  6.  
  7. ; Структура TRACKMOUSEEVENT не определена, сделаем это сами
  8. struct TRACKMOUSEEVENT
  9.   cbSize        dd ?
  10.   dwFlags       dd ?
  11.   hwndTrack     dd ?
  12.   dwHoverTime   dd ?
  13. ends
  14.  
  15. ; Определяем нужные структуры
  16. tme     TRACKMOUSEEVENT
  17. pt      POINT
  18. ttip    TOOLINFO
  19. trect   RECT
  20.  
  21. oldX    dd ?    ; Сохраненные координаты мыши
  22. oldY    dd ?
  23.  
  24. ; Определяем нужные константы
  25. TTM_TRACKACTIVATE  = WM_USER + 17
  26. TTM_TRACKPOSITION  = WM_USER + 18
  27. TTM_SETMAXTIPWIDTH = WM_USER + 24
  28.  
  29. ; Сообщения окну подсказки
  30. TTF_SUBCLASS       = 0x0010
  31. TTF_TRACK          = 0x0020
  32. TTF_ABSOLUTE       = 0x0080
  33. TTF_TRANSPARENT    = 0x0100
  34.  
  35. ; Сообщение обработчика мыши
  36. TME_LEAVE          = 0x00000002
  37.  
  38. ; Максимальная ширина всплывающей подсказки
  39. TOOLTIP_WIDTH      = 200
  40.  
  41. ; Предустановленное количество элементов в массиве подсказок
  42. TOOLTIPS_COUNT     = 5
  43.  
  44. ; Массив данных для всплывающих подсказок
  45. ; Формат массива:
  46. ;   1 DWORD - сохраненный адрес обработчика
  47. ;   2 DWORD - адрес подсказки
  48. tt_data rd  (TOOLTIPS_COUNT*2)
Для добавления подсказок к элементам диалогового окна я написал отдельную процедуру, использующую субклассирование. Она же является процедурой, создающей исходное окно подсказки, если оно до этого не было создано. Окну подсказки присваивается максимальная ширина, определяемая константой TOOLTIP_WIDTH, и для большей изящности добавляется эффект тени.

Читать статью целиком »
Просмотров: 5618 | Комментариев: 10

Поле EDIT для ввода шестнадцатеричных цифр

23.08.2009 | Категория: Образ мышления: Assembler | Автор: ManHunter
Поле для ввода только цифр организовать несложно, для этого достаточно просто прописать в ресурсах у нужного поля флаг ES_NUMBER. После этого с клавиатуры в это поле можно будет ввести только символ из интервала "0" - "9". Впрочем этот ничуть не мешает через Ctrl+C / Ctrl+V затолкать в него все что угодно, вплоть до непечатных бинарных данных. А как сделать поле, в которое можно вводить с клавиатуры только шестнадцатеричные цифры? Ведь там могут быть не только символы с десятичными цифрами, но и символы "A" - "F", которые также являются шестнадцатеричными цифрами. Это делается через субклассирование. Мы уже рассмотрели один пример субклассирования, превратив поле EDIT в гиперссылку, и там же определили алгоритм обработчика субклассированного элемента. Как и в прошлый раз, субклассирование должно выполняться на этапе инициализации диалогового окна.
  1. ; Сегмент данных
  2. section '.data' data readable writeable  
  3. OldProc dd ?    ; Адрес предыдущего обработчика
  4.  
  5. ; Сегмент кода
  6. section '.code' code readable executable
  7.         ...
  8.         ; Субклассирование на этапе инициализации окна
  9.         invoke  GetDlgItem,[hwnddlg],ID_HEX
  10.         ; Установить наш собственный обработчик
  11.         invoke  SetWindowLong,eax,GWL_WNDPROC,EditWindowProc
  12.         ; Сохранить хэндл предыдущего обработчика
  13.         mov     [OldProc],eax
  14.         ...
Здесь все почти то же самое, разница будет лишь в обрабатываемых сообщениях. Соответственно, если будет несколько полей ввода, то надо субклассировать каждое из них отдельно.

Читать статью целиком »
Просмотров: 6167 | Комментариев: 9

gzuncompress и gzinflate: Assembler vs PHP

11.08.2009 | Категория: Темная сторона Силы | Автор: ManHunter
При разработке проекта Massacre возникла необходимость реализовать функции распаковки PHP-кода на Ассемблере. В этой статье я распишу все выкладки по этому вопросу. Кому-нибудь пригодится - хорошо, не пригодится - оставлю для себя, чтобы не забыть. Как всегда, начнем с теории. Функции gzuncompress и gzinflate обратны к функциям gzcompress и gzdeflate, соответственно. Все они используют алгоритм сжатия LZW, который также используется в бесплатной библиотеке zlib. Сперва скачаем эту библиотеку и воспользуемся Ассемблером, чтобы сжать какую-нибудь эталонную строку.
  1. format PE GUI 4.0
  2. entry start
  3.  
  4. include 'win32a.inc'
  5.  
  6. section '.data' data readable writeable
  7.  
  8. strr    db 'ManHunter'  ; Строка для компрессии
  9. lend    = $-strr
  10. bsize   = 1000
  11.  
  12. blen    dd bsize
  13.  
  14. tmp     rb bsize
  15. tmp2    rb bsize
  16. tmp3    rb bsize
  17.  
  18. mask    db '%.2X ',0
  19.  
  20. ;----------------------------------------------------------
  21.  
  22. section '.code' code readable executable
  23. start:
  24.  
  25.         invoke  compress,tmp,blen,strr,dword lend
  26.  
  27.         mov     ecx,[blen]
  28.         mov     esi,tmp
  29. @@:
  30.         push    ecx
  31.         movzx   eax,byte [esi]
  32.         invoke  wsprintf,tmp2,mask,eax
  33.         add     esp,12
  34.         invoke  lstrcat,tmp3,tmp2
  35.         inc     esi
  36.         pop     ecx
  37.         loop    @b
  38.  
  39.         invoke  MessageBox,HWND_DESKTOP,tmp3,NULL,MB_OK
  40.         invoke  ExitProcess,0
  41.  
  42. ;----------------------------------------------------------
  43.  
  44. section '.idata' import data readable writeable
  45.  
  46. library kernel32,"kernel32.dll",\
  47.         user32,"user32.dll",\
  48.         zlib,"zlib1.dll"
  49.  
  50. include "apia\kernel32.inc"
  51. include "apia\user32.inc"
  52.  
  53.   import zlib,\
  54.          compress,'compress'
В окне будет показана следующая строка:

78 9C F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
Часть строки я специально выделил красным цветом, дальше будет понятно зачем это сделано.

Читать статью целиком »
Просмотров: 6176 | Комментариев: 6

Создание диалоговых окон с тенью

03.08.2009 | Категория: Образ мышления: Assembler | Автор: ManHunter
Сегодня разберем очередное украшательство для ваших программ, а именно тень от диалоговых окон. Обычная тень создается штатными средствами системы, но поддерживается только начиная с Windows XP. Для этого требуется, чтобы стиль окна включал в себя флаг CS_DROPSHADOW, и здесь есть одна тонкость: этот флаг нельзя прописать в ресурсах, а надо устанавливать при инициализации диалогового окна. В обработчике инициализации должен быть такой код:
  1.         ...
  2.         ; Определить константу CS_DROPSHADOW
  3.         CS_DROPSHADOW = 00020000h
  4.         ; Получить текущее значение стиля окна
  5.         invoke  GetWindowLong,[hwnddlg],GCL_STYLE
  6.         ; Добавить к нему атрибут тень
  7.         or      eax,CS_DROPSHADOW
  8.         ; Установить новый стиль окна
  9.         invoke  SetClassLong,[hwnddlg],GCL_STYLE,eax   
  10.         ...
Тут есть плюсы: корректно поддерживаются окна любой нестандартной и сложной формы, а все следующие окна процесса автоматически создаются сразу с тенью. Но есть один странный момент. Несмотря на то, что дочерние окна сперва создаются с корректной тенью, при любом перемещении их над родительским окном тени родительского и дочернего окна сливаются в одну. Пример такого нездорового явления природы показан на скриншоте.

Читать статью целиком »
Просмотров: 6591 | Комментариев: 1

Гиперссылки в диалоговых окнах на Ассемблере

11.07.2009 | Категория: Образ мышления: Assembler | Автор: ManHunter
Создание текстовой гиперссылки в диалоговом окне, казалось бы, простая задача. Но дело в том, что в Windows по умолчанию нет элементов диалоговых окон, которые бы выполняли роль гиперссылки. Готовых решений на FASM тоже не нашлось, значит придется создавать такой элемент самостоятельно. Сперва определимся с задачами, что нам надо сделать. Должен получиться элемент диалогового окна в виде текста определенного цвета, при наведении на который курсор должен менять свою форму, а цвет изменяться на подсвеченный. При клике на такой элемент должна открываться заданная ссылка. Задачи ясны, начнем их решать. Сперва выберем элемент диалоговых окон из списка стандартных, который и будет использоваться в качестве гиперссылки. Сразу же приходит на ум STATIC. По умолчанию элемент класса STATIC полностью оправдывает свое название и не реагирует практически ни на какие сообщения. Чтобы STATIC принимал движение курсора и нажатия клавиш мышки, его надо описать в ресурсах с флагом стилей SS_NOTIFY.

А как отследить движение курсора только над нашей гиперссылкой? Тут нам на помощь придет такая полезная вещь, как субклассирование. Суть субклассирования проста. С каждым окном связан указатель на оконную процедуру, которая обрабатывает сообщения Windows. Когда система получает сообщение, предназначенное для некоторого окна, она находит адрес оконной процедуры этого окна и вызывает ее. При субклассировании мы заменяем эту процедуру нашей и сохраняем указатель на старую процедуру, чтобы можно было передать ей сообщения для дальнейшей обработки. Это делается функцией SetWindowLong с индексом GWL_WNDPROC на этапе инициализации главного окна:
  1.         ...
  2.         ; Получить хэндл нашего STATIC'а
  3.         invoke  GetDlgItem,[hwnddlg],ID_LINK
  4.         ; Субклассировать гиперссылку и установить собственный
  5.         ; обработчик для STATIC'а
  6.         invoke  SetWindowLong,eax,GWL_WNDPROC,WindowProc
  7.         ; Сохранить адрес предыдущего обработчика
  8.         mov     [OldWndProc],eax
  9.         ...
Теперь напишем процедуру обработки. Тут важно понять основной принцип: при сообщениях, которые мы подавляем или обрабатываем самостоятельно, процедура должна возвращать FALSE, как будто бы их вообще не было. Если сообщение не обрабатывается или оно было модифицировано нашим обработчиком, то его обязательно надо передавать функцией CallWindowProc предыдущему обработчику, адрес которого сохранен при субклассировании. Это можно посмотреть на примере обработчика нашей гиперссылки.

Читать статью целиком »
Просмотров: 6780 | Комментариев: 6

01 ... 62 63 64 65 66 67 68 ... 71
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 3 (0.0131 сек.) / Память: 4.5 Mb
Наверх