我有一个WPF应用程序,既可以使用鼠标又可以使用Touch。我禁用所有窗口“增强功能”以仅具有触摸事件:
Stylus.IsPressAndHoldEnabled="False"
Stylus.IsTapFeedbackEnabled="False"
Stylus.IsTouchFeedbackEnabled="False"
Stylus.IsFlicksEnabled="False"
结果是,单击行为与我想要的一样,但有两点:
两者都是以下事实的结果:在窗口正确传输触摸事件的同时,他仍将鼠标移至最后一个主触摸事件。
当我在应用程序内部使用touch时,我根本不希望Windows完全移动鼠标。有没有一种方法可以完全避免这种情况?
笔记:
最佳答案
这是我从现在开始发现的最佳解决方案。不要犹豫,发表自己的文章,特别是如果它更好。
使用 SetWindowsHookEx
低级鼠标事件捕获(WH_MOUSE_LL
)以及将所有从Touch转换为Mouse的事件都标记为这样的事实(在事件的ExtraInfo中设置了MOUSEEVENTF_FROMTOUCH
标志,请参阅Microsoft's FAQ),我能够全局删除所有鼠标事件来自触摸面板。
这不是一个理想的解决方案,但是当它以全屏模式运行时(在99%的时间中它是专用的硬件设备),它将在我的应用程序中实现。
第二步也仅在全屏模式下很好(我不会提供代码,因为它非常简单),只是将鼠标移到“安全”位置,如 SetCursorPos
在屏幕的右下角。
如果您需要代码,则在a Gist on Github中,我将在本文末尾发布当前版本。要使用它:
// As long as the instance is alive the conversion won't occur
var disableTouchMouse = new DisableTouchConversionToMouse();
// To let the conversion happen again, Dispose the class.
disableTouchMouse.Dispose();
该类的完整源代码:
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_MASK) == MOUSEEVENTF_FROMTOUCH)
{
if((extraInfo & 0x80) != 0)
{
//Touch Input
return new IntPtr(1);
}
else
{
//Pen Input
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_MASK = 0xFFFFFF00;
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
}
}
编辑:从Troubleshooting Applications和System Events and Mouse Messages的注释部分,可以消除笔触的歧义。
关于c# - 如何避免鼠标在Touch上移动,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8010104/