如何使用UI自动化激活Google Chrome标签项

时间:2016-08-26 10:28:03

标签: c# google-chrome ui-automation

我正在使用C#应用程序中的代码在Google Chrome中找到一个标签:

        Process[] procsChrome = Process.GetProcessesByName("chrome");
        foreach (Process chrome in procsChrome)
        {
            // the chrome process must have a window
            if (chrome.MainWindowHandle == IntPtr.Zero)
            {
                continue;
            }

            AutomationElement root = AutomationElement.FromHandle(chrome.MainWindowHandle);
            /*
            Condition condNewTab = new PropertyCondition(AutomationElement.NameProperty, "Nueva pestaña");
            AutomationElement elmNewTab = root.FindFirst(TreeScope.Descendants, condNewTab);
            // get the tabstrip by getting the parent of the 'new tab' button 
            TreeWalker treewalker = TreeWalker.ControlViewWalker;
            AutomationElement elmTabStrip = treewalker.GetParent(elmNewTab);
             */
            // loop through all the tabs and get the names which is the page title 
            Condition condTabItem = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.TabItem);
            foreach (AutomationElement tabitem in root.FindAll(TreeScope.Descendants, condTabItem))
            {
                Console.WriteLine(tabitem.Current.Name);

                // I NEED TO ACTIVATE THE TAB HERE

                break;
            }

            Condition condUrl = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit);
            foreach (AutomationElement edit in root.FindAll(TreeScope.Descendants, condUrl))
            {
                string value = ((System.Windows.Automation.ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value;
                Console.WriteLine(value);
            }

        }

我需要使用UI Automation选择某个标签项。我该怎么办?

2 个答案:

答案 0 :(得分:0)

我需要解决类似的问题。由于Chrome不能完全实现Windows自动化功能,因此必须采用不同的方式实现。

感谢此GitHub project我能够激活正确的Chrome标签。诀窍是按Ctrl + tab index激活选项卡,如果它的位置在1到8之间(9切换到最后一个选项卡,请参阅Chromebook keyboard shortcuts)。对于在集合Ctrl + Tab中进一步显示的标签,会反复按下,直到找到所需的标签。

但是,这并不容易,因为有时候选项卡可能会出现在UI自动化集合中。我已通过为每个选项卡调用TryGetClickablePoint方法并按返回的点的X坐标对选项卡进行排序来解决此问题。

bool ActivateChromeTab(string title)
{
  Process[] procsChrome = Process.GetProcessesByName("chrome");
  foreach (Process proc in procsChrome)
  {
    if (proc.MainWindowHandle == IntPtr.Zero)
    {
        continue;
    }
    AutomationElement root = AutomationElement.FromHandle(proc.MainWindowHandle);
    Condition condNewTab = new PropertyCondition(AutomationElement.NameProperty, "New Tab");
    AutomationElement elmNewTab = root.FindFirst(TreeScope.Descendants, condNewTab);
    TreeWalker treewalker = TreeWalker.ControlViewWalker;
    AutomationElement elmTabStrip = treewalker.GetParent(elmNewTab);
    Condition condTabItem = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.TabItem);
    var index = 0;

    var tabItems = elmTabStrip.FindAll(TreeScope.Children, condTabItem);

    var coll = new List<AutomationElement>();
    foreach (AutomationElement element in tabItems)
    {
        coll.Add(element);
    }

    bool NameMatch(string name)
    {
        return name == title || name.StartsWith(title + " ");
    }

    // short-circuit the search when no searched string cannot be found
    if (!coll.Any(e => NameMatch(e.Current.Name)))
    {
        continue;
    }

    var t = new Stopwatch();
    t.Start();
    var withPoints = coll.AsParallel().Select(e =>
    {
        var point = new System.Windows.Point(int.MaxValue, int.MaxValue);
        if (e.TryGetClickablePoint(out point))
        {

        }

        return new
        {
            Name = e.Current.Name,
            Element = e,
            Point = point
        };
    }).OrderBy(e => e.Point.X);

    foreach (var tabItem in withPoints)
    {
        index++;
        var name = tabItem.Name;
        if (NameMatch(name))
        {
            SetForegroundWindow(proc.MainWindowHandle); // activate window
            Select(index); // select tab                
            return true;
        }
    }
  }

  return false;
}

选择标签的方法:

public void Select(int tabIndex)
{
  const int maxShortcutNumber = 8;

  if (tabIndex <= 0) { return; }

  KeyDown(LCtrl);

  if (tabIndex <= maxShortcutNumber)
  {
    KeyPress(GetKeyNumber(tabIndex));
  }
  else
  {
    KeyPress(GetKeyNumber(maxShortcutNumber));

    for (var i = 0; i < tabIndex - maxShortcutNumber; i++)
    {
        i.Dump();
        const int timeToDigestPreviousKeyPress = 75;
        Thread.Sleep(timeToDigestPreviousKeyPress);
        KeyPress(Tab);
    }
  }
  KeyUp(LCtrl);
}

键盘处理方法(改编自KeyboardSend类)     [的DllImport( “USER32.DLL”)]     private static extern void keybd_event(byte bVk,byte bScan,int dwFlags,int dwExtraInfo);

public static byte GetKeyNumber(int number)
{
    if (number < 0 || number > 9)
        throw new ApplicationException("Invalid number for key press.");

    return (byte)(0x30 + number);
}

public static void KeyDown(byte vKey)
{
    keybd_event(vKey, 0, KEYEVENTF_EXTENDEDKEY, 0);
}

public static void KeyUp(byte vKey)
{
    keybd_event(vKey, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}

public static void KeyPress(byte vKey)
{
    KeyDown(vKey);
    KeyUp(vKey);
}

public static byte LCtrl = 0xA2; //VK_LCONTROL
public static byte LWin = 0x5B; //VK_LWIN
public static byte LAlt = 0xA4; //VK_LMENU
public static byte Tab = 0x09; //VK_TAB
private const int KEYEVENTF_EXTENDEDKEY = 1;
private const int KEYEVENTF_KEYUP = 2;

答案 1 :(得分:0)

对于那些绝望的灵魂,仍在寻找答案。这是我的方法,仅基于UI自动化API,而无需关注窗口和发送点击事件或热键。要使用下面的代码,您需要使用Guy Barker中所述的UIAutomationCore.dll互操作引用。

    Process[] allChromeProcesses = Process.GetProcessesByName("chrome");
    Process[] mainChromes = allChromeProcesses.Where(p => !String.IsNullOrEmpty(p.MainWindowTitle)).ToArray();
    //...
    //Here you need to check if you have found correct chrome instance
    //...
    var uiaClassObject = new CUIAutomation();

    IUIAutomationElement chromeMainUIAElement = uiaClassObject.ElementFromHandle(mainChromes[0].MainWindowHandle);
    //UIA_ControlTypePropertyId =30003, UIA_TabItemControlTypeId = 50019
    IUIAutomationCondition chromeTabCondition = uiaClassObject.CreatePropertyCondition(30003, 50019); 
    var chromeTabCollection = chromeMainUIAElement.FindAll(TreeScope.TreeScope_Descendants, chromeTabCondition);
    //UIA_LegacyIAccessiblePatternId = 10018, 0 -> Number of Chrome tab you want to activate
    var lp = chromeTabCollection.GetElement(0).GetCurrentPattern(10018) as IUIAutomationLegacyIAccessiblePattern;
    lp.DoDefaultAction();

您唯一需要记住的是,不可能在标签页中搜索最小化的Chrome窗口。