Пункты меню поддерживают 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();
}
}