Программирование на Visual C++. Архив рассылки
Шрифт:
Хук | Имя статьи с описанием фильтрующей функции в SDK |
---|---|
WH_CALLWNDPROC | CallWndProc |
WH_CBT | CBTProc |
WH_DEBUG | DebugProc |
WH_GETMESSAGE | GetMsgProc |
WH_JOURNALRECORD | JournalRecordProc |
WH_JOURNALPLAYBACK | JournalPlaybackProc |
WH_SHELL | ShellProc |
WH_KEYBOARD | KeyboardProc |
WH_MOUSE | MouseProc |
WH_MSGFILTER | MessageProc |
WH_SYSMSGFILTER | SysMsgProc |
Когда хук уже установлен, Windows вызывает первую функцию в очереди, и на этом ее ответственность заканчивается. После этого функция ответственна за то, чтобы вызвать следующую функцию в цепочке. В Windows имеется функция CallNextHookEx для вызова следующего фильтра в очереди фильтров. CallNextHookEx принимает четыре параметра.
Первый параметр – это значение, возвращенное функцией SetWindowsHookEx. В настоящее время Windows игнорирует это значение, но в будущем это может измениться.
Следующие три параметра – nCode, wParam, и lParam – Windows передает дальше по цепочке функций.
Windows хранит в своих внутренних структурах цепочку фильтрующих функций и следит за тем, какая функция вызывается в настоящий момент. При вызове CallNextHookEx windows определяет следующую функцию в очереди и вызывает ее.
Иногда функции-фильтры могут не пожелать передать обработку события другим фильтрам в той же цепочке. В частности, когда хук позволяет функции отменить событие и функция решает так поступить, она не должна вызывать CallNextHookEx. Когда фильтрующая функция модифицирует сообщение, она может решить не передавать его остальным функциям, ожидающим в очереди.
Из-за того, что фильтры никак не сортируются при помещении их в очередь, вы не можете быть уверены, где находится ваша функция в любой момент времени кроме момента установки, когда ваша функция помещается в самое начало очереди. В результате, вы никогда не можете точно знать, что каждое событие в системе дойдет до вашего фильтра. Фильтрующая функция перед вашей функцией в цепочке – то есть функция, которая была установлена позже вашей – может не передать вам обработку события.
Фильтрующие функции с системной областью видимости должны быть реализованы в DLL. В Win16 было возможно (хотя и не рекомендовалось) установить системный хук, находящийся в приложении. Это не сработает в Win32. Ни в коем случае не устанавливайте глобальных фильтров, не находящихся
Фильтрующие функции для хуков с системной областью видимости должны быть готовы разделять свои данные между разными процессами, из которых они запускаются. Каждая DLL отображается в адресное пространство использующего ее клиентского процесса. Глобальные переменные в DLL будут таковыми лишь в пределах одного экземпляра приложения, если только они не будут находиться в разделяемом сегменте данных (shared data section). Например, библиотека HOOKSDLL.DLL в примере Hooks использует две глобальные переменные:
• Хэндл окна для отображения сообщений.
• Высоту строк текста в этом окне.
Для того, чтобы сделать эти данные общими для всех экземпляров библиотеки, HOOKSDLL помещает их в разделяемый сегмент данных. Для этого HOOKSDLL предпринимает следующие шаги:
• Использует директивы компилятора (pragma) для помещения данных в именованный сегмент данных. Заметьте, что при этом переменные должны быть обязательно инициализированы.
Добавляет блок SECTIONS в .DEF-файл библиотеки:
Создает .EXP-файл из .DEF-файла:
Прилинковывает получившийся файл HOOKSDLL.EXP:
Windows вызывает этот хук при каждом вызове функции SendMessage. Фильтрующей функции передается код хука, показывающий, была ли произведена посылка сообщения из текущего потока, а также указатель на структуру с информацией о сообщении.
Структура CWPSTRUCT описана следующим образом: