Создание и обработка улучшенного MessageBox
В одной из прошлых статей мы уже научились обрабатывать и облагораживать окно выбора каталога, а теперь сделаем что-нибудь необычное и противоестественное с окном сообщения MessageBox. Первое, что приходит на ум - это описать аналог MessageBox в ресурсах или создавать его динамически по мере надобности, но это получается как-то слишком просто. Попробуем перехватить стандартное окно MessageBox в момент создания. Для этого поставим хук на текущий тред нашего процесса, хук должен иметь тип WH_CBT:Code (Assembler) : Убрать нумерацию
- ...
- ; Получить хэндл текущего потока
- invoke GetCurrentThreadId
- ; Установить перехватчик событий
- invoke SetWindowsHookEx,WH_CBT,MBHookProc,NULL,eax
- ; Сохранить хэндл хука
- mov [hMBHook],eax
- ...
Code (Assembler) : Убрать нумерацию
- section '.date' data readable writeable
- ; Заголовок и текст окна
- szTitle db 'Hello!',0
- szMess db 'This is a Customized MessageBox with long text!',13,10
- db 'FASM is the BEST Assembler!',0
- ; Новый текст на кнопках
- szButt1 db 'Of Course ;)',0
- szButt2 db 'No-no-no!!!',0
- ; Название класса окна
- cname db 'EDIT',0
- hMBHook dd ? ; Хэндл хука
- pOldProc dd ? ; Адрес старого обработчика окна
- hInstance dd ? ; Хэндл модуля
- hHeap dd ? ; Хэндл кучи
- hMemory dd ? ; Указатель на память
- coord RECT ; Размеры текста
Функция перехватчика будет иметь следующий вид:
Code (Assembler) : Убрать нумерацию
- ;-----------------------------------------------------------------------
- ; Функция обработки перехватчика
- ;-----------------------------------------------------------------------
- proc MBHookProc nCode:DWORD,wParam:DWORD,lParam:DWORD
- ; Сохранить все регистры
- pusha
- cmp [nCode],0
- jb @f
- cmp [nCode],HCBT_ACTIVATE
- jne @f
- ; Установить иконку окна
- invoke GetModuleHandle,0
- invoke LoadIcon,eax,1
- invoke SendMessage,[wParam],WM_SETICON,ICON_BIG,eax
- ; Поменять текст на кнопке Yes
- invoke GetDlgItem,[wParam],IDYES
- invoke SetWindowText,eax,szButt1
- ; Поменять текст на кнопке No
- invoke GetDlgItem,[wParam],IDNO
- invoke SetWindowText,eax,szButt2
- ; Изменить стиль окна
- invoke GetWindowLong,[wParam],GWL_EXSTYLE
- add eax,WS_EX_LAYERED
- invoke SetWindowLong,[wParam],GWL_EXSTYLE,eax
- ; Установить атрибут прозрачности
- invoke SetLayeredWindowAttributes,[wParam],0,200,LWA_ALPHA
- ; Получить хэндл текстового поля
- invoke GetDlgItem,[wParam],0FFFFh
- ; Сохранить хэндл текстового поля
- mov ebx,eax
- ; Получить длину текста в окне
- invoke GetWindowTextLength,ebx
- or eax,eax
- jz no_text
- ; Получить координаты текстового блока
- invoke GetClientRect,ebx,coord
- ; Пересчитать координаты на дочернее окно
- invoke MapWindowPoints,ebx,[wParam],coord,2
- mov eax,[coord.left]
- sub [coord.right],eax
- add [coord.right],5
- sub [coord.left],7
- mov eax,[coord.top]
- sub [coord.bottom],eax
- add [coord.top],2
- ; Получить кучу текущего процесса
- invoke GetProcessHeap
- mov [hHeap],eax
- mov esi,eax
- ; Выделить память для текста
- invoke HeapAlloc,[hHeap],HEAP_ZERO_MEMORY,eax
- mov [hMemory],eax
- ; Прочитать текст в буфер
- invoke GetWindowText,ebx,[hMemory],esi
- ; Спрятать основной текст
- invoke ShowWindow,ebx,SW_HIDE
- ; Получить шрифт текста в окне
- invoke SendMessage,ebx,WM_GETFONT,NULL,NULL
- mov esi,eax
- ; Создать поле EDIT вместо STATIC
- invoke CreateWindowEx,WS_EX_WINDOWEDGE,cname,[hMemory],\
- WS_CHILD+WS_VISIBLE+ES_MULTILINE+ES_READONLY,[coord.left],\
- [coord.top],[coord.right],[coord.bottom],[wParam],0FFFFh,\
- [hInstance],NULL
- ; Установить шрифт как было у исходного текста
- invoke SendMessage,eax,WM_SETFONT,esi,NULL
- ; Очистить память в куче
- invoke HeapFree,[hHeap],NULL,[hMemory]
- no_text:
- ; Субклассировать обработчик окна
- invoke SetWindowLong,[wParam],GWL_WNDPROC,NewWindowProc
- ; Сохранить адрес предыдущего обработчика
- mov [pOldProc],eax
- ; Снять перехватчик
- invoke UnhookWindowsHookEx,[hMBHook]
- ; Восстановить регистры
- popa
- xor eax,eax
- ret
- @@:
- ; Восстановить регистры
- popa
- ; Передать управление следующему обработчику
- invoke CallNextHookEx,[hMBHook],[nCode],[wParam],[lParam]
- ret
- endp
В приложении пример программы с исходным текстом, реализующей описанный в статье метод перехвата и обработки MessageBox.
Просмотров: 7054 | Комментариев: 6
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
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)) главное процесс)))
Ничем сторонним не пользуюсь, вполне хватает редактора, который идет в комплекте."
Согласен FASMW)) главное процесс)))
ManHunter
(02.08.2010 в 01:43):
Ничем сторонним не пользуюсь, вполне хватает редактора, который идет в комплекте.
end_now
(02.08.2010 в 01:34):
немного оффтоп:
как я вижу вы юзаете FASM, пользуетесь стандартным пакетом для разработки софта, или же прикуртили какой-нить редактор, по типу EmEditor etc. ??
если последнее, что посоветуете?
спасибо.
как я вижу вы юзаете FASM, пользуетесь стандартным пакетом для разработки софта, или же прикуртили какой-нить редактор, по типу EmEditor etc. ??
если последнее, что посоветуете?
спасибо.
Добавить комментарий
Заполните форму для добавления комментария