Blog. Just Blog

Создание и обработка улучшенного MessageBox

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
В одной из прошлых статей мы уже научились обрабатывать и облагораживать окно выбора каталога, а теперь сделаем что-нибудь необычное и противоестественное с окном сообщения MessageBox. Первое, что приходит на ум - это описать аналог MessageBox в ресурсах или создавать его динамически по мере надобности, но это получается как-то слишком просто. Попробуем перехватить стандартное окно MessageBox в момент создания. Для этого поставим хук на текущий тред нашего процесса, хук должен иметь тип WH_CBT:
  1.         ...
  2.         ; Получить хэндл текущего потока
  3.         invoke  GetCurrentThreadId
  4.         ; Установить перехватчик событий
  5.         invoke  SetWindowsHookEx,WH_CBT,MBHookProc,NULL,eax
  6.         ; Сохранить хэндл хука
  7.         mov     [hMBHook],eax
  8.         ...
Теперь мы можем отследить и обработать момент, когда система захочет активировать любое окно, принадлежащее треду. Значит, если сразу после установки этого хука вызвать функцию MessageBox, то перехватчик также получит управление и мы сможем получить хэндл окна создаваемого MessageBox. В сегменте данных определим нужные переменные, структуры и строки. Их назначение будет раскрыто дальше.
  1. section '.date' data readable writeable
  2.  
  3. ; Заголовок и текст окна
  4. szTitle         db 'Hello!',0
  5. szMess          db 'This is a Customized MessageBox with long text!',13,10
  6.                 db 'FASM is the BEST Assembler!',0
  7.  
  8. ; Новый текст на кнопках
  9. szButt1         db 'Of Course ;)',0
  10. szButt2         db 'No-no-no!!!',0
  11.  
  12. ; Название класса окна
  13. cname           db 'EDIT',0
  14.  
  15. hMBHook         dd ?    ; Хэндл хука
  16. pOldProc        dd ?    ; Адрес старого обработчика окна
  17. hInstance       dd ?    ; Хэндл модуля
  18. hHeap           dd ?    ; Хэндл кучи
  19. hMemory         dd ?    ; Указатель на память
  20. coord           RECT    ; Размеры текста
Зная хэндл, с окном можно сделать практически все что угодно. Здесь есть важный момент: после обработки окна надо обязательно сразу же снять хук, чтобы не было никаких накладок.

Функция перехватчика будет иметь следующий вид:
  1. ;-----------------------------------------------------------------------
  2. ; Функция обработки перехватчика
  3. ;-----------------------------------------------------------------------
  4. proc MBHookProc nCode:DWORD,wParam:DWORD,lParam:DWORD
  5.         ; Сохранить все регистры
  6.         pusha
  7.  
  8.         cmp     [nCode],0
  9.         jb      @f
  10.         cmp     [nCode],HCBT_ACTIVATE
  11.         jne     @f
  12.  
  13.         ; Установить иконку окна
  14.         invoke  GetModuleHandle,0
  15.         invoke  LoadIcon,eax,1
  16.         invoke  SendMessage,[wParam],WM_SETICON,ICON_BIG,eax
  17.  
  18.         ; Поменять текст на кнопке Yes
  19.         invoke  GetDlgItem,[wParam],IDYES
  20.         invoke  SetWindowText,eax,szButt1
  21.         ; Поменять текст на кнопке No
  22.         invoke  GetDlgItem,[wParam],IDNO
  23.         invoke  SetWindowText,eax,szButt2
  24.  
  25.         ; Изменить стиль окна
  26.         invoke  GetWindowLong,[wParam],GWL_EXSTYLE
  27.         add     eax,WS_EX_LAYERED
  28.         invoke  SetWindowLong,[wParam],GWL_EXSTYLE,eax
  29.         ; Установить атрибут прозрачности
  30.         invoke  SetLayeredWindowAttributes,[wParam],0,200,LWA_ALPHA
  31.  
  32.         ; Получить хэндл текстового поля
  33.         invoke  GetDlgItem,[wParam],0FFFFh
  34.         ; Сохранить хэндл текстового поля
  35.         mov     ebx,eax
  36.  
  37.         ; Получить длину текста в окне
  38.         invoke  GetWindowTextLength,ebx
  39.         or      eax,eax
  40.         jz      no_text
  41.  
  42.         ; Получить координаты текстового блока
  43.         invoke  GetClientRect,ebx,coord
  44.         ; Пересчитать координаты на дочернее окно
  45.         invoke  MapWindowPoints,ebx,[wParam],coord,2
  46.         mov     eax,[coord.left]
  47.         sub     [coord.right],eax
  48.         add     [coord.right],5
  49.         sub     [coord.left],7
  50.         mov     eax,[coord.top]
  51.         sub     [coord.bottom],eax
  52.         add     [coord.top],2
  53.  
  54.         ; Получить кучу текущего процесса
  55.         invoke  GetProcessHeap
  56.         mov     [hHeap],eax
  57.  
  58.         mov     esi,eax
  59.         ; Выделить память для текста
  60.         invoke  HeapAlloc,[hHeap],HEAP_ZERO_MEMORY,eax
  61.         mov     [hMemory],eax
  62.  
  63.         ; Прочитать текст в буфер
  64.         invoke  GetWindowText,ebx,[hMemory],esi
  65.  
  66.         ; Спрятать основной текст
  67.         invoke  ShowWindow,ebx,SW_HIDE
  68.         ; Получить шрифт текста в окне
  69.         invoke  SendMessage,ebx,WM_GETFONT,NULL,NULL
  70.         mov     esi,eax
  71.  
  72.         ; Создать поле EDIT вместо STATIC
  73.         invoke  CreateWindowEx,WS_EX_WINDOWEDGE,cname,[hMemory],\
  74.                 WS_CHILD+WS_VISIBLE+ES_MULTILINE+ES_READONLY,[coord.left],\
  75.                 [coord.top],[coord.right],[coord.bottom],[wParam],0FFFFh,\
  76.                 [hInstance],NULL
  77.         ; Установить шрифт как было у исходного текста
  78.         invoke  SendMessage,eax,WM_SETFONT,esi,NULL
  79.  
  80.         ; Очистить память в куче
  81.         invoke  HeapFree,[hHeap],NULL,[hMemory]
  82.  
  83. no_text:
  84.         ; Субклассировать обработчик окна
  85.         invoke  SetWindowLong,[wParam],GWL_WNDPROC,NewWindowProc
  86.         ; Сохранить адрес предыдущего обработчика
  87.         mov     [pOldProc],eax
  88.  
  89.         ; Снять перехватчик
  90.         invoke  UnhookWindowsHookEx,[hMBHook]
  91.  
  92.         ; Восстановить регистры
  93.         popa
  94.  
  95.         xor     eax,eax
  96.         ret     
  97. @@:
  98.         ; Восстановить регистры
  99.         popa
  100.  
  101.         ; Передать управление следующему обработчику
  102.         invoke  CallNextHookEx,[hMBHook],[nCode],[wParam],[lParam]
  103.         ret
  104. endp
Субклассированный обработчик окна для перетаскивания его за любое место почти такой же, как и в предыдущей статье. Разница только в том, что адрес предыдущего обработчика должен храниться в отдельной переменной. Это связано с особенностями заполнения структур окна MessageBox. После выполнения получается полупрозрачный MessageBox с иконкой в заголовке, измененным текстом на стандартных кнопках "Да" и "Нет", текст сообщения помещен в EDIT и его можно выделить мышкой и скопировать, а само окно можно перемещать за любое место. Естественно, что в прикладных программах одновременно столько наворотов не потребуется, это сделано только для демонстрации.

В приложении пример программы с исходным текстом, реализующей описанный в статье метод перехвата и обработки MessageBox.

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

Advanced.MessageBox.Demo.zip (4,858 bytes)


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

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

Комментарии

Отзывы посетителей сайта о статье
Fred (26.03.2011 в 09:58):
Про аналог в ресурсах тоже интересно кто знает о чем речь напишите пару строк.
Alex (19.03.2011 в 22:18):
"Первое, что приходит на ум - это описать аналог MessageBox в ресурсах или создавать его динамически по мере надобности, но это получается как-то слишком просто."
если есть время привидите примеры и этих способов.
Спасибо .
ChernoHod (18.03.2011 в 01:48):
FASM РУЛИТ!!!
chak_xakep (22.12.2010 в 09:57):
"ManHunter (02.08.2010 в 01:43):
Ничем сторонним не пользуюсь, вполне хватает редактора, который идет в комплекте."

Согласен FASMW)) главное процесс)))
ManHunter (02.08.2010 в 01:43):
Ничем сторонним не пользуюсь, вполне хватает редактора, который идет в комплекте.
end_now (02.08.2010 в 01:34):
немного оффтоп:
как я вижу вы юзаете FASM, пользуетесь стандартным пакетом для разработки софта, или же прикуртили какой-нить редактор, по типу EmEditor etc. ??
если последнее, что посоветуете?
спасибо.

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

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

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