Имя Пароль
Зарегистрироваться


* При перепечатке материалов ссылка на www.SeoLiga.ru обязательна! RSS



Сабклассинг
19 февраля 2009

Сабклассинг (subclassing) - контроль сообщений окон путем модификации (взятия под контроль) оконной процедуры последних. Сабклассинг подразумевает использование изменённой оконной процедуры до оригинальной, что позволяет нам создать сколь угодно заготовок оконных процедур. Хотя на практике обычно используется только одна.
Оконная процедура

Оконная процедура (window procedure) - специальная функция любого окна, имеющего дескриптор, которая принимает и обрабатывает все поступающие окну сообщения (от других программ или от Windows). Оконная процедура является косвенно вызываемой (callback) пользовательской (user-defined) функцией. Соответственно, реакцию на сообщения задаёт программист.

Оконная процедура - самое существенное из всего того, что принадлежит окну, поэтому сабклассинг является очень мощной технологией, необходимой для полноценной работы с Windows API. Важно уметь правильно обрабатывать сообщения, чтобы использовать сабклассинг.

Оконная процедура обычно назначается при создании окна, когда заполняется структура класса последнего TWndClass(Ex).

Оконная процедура имеет такой прототип:
код Pascal/Delphi

Function XWindowProc(HWnd: THandle; Msg: Cardinal;
WParam, LParam: Integer): Integer; Stdcall;

Где X - любой префикс (можно и опустить), по которому можно идентифицировать
нужную оконную процедуру (например, Edit или New).

Рассмотрим, какие параметры передаются при вызове оконной процедуры. В параметреHWnd передаётся дескриптор окна, классу которого принадлежит оконная процедура. В параметре Msg передаётся идентификатор поступившего сообщения. В параметрах WParamи LParam передаётся дополнительная информация, которая зависит от типа посланного сообщения.

Возвращаемый функцией результат должен определить программист.

Рекомендуется обрабатывать сообщения через оператор Case:
код Pascal/Delphi

Case Msg Of
WM_DESTROY:
End;

Для игнорирования сообщения необходимо осуществить выход из блока Case:
код Pascal/Delphi

Case Msg Of
WM_CLOSE: Exit;
End;

Этот способ также применяется для того, чтобы функция DefWindowProc не обрабатывала сообщение.

Для вызова оконной процедуры по её адресу используется функция CallWindowProc. По параметрам она аналогична любой оконной процедуре, но помимо этого она имеет еще один параметр, определяющий адрес требуемой оконной процедуры для вызова (параметр первый).
код Pascal/Delphi
...
{ Тип первого параметра представляет собой простой указатель }
TFarProc = Pointer;
TFNWndProc = TFarProc;
...
Function CallWindowProc(lpPrevWndFunc: TFNWndProc; HWnd: HWND; Msg: Cardinal;
WParam: Integer; LParam: Integer): Integer; Stdcall;

Функция CallWindowProc позволяет нам, по сути, менять поведение окна, ведь мы можем сабклассировать его множество раз с сохранением адресов оконных процедур, а потом вызывать нужные оконные процедуры по надобности. Но на практике чаще всего эта функция используется для вызова одной оригинальной оконной процедуры окна, которая была до его сабклассирования.

После детального рассмотрения основ сабклассинга непосредственно перейдём к его реализации в Delphi.

Примечание: суперклассинг, как один из видов сабклассинга, будет описан далее отдельно!

Примечание: сабклассинг для окон, принадлежащих чужим процессам, в данной статье не рассматривается! В частности, для начинающих программистов он достаточно сложен.

Основная функция сабклассирования окна: SetWindowLong. Вообще, эта функция предназначена для изменения определённого аттрибута окна (функция может изменять аттрибут как самого окна, так и аттрибут его класса). Рассмотрим её параметры.

Объявление функции:
код Pascal/Delphi

Function SetWindowLong(HWnd: HWND; nIndex: Integer;
dwNewLong: LongInt): LongInt; Stdcall;

Параметр HWnd определяет окно, с которым будет производиться работа. Параметр nIndex определяет индекс аттрибута, который мы хотим изменить. Пока нас будут интересовать значения GWL_WNDPROC и GWL_USERDATA. Первый индекс определяет, что изменения затронут оконную процедуру окна, второй - то, что будет изменена специальная внутренняя четырёхбайтовая переменная, которой обладает каждое окно. В ней удобно хранить адрес старой оконной процедуры при сабклассинге.

Рассмотрим, как по шагам засабклассировать окно. :)
Создаём заготовку новой оконной процедуры;
Помещаем в переменную GWL_USERDATA адрес старой оконной процедуры;
Изменяем адрес оконной процедуры на новый.
Последние два действия можно объединить в одно, так как функция SetWindowLongвозвращает предыдущее значение изменённого параметра.

Далее я публикую примеры кода, в которых будут рассмотрены способы сабклассирования окон как средствами VCL, так и средствами WinAPI. Все примеры кода хорошо комментированы.


Теги: Borland Delphi

Статьи по теме:

Определение готовности сокета
Панель Debug
Общая тенденция развития систем делопроизводства и документооборота
SetRange
Исполнительные информационные системы (Executive Support System)
Свойство Brush
Информация о протоколе
Печать графики
Определение и типовые архитектуры хранилищ данных
Протокол TCP
Сервис сетевой печати
Неблокирующий режим
Инструментальные средства автоматизированного рабочего места
MMX и SSE2
Translate
| Borland Delphi | ext |
 


Пн Вт Ср Чт Пт Сб Вс
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30


     



Rambler's Top100

Данный сайт или домен продается ICQ: 403-353-727

© 2009 Seoliga.ru | Borland Delphi | Сабклассинг. Регион сайта: Москва и Санкт-Петербург