UI Automation Control Desktop Application and Click on Menu Strip(UI自动化控制桌面应用程序并单击菜单条)
问题描述
我正在使用 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).
如何进行:
- 找到您要与之交互的应用程序的主窗口句柄:
- Process.GetProcessesByName()(或通过 ID),EnumWindows(), FindWindowEx() 可用于获取窗口句柄.
- Find the handle of main Window of the Application you want to interact with:
- Process.GetProcessesByName() (or by ID), EnumWindows(), FindWindowEx() can be used to get the Window Handle.
- 注意
SystemMenu
也包含在MenuBar
中,可以通过Element Name来判断,它包含:"System"
而不是应用程序"
.
- Note that the
SystemMenu
is also contained in aMenuBar
, 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 theExit
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自动化控制桌面应用程序并单击菜单条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:UI自动化控制桌面应用程序并单击菜单条
基础教程推荐
- 从 VB6 迁移到 .NET/.NET Core 的最佳策略或工具 2022-01-01
- 如何使用OpenXML SDK将Excel转换为CSV? 2022-01-01
- 创建属性设置器委托 2022-01-01
- Page.OnAppearing 中的 Xamarin.Forms Page.DisplayAlert 2022-01-01
- 覆盖 Json.Net 中的默认原始类型处理 2022-01-01
- 使用 SED 在 XML 标签之间提取值 2022-01-01
- 我什么时候应该使用 GC.SuppressFinalize()? 2022-01-01
- C# - 将浮点数转换为整数...并根据余数更改整数 2022-01-01
- 当键值未知时反序列化 JSON 2022-01-01
- C# - 如何列出发布到 ASPX 页面的变量名称和值 2022-01-01