c# - UIAutomation 方法 ElementFromPoint() 从 Windows 10 上的记事本中检索不正确的元素

标签 c# winforms windows-10 notepad dpi-aware

我们正在开发 C# Windows 窗体应用程序并使用 UI 自动化来记录用户事件。我们的应用将其 DPI 感知声明为每显示器,因此系统不会通过坐标虚拟化对其撒谎。

在 Windows 10 上,我们遇到了 记事本 的问题:执行屏幕缩放后,调用 UIA 方法 ElementFromPoint() 时返回不正确的元素通过了正确的物理坐标。此外,CurrentBoundingRectangle() 调用返回的 BoundingRectangle 的坐标也不正确:除以当前屏幕比例值,即 1.5 表示 150%。

有没有人遇到过这个问题,你是怎么解决的?

背景

并非记事本窗口的所有 UI 元素都受到影响:只有系统按钮和主菜单项。其他元素,如主文本区域、滚动条、窗口标题、对话框按钮、子菜单项,都得到了正确处理。

考虑以下测试代码:

private CUIAutomation automation = new CUIAutomation();
public async Task GetElement(int x, int y)
{
    try
    {
        Debug.WriteLine($"MouseDown received: X={x} Y={y}");
        await Task.Run(() =>
        {
            // Retrieving an UIA element lying on physical coordinates
            tagPOINT point = new tagPOINT { x = x, y = y };
            IUIAutomationElement clickedElement = automation.ElementFromPoint(point);
            var elementName = clickedElement.GetCurrentPropertyValue(30005);
            var elementRect = clickedElement.CurrentBoundingRectangle;

            // Actually retrieved UIA element
            Debug.WriteLine($"UIA element: Name={elementName} " +
                $"Rect=[left={elementRect.left} top={elementRect.top} right={elementRect.right} bot={elementRect.bottom}]");
        });
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex);
    }
}

在 Win 10 上,此代码为"file"主菜单项返回不正确的元素和 BoundingRectangle:

MouseDown received: X=735 Y=391

UIA element: Name=Application

Rect=[left=475 top=249 right=822 bot=268]

系统按钮的 BoundingRectangle 不正确:

MouseDown received: X=701 Y=282

UIA element: Name=System

Rect=[left=453 top=183 right=475 bot=205]

并为其他 UI 控件(即文件 -> 保存子菜单项)更正元素和 BoundingRectangle:

MouseDown received: X=1386 Y=666

UIA element: Name=Save

Rect=[left=1320 top=652 right=1452 bot=691]

这些结果不会在声明自己为 System-DPI-aware 的旧版记事本上重现。

例如,在 Windows 7 上,始终会检索到正确的元素和边界矩形。

此外,我还在 Win 10 上测试了其他应用程序,这些应用程序实现了每显示器 DPI 感知模式:Acrobat Reader DC、Edge、Skype、Slack、Explorer。这些应用程序的主菜单也得到了正确处理:检索了正确的元素和边界矩形。

因此 Windows 10 记事本的按监视器模式实现可能存在问题。

最佳答案

经过大量测试后,我发现原因在于“首选 32 位”标志:当为可执行项目启用它时,从记事本中检索到不正确的 UIA 元素和边界矩形。

启用“首选 32 位”:

(注意菜单元素边界框位置enter image description here和点击点enter image description here)

enter image description here

禁用“首选 32 位”:

enter image description here

关于c# - UIAutomation 方法 ElementFromPoint() 从 Windows 10 上的记事本中检索不正确的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50591092/

相关文章:

c# - .net StopWatch 的计时不一致

javascript - 将数组从客户端传递到服务端 C#

windows - Windows 窗体中的主窗体

c# - 控制显示在 winform 中做某事的步骤

docker - Windows 10 和 Docker 容器日志/Docker Logging 驱动程序

c# - 去掉 ASP.NET MVC 中的/Home 路径名

c# - 如何/在何处使用 PRISM 和 Unity 在 MVVM 中实例化模型对象

c# - 后台worker中的进度条和后台运行方法

windows - 运行neofetch后powershell立即关闭(Windows终端)

powershell - 如何从 Windows PowerShell 中的 doskey 别名获取完整命令