Skip to content

Instantly share code, notes, and snippets.

@vbfox
Created November 4, 2011 15:54
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save vbfox/1339671 to your computer and use it in GitHub Desktop.
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
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
}
}
@barak-nagar
Copy link

It does not seem to work for me. THe device is still moving the mouse around...
What seems to be the problem, is that It finds the touch event, but the touch device does not react to
"return new IntPtr(1);" altough the regular mouse is.

What Im trying to say is, that the code is running, but the Only mouse that get cancels is the Regular mouse and not the Touch mouse.
If I use "return new IntPtr(1);" ALWAYS no matter what, my regular mouse does not work at all but my touch screen mouse works all the time.

One may say that the hook is not being called for the touch screen device, but it does, as I print a message to console just before returning the "new IntPtr(1)" and I see this message whenever I use the touch-device, however, as said, the mouse moves as usual on return from that function.

I need a way to make the opposite!

How can i make this work?

@AleksLitynski
Copy link

I'm trying to allow multiple users to interact with my program at once. One may use the mouse while the others use the touch screen.

Windows seems to automatically jump the mouse to the first touch (as you have observed).

Your code seems perfect to prevent this behavior, but it doesn't seem to be working.

I can log out when a touch has or hasn't been simulated by the mouse, but I can't prevent it.

Any advise? Am I barking up the right tree?

@ulatekh
Copy link

ulatekh commented May 25, 2016

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 under WH_MOUSE. So I modified this code to hook into both types of events, and return new 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 whether IntPtr.Size is 4 or 8, and if the latter, call ToInt64() instead.

I've forked this gist & submitted my changes.

@SaveTheHuman5
Copy link

Same as @tavoe and @ulatekh

Windows seems to automatically jump the mouse to the first touch (as you have observed).

I want prevent that happen and cant find the way.

Somebody have some news about this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment