2016-07-28 2 views
2

Net 3.5を対象とするWPFアプリケーションを継承しました。それをSurface Pro 4(I5)にインストールする必要があります。アプリケーションはさまざまな点でハングしていますが、アニメーションでは完了したイベントが発生しないことがあります(ある時点で終了する可能性はありますが、Durationプロパティで表される時点では発生しないことがあります)。私は、DisableWPFTabletSupportメソッドが実行されて終了しましたが(DisableWPFTabletSupportメソッドでログコードを追加し、Surface Pro 4では4つのデバイスが削除されていました)、おそらくWPFタブレットであることに気づきました。アプリケーションは時々ぶら下がり続けて画面のタッチを捕捉し続けるため、アプリケーションではまだサポートが有効です。Surface 4 ProでWPFタブレットサポートを無効にするにはどうすればよいですか?

Surface 4 ProでNet 3.5をターゲットとするWPFアプリケーションを正常に実行するには、Windowsデバイスマネージャを使用してヒューマンインターフェイスのすべてのタッチスクリーン関連デバイスを無効にするしかありません。

Surface 4 ProのWPFタブレットサポートをどのように無効にすることができますか?

注意。 disable and enable the touchscreen driverに記載されていることにもかかわらず、「HID準拠のタッチスクリーンデバイス」を無効にするだけでは不十分です。「Intel(R)Preciseタッチデバイス」が無効にされるまで、タッチスクリーンは有効のままであり、ほとんどのWPFアプリケーションは失敗します。

答えて

2

私は同じ問題があり、反射を使って回避策を見つけることができました。

この問題は、ウィンドウメッセージWM_TABLET_ADDED、WM_TABLET_REMOVEDまたはWM_DEVICECHANGEDが送信されたときに、内部タブレットデバイスの処理をWPFが更新することによって発生します(see .net referencesource)。これらのメッセージは、使用されるハードウェアに応じて生成される場合と生成されない場合があるため、元の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からこれら3つのウィンドウメッセージを処理し、非表示にしましたこれらのメッセージはアプリケーションのMainWindow上にありますが、各アプリケーションインスタンスに対して作成される "SystemResources ..."という名前の隠れたウィンドウを介して表示されます。 MainWindowでこれらのメッセージを処理するのは簡単ですが、ここでは役に立ちません。

私のソリューションでは、内部クラスと内部プロパティへの反映と呼び出しもかなり使用されています。これは.net 4.6.2で動作し、以前のバージョンではテストしていません。さらに、.netソースコードの深いところで、このソリューションでは扱われない、タブレット処理が更新される2つの可能性のある他のパスも見た。TabletCollectionとHwndStylusInputProviderのコンストラクタ。

+0

Surface 4プロでテストしましたか?あなたの解決策を教えてくれてありがとう – SERWare

+0

@SERWare:はい、それはSP4で動作します。個人的にはテストしていませんが、お客様のSP4で動作します。サーフェイスブックでも動作するのであれば、私はまだ分かりませんが、私は自信があります。 – tseifried

+0

私はほとんど同じです。顧客のSP4でエラーを検出したので、ソリューションをテストするために返すまで待つ必要があります。再度、感謝します。 – SERWare

関連する問題