C# UIAutomation在不使窗口聚焦的情况下单击按钮,GetCurrentPattern()返回不支持的模式
我有一个窗口的句柄,我想做的是点击它的按钮“加载设置”。我有两个问题C# UIAutomation在不使窗口聚焦的情况下单击按钮,GetCurrentPattern()返回不支持的模式,c#,.net,ui-automation,openfiledialog,microsoft-ui-automation,C#,.net,Ui Automation,Openfiledialog,Microsoft Ui Automation,我有一个窗口的句柄,我想做的是点击它的按钮“加载设置”。我有两个问题 我的第一个问题是,当我对某个InvokePattern调用Invoke时,它会使窗口聚焦,这对我的应用程序来说是不可取的 我的第二个问题可见,并记录在我下面代码末尾的注释中: AutomationElement aeBot = AutomationElement.FromHandle(mbotSettingList.ElementAt(i).getWindowHandle()); AutomationElement aeBu
- 我的第一个问题是,当我对某个InvokePattern调用Invoke时,它会使窗口聚焦,这对我的应用程序来说是不可取的
- 我的第二个问题可见,并记录在我下面代码末尾的注释中:
AutomationElement aeBot = AutomationElement.FromHandle(mbotSettingList.ElementAt(i).getWindowHandle()); AutomationElement aeButtonLoadSettings = aeBot.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Load Settings")); InvokePattern ipClickLoadSettings = (InvokePattern)aeButtonLoadSettings.GetCurrentPattern(InvokePattern.Pattern); Thread invokeLoadSettingsThread = new Thread(ipClickLoadSettings.Invoke); InvokePattern ipClickOpen = null; AutomationElement aeOpenDialogEdit = null; AutomationElement aeButtonOpen = null; AutomationElementCollection aeDialogs = null; AutomationElement aeOpenDialog = null; ValuePattern vpOpenDialogEdit = null; //Using a thread to invoke the Load Settings button click because as a result of clicking Load Settings a dialog is opened and invoke doesnt return for nealy 10 seconds invokeLoadSettingsThread.Start(); //We probably wont join() this thread because it goes on for far longer than we expect to be in this function //Get a collection of the Dialog windows that are direct children of the main window we have a handle to aeDialogs = aeBot.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "#32770")); while (aeDialogs.Count == 0) { //This while loop is to continue to check for the Open file dialog as it may take a little time to open aeDialogs = aeBot.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "#32770")); Thread.Sleep(250); } for (int j = 0; j < aeDialogs.Count; j++) { //There is usually only 1 child dialog window, but just make sure we have the correct one if (aeDialogs[j].Current.Name == "Open") { Debug.WriteLine("Found open dialog!"); aeOpenDialog = aeDialogs[j]; break; } } //Inside the Open window, the first Edit window is the one where the file name/path should be entered aeOpenDialogEdit = aeOpenDialog.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, "Edit")); //Set the value of the file name/path to the string variable "loadSettingsString" vpOpenDialogEdit = (ValuePattern)aeOpenDialogEdit.GetCurrentPattern(ValuePattern.Pattern); vpOpenDialogEdit.SetValue(loadSettingsString); //******************************************PROBLEM BEGINING BELOW****************************************** //Using multiple methods, we can successfully get a successful AutomationElement for the "Open" button in the Open file dialog aeButtonOpen = aeOpenDialog.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "Open")); //aeButtonOpen = aeOpenDialog.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "Cancel")); //Something to consider: If we assigned aeButtonOpen to the AutomationElement we find be looking for "Cancel" rather than "Open" Debug.WriteLine(aeButtonOpen.Current.Name + " button found!"); //Prints "Open button found!" //If aeButtonOpen were assigned to "Cancel", this would print "Cancel button found!" ipClickOpen = (InvokePattern)aeButtonOpen.GetCurrentPattern(InvokePattern.Pattern); //GetCurrentPattern has returned null //If aeButtonOpen were assigned to "Cancel", this would NOT be null ipClickOpen.Invoke(); //Invoke() on a null results in "Unsupported Pattern" exception //If aeButtonOpen were assigned to "Cancel", this would work and the Open file dialog would then be exited just as if cancel were clicked
AutomationElement aeBot=AutomationElement.FromHandle(mbotSettingList.ElementAt(i).getWindowHandle()); AutomationElement aeButtonLoadSettings=aeBot.FindFirst(TreeScope.Children,新属性条件(AutomationElement.NameProperty,“加载设置”); InvokePattern ipClickLoadSettings=(InvokePattern)aeButtonLoadSettings.GetCurrentPattern(InvokePattern.Pattern); Thread invokeLoadSettingsThread=新线程(ipClickLoadSettings.Invoke); InvokePattern ipClickOpen=null; AutomationElement aeOpenDialogEdit=null; AutomationElement aeButtonOpen=null; AutomationElementCollection aeDialogs=null; AutomationElement aeOpenDialog=null; ValuePattern vpOpenDialogEdit=null; //使用线程调用Load Settings按钮单击,因为单击Load Settings会打开一个对话框,并且invoke在短短10秒钟内不会返回 invokeLoadSettingsThread.Start(); //我们可能不会加入()这个线程,因为它持续的时间比我们预期的要长得多 //获取对话框窗口的集合,这些窗口是我们拥有句柄的主窗口的直接子窗口 aeDialogs=aeBot.FindAll(TreeScope.Children,新属性条件(AutomationElement.ClassNameProperty,“#32770”); 而(aeDialogs.Count==0) { //此while循环将继续检查“打开文件”对话框,因为打开该对话框可能需要一点时间 aeDialogs=aeBot.FindAll(TreeScope.Children,新属性条件(AutomationElement.ClassNameProperty,“#32770”); 睡眠(250); } 对于(int j=0;j
或者,打开一个对话框,然后立即搜索该对话框的子元素。您可能在此处遇到了可靠性问题,此时仍在为该对话框创建UIA树。要检查这一点,请添加一秒钟的睡眠,看看这是否解决了您的问题。如果是这种情况,请查看UIA结构更改事件。这些事件将允许您根据UIA树中的更改同步UIA测试代码。可能的问题是,我现在看到“打开”按钮实际上是一个拆分按钮,我不确定这是如何导致我的问题的,如果是这样的话。您真的需要使用UIA验证来查看您正在查找的元素。详细说明拆分按钮在树中的外观。您可能需要选择菜单项(请参阅SelectionItem模式),然后在button元素上使用Invoke模式。除非您定义自己的可访问对等方并实现其调用模式,这样您就不可能在调用invoke时设置焦点,否则无法阻止设置焦点。我建议在调用invoke之前找到具有焦点的元素,并在调用invoke之后再次赋予它焦点。如果您能告诉我为什么不希望被测应用程序接收焦点,我可能会想出一个更好的主意。不希望被测应用程序接收焦点的目的是,该应用程序的典型用户将在某个游戏中处于全屏模式,并且一旦他们按下某个键盘按键我正在创建的应用程序应该去“点击”另一个“正在测试”的应用程序上的某些按钮。这另一个应用程序是做什么的?保存游戏重播?它控制游戏中的角色,它是一个机器人。