這是我從現在發現的最佳解決方案。不要猶豫,張貼你自己的,特別是如果它更好。
使用SetWindowsHookEx
低水平鼠標事件捕獲(WH_MOUSE_LL
),並從觸摸轉換成鼠標的所有事件都被標記爲這樣的事實(該MOUSEEVENTF_FROMTOUCH
標誌設置在事件的ExtraInfo,見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附加信息的評論部分,從觸摸筆歧義。
經過深入研究,似乎並不僅僅可以用於我的窗口,而是使用SetWindowsHookEx我可以在全球範圍內完成。我現在可以在我的應用全屏顯示時啓用此功能。當我有一些乾淨的東西時,我會發布解決方案。 –
如果有人(比如說來自微軟)碰巧有更好的解決方案,請隨時發佈。 –
我不知道你是否足夠,但你可以通過檢查是否(e.StylusDevice!= null)來發現是否觸摸了鼠標事件。 – Andreas