Обзор перехватчиков

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

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

  • Мониторинг сообщений для целей отладки
  • Поддержка записи и воспроизведения макросов
  • Предоставление поддержки ключа справки (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. Дополнительные сведения см. в разделе Библиотеки динамической компоновки.

Примечание

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

 

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

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

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 TextInput.

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

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

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

WH_JOURNALRECORD

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

API обработчиков журналов не поддерживаются начиная с Windows 11 и будут удалены в будущем выпуске. Поэтому мы настоятельно рекомендуем вместо этого вызывать API 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 позволяют выполнять фильтрацию сообщений во время модальных циклов, что эквивалентно фильтрации в цикле сообщений main. Например, приложение часто проверяет новое сообщение в цикле main между временем извлечения сообщения из очереди и временем отправки сообщения, выполняя специальную обработку соответствующим образом. Однако во время модального цикла система получает и отправляет сообщения, не позволяя приложению фильтровать сообщения в цикле сообщений main. Если приложение устанавливает процедуру перехватчика WH_MSGFILTER или WH_SYSMSGFILTER , система вызывает процедуру во время модального цикла.

Приложение может вызвать обработчик WH_MSGFILTER напрямую, вызвав функцию CallMsgFilter . С помощью этой функции приложение может использовать тот же код для фильтрации сообщений во время модальных циклов, как и в цикле сообщений main. Для этого инкапсулируете операции фильтрации в процедуре перехватчика 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 .