使用UI自动化时避免切换焦点

时间:2012-02-19 23:06:43

标签: .net wpf focus ui-automation

出于好奇,我决定编写一个功能类似于UI Spy的简单工具。基本上它显示一个控件树,并允许查看每个控件的属性。现在,我开始实施模式交互,并遇到以下问题:用户点击后,例如“InvokePatter.Invoke”#39;在我的应用程序UI自动化开关专注于我的目标应用程序。其他模式也是如此。它在原始UI Spy应用程序中的行为方式也相同。

这种行为使我的应用程序无法操作菜单,因为我很快再次点击我的应用程序,测试的应用程序失去焦点,菜单正在关闭。我想做的是使用UI自动化与应用程序交互,但保持我的(UI间谍)应用程序的重点。任何想法如何实现呢?或者至少如何实现所需的功能 - 允许用户与菜单交互?

2 个答案:

答案 0 :(得分:4)

UIAutomation是故意这样做的:应用程序通常只希望在有焦点时接收输入。要发送键盘输入,您必须先将其关注。或者,如果您单击控件以与其进行交互 - 它通常会因点击而获得焦点,然后执行操作。如果你发送输入而没有首先发送焦点,有些应用程序会非常混淆(有时会崩溃)。

(例如,这些应用程序可能会在WM_SETFOCUS中初始化一些内部状态,并在接收输入时依赖该状态。这实际上不能被视为错误,因为Windows本质上承诺在发送输入之前发送WM_SETFOCUS,所以它真的是发送'伪造'输入的工具,它在这里破坏了合同。)

菜单是一个棘手的案例:首先,在Windows中,菜单只存在于具有焦点的应用程序上。因此,为了显示菜单,带有菜单的应用程序必须具有焦点,因此焦点必须切换离开UISpy:无处可去。但是菜单的真正问题不是UIAutomation切换焦点到应用程序:点击工具(UISpy)将导致菜单被解雇。这不是UIAutomation问题 - 它只是Win32处理菜单的方式。所以真正的问题是:如何使用工具来浏览器或以其他方式操作菜单,当点击工具时会忽略我正在尝试使用的菜单?

有几种方法可以解决这个问题 - Inspect Objects tool (inspect.exe) uses。 Inspect.exe是UISpy的旧MSAA前身,但更新版本 - 作为SDK的一部分提供 - 现在支持MSAA和UIAutomation。以下技术仅在几个地方实现(例如,SetFocus,导航命令,但不是Invoke.Invoke()),但您可以根据需要在自己的工具中使用这些技术。

它使用两种方法解决了这个问题:

  • 热键 - 热键本身不会更改焦点或关闭菜单 - 因此请使用RegisterHotKey()为您可能要执行的每个操作分配一个热键(例如Ctrl-Shift-X)当前的对象。现在,当目标应用程序被聚焦并且菜单存在时,您可以使用热键组合向工具发出信号以执行相应的操作。

  • 鼠标的创造性使用:您无法使用鼠标单击UI,但仍可以利用鼠标位置。 Inspect有一个“Active Hover Toolbar”选项(在Options菜单下):选中后,如果将鼠标悬停在工具栏项上几秒钟,它会将其视为单击它。这允许您浏览菜单项,例如,无需实际点击任何Inspect UI。在内部,它可能使用轮询和TB_HITTEST的某种组合来确定指针所在的按钮。

或者您可以滚动这些组合:使用热键在鼠标指针结束的工具中触发命令 - 无论哪种方式都适合您。

答案 1 :(得分:0)

每隔x(毫秒)运行一次的计时器怎么样,如果焦点丢失,它会带回焦点。