我正在使用 UI 自动化来单击菜单条控件.
我已经预先填充了文本框,现在也可以调用按钮了.
I am using UI Automation to click on a Menu Strip control.
I have already pre filled the textboxes and can now invoke the button as well.
但我想遍历菜单栏选择一个选项让我们说文件应该打开它的子菜单项然后点击一个子菜单按钮,比如说退出.
But I would like to traverse to the Menu Bar select an option lets say File which should open its sub menu items and then click on a sub menu button, let's say Exit.
我怎样才能实现它,下面是我的代码,
How can I achieve it, below is my code till now,
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();
菜单项支持 ExpandCollapsePattern.您可以在扩展后调用子 MenuItem
.这将创建 MenuItem
后代对象.如果您不展开菜单,则它没有后代,因此没有任何可调用的内容.
调用是使用 InvokePattern
Menu Items support the ExpandCollapsePattern. You can invoke a sub MenuItem
after you have expanded it. This creates the MenuItem
descendant objects. If you don't expand the Menu, it has no descendants so there's nothing to invoke.
The invocation is performd using an InvokePattern
要获得 ExpandCollapsePattern
和 InvokePattern
,请使用 TryGetCurrentPattern 方法:
[MenuItem].TryGetCurrentPattern(ExpandCollapsePattern.Pattern, out object pattern)
[MenuItem].TryGetCurrentPattern(InvokePattern.Pattern, out object pattern)
如果该方法返回成功的结果,则可以调用 Expand() 和 Invoke() 方法.
If the method returns a successful result, you can then call the Expand() and Invoke() methods.
要注意 MenuBar 元素具有 Children
,而 MenuItem 有 Descendants
.如果您使用 FindAll() 搜索孩子的方法,你不会找到任何.
To note that a MenuBar Element has Children
, while a MenuItem has Descendants
. If you use the FindAll() method to search for children, you won't find any.
检查实用程序在以下情况下非常有用编写 UI 自动化程序.它通常位于:
The Inspect utility is quite useful when coding an UI Automation procedure. It's usually located in:
C:Program Files (x86)Windows Kits10inx64inspect.exe
有 32 位版本可用(inx86
文件夹).
A 32bit version is available (inx86
folder).
如何进行:
SystemMenu
也包含在MenuBar
中,可以通过Element Name来判断,它包含:"System"
而不是 应用程序"
.SystemMenu
is also contained in a MenuBar
, it can be determined using the Element Name, it contains: "System"
instead of "Application"
. 当然,可以重复相同的操作来扩展和调用嵌套子菜单的 MenuItem.
Of course, the same actions can be repeated to expand and invoke the MenuItems of nested Sub-Menus.
用于查找和展开 Notepad.exe
的文件菜单并调用 Exit
MenuItem 操作的示例代码和辅助方法:
Sample code and helper methods to find and expand the File Menu of Notepad.exe
and invoke the Exit
MenuItem action:
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();
}
}
这篇关于UI自动化控制桌面应用程序并单击菜单条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!