UI Automation Control Настольное приложение и нажмите на полосу меню - PullRequest
0 голосов
/ 23 мая 2019

Я использую UI Automation, чтобы щелкнуть элемент управления полосы меню. Я уже предварительно заполнил текстовые поля и теперь могу также вызывать кнопку.

Но я бы хотел перейти в строку меню, выбрав опцию, скажем, «Файл», которая должна открыть пункты своего подменю, и затем нажать кнопку подменю, скажем, «Выход».

Как мне это сделать, ниже мой код до сих пор,

 AutomationElement rootElement = AutomationElement.RootElement;
            if (rootElement != null)
            {

                System.Windows.Automation.Condition condition = new PropertyCondition
             (AutomationElement.NameProperty, "This Is My Title");
              rootElement.FindAll(TreeScope.Children, condition1);
                AutomationElement appElement = rootElement.FindFirst(TreeScope.Children, condition);


                if (appElement != null)
                {
                    foreach (var el in eles)
                    {
                        AutomationElement txtElementA = GetTextElement(appElement, el.textboxid);
                        if (txtElementA != null)
                        {
                            ValuePattern valuePatternA =
                            txtElementA.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                            valuePatternA.SetValue(el.value);
                            el.found = true;
                        }

                    }


                    System.Threading.Thread.Sleep(5000);
                    System.Windows.Automation.Condition condition1 = new PropertyCondition
                    (AutomationElement.AutomationIdProperty, "button1");
                    AutomationElement btnElement = appElement.FindFirst
                            (TreeScope.Descendants, condition1);

                    InvokePattern btnPattern =
                    btnElement.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
                    btnPattern.Invoke();

1 Ответ

0 голосов
/ 23 мая 2019

Пункты меню поддерживают ExpandCollapsePattern . Вы можете вызвать подпрограмму MenuItem после ее расширения. Это создает MenuItem объекты-потомки. Если вы не развернете Меню, у него нет потомков, поэтому не к чему вызывать.
Вызов выполняется с использованием InvokePattern

Чтобы получить ExpandCollapsePattern и InvokePattern, используйте метод TryGetCurrentPattern :

[MenuItem].TryGetCurrentPattern(ExpandCollapsePattern.Pattern, out object pattern)

[MenuItem].TryGetCurrentPattern(InvokePattern.Pattern, out object pattern)

Если метод возвращает успешный результат, вы можете вызвать методы Expand () и Invoke () .

Обратите внимание, что элемент MenuBar имеет Children, а MenuItem имеет Descendants. Если вы используете метод FindAll () для поиска детей, вы его не найдете.

Утилита Inspect весьма полезна при кодировании автоматизации пользовательского интерфейса. процедура. Обычно находится в:

C:\Program Files (x86)\Windows Kits\10\bin\x64\inspect.exe 

Доступна 32-битная версия (папка \bin\x86\).

Как продолжить:

  • Найдите дескриптор главного окна приложения, с которым вы хотите взаимодействовать:
  • Получите MenuBar элемент автоматизации.
    • Обратите внимание, что SystemMenu также содержится в MenuBar, его можно определить с помощью имени элемента, оно содержит: "System" вместо "Application".
  • Перечислять дочерние элементы MenuBar или FindFirst () по имени.
    • Обратите внимание, что названия пунктов меню и ускорители локализованы.
  • Разверните меню, используя метод ExpandCollapsePattern.Expand(), для создания его элементов Потомки.
  • Найдите один из элементов подменю с помощью Name или AutomationId или AccessKey.
  • Вызвать действие подменю, используя метод InvokePattern.Invoke().

Конечно, те же самые действия можно повторить, чтобы развернуть и вызвать элементы Menu вложенных подменю.

Пример кода и вспомогательные методы для поиска и расширения меню «Файл» Notepad.exe и вызова действия Exit MenuItem:

public void CloseNotepad()
{
    IntPtr hWnd = IntPtr.Zero;
    using (Process p = Process.GetProcessesByName("notepad").FirstOrDefault()) {
        hWnd = p.MainWindowHandle;
    }
    if (hWnd == IntPtr.Zero) return;
    var window = GetMainWindowElement(hWnd);
    var menuBar = GetWindowMenuBarElement(window);
    var fileMenu = GetMenuBarMenuByName(menuBar, "File");

    if (fileMenu is null) return;

    // var fileSubMenus = GetMenuSubMenuList(fileMenu);
    bool result = InvokeSubMenuItemByName(fileMenu, "Exit", true);
}

private AutomationElement GetMainWindowElement(IntPtr hWnd) 
    => AutomationElement.FromHandle(hWnd) as AutomationElement;

private AutomationElement GetWindowMenuBarElement(AutomationElement window)
{
    var condMenuBar = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.MenuBar);
    var menuBar = window.FindAll(TreeScope.Descendants, condMenuBar)
        .OfType<AutomationElement>().FirstOrDefault(ui => !ui.Current.Name.Contains("System"));
    return menuBar;
}

private AutomationElement GetMenuBarMenuByName(AutomationElement menuBar, string menuName)
{
    var condition = new AndCondition(
        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.MenuItem),
        new PropertyCondition(AutomationElement.NameProperty, menuName)
    );
    if (menuBar.Current.ControlType != ControlType.MenuBar) return null;
    var menuItem = menuBar.FindFirst(TreeScope.Children, condition);
    return menuItem;
}

private List<AutomationElement> GetMenuSubMenuList(AutomationElement menu)
{
    if (menu.Current.ControlType != ControlType.MenuItem) return null;
    ExpandMenu(menu);
    var submenus = new List<AutomationElement>();
    submenus.AddRange(menu.FindAll(TreeScope.Descendants,
        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.MenuItem))
                                               .OfType<AutomationElement>().ToArray());
    return submenus;
}

private bool InvokeSubMenuItemByName(AutomationElement menuItem, string menuName, bool exactMatch)
{
    var subMenus = GetMenuSubMenuList(menuItem);
    AutomationElement namedMenu = null;
    if (exactMatch) {
        namedMenu = subMenus.FirstOrDefault(elm => elm.Current.Name.Equals(menuName));
    }
    else {
        namedMenu = subMenus.FirstOrDefault(elm => elm.Current.Name.Contains(menuName));
    }
    if (namedMenu is null) return false;
    InvokeMenu(namedMenu);
    return true;
}

private void ExpandMenu(AutomationElement menu)
{
    if (menu.TryGetCurrentPattern(ExpandCollapsePattern.Pattern, out object pattern))
    {
        (pattern as ExpandCollapsePattern).Expand();
    }
}

private void InvokeMenu(AutomationElement menu)
{
    if (menu.TryGetCurrentPattern(InvokePattern.Pattern, out object pattern))
    {
        (pattern as InvokePattern).Invoke();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...