Поделиться через


Обзор хуков

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

В следующем приведены некоторые примеры использования хуков:

  • Мониторинг сообщений для целей отладки
  • Поддержка записи и воспроизведения макросов
  • Поддержка клавиши помощи (F1)
  • Имитация ввода мыши и клавиатуры
  • Реализация приложения для обучения на основе компьютеров (CBT)

Заметка

Перехватчики, как правило, замедляют работу системы, так как увеличивают объем обработки, который система должна выполнить для каждого сообщения. Установите крючок только при необходимости и удалите его как можно скорее.

 

В этом разделе рассматривается следующее:

Цепи с крючьями

Система поддерживает множество различных типов перехватчиков; каждый тип предоставляет доступ к другому аспекту механизма обработки сообщений. Например, приложение может использовать WH_MOUSE хук для мониторинга сообщений мышиного трафика.

Система поддерживает отдельную цепочку перехватчиков для каждого типа крючка. цепочка перехватчиков — это список указателей на специальные, определяемые приложением функции обратного вызова, называемые процедуры перехватчика. При возникновении сообщения, связанного с определенным типом перехватчика, система передает сообщение каждой процедуре перехватчика, на которую ссылается цепочка перехватчиков, одна после другой. Действие, которое может выполнить процедура перехвата, зависит от типа перехвата. Процедуры перехвата для некоторых типов крючков могут только отслеживать сообщения; другие могут изменять сообщения или останавливать их продвижение по цепочке, предотвращая их достижение следующей процедуры перехвата или конечного окна.

Процедуры перехватчика

Чтобы воспользоваться определенным типом крючка, разработчик предоставляет процедуру крючка и использует функцию SetWindowsHookEx для его установки в цепочку, связанную с этим крючком. Процедура перехватчика должна иметь следующий синтаксис:

LRESULT CALLBACK HookProc(
  int nCode, 
  WPARAM wParam, 
  LPARAM lParam
)
{
   // process event
   ...

   return CallNextHookEx(NULL, nCode, wParam, lParam);
}

HookProc является заполнителем для определяемого приложением имени.

Параметр nCode — это код перехвата, который используется процедурой перехвата для определения действия, которое следует выполнить. Значение кода хука зависит от его типа; каждый тип имеет собственный набор кодов. Значения wParam и lParam зависят от кода перехватчика, но обычно содержат сведения о отправленном или размещенном сообщении.

Функция SetWindowsHookEx всегда устанавливает перехватывающую процедуру в начале цепи перехватчиков. При возникновении события, отслеживаемого определенным типом перехватчика, система вызывает процедуру в начале цепочки перехватчиков, связанной с перехватчиком. Каждая процедура обработчика в цепочке определяет, следует ли передать событие в следующую процедуру. Процедура перехватчика передает событие следующей процедуре, вызывая функцию CallNextHookEx.

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

глобальный хук отслеживает сообщения для всех потоков на том же рабочем столе, что и вызывающий поток. перехватчик для конкретного потока отслеживает сообщения только для отдельного потока. Глобальная процедура хука может вызываться в контексте любого приложения на том же рабочем столе, что и вызывающий поток, поэтому процедура должна находиться в отдельном модуле DLL. Процедура привязки для конкретного потока вызывается только в контексте связанного потока. Если приложение устанавливает процедуру перехватчика для одного из своих собственных потоков, процедура перехватчика может находиться в том же модуле, что и остальная часть кода приложения или в библиотеке DLL. Если приложение устанавливает процедуру-хука для потока другого приложения, эта процедура должна находиться в библиотеке DLL. Дополнительные сведения см. в Dynamic-Link библиотеках.

Заметка

Глобальные перехватчики следует использовать только для отладки; в противном случае их следует избегать. Глобальные перехватчики негативно влияют на производительность системы и вызывают конфликты с другими приложениями, которые используют тот же тип глобального перехватчика.

 

Типы перехватчиков

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

WH_CALLWNDPROC и WH_CALLWNDPROCRET

Перехватчики WH_CALLWNDPROC и WH_CALLWNDPROCRET позволяют вам отслеживать сообщения, отправляемые в оконные процедуры. Система вызывает хук-процедуру WH_CALLWNDPROC перед передачей сообщения в процедуру окна-получателя и вызывает хук-процедуру WH_CALLWNDPROCRET после того, как процедура окна прошла обработку сообщения.

WH_CALLWNDPROCRET перехватчик передает указатель на CWPRETSTRUCT структуру в процедуру перехватчика. Структура содержит возвращаемое значение из процедуры окна, обрабатывающей сообщение, а также параметры сообщения, связанные с сообщением. Подклассы окна не работают для сообщений, заданных между процессами.

Дополнительную информацию см. в функциях обратного вызова CallWndProc и CallWndRetProc.

WH_CBT

Система вызывает процедуру перехватчика WH_CBT перед активацией, созданием, уничтожением, минимизацией, максимизированием, перемещением или изменением размера окна; перед выполнением системной команды; перед удалением события мыши или клавиатуры из очереди системных сообщений; перед настройкой фокуса ввода; или перед синхронизацией с системной очередью сообщений. Возвращаемое значение процедуры перехватчика определяет, разрешает ли система выполнение одной из этих операций или предотвращает её. WH_CBT крючок предназначен в первую очередь для приложений, связанных с компьютерным обучением (CBT).

Дополнительные сведения см. в функции обратного вызова CBTProc.

Дополнительные сведения см. в разделе WinEvents.

WH_DEBUG

Система вызывает процедуру WH_DEBUG перехвата перед вызовом процедур перехвата, связанных с любым другим перехватчиком в системе. Этот хук можно использовать для определения того, разрешать ли системе выполнять процедуры, связанные с другими типами хуков.

Для получения дополнительной информации см. функцию обратного вызова DebugProc.

WH_FOREGROUNDIDLE

Хук WH_FOREGROUNDIDLE позволяет выполнять низкоприоритетные задачи, когда поток переднего плана простаивает. Система вызывает процедуру WH_FOREGROUNDIDLE перехватчика, когда поток переднего плана приложения будет неактивен.

Дополнительные сведения см. в функции обратного вызова ForegroundIdleProc.

WH_GETMESSAGE

Перехватчик WH_GETMESSAGE позволяет приложению отслеживать сообщения, которые должны быть возвращены функцией GetMessage или PeekMessage. Вы можете использовать WH_GETMESSAGE перехватчик для отслеживания ввода мыши и клавиатуры и других сообщений, попавших в очередь сообщений.

Дополнительные сведения см. в функции обратного вызова GetMsgProc.

WH_JOURNALPLAYBACK

Предупреждение

API журналирования не поддерживаются начиная с Windows 11 и будут удалены в одном из будущих выпусков. Из-за этого мы настоятельно рекомендуем вместо этого вызывать API SendInput SendInput TextInput.

Хук WH_JOURNALPLAYBACK предоставляет приложению возможность вставлять сообщения в системную очередь сообщений. Этот крючок можно использовать для воспроизведения ряда событий мыши и клавиатуры, записанных ранее с помощью WH_JOURNALRECORD. Обычные входные данные мыши и клавиатуры отключены, пока установлен WH_JOURNALPLAYBACK крючок. WH_JOURNALPLAYBACK крючок — это глобальный крючок— его нельзя использовать в качестве цепочки для конкретного крючка.

WH_JOURNALPLAYBACK хук возвращает значение времени ожидания. Это значение указывает системе, сколько миллисекунд ждать перед обработкой текущего сообщения из перехватчика воспроизведения. Это позволяет перехватчику управлять временем воспроизведения событий.

Дополнительные сведения см. в функции обратного вызова JournalPlaybackProc .

WH_JOURNALRECORD

Предупреждение

API журналирования не поддерживаются начиная с Windows 11 и будут удалены в одном из будущих выпусков. Из-за этого мы настоятельно рекомендуем вместо этого вызывать API SendInput SendInput TextInput.

Перехватчик WH_JOURNALRECORD позволяет отслеживать и записывать входные события. Обычно этот перехватчик используется для записи последовательности событий мыши и клавиатуры для воспроизведения позже с помощью WH_JOURNALPLAYBACK. WH_JOURNALRECORD хук является глобальным хук — его нельзя использовать как специфичный для потока хук.

Для получения дополнительной информации см. функцию обратного вызова JournalRecordProc.

WH_KEYBOARD_LL

Перехватчик WH_KEYBOARD_LL позволяет отслеживать события ввода клавиатуры, которые собираются быть размещены в очереди ввода потока.

Дополнительные сведения см. в функции обратного вызова LowLevelKeyboardProc.

WH_KEYBOARD

Перехватчик WH_KEYBOARD позволяет приложению отслеживать поток сообщений для WM_KEYDOWN и WM_KEYUP, которые должны быть возвращены функцией GetMessage или PeekMessage. Вы можете использовать перехватчик WH_KEYBOARD для отслеживания ввода с клавиатуры, поступающего в очередь сообщений.

Дополнительные сведения см. в функции обратного вызова KeyboardProc.

WH_MOUSE_LL

Перехватчик WH_MOUSE_LL позволяет отслеживать события ввода мыши, которые будут размещаться в очереди ввода потока.

Дополнительные сведения см. в функции обратного вызова LowLevelMouseProc.

WH_MOUSE

Перехватчик WH_MOUSE позволяет отслеживать сообщения мыши, возвращаемые функцией GetMessage или PeekMessage. С помощью перехватчика WH_MOUSE можно мониторить входные данные мыши, размещенные в очереди сообщений.

Дополнительные сведения см. в функции MouseProcобратного вызова.

WH_MSGFILTER и WH_SYSMSGFILTER

Перехватчики WH_MSGFILTER и WH_SYSMSGFILTER позволяют отслеживать сообщения, которые будут обрабатываться меню, полосой прокрутки, окном сообщения или диалоговым окном, а также определять, когда другое окно будет активировано в результате нажатия клавиш ALT+TAB или ALT+ESC. Перехватчик WH_MSGFILTER может отслеживать только сообщения, передаваемые в меню, полосу прокрутки, окно сообщения или диалоговое окно, созданное приложением, которое установило процедуру перехватчика. WH_SYSMSGFILTER перехватчик отслеживает такие сообщения для всех приложений.

Перехватчики WH_MSGFILTER и WH_SYSMSGFILTER позволяют выполнять фильтрацию сообщений во время модальных циклов, подобно фильтрации, выполняемой в основном цикле сообщений. Например, приложение часто проверяет новое сообщение в основном цикле между временем, когда оно извлекает сообщение из очереди и время отправки сообщения, выполняя специальную обработку соответствующим образом. Однако во время модального цикла система извлекает и отправляет сообщения, не позволяя приложению фильтровать сообщения в основном цикле сообщений. Если приложение устанавливает перехватчик WH_MSGFILTER или WH_SYSMSGFILTER, система вызывает процедуру во время модального цикла.

Приложение может вызвать перехватчик WH_MSGFILTER напрямую, используя функцию CallMsgFilter. С помощью этой функции приложение может использовать тот же код для фильтрации сообщений во время модальных циклов, как и в основном цикле сообщений. Для этого инкапсулируйте операции фильтрации в процедуре перехватчика WH_MSGFILTER и вызовите CallMsgFilter между вызовами GetMessage и DispatchMessage.

while (GetMessage(&msg, (HWND) NULL, 0, 0)) 
{ 
    if (!CallMsgFilter(&qmsg, 0)) 
        DispatchMessage(&qmsg); 
} 

Последний аргумент CallMsgFilter просто передается в процедуру перехватчика; можно ввести любое значение. Процедура перехватчика, задавая константу, такую как MSGF_MAINLOOP, может использовать это значение, чтобы определить, из какого контекста была вызвана процедура.

Для получения дополнительной информации см. функции обратного вызова MessageProc и SysMsgProc.

WH_SHELL

Приложение оболочки может использовать хук WH_SHELL, чтобы получать важные уведомления. Система вызывает процедуру перехвата WH_SHELL, когда приложение оболочки готовится к активации и когда создается или уничтожается окно верхнего уровня.

Обратите внимание, что настраиваемые оболочечные приложения не получают WH_SHELL сообщения. Поэтому любое приложение, которое регистрируется в качестве оболочки по умолчанию, должно вызывать функцию SystemParametersInfo, прежде чем оно (или любое другое приложение) сможет получать сообщения WH_SHELL. Эта функция должна вызываться с SPI_SETMINIMIZEDMETRICS и структурой MINIMIZEDMETRICS. Задайте для элемента iArrange этой структуры значение ARW_HIDE.

Смотрите функцию обратного вызова ShellProc для получения дополнительной информации.