Saya memiliki masalah yang sama dan dapat menemukan solusi menggunakan refleksi.
Masalah ini disebabkan oleh WPF memperbarui penanganan perangkat tablet internalnya ketika pesan jendela WM_TABLET_ADDED, WM_TABLET_REMOVED atau WM_DEVICECHANGED dikirim (lihat sumber referensi .net). Karena pesan-pesan ini mungkin dihasilkan atau tidak tergantung pada perangkat keras yang digunakan, metode DisableWPFTabletSupport asli mungkin cukup atau tidak.
Solusi saya adalah menangani dan menyembunyikan ketiga pesan jendela tersebut dari WPF selain kode asli:
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
}
}
Beberapa catatan tentang penerapan dan batasan ini:
WPF tidak mendaftarkan pesan-pesan ini pada aplikasi MainWindow, tetapi melalui jendela tersembunyi bernama "SystemResources..." yang dibuat untuk setiap contoh aplikasi. Jadi menangani pesan-pesan itu di MainWindow (yang mudah) tidak membantu di sini.
Solusi saya juga menggunakan beberapa refleksi dan panggilan ke kelas internal dan properti internal. Ini berfungsi untuk .net 4.6.2 dan belum mengujinya pada versi sebelumnya. Selain itu, saat mendalami kode sumber .net, saya juga melihat dua jalur potensial lainnya yang memperbarui penanganan tablet, yang tidak ditangani dalam solusi ini: Konstruktor TabletCollection dan HwndStylusInputProvider.
person
tseifried
schedule
09.09.2016