いくつかの自動テストのために、アプリケーションでMSUIオートメーションフレームワークを使用しようとしています。今のところ私の目標は、Windows SDKで提供されているサンプル(TestScriptGeneratorSample)と同様に、GUIイベントをリッスンして記録することです。
そのデモアプリケーションを使用するだけで、ボタン1つで単純なWindowsフォームアプリケーションを起動し、クリックイベントを「呼び出し」UIAイベントとして記録することを確認できます。ただし、ボタンをクリックするたびに、デモアプリケーションは4つの「呼び出し」イベントを記録します。何故ですか?WPFボタンを使用している場合、この問題は発生しません。
私の推測では、System.Windows.Forms.Button
クラスはUIAではなくMSAAをサポートしているため、MSAAインターフェイスをブリッジしているUIAの部分が誤動作しているか、少なくとも私が理解できず、ドキュメントが見つからない方法で動作していると思います。たぶん、マウスを下、上、クリックしてから実際にボタンを押したときの呼び出しイベントを報告しているのでしょうか。
誰かがこの動作を説明したり、ボタンを1回押すと1回の呼び出しイベントが発生するように回避策を提供したりできますか?
編集:これはWinXPSP3の下にあります。Windows Automation API 3.0 アップデートをインストールしたところ、同じ動作が見られます。
編集2:著者がこの動作をWin32コントロールのバグとして不当に言及しているが、証拠を引用していないこの例を見つけました...
これが私のサンプルアプリケーション(ボタンが付いたフォーム)と、それに焼き付けられたイベントリスニングです。UIAutomationClient
およびへの参照を追加しますUIAutomationTypes
。ボタンをクリックして、呼び出しが1回ではなく4回発生することを確認します。
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);
}
}
}
}