解决方法
看了几次,还没有找到WebDriver的优雅解决方案(他们有一个看起来支持他们的ILocatable设置的参数,但该方法尚未实现).
我所做的是使用UIAutomation获取windows AutomationElement并使用树木行者来查找窗口的实际对象 – 缺点是我注意到浏览器偶尔会更新它们的窗口,因此条件必须每隔一段时间更改一次以适应.
这是一些示例代码(我在这里删除了一些公司代码,所以它在我的结尾更优雅,但这应该适用于C#)
public static Rectangle GetAbsCoordinates(this IWebElement element) { var driver = GetDriver(element); var handle = GetIntPtrHandle(driver); var ae = AutomationElement.FromHandle(handle); AutomationElement doc = null; var caps = ((RemoteWebDriver) driver).Capabilities; var browserName = caps.BrowserName; switch (browserName) { case "safari": var conditions = (new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty,ControlType.Pane),new PropertyCondition(AutomationElement.ClassNameProperty,"SearchableWebView"))); doc = ae.FindFirst(TreeScope.Descendants,conditions); break; case "firefox": doc = ae.FindFirst(TreeScope.Descendants,new PropertyCondition(AutomationElement.ControlTypeProperty,ControlType.Document)); break; case "chrome": doc = ae.FindFirst(TreeScope.Descendants,new PropertyCondition(AutomationElement.NameProperty,"Chrome Legacy Window")); if (doc == null) { doc = ae.FindFirst(TreeScope.Descendants,"Google Chrome")); if (doc == null) throw new Exception("unable to find element containing browser window"); doc = doc.FindFirst(TreeScope.Descendants,ControlType.Document)); } break; case "internet explorer": doc = ae.FindFirst(TreeScope.Descendants,new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty,"TabWindowClass"))); break; } if (doc == null) throw new Exception("unable to find element containing browser window"); var iWinLeft = (int) doc.Current.BoundingRectangle.Left; var iWinTop = (int)doc.Current.BoundingRectangle.Top; var coords = ((ILocatable) element).Coordinates; var rect = new Rectangle(iWinLeft + coords.LocationInDom.X,iWinTop + coords.LocationInDom.Y,element.Size.Width,element.Size.Height); return rect; } public static IWebDriver GetDriver(this IWebElement e) { return ((IWrapsDriver)e).WrappedDriver; } public static IntPtr GetIntPtrHandle(this IWebDriver driver,int timeoutSeconds = Timeout) { var end = DateTime.Now.AddSeconds(timeoutSeconds); while(DateTime.Now < end) { // Searching by AutomationElement is a bit faster (can filter by children only) var ele = AutomationElement.RootElement; foreach (AutomationElement child in ele.FindAll(TreeScope.Children,Condition.TrueCondition)) { if (!child.Current.Name.Contains(driver.Title)) continue; return new IntPtr(child.Current.NativeWindowHandle);; } } return IntPtr.Zero; }