나는 동일한 문제가있어서 리플렉션을 사용하여 해결 방법을 찾을 수있었습니다.
이 문제는 창 메시지 WM_TABLET_ADDED, WM_TABLET_REMOVED 또는 WM_DEVICECHANGED (see .net referencesource)를 보낼 때 WPF에서 내부 타블렛 장치 처리를 업데이트 할 때 발생합니다. 이러한 메시지는 사용 된 하드웨어에 따라 생성되거나 생성되지 않을 수 있으므로 원래의 DisableWPFTabletSupport 메소드로 충분할 수도 있고 그렇지 않을 수도 있습니다.
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는에 등록하지 않습니다
내 솔루션은 원래의 코드에 추가 WPF에서이 세 가지 윈도우 메시지를 처리하고 숨길 수 있었다 이러한 메시지는 응용 프로그램 MainWindow에 있지만 각 응용 프로그램 인스턴스에 대해 생성되는 "SystemResources ..."라는 숨겨진 창을 통해 표시됩니다. 따라서 MainWindow에서 이러한 메시지를 처리하는 것은 쉬운 일이 아닙니다.
또한 내 솔루션은 내부 클래스와 내부 속성에 대한 반영과 호출을 많이 사용합니다. .net 4.6.2에서 작동하며 이전 버전에서는 테스트하지 않았습니다. 또한, 닷넷 소스 코드에 대해 자세히 살펴보면이 솔루션에서 처리되지 않는 태블릿 처리가 업데이트되는 다른 두 가지 경로가 있음을 알게되었습니다. TabletCollection 및 HwndStylusInputProvider의 생성자.
표면 4 프로에서 테스트 해 보셨습니까? 솔루션을 공유해 주셔서 감사합니다 – SERWare
@SERWare : 예, SP4에서 작동합니다. 개인적으로 테스트하지는 않았지만 고객의 SP4에서 작동합니다. 내가 아직 서적 책에서 작동한다면, 나는 아직 모른다. 그러나 나는 확신한다. – tseifried
저는 거의 같은 경우입니다. 고객의 SP4에서 오류를 감지했으며 솔루션을 테스트하기 위해 반환 할 때까지 기다려야합니다. 다시 한번 감사드립니다. – SERWare