我们正在开发一个 C# Windows 窗体应用程序并使用 UI 自动化来记录用户活动。我们的应用程序将其 DPI 感知声明为 Per-monitor,因此系统不会通过坐标虚拟化对其进行欺骗。
在 Windows 10 上,我们遇到了记事本的问题:在执行屏幕缩放后,调用 UIA 方法ElementFromPoint()
并传递了正确的物理坐标时返回了不正确的元素。此外,调用返回的 BoundingRectangle 的坐标CurrentBoundingRectangle()
也不正确:除以当前屏幕比例值,即 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 上,此代码为“文件”主菜单项返回不正确的元素和 BoundingRectangle:
MouseDown 收到:X=735 Y=391
UIA 元素:名称=应用程序
rect=[left=475 top=249 right=822 bot=268]
系统按钮的 BoundingRectangle 不正确:
收到 MouseDown:X=701 Y=282
UIA 元素:名称=系统
rect=[left=453 top=183 right=475 bot=205]
并为其他 UI 控件更正元素和 BoundingRectangle(即文件 -> 保存子菜单项):
MouseDown 收到:X=1386 Y=666
UIA 元素:名称=保存
矩形=[左=1320 上=652 右=1452 机器人=691]
这些结果不会在自称为系统 DPI 感知的旧版本记事本上重现。
例如,在 Windows 7 上,总是检索正确的元素和边界矩形。
此外,我还在 Win 10 上测试了其他实现 Per-monitor DPI 感知模式的应用程序:Acrobat Reader DC、Edge、Skype、Slack、Explorer。这些应用程序的主菜单也得到了正确处理:检索了正确的元素和边界矩形。
因此,Windows 10 记事本的每监视器模式实现中可能存在问题。