I am trying to take a screenshot of an element by calling the following (example) code:
var element = this.driver.FindElementByName("Example");
var sc = element.TakeScreenshot();
Now, when I was comparing the screenshot with the reference image (using OpenCvSharp) I kept getting very big errors. So I decided to take a look at the images, low and behold, the screenshot was always taken on the primary monitor, the app (Winforms) was running on the secondary monitor. All the actions performed on the element work normally, clicking it, getting it's attributes, … But for some reason, taking a screenshot does not work. Is there something I am missing, is this an Appium issue? Any help would be appreciated.
It turns out when using more than 1 monitor the .GetScreenshot()
probably doesn't take the correct X coordinate of the element. I bypassed this by updating the X coordinate based on the detected screens using an extension method and taking the picture out of the entire screen's screenshot. For any one that might be looking at a solution, here is what I did :
public static byte[] TakeSnapshot(this AppiumWebElement element, WindowsDriver<WindowsElement> driver)
{
Screenshot sc = driver.GetScreenshot();
Rectangle rect = GetBoundingRectangle(element);
using (MemoryStream ms = new(sc.AsByteArray))
{
using (Bitmap bmp = new(ms))
{
// If more than 1 screen is used, we need to adjust the rectangle's X based on screen count
// otherwise the screenshot will be always taken on the primary screen
int screenResolutionWidth = 1920;
int screenCount = GetScreenCount(bmp, screenResolutionWidth);
if (screenCount > 1)
{
rect.X += (screenCount - 1) * screenResolutionWidth;
}
using (Bitmap elementScreenshot = bmp.Clone(rect, bmp.PixelFormat))
using (MemoryStream croppedMemoryStream = new())
{
elementScreenshot.Save(croppedMemoryStream, ImageFormat.Bmp);
return croppedMemoryStream.ToArray();
}
}
}
}
private static int GetScreenCount(Bitmap bmp, int screenResWidth)
{
if (bmp.Width % screenResWidth != 0)
{
throw new ArgumentException(
$"Invalid parameters calculating screen resolution! {nameof(bmp.Width)}={bmp.Width}, {nameof(screenResWidth)}={screenResWidth} ");
}
return bmp.Width / screenResWidth;
}