В каком потоке работает низкоуровневый обратный вызов мыши и клавиатуры? - PullRequest
8 голосов
/ 14 января 2010

Я устанавливаю низкоуровневый крючок для мыши с SetWindowsHookEx:

HANDLE handle = SetWindowsHookEx(WH_MOUSE_LL, 
                                 &callback, 
                                 GetModuleHandle(NULL), 
                                 NULL);

Поскольку это обратный вызов низкого уровня, он будет выполняться внутри моего собственного процесса; DLL-инъекция не выполняется.

Теперь я заметил, что обратный вызов иногда (косвенно) вызывается из стандартных функций API, таких как GetAncestor, GetWindowRect и тому подобное. Похоже, это может привести к сбросу очереди сообщений.

На самом деле, мой вопрос тройной ...

  1. Когда вызывается обратный вызов?

    Может ли она вызываться изнутри любой API-функции? Как мне сказать?

  2. В каком потоке выполняется обратный вызов?

    Будет ли он выполняться только в потоке, который установил хук, или система может вызвать его в любом потоке?

  3. Почему хуки реализованы как обратный вызов?

    (Рэймонд Чен тут болтается?) Мне бы показалось более разумным реализовывать перехватчики просто как (отправленные) сообщения, как и почти все остальные компоненты Windows. Для сообщений, по крайней мере, я знаю, какие функции могут вызвать обработку ожидающих отправленных сообщений (GetMessage, PeekMessage и несколько других), и я бы знал, в каком потоке они обрабатываются (поток, который получил сообщение в первое место).

1 Ответ

9 голосов
/ 15 января 2010
  1. См. 3.

  2. Это довольно четко написано в документации :

    [...] Однако хук WH_MOUSE_LL не внедряется в другой процесс. Вместо этого контекст переключается обратно на процесс, который установил хук, и он вызывается в своем первоначальном контексте. Затем контекст переключается обратно на приложение, которое сгенерировало событие. [...] Этот хук вызывается в контексте потока, который его установил.

  3. На самом деле это реализовано так:

    [...] Вызов осуществляется путем отправки сообщения в поток, который установил ловушку. Поэтому поток, который установил ловушку, должен иметь цикл сообщений.

AFAIK, когда ваш хук должен вызываться, Windows помещает специальное сообщение в очередь сообщений вашего потока. Ваш код в насосе сообщений вызывает Peek / GetMessage, который проверяет, является ли это специальное сообщение, и, если это так, вызывает вашу процедуру подключения (некоторые доказательства здесь , откуда я взял изображение). Стек вызовов диспетчеризации вызовов http://cboard.cprogramming.com/attachments/windows-programming/9323d1253895425-setwindowshookex-lowlevelmouseproc-hook-callback-callstack-png

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