Универсальное субклассирование окон на Ассемблере
Тема субклассирования окон уже не один раз поднималась в статьях на этом сайте. Теперь пришло время навести порядок и сделать наиболее удобное и универсальное решение для этой задачи. Воспользуемся функциями SetProp и GetProp, чтобы хранить адреса обработчиков прямо в свойствах окна без заведения дополнительных переменных.Code (Assembler) : Убрать нумерацию
- ;-------------------------------------------------------------------------
- ; Наименования свойств. Можно переименовать, если конфликтуют с другими
- ; строками в программе
- ;-------------------------------------------------------------------------
- szOld db 'OldWndProc', 0
- szNew db 'NewWndProc', 0
- ;-------------------------------------------------------------------------
- ; Функция субклассирования окна
- ;-------------------------------------------------------------------------
- ; hWnd - хэндл окна для субклассирования
- ; SubclassProc - адрес нового обработчика окна
- ;-------------------------------------------------------------------------
- proc SubclassWindow hWnd:DWORD,SubclassProc:DWORD
- pusha
- ; Получить старый обработчик окна
- invoke GetWindowLong,[hWnd],GWL_WNDPROC
- ; Сохранить его в свойствах окна
- invoke SetProp,[hWnd],szOld,eax
- ; Сохранить в свойствах новый обработчик окна
- invoke SetProp,[hWnd],szNew,[SubclassProc]
- ; Назначить окну универсальную функцию обработки
- invoke SetWindowLong,[hWnd],GWL_WNDPROC,CommonSubclassProc
- popa
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ; Субклассировать поле ввода
- invoke GetDlgItem,[hwnddlg],ID_HEX
- stdcall SubclassWindow,eax,EditWindowProc
- ; Субклассировать кнопку
- invoke GetDlgItem,[hwnddlg],ID_BTN
- stdcall SubclassWindow,eax,ButtonProc
Code (Assembler) : Убрать нумерацию
- ;-------------------------------------------------------------------------
- ; Функция снятия субклассирования с окна
- ;-------------------------------------------------------------------------
- ; hWnd - хэндл окна
- ;-------------------------------------------------------------------------
- proc UnSubclassWindow hWnd:DWORD
- pusha
- ; Получить сохраненный обработчик окна
- invoke GetProp,[hWnd],szOld
- or eax,eax
- ; Сохраненного обработчика нет
- jz .loc_ret
- ; Назначить окну старую функцию обработки
- invoke SetWindowLong,[hWnd],GWL_WNDPROC,eax
- ; Удалить сохраненные обработчики
- invoke RemoveProp,[hWnd],szOld
- invoke RemoveProp,[hWnd],szNew
- .loc_ret:
- popa
- ret
- endp
В чем же главная фишка этого способа субклассирования? Наверняка вы обратили внимание, что в качестве обработчика окна назначается не пользовательская процедура, а некая процедура CommonSubclassProc. Это и есть универсальная функция обработки субклассированого окна, вот ее код:
Code (Assembler) : Убрать нумерацию
- ;-------------------------------------------------------------------------
- ; Универсальная функция обработки субклассированого окна
- ;-------------------------------------------------------------------------
- proc CommonSubclassProc hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD
- ; Получить адрес нового обработчика
- invoke GetProp,[hWnd],szNew
- or eax,eax
- jz .call_old_proc
- ; Сохранить изменяемые регистры и вызвать обработчик
- push esi
- push edi
- push ebx
- stdcall eax,[hWnd],[wMsg],[wParam],[lParam]
- pop ebx
- pop edi
- pop esi
- ; Если обработчик вернул CF=0, то больше ничего не делать
- jnc .loc_ret
- .call_old_proc:
- ; Получить адрес старого обработчика
- invoke GetProp,[hWnd],szOld
- or eax,eax
- jz .loc_ret
- ; Вызывать старый обработчик окна
- invoke CallWindowProc,eax,[hWnd],[wMsg],[wParam],[lParam]
- .loc_ret:
- ret
- endp
В приложении пример программы с исходным текстом, которая создает диалоговое окно с двумя субклассированными элементами: полем ввода для HEX-цифр и кнопкой, реагирующей на клик правой кнопкой мыши.
Просмотров: 1530 | Комментариев: 0
Метки: Assembler, полезные функции
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Комментариeв нет
Добавить комментарий
Заполните форму для добавления комментария