Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disabling Touch Screen Mouse Device events Using setwindowshookex (user32.dll)

I have a WPF C# Application. I have dual screens, and I want to cancel the mouse event on one of the screens, since it is a touch screen and it takes the focus off the main screen when ever a user presses it. I want to enable touch only when asking for data from the user, and then block it.

I have found some good examples about application hooks using user32.dll, which helps me to catch the devices input. One example shows here: http://www.pinvoke.net/default.aspx/user32.setwindowshookex . And another, that is more suitable for mouse events can be show here: How to avoid mouse move on Touch

My problem is not with catching the device input, but with disabling it. The first example above shows how to catch keyboard inputs and extract the key-pressed, but not disabling it.

The second example does not work as well. It catches both mouse events, the regular usb-mouse device and the touch screen device. I can tell which is which, but I can't cancel the touch-screen device. In the example, a new IntPtr(1); is returned for the touch device. This does nothing to the device input.

On the other hand, when I do the opposite, meaning returning new IntPtr(1); on every mouse event BUT the touch event, it seems my regular mouse does not move at all (while the touch device mouse does move).

This method can help block the regular mouse, but not the touch mouse, as no code I return will block this mouse (I do find this mouse and return a code, I checked that many times, The code does nothing though).

Here Is My Code Based on the examples above:

   static readonly LowLevelMouseProc hookCallback = HookCallback;
        static IntPtr hookId = IntPtr.Zero;

        public DisableTouchConversionToMouse()
        {
            hookId = SetHook(hookCallback);
        }

        static IntPtr SetHook(LowLevelMouseProc proc)
        {
            var moduleHandle = UnsafeNativeMethods.GetModuleHandle(null);

            var setHookResult = UnsafeNativeMethods.SetWindowsHookEx(HookType.WH_MOUSE_LL, 
proc, moduleHandle, 0);
            if (setHookResult == IntPtr.Zero)
            {
                throw new Win32Exception();
            }
            return setHookResult;
        }

        delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

        static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {

            if (nCode >= 0)
            {
                var info = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));

                var extraInfo = (uint)info.dwExtraInfo.ToInt32();

               // if ((extraInfo & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH)
                if (extraInfo>0)
                {
               Console.WriteLine("TOUCH SCREEN FOUND!");
                    return new IntPtr(1);
                }
            }

            return UnsafeNativeMethods.CallNextHookEx(hookId, nCode, wParam, lParam);
        }
   public enum HookType : int
        {
            WH_JOURNALRECORD = 0,
            WH_JOURNALPLAYBACK = 1,
            WH_KEYBOARD = 2,
            WH_GETMESSAGE = 3,
            WH_CALLWNDPROC = 4,
            WH_CBT = 5,
            WH_SYSMSGFILTER = 6,
            WH_MOUSE = 7,
            WH_HARDWARE = 8,
            WH_DEBUG = 9,
            WH_SHELL = 10,
            WH_FOREGROUNDIDLE = 11,
            WH_CALLWNDPROCRET = 12,
            WH_KEYBOARD_LL = 13,
            WH_MOUSE_LL = 14
        }

        [StructLayout(LayoutKind.Sequential)]
        struct POINT
        {

            public int x;
            public int y;
        }

        [StructLayout(LayoutKind.Sequential)]
        struct MSLLHOOKSTRUCT
        {
            public POINT pt;
            public uint mouseData;
            public uint flags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        [SuppressUnmanagedCodeSecurity]
        static class UnsafeNativeMethods
        {
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern IntPtr SetWindowsHookEx(HookType code, LowLevelMouseProc lpfn, IntPtr hMod,
                uint dwThreadId);

            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool UnhookWindowsHookEx(IntPtr hhk);

            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
                IntPtr wParam, IntPtr lParam);

            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern IntPtr GetModuleHandle(string lpModuleName);
        }
like image 278
Programer Avatar asked May 23 '13 07:05

Programer


1 Answers

If your main aim is to avoid the focus being moved from your main window then there's a simpler workaround using WS_EX_NOACTIVATE

see: Not take focus, but allow interaction?

like image 62
user2466466 Avatar answered Oct 15 '22 12:10

user2466466