有没有办法在.net-core中捕获窗口的屏幕图像?

时间:2019-02-13 08:34:29

标签: .net-core cross-platform screen-capture image-capture

我要将项目从.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上使用提到的导入功能?

0 个答案:

没有答案