Используя UI Automation, кнопка Winforms вызывает несколько раз

Я пытаюсь использовать MS UI Automation Framework в своем приложении для автоматического тестирования. Моя цель на данный момент - прослушивать события графического интерфейса и записывать их, как в примере, представленном (TestScriptGeneratorSample) в Windows SDK.

Просто используя это демонстрационное приложение, я могу запустить простое приложение Windows Forms с помощью одной кнопки и увидеть, что оно записывает события нажатия как "вызов" событий UIA. Однако для каждого нажатия кнопки демо-приложение записывает 4 события "вызова". Это почему? Я не вижу этой проблемы при использовании кнопки WPF.

Я думаю, что так как System.Windows.Forms.Button Класс поддерживает MSAA вместо UIA, часть UIA, которая соединяет интерфейс MSAA, ведет себя неправильно или, по крайней мере, ведет себя так, как я не понимаю, и не могу найти никакой документации. Может быть, он сообщает о событии вызова мышью вниз, вверх, щелчком, а затем фактическим нажатием кнопки?

Может кто-нибудь объяснить это поведение и / или предоставить обходной путь, чтобы одно нажатие кнопки приводило к одному событию вызова?

Изменить: это под WinXP SP3. Я только что установил обновление Windows Automation API 3.0 и все еще вижу такое же поведение.

Редактировать 2: я нашел этот пример, где автор неосознанно упоминает это поведение как ошибку в элементе управления 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);
            }
        }
    }
}

1 ответ

Для чего бы это ни стоило, я обошел его, отфильтровав несколько событий, которые выдают в одно. Во время тестирования я обнаружил следующее:

  • Кнопки.NET (например, Winforms) генерируют следующие события по порядку при нажатии:
    1. Вызванный
    2. Вызванный
    3. Вызванный
    4. Собственность изменилась (Name имущество)
    5. Вызванный
  • Кнопки Win32 генерируют следующие события в некоторых сценариях (кнопки в calc.exe):
    1. Собственность изменилась (HasKeyboardFocus имущество)
    2. Вызванный
  • Кнопки Win32 генерируют следующие события в других сценариях ("Отмена" в диалоговом окне сохранения файла):
    1. Вызванный
    2. Собственность изменилась (HasKeyboardFocus имущество)
    3. Вызванный

С использованием FrameworkId собственность на AutomationElement что связано с событием, я могу различить первую и вторую две ситуации (это "Winform" для кнопок.NET и "Win32" для кнопок Win32). Затем для двух сценариев Win32 я просто гарантирую, что получаю HasKeyboardFocus событие изменения свойства перед записью вызванного события.

Я еще не видел, чтобы это не работало, так как я всегда HasKeyboardFocus событие изменения свойства, даже если кнопка уже была в фокусе (т.е. я нажимаю ее дважды).

Я все еще хотел бы видеть больше понимания, если у кого-то есть некоторые...

Другие вопросы по тегам