What does WPF use to capture mouse and keyboard input?
Asked Answered
P

2

17

I globally (system-wide) filter certain mouse clicks using SetWindowsHookEx and WH_MOUSE_LL. The problem is it doesn't work for WPF applications (all WPF applications detect mouse clicks whether or not I have instructed the system to ignore these clicks). I've already asked a similar question here, but I made an assumption that WPF uses DirectInput instead of standard Windows messages for detecting the input. But does it?

I've been able to find a code that was able to inject mouse clicks into WPF applications using SendMessage. If that's possible, then I think it somehow means WPF does not use DirectInput for mouse input. But then, why it's not possible to prevent WPF applications from detecting mouse clicks with SetWindowsHookEx?

Although this question is mainly about the mouse input, I would also like to know how it works for keyboard input as well.

Example

I've quickly created the following solution to reproduce the odd WPF behavior. It consists of 3 projects:

  • HookTester
    StartUp project, automatically launches other 2 projects, so you should be mainly concerned about this one. Installs mouse hook when launched, and uninstalls the hook when you close the form.

  • WinFormsTest
    Contains a TextBox with default context menu where you can test the right mouse button. When the HookTester is running, you should not be able invoke the context menu using right mouse button.

  • WpfTest
    Contains a TextBox as well, with custom context menu (although I could use default menu as well), so this is again the place to test right mouse button. You should not be able to invoke the context menu (using right mouse button) as long as HookTester is running, but for some reason, the menu will be showed anyway (Why???).

WARNING: When you run the solution, the HookTester project will start and will immediately install the hook to reject any right-buttom mouse clicks (system-wide). You can easily uninstall the hook simply by closing the HookTester form. Test with caution.

Download SO5036143.ZIP: mirror 1, mirror 2

Plasticize answered 17/2, 2011 at 23:47 Comment(0)
G
11
  • WPF Window creates HwndSource (Window.CreateSourceWindow).
  • HwndSource creates HwndWrapper (HwndSource.Initialize).
  • HwndWrapper creates Win32 window with window procedure that delegate Windows messages to hooks, specified by HwndSource.
  • One hook is the HwndSource.InputFilterMessage that delegate Windows messages to four input providers: stylus, mouse, keyboard, appcommand.
  • Provider parses appropriate Windows message and invokes InputManager to raise input events on elements.

HwndMouseInputProvider process messages such as WM_MOUSEMOVE, WM_LBUTTONDOWN, etc. So I think there is no DirectInput used to handle mouse and keyboard input.

Giffin answered 1/3, 2011 at 19:16 Comment(9)
Thanks, great info! But how is it possible low level hooks do not work when WPF uses wrappers around standard windows messages? It works great in any non-WPF applications, but the apps using WPF do not behave as expected (I can correctly detect mouse events in a WPF application, but I can't cancel that event, even though it works in any other non-WPF application).Plasticize
Maybe you should post an example? By the way, if you want to manage WPF input, you should look at the InputManager class.Giffin
Well, I have my application, and I need to manage input for every single running application on the computer, regardless if they use WPF or Win32 UI. I believe hooks are the best solution for this scenario. I will post some example to reproduce the behavior soon.Plasticize
@Marat Khasanov: I've updated the question with example project. Could you please take a look?Plasticize
Thanks. I found that your constant value for WM_RBUTTONUP is wrong. It should be 0x205. And there will be no context menu in WPF application ;)Giffin
Ah, thanks. I've quickly created that example, so in rush I've missed that (I use different class with correct WM_RBUTTONUP for development). I've done further testing and have discovered where the problem lies - I use computer with stylus for development, and I thought system just translates stylus input into mouse messages and that's it (for stylus-unaware apps). So it works correctly with standard Win32 app (stylus right click does nothing), but WPF apps are still able to detect that click, because they are stylus-aware (didn't know that). So now I need something like low level stylus hook.Plasticize
But that's probably for a different question ... unless you are aware that something like that already exists? Is it possible to achieve what I'm trying to do? Block right-click in all applications regardless if it comes from mouse or stylus?Plasticize
Unfortunately, I never worked with stylus and have no touch screen to test WPF stylus behavior. But I can tell you that it is very interesting how it works! HwndStylusInputProvider handles only WM_TABLET_FLICK and WM_TABLET_QUERYSYSTEMGESTURESTATUS and raises no events. There is another class called PenThreadWorker. It launches a new thread called "Stylus Input". This thread queries input events using GetPenEvent and GetPenEventMultiple functions from native DLL called "penimc.dll". Then it fires Stylus events corresponding to interop result.Giffin
Thanks! That's quite interesting! But hooking this kind of mechanism will probably be very tricky.Plasticize
T
1

Even if you try to set filter, .NET Framework may have some undocumented API to put WPF's filter on high priority not allowing your filter to execute at all in order to make sure WPF works correctly.

WPF windows are same as normal window and they are supposed to work correctly with pre-existing input APIs as well as new APIs in order to make WPF work with remote desktop and other such software.

Update:

Windows Hook were provided in earlier windows API because that time the concepts like Event Bubbling and Preview of events were not available and for such implementations hooks were useful. WPF already provides event filtering with Preview events and bubbling of events, and that is the reason hooks may not be supported.

Hooks are not very standard part of API because only very few applications use them. May be you can post bug at Microsoft that their filter is not allowing your hook filter.

Towhee answered 27/2, 2011 at 8:10 Comment(2)
If it's supposed to work correctly with pre-existing input APIs, then I think it should allow my app to filter the input using hooks, because that's the expected behavior of a standard windows. Anyway, that's what this question is about - to determine what WPF is using, and when I know that information, I can arrange my app to properly filter the input in other WPF applications (using drivers, API hooking, etc).Plasticize
+1, thanks for the info, however my question remains unanswered - I still want to know what WPF uses for input handling, because there still might be some workaround which will allow me to achieve what I need.Plasticize

© 2022 - 2024 — McMap. All rights reserved.