Что WPF использует для захвата ввода с клавиатуры и мыши?

Я глобально (общесистемный) фильтрую определенные щелчки мыши, используя SetWindowsHookEx а также WH_MOUSE_LL, Проблема в том, что он не работает для приложений WPF (все приложения WPF обнаруживают щелчки мышью, независимо от того, приказал ли я системе игнорировать эти щелчки). Я уже задавал подобный вопрос здесь, но я предположил, что WPF использует DirectInput вместо стандартных сообщений Windows для обнаружения ввода. Но так ли это?

Мне удалось найти код, который был способен вводить щелчки мыши в приложениях WPF, используяSendMessage, Если это возможно, то я думаю, что это как-то означает, что WPF не использует DirectInput для ввода мышью. Но почему же приложения WPF не могут обнаружить щелчки мышью с помощью SetWindowsHookEx?

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

пример

Я быстро создал следующее решение для воспроизведения странного поведения WPF. Он состоит из 3 проектов:

  • HookTester
    StartUp project, автоматически запускает 2 других проекта, так что вы должны быть в основном обеспокоены этим. Устанавливает ловушку мыши при запуске и удаляет ловушку при закрытии формы.

  • WinFormsTest
    Содержит TextBox с контекстным меню по умолчанию, где вы можете проверить правую кнопку мыши. Когда HookTester запущен, вы не сможете вызвать контекстное меню, используя правую кнопку мыши.

  • WpfTest
    Также содержит TextBox с пользовательским контекстным меню (хотя я мог бы также использовать меню по умолчанию), так что это снова место для проверки правой кнопки мыши. Вы не сможете вызывать контекстное меню (используя правую кнопку мыши), пока работает HookTester, но по какой-то причине меню все равно будет отображаться (почему???).

ВНИМАНИЕ: Когда вы запустите решение, запустится проект HookTester, и он немедленно установит хук, чтобы отклонить любые щелчки правой кнопкой мыши (по всей системе). Вы можете легко удалить крюк, просто закрыв форму HookTester. Проверьте с осторожностью.

Скачать SO5036143.ZIP: зеркало 1, зеркало 2

2 ответа

Решение
  • WPF Window создает HwndSource (Window.CreateSourceWindow).
  • HwndSource создает HwndWrapper (HwndSource.Initialize).
  • HwndWrapper создает окно Win32 с процедурой окна, которая делегирует сообщения Windows хукам, указанным HwndSource.
  • Одним из способов является HwndSource.InputFilterMessage, который делегирует сообщения Windows четырем поставщикам ввода: стилус, мышь, клавиатура, команда приложения.
  • Поставщик анализирует соответствующее сообщение Windows и вызывает InputManager, чтобы вызвать события ввода для элементов.

HwndMouseInputProvider обрабатывает сообщения, такие как WM_MOUSEMOVE, WM_LBUTTONDOWN и т. Д. Поэтому я думаю, что нет DirectInput, используемого для обработки ввода с помощью мыши и клавиатуры.

Даже если вы попытаетесь установить фильтр, в.NET Framework может быть какой-то недокументированный API, чтобы поставить фильтр WPF с высоким приоритетом, не позволяя вашему фильтру работать вообще, чтобы убедиться, что WPF работает правильно.

Окна WPF такие же, как обычные окна, и они должны корректно работать с уже существующими API ввода, а также с новыми API, чтобы заставить WPF работать с удаленным рабочим столом и другим подобным программным обеспечением.

Обновить:

Хук Windows был предоставлен в более ранних версиях Windows API, потому что в то время такие понятия, как Event Bubbling и Preview событий, были недоступны, и для таких реализаций хуки были полезны. В WPF уже предусмотрена фильтрация событий с предварительным просмотром и всплывающими событиями, поэтому перехватчики могут не поддерживаться.

Хуки не являются стандартной частью API, потому что их используют лишь очень немногие приложения. Может быть, вы можете отправить сообщение об ошибке в Microsoft, что их фильтр не позволяет использовать фильтр хуков.

Другие вопросы по тегам