Created
November 4, 2011 15:54
-
-
Save vbfox/1339671 to your computer and use it in GitHub Desktop.
Globally disable the conversion of touch events to mouse events in Windows 7
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace BlackFox | |
{ | |
using System; | |
using System.ComponentModel; | |
using System.Runtime.InteropServices; | |
using System.Security; | |
/// <summary> | |
/// As long as this object exists all mouse events created from a touch event for legacy support will be disabled. | |
/// </summary> | |
class DisableTouchConversionToMouse : IDisposable | |
{ | |
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(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) | |
{ | |
return new IntPtr(1); | |
} | |
} | |
return UnsafeNativeMethods.CallNextHookEx(hookId, nCode, wParam, lParam); | |
} | |
bool disposed; | |
public void Dispose() | |
{ | |
if (disposed) return; | |
UnsafeNativeMethods.UnhookWindowsHookEx(hookId); | |
disposed = true; | |
GC.SuppressFinalize(this); | |
} | |
~DisableTouchConversionToMouse() | |
{ | |
Dispose(); | |
} | |
#region Interop | |
// ReSharper disable InconsistentNaming | |
// ReSharper disable MemberCanBePrivate.Local | |
// ReSharper disable FieldCanBeMadeReadOnly.Local | |
const uint MOUSEEVENTF_FROMTOUCH = 0xFF515700; | |
const int 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(int idHook, 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); | |
} | |
// ReSharper restore InconsistentNaming | |
// ReSharper restore FieldCanBeMadeReadOnly.Local | |
// ReSharper restore MemberCanBePrivate.Local | |
#endregion | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
From what I can tell (running under Windows 7), touch-events converted to mouse-events are NOT reported under
WH_MOUSE_LL
, but instead are reported underWH_MOUSE
. So I modified this code to hook into both types of events, and returnnew IntPtr(1)
when a mouse-event created from a touch-event has been detected. Unfortunately, the system cursor is still moved to the position of the last touch. (My goal is similar to @tavoe; I want to allow one user to interact with a window using touch, and another user to interact with a different window using the mouse, on the same computer.)Also, the call to
ToInt32()
on line 41 will break in a 64-bit process. One should test whetherIntPtr.Size
is 4 or 8, and if the latter, callToInt64()
instead.I've forked this gist & submitted my changes.