Я перевожу проект из .net в .net-core, потому что требуется запустить приложение на Linux.Одной из особенностей является захват окна отдельного процесса, который выполняется вдоль основного приложения.
До .net-core я использовал два способа захвата изображения из второго окна.Оба решения использовали IntPtr и импортировали функции из user32.dll или user32.dll для захвата изображения (см. Фрагменты кода).
// Solution A:
private System.Drawing.Bitmap PrintImageFromWindow(IntPtr hwnd)
{
// get windows rect
RECT rc = new RECT();
GetWindowRect(hwnd, ref rc);
// create compatybile bitmap from window
Bitmap bmp = new Bitmap(rc.Right - rc.Left, rc.Bottom - rc.Top, PixelFormat.Format32bppPArgb);
// create GDI+ graphic
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();
// copies a visual window into the specified device context
bool succeeded = PrintWindow(hwnd, hdcBitmap, 0);
gfxBmp.ReleaseHdc(hdcBitmap);
// bmp now contains the screenshot
if (!succeeded)
{
gfxBmp.FillRectangle(new SolidBrush(System.Drawing.Color.Gray), new Rectangle(System.Drawing.Point.Empty, bmp.Size));
}
IntPtr hRgn = CreateRectRgn(0, 0, 0, 0);
GetWindowRgn(hwnd, hRgn);
Region region = Region.FromHrgn(hRgn);
if (!region.IsEmpty(gfxBmp))
{
gfxBmp.ExcludeClip(region);
gfxBmp.Clear(System.Drawing.Color.Transparent);
}
// cleanup
gfxBmp.Dispose();
return bmp;
}
// SOLUTION B:
private System.Drawing.Bitmap ScreenshotImageFromWindow(IntPtr windowHandle)
{
// get context for window
IntPtr windowHDC = GetWindowDC(windowHandle);
if (windowHDC == IntPtr.Zero)
return null;
// Create a compatible DC which is used in a BitBlt from the window DC
IntPtr sourceDC = CreateCompatibleDC(windowHDC);
if (sourceDC == IntPtr.Zero)
{
return null;
}
// Create a compatible bitmap from the Window DC
System.Drawing.Rectangle rctForm = System.Drawing.Rectangle.Empty;
using (System.Drawing.Graphics grfx = System.Drawing.Graphics.FromHdc(windowHDC))
{
rctForm = System.Drawing.Rectangle.Round(grfx.VisibleClipBounds);
}
IntPtr sourceBMP = CreateCompatibleBitmap(windowHDC, rctForm.Width, rctForm.Height);
if (sourceBMP == IntPtr.Zero)// if no compatible bitmap
{
return null;
}
// Select the compatible bitmap into the compatible memory DC.
SelectObject(sourceDC, sourceBMP);
// Bit block transfer into our compatible memory DC.
if (!BitBlt(sourceDC, 0, 0, rctForm.Width, rctForm.Height, windowHDC, 0, 0, DWROP_SRCCOPY))
{
return null;
}
// Create GDI+ bitmap for window
System.Drawing.Bitmap bmp = System.Drawing.Image.FromHbitmap(sourceBMP);
// Clean up
DeleteObject(sourceBMP);
DeleteObject(sourceDC);
ReleaseDC(windowHandle, windowHDC);
// return bitmap image to user
return bmp; // return bitmap
}
// some of imported code
[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);
[DllImport("gdi32.dll")]
private static extern IntPtr DeleteDC(IntPtr hDc);
[DllImport("user32.dll")]
private static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("gdi32.dll")]
private static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
[DllImport("gdi32.dll")]
private static extern IntPtr DeleteObject(IntPtr hDc);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("user32.dll")]
private static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);
Было бы другое решение для захвата изображения окна, которое будет работать и в Linux?Или есть возможность использовать упомянутые импортированные функции в Linux?