ฉันมีปัญหาเดียวกันและสามารถหาวิธีแก้ไขได้โดยใช้การไตร่ตรอง
ปัญหานี้เกิดจากการที่ WPF อัปเดตการจัดการอุปกรณ์แท็บเล็ตภายในเมื่อมีการส่งข้อความหน้าต่าง WM_TABLET_ADDED, WM_TABLET_REMOVED หรือ WM_DEVICECHANGED ถูกส่งไป (ดู .net Referencesource) เนื่องจากข้อความเหล่านี้อาจถูกสร้างขึ้นหรือไม่ขึ้นอยู่กับฮาร์ดแวร์ที่ใช้ วิธี DisableWPFTabletSupport ดั้งเดิมอาจเพียงพอหรือไม่
โซลูชันของฉันคือจัดการและซ่อนข้อความหน้าต่างทั้งสามนั้นจาก WPF นอกเหนือจากโค้ดต้นฉบับ:
class DisableWPFTouchAndStylus
{
private static void DisableWPFTabletSupport()
{
// Get a collection of the tablet devices for this window.
var devices = Tablet.TabletDevices;
if (devices.Count > 0)
{
// Get the Type of InputManager.
var inputManagerType = typeof(InputManager);
// Call the StylusLogic method on the InputManager.Current instance.
var stylusLogic = inputManagerType.InvokeMember("StylusLogic",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, InputManager.Current, null);
if (stylusLogic != null)
{
// Get the type of the stylusLogic returned from the call to StylusLogic.
var stylusLogicType = stylusLogic.GetType();
// Loop until there are no more devices to remove.
while (devices.Count > 0)
{
// Remove the first tablet device in the devices collection.
stylusLogicType.InvokeMember("OnTabletRemoved",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic,
null, stylusLogic, new object[] { (uint)0 });
}
}
}
// END OF ORIGINAL CODE
// hook into internal class SystemResources to keep it from updating the TabletDevices on system events
object hwndWrapper = GetSystemResourcesHwnd();
if (hwndWrapper != null)
{
// invoke hwndWrapper.AddHook( .. our method ..)
var internalHwndWrapperType = hwndWrapper.GetType();
// if the delegate is already set, we have already added the hook.
if (_handleAndHideMessageDelegate == null)
{
// create the internal delegate that will hook into the window messages
// need to hold a reference to that one, because internally the delegate is stored through a WeakReference object
var internalHwndWrapperHookDelegate = internalHwndWrapperType.Assembly.GetType("MS.Win32.HwndWrapperHook");
var handleAndHideMessagesHandle = typeof(DisableWPFTouchAndStylus).GetMethod(nameof(HandleAndHideMessages), BindingFlags.Static | BindingFlags.NonPublic);
_handleAndHideMessageDelegate = Delegate.CreateDelegate(internalHwndWrapperHookDelegate, handleAndHideMessagesHandle);
// add a delegate that handles WM_TABLET_ADD
internalHwndWrapperType.InvokeMember("AddHook",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public,
null, hwndWrapper, new object[] { _handleAndHideMessageDelegate });
}
}
}
private static Delegate _handleAndHideMessageDelegate = null;
private static object GetSystemResourcesHwnd()
{
var internalSystemResourcesType = typeof(Application).Assembly.GetType("System.Windows.SystemResources");
// get HwndWrapper from internal property SystemRessources.Hwnd;
var hwndWrapper = internalSystemResourcesType.InvokeMember("Hwnd",
BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.NonPublic,
null, null, null);
return hwndWrapper;
}
private static IntPtr HandleAndHideMessages(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == (int)WindowMessage.WM_TABLET_ADDED ||
msg == (int)WindowMessage.WM_TABLET_DELETED ||
msg == (int)WindowMessage.WM_DEVICECHANGE)
{
handled = true;
}
return IntPtr.Zero;
}
enum WindowMessage : int
{
WM_TABLET_DEFBASE = 0x02C0,
WM_TABLET_ADDED = WM_TABLET_DEFBASE + 8,
WM_TABLET_DELETED = WM_TABLET_DEFBASE + 9,
WM_DEVICECHANGE = 0x0219
}
}
หมายเหตุบางประการเกี่ยวกับการใช้งานและข้อจำกัดนี้:
WPF ไม่ได้ลงทะเบียนกับข้อความเหล่านี้บนแอปพลิเคชัน MainWindow แต่ผ่านหน้าต่างที่ซ่อนอยู่ชื่อ "SystemResources..." ซึ่งสร้างขึ้นสำหรับแต่ละอินสแตนซ์ของแอปพลิเคชัน ดังนั้นการจัดการข้อความเหล่านั้นบน MainWindow (ซึ่งน่าจะง่าย) จึงไม่ช่วยอะไรที่นี่
โซลูชันของฉันยังใช้การไตร่ตรองและการเรียกคลาสภายในและคุณสมบัติภายในค่อนข้างมาก ใช้งานได้กับ .net 4.6.2 และยังไม่ได้ทดสอบกับเวอร์ชันก่อนหน้า ยิ่งไปกว่านั้น ในการเจาะลึกซอร์สโค้ด .net ฉันยังเห็นอีกสองเส้นทางที่เป็นไปได้ซึ่งมีการอัปเดตการจัดการแท็บเล็ต ซึ่งไม่ได้รับการจัดการในโซลูชันนี้: ตัวสร้างของ TabletCollection และของ HwndStylusInputProvider
person
tseifried
schedule
09.09.2016