WatiN NativeElement.GetElementBounds () - What is the unit of measure?
When I test WatiN I like to save screenshots. Sometimes I don't really want a photo of the entire browser window, although I just want to get an image of the element I'm testing.
My attempt to save an image of an element with the code below resulted in the block block being displayed because elementBounds.Top points to a pixel position past the bottom of the screen. The elementBounds.Width and .Height values also seem to be about half of what they should be.
Is this a WatiN bug or are these properties in a different unit that I have to convert to pixels somehow?
public static void SaveElementScreenshot
(WatiN.Core.IE ie, WatiN.Core.Element element, string screenshotPath)
{
ScrollIntoView(ie, element);
ie.BringToFront();
var ieClass = (InternetExplorerClass) ie.InternetExplorer;
Rectangle elementBounds = element.NativeElement.GetElementBounds();
int left = ieClass.Left + elementBounds.Left;
int top = ieClass.Top + elementBounds.Top;
int width = elementBounds.Width;
int height = elementBounds.Height;
using (var bitmap = new Bitmap(width, height))
{
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.CopyFromScreen
(new Point(left, top), Point.Empty, new Size(width, height));
}
bitmap.Save(screenshotPath, ImageFormat.Jpeg);
}
}
a source to share
It looks like this is a WatiN bug. As discussed on issue tracker WatiN , the "get bounds" method for Internet Explorer items looks like this:
internal static Rectangle GetHtmlElementBounds(IHTMLElement element)
{
int offsetLeft = element.offsetLeft;
int offsetTop = element.offsetTop;
for (IHTMLElement element2 = element.parentElement; element2 != null; element2 = element2.parentElement)
{
offsetLeft += element2.offsetLeft;
offsetTop += element2.offsetTop;
}
int width = element.offsetWidth / 2;
return new Rectangle(offsetLeft, offsetTop, width, element.offsetHeight / 2);
}
The error is because it divides offsetWidth and offsetHeight by 2.
I replaced the call to element.NativeElement.GetElementBounds to call my own GetElementBounds method and it works the way I want:
private static Rectangle GetElementBounds(Element element)
{
var ieElem = element.NativeElement as WatiN.Core.Native.InternetExplorer.IEElement;
IHTMLElement elem = ieElem.AsHtmlElement;
int left = elem.offsetLeft;
int top = elem.offsetTop;
for (IHTMLElement parent = elem.offsetParent; parent != null; parent = parent.offsetParent)
{
left += parent.offsetLeft;
top += parent.offsetTop;
}
return new Rectangle(left, top, elem.offsetWidth, elem.offsetHeight);
}
The only remaining problem is that the top and left properties do not compensate for the chrome browser window size, so the screen shot of the element is farther and to the right than it should be.
Until I figure out how to compensate for this, I avoid this by setting the browser to "full screen" mode before taking a screenshot.
a source to share