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

C# UIAutomation方法ElementFromPoint()在Windows 10上从记事本检索不正确的元素,c#,winforms,windows-10,notepad,dpi-aware,C#,Winforms,Windows 10,Notepad,Dpi Aware,我们正在开发一个C#Windows窗体应用程序,并使用UI自动化来记录用户活动。我们的应用程序根据监视器声明其DPI感知,因此系统不会对它撒谎,因为它采用了坐标虚拟化 在Windows 10上,我们在记事本上遇到了一个问题:在执行屏幕缩放后,调用传递了正确物理坐标的UIA方法ElementFromPoint()时返回了一个不正确的元素。另外,调用CurrentBoundingRectangle()返回的BoundingRectangle的坐标也不正确:除以当前屏幕比例值,即1.5表示150% 以

我们正在开发一个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上,此代码为“文件”主菜单项返回不正确的元素和边框:

收到鼠标向下移动:X=735 Y=391

UIA元素:名称=应用程序

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

系统按钮的边框不正确:

接收到鼠标向下移动:X=701 Y=282

UIA元素:名称=系统

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

以及其他UI控件(即文件->保存子菜单项)的正确元素和边框:

收到鼠标向下移动:X=1386 Y=666

UIA元素:名称=保存

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

这些结果不会在声明自己支持系统DPI的旧版本记事本上重现

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

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


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

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

“首选32位”已启用:

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

“首选32位”已禁用: