我正在尝试在我的应用程序中使用MS UI Automation Framework进行一些自动化测试。我现在的目标是监听GUI事件并记录它们,类似于Windows SDK中提供的示例(TestScriptGeneratorSample)。
只需使用该演示应用程序,我就可以使用单个按钮启动一个简单的Windows窗体应用程序,并看到它将点击事件记录为“调用”UIA事件。但是,对于每次单击按钮,演示应用程序都会记录 4 “调用”事件。这是为什么?使用WPF按钮时,我没有看到这个问题。
我的猜测是,由于System.Windows.Forms.Button
班级支持MSAA而不是UIA,UIA的桥接MSAA界面的部分是行为不端,或者至少表现得我不喜欢理解,找不到任何文档。
也许它报告了鼠标按下,向上,单击,然后按下实际按钮的调用事件?
任何人都可以解释这种行为,并且/或者提供一种解决方法,以便按下一个按钮会导致一次调用事件吗?
编辑:这是在WinXP SP3下。我刚刚安装了Windows Automation API 3.0 update,但仍然看到相同的行为。
编辑2:我发现this example作者在Win32控件中不明智地提到这种行为,但引用没有证据......
这是我的示例应用程序(带有按钮的表单),以及烘焙事件监听。添加对UIAutomationClient
和UIAutomationTypes
的引用。单击按钮,看到调用发生了四次而不是一次。
using System;
using System.Drawing;
using System.Windows.Automation;
using System.Windows.Forms;
namespace WindowsFormsApplication6
{
public partial class Form1 : Form
{
private TextBox m_Output;
public Form1()
{
InitializeComponent();
// set up the GUI with a single button...
Button b = new Button {Location = new Point(5, 5), Name = "Test", Text = "Click Me"};
// ... and a textbox to write events to.
m_Output = new TextBox { Location = new Point(5, 30), Name = "Output", Multiline = true, Size = new Size(250, 200) };
this.Controls.Add(b);
this.Controls.Add(m_Output);
// get the button as an UIA element
AutomationElement button = AutomationElement.FromHandle(b.Handle);
// attach a handler to the button, listening for the Invoke event
Automation.AddAutomationEventHandler(
InvokePattern.InvokedEvent,
button,
TreeScope.Element,
OnInvoked);
}
// Handler for button invoke events
private void OnInvoked(object Sender, AutomationEventArgs E)
{
AppendText("Invoked: " + ((AutomationElement)Sender).Current.AutomationId);
}
// Just dumps text to the textbox
private void AppendText(string Text)
{
if (m_Output.InvokeRequired)
{
m_Output.BeginInvoke((Action<string>)AppendText, Text);
}
else
{
m_Output.AppendText(DateTime.Now.ToString("hh:mm:ss.fff") + ": " + Text + Environment.NewLine);
}
}
}
}
答案 0 :(得分:0)
对于它的价值,我通过过滤发布的多个事件来解决它。在测试期间,我发现了以下内容:
Name
属性)calc.exe
中的按钮):
HasKeyboardFocus
属性)HasKeyboardFocus
属性)使用与事件关联的FrameworkId
上的AutomationElement
属性,我可以区分第一种和第二种情况(对于.NET按钮"Winform"
和{{1}对于Win32按钮)。然后,对于两个Win32场景,我只确保在记录调用的事件之前得到"Win32"
属性更改事件。
我还没有看到这个不起作用,因为我似乎总是得到HasKeyboardFocus
属性更改事件,即使按钮已经被聚焦(即我按两次)。
我还是希望看到更多的见解,如果有人有...