Есть ли способ захватить изображение экрана окна в .net-core? - PullRequest
0 голосов
/ 13 февраля 2019

Я перевожу проект из .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?

...