如何禁用 Surface 4 Pro 中的 WPF 平板电脑支持?

2023-12-26

我继承了一个面向 Net 3.5 的 WPF 应用程序,并且必须将其安装在 Surface Pro 4 (I5) 中。应用程序挂在不同的点,我观察到动画有时永远不会触发已完成的事件(也许它们在某个点结束,但不是在 Duration 属性中表示的时间)。

作为一个转变,我尝试了禁用 WPF 应用程序的 RealTimeStylus https://msdn.microsoft.com/en-us/library/ee230087.aspx/但经过几次尝试后,我注意到虽然DisableWPFTabletSupport方法已执行并完成(我在DisableWPFTabletSupport方法中添加了日志代码,并且在Surface Pro 4中删除了四个设备),但WPF Tablet Support可能在我的应用程序中仍然处于活动状态,因为该应用程序时不时地继续挂起并继续捕获屏幕触摸。

因此,我发现能够在 Surface 4 Pro 中成功运行针对 Net 3.5 的 WPF 应用程序的唯一方法是使用 Windows 设备管理器禁用人机界面中的所有触摸屏相关设备。

有人知道如何在 Surface 4 Pro 中禁用 WPF 平板电脑支持吗?

笔记。尽管上面说的,仅禁用“HID 兼容触摸屏设备”是不够的:在未禁用“Intel(R) Precise 触摸设备”之前,触摸屏将保持激活状态,并且大多数 WPF 应用程序将失败。


我遇到了同样的问题,并且能够使用反射找到解决方法。

该问题是由 WPF 在发送窗口消息 WM_TABLET_ADDED、WM_TABLET_REMOVED 或 WM_DEVICECHANGED 时更新其内部平板电脑设备处理引起的(请参阅 .net 参考源 http://referencesource.microsoft.com/#PresentationCore/Core/CSharp/System/Windows/Input/Stylus/StylusLogic.cs,30fed96d616c6a93)。由于这些消息可能会也可能不会生成,具体取决于所使用的硬件,因此原始的 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 不会在应用程序主窗口上注册这些消息,而是通过为每个应用程序实例创建的名为“SystemResources...”的隐藏窗口注册。因此,在主窗口上处理这些消息(这很容易)在这里没有帮助。

我的解决方案还使用了相当多的反射并调用内部类和内部属性。它适用于 .net 4.6.2,尚未在早期版本上进行测试。此外,在深入研究 .net 源代码时,我还看到了更新平板电脑处理的另外两个潜在路径,但在此解决方案中未处理:TabletCollection 和 HwndStylusInputProvider 的构造函数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何禁用 Surface 4 Pro 中的 WPF 平板电脑支持? 的相关文章

  • 进程退出后 POSIX 名称信号量不会释放

    我正在尝试使用 POSIX 命名信号量进行跨进程同步 我注意到进程死亡或退出后 信号量仍然被系统打开 在进程 打开它 死亡或退出后是否有办法使其关闭 释放 早期的讨论在这里 当将信号量递减至零的进程崩溃时 如何恢复信号量 https sta
  • 将下拉列表与字典绑定

    我将字典绑定到下拉列表 举例来说 我的字典中有以下项目 Test1 123 Test2 321 我希望下拉文本采用以下格式 Test1 Count 123 Test2 Count 321 我沿着以下路径走 但没有运气 MyDropDown
  • WPF水平滚动条不可见

    我在 ScrollViewer 中有一个网格 网格只有一列和许多行 我将控件添加到网格行中 问题是 当我添加控件时 我可以看到 VerticalScrollBar 但尽管我添加了非常宽的控件 但我看不到 Horizo ntalScrollB
  • 在 C++11 中移出 stdpriority_queue 的元素

    最小的工作示例 include
  • 如何在win32中使用GetSaveFileName保存文件?

    我编写此代码是为了获取 fileName 来保存我的文件 include stdafx h include
  • 如何使用递归查找数字中的最小元素 [C]

    好的 所以我正在准备我的 C 考试 当谈到递归时我有点卡住了我是大学一年级的学生 这对我来说似乎有点困难 练习要求在给定的数字中使用递归函数我需要找到最小的元素 例如 52873 是 2 程序需要打印 2 include
  • Resharper:IEnumerable 的可能多重枚举

    我正在使用新的 Resharper 版本 6 在我的代码中的几个地方 它给一些文本加了下划线 并警告我可能存在IEnumerable 可能的多重枚举 我理解这意味着什么 并在适当的情况下采纳了建议 但在某些情况下 我不确定这实际上是一个大问
  • 如何在 C# 中获取 Json 数组?

    我有一个像这样的 Json 字符串 我想将它加载到 C 数组中 当我尝试这样做时 我收到异常 我的字符串 customerInformation customerId 123 CustomerName Age 39 Gender Male
  • C++ 到 C# 事件处理

    所以我有我的C WinForm 应用程序 我从中调用我的C CLI MFC dll图书馆 但也有一些events在我的 C 库上 甚至此事件也发生在该库的本机 非 CLI 部分 我需要从我的 C 应用程序调用一些代码 并获取一些有关此事件的
  • 如何使用 CSI.exe 脚本参数

    当你运行csi exe 安装了 Visual Studio 2015 update 2 您将得到以下语法 Microsoft R Visual C Interactive Compiler version 1 2 0 51106 Copyr
  • 为什么 f(i = -1, i = -1) 是未定义的行为?

    我正在读关于违反评估顺序 http en cppreference com w cpp language eval order 他们举了一个令我困惑的例子 1 如果标量对象上的副作用相对于同一标量对象上的另一个副作用是无序的 则行为未定义
  • 无法在 C# 中为 EventArgs 分配使用派生类型的事件处理程序

    所以我有一个事件声明如下 public event EventHandler OnChangeDetected 然后我有以下处理程序被分配给该事件 myObject OnChangeDetected OnTableChanged 我的理解是
  • 使用 xslt 将 xml 转换为 xsl-fo 时动态创建超链接?

    我想使用 xsl 文件在 PDF 报告中创建标题 如果源文件包含超链接 则应将其呈现为超链接 否则呈现为纯文本 例如 我的 xml 如下所示 a href http google com target blank This is the h
  • rabbitmq 的 REST API

    有没有办法从 ajax 向 RabbitMQ 发送数据 我的应用程序由数千个 Web 客户端 用 js 编写 和 WCF REST 服务组成 现在我试图弄清楚如何为我的应用程序创建可扩展点 这个想法是有一个rabbitmq实例 它从放置在一
  • 浮点字节序?

    我正在为实时海上模拟器编写客户端和服务器 并且由于我必须通过套接字发送大量数据 因此我使用二进制数据来最大化可以发送的数据量 我已经了解整数字节顺序以及如何使用htonl and ntohl为了规避字节顺序问题 但我的应用程序与几乎所有模拟
  • 从 NumPy 数组到 Mat 的 C++ 转换 (OpenCV)

    我正在围绕 ArUco 增强现实库 基于 OpenCV 编写一个薄包装器 我试图构建的界面非常简单 Python 将图像传递给 C 代码 C 代码检测标记并将其位置和其他信息作为字典元组返回给 Python 但是 我不知道如何在 Pytho
  • Linq.Select() 中的嵌套表达式方法调用

    I use Select i gt new T 每次手动点击数据库后将我的实体对象转换为 DTO 对象 以下是一些示例实体和 DTOS 用户实体 public partial class User public int Id get set
  • 如何将 int 作为“void *”传递给线程启动函数?

    我最初有一个用于斐波那契变量数组的全局变量 但发现这是不允许的 我需要进行基本的多线程处理并处理竞争条件 但我无法在 pthread 创建中将 int 作为 void 参数提供 我尝试过使用常量指针 但没有成功 由于某些奇怪的原因 void
  • 使用 C# 动态创建按钮并按预定义的顺序放置它们

    NET 4 5 C 创建 Windows 窗体 我想动态创建和添加按钮并为其分配单击事件 但希望它们以特定的方式动态放置 就像图像一样 我的问题是如何以上述方式动态放置按钮 即 4x4 格式 一行 4 个按钮 4 列 但行数不受限制 是否可
  • 如何提高环复杂度?

    对于具有大量决策语句 包括 if while for 语句 的方法 循环复杂度会很高 那么我们该如何改进呢 我正在处理一个大项目 我应该减少 CC gt 10 的方法的 CC 并且有很多方法都存在这个问题 下面我将列出一些例如我遇到的问题的

随机推荐

  • 检查软盘驱动器

    获取我使用过的可移动驱动器获取驱动器类型 功能 是否可以检查驱动器是否是软盘驱动器 请让我知道您对此的建议 感谢您的任何帮助 在内部 Microsoft Windows 为每个设备保存命名的特征标志 在 wdm h 中定义 如果该盘符对应的
  • Android VR工具包-HeadTransform getHeadView矩阵表示

    我从适用于谷歌纸板的 Android VR Toolkit 开始 我使用谷歌网站上的示例 https developers google com cardboard get started https developers google c
  • 音频标签持续时间属性返回“无穷大”

    它可能是重复的 但我有一个非常奇怪的场景 用例是在播放音频之前动态显示源集的音频持续时间 这是我到目前为止所尝试过的 var tempVid document 0 createElement audio tempVid preload me
  • CollapsingToolbarLayout:类似于 Facebook 的自定义 contentScrim

    我想为我的产品创建一个自定义 contentScrimcollapsingToolbarLayout 我的 collapsingToolbarLayout 有一个imageview里面 当它滚动时 理论上图像视图应该淡出 而我的稀松布颜色应
  • 显示加载窗口

    我在 WPF 中的应用程序加载外部资源 因此我想在程序加载时显示加载表单 我尝试创建表单 并在加载代码之前显示 并在加载结束时关闭 private void Window Loaded object sender RoutedEventAr
  • 本地Tomcat环境未启动

    我正在尝试运行本地 Tomcat 环境 但始终遇到以下错误 Can t load log handler 2localhost org apache juli FileHandler java lang ClassNotFoundExcep
  • 使用 fread() 将文本文件读入缓冲区 - 为什么缓冲区中的值不是每个字符各自的 ASCII 值?

    首先 这不是家庭作业 只是想了解为什么我会在屏幕上看到这些内容 下面的内容 我自己的工作 当前采用输入文件并将其作为二进制文件读取 我希望它将读取的每个字节存储在数组中 以供以后使用 为了简洁起见 输入文件 Hello txt 仅包含 He
  • ALV 列表中的两级列标题

    我想添加一个标题行来对列标题进行分组 Departure Arrival lt This row is what I want to add Airport Gate Date Airport Gate Date O Hare A10 10
  • 手机端口0接收短信

    我正在将 J2ME 应用程序配置为在收到 SMS 时从推送注册表获取事件 在 SMS 消息到达收件箱之前 我能否访问该消息 我读到发送到移动设备 port0 的消息会直接发送到本机收件箱 我们无法访问它 是否有任何方法可以转移甚至嗅探这些消
  • 单个应用程序窗口的任务管理器中 Visual Studio Code 的多个实例或进程

    我正在使用 Visual Studio 代码 我的机器面临性能问题 我去了任务管理器 看到有几个实例Code exe在进程选项卡中 即使有only我的电脑上正在运行 活动的 Visual Studio Code 的一个窗口 我可以看到总共有
  • 以编程方式编写 gui,还是使用高级 gui 编辑器(Java Swing)?

    我计划编写一个基于 Swing 的应用程序 使用 Netbeans 6 8 看来 Netbeans 有一个非常先进的 GUI 编辑器 我仍然对它生成的代码存有疑问 另外 我不喜欢代码部分被锁定的事实 我仍然理解这种需要 有人成功使用 Net
  • DbConnectionStringBuilder 在 PowerShell 中使用时不会解析

    我正在尝试使用以下功能DbConnectionStringBuilder用于解析类似连接字符串的用户输入 这在 C 中工作得很好 using System using System Data Common class Program sta
  • postgresql - 查询构建 json

    运行 PostgreSQL 9 6 2 我的数据以键 值对的形式存储在表中 key 实际上是一个json对象的路径 每一个都是一个属性 例如 如果键是 cogs props1 value 那么 json 对象将如下所示 cogs props
  • Python-将脚本安装到系统

    如何为我自己的脚本制作 setup py 文件 我必须使我的脚本全球化 将其添加到 usr bin 这样我就可以从控制台运行它 只需键入 scriptName 参数 操作系统 Linux EDIT 现在我的脚本可以安装了 但是如何使其全局化
  • JavaScript 立即函数

    Stoyan Stefanov 在 Javascript Patterns 中说道 你需要一个即时函数来将所有代码包装在其本地作用域中 并且不会将任何变量泄漏到全局作用域 第 70 页 这是他的例子 function var days Su
  • Angular 9 中的视频 JS - 实时视频 - “无法解决 videojs”问题?

    我正在努力让 videojs 在我的 Angular 9 应用程序中工作 我已经查看了所有现有的 stackoverflow 帖子 应用了他们的解决方案 查看了不同的博客文章和 github 来了解视频 js 的问题 但我仍然遇到 无法解决
  • 清除 mySql 中的电话号码字段

    不是数据库人员 而是 我混淆了我继承的 mySql 数据库中的数据 部分电话号码已格式化 512 555 1212 称之为肮脏 其他的5125551212 称之为干净 我需要一个 sqlstamet 说 UPDATE table name
  • UINavigationBar 不与 swift 4 中的 UICollectionView 重叠

    我将导航栏放在 swift 4 中的 UICollectionView 中 当我滚动 collectionView 时 它不会转到后层 而是与导航栏重叠 self collectionview contentInset UIEdgeInse
  • 常见 Linq 表达式的示例 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 当我编写代码时 我开始确定可以使用 Linq 的地方 我的问题是我对语法还很陌生 我通过示例学习效果最好 但我似乎无法轻松找到我需要的
  • 如何禁用 Surface 4 Pro 中的 WPF 平板电脑支持?

    我继承了一个面向 Net 3 5 的 WPF 应用程序 并且必须将其安装在 Surface Pro 4 I5 中 应用程序挂在不同的点 我观察到动画有时永远不会触发已完成的事件 也许它们在某个点结束 但不是在 Duration 属性中表示的