【问题标题】:BitBlt screen capture not working on Windows 10BitBlt 屏幕截图在 Windows 10 上不起作用
【发布时间】:2018-05-27 20:56:33
【问题描述】:

我正在使用此代码在后台捕获进程窗口:

IntPtr = Process.GetProcessByName("memu")[0].MainWindowHandle;
RECT rc;
GetClientRect(hwnd, out rc);

IntPtr hdcFrom = GetDC(hwnd);
IntPtr hdcTo = CreateCompatibleDC(hdcFrom);

int Width = rc.right;
int Height = rc.bottom;

Bitmap bmp = null;

IntPtr hBitmap = CreateCompatibleBitmap(hdcFrom, Width, Height);
if (hBitmap != IntPtr.Zero) {
   IntPtr hLocalBitmap = SelectObject(hdcTo, hBitmap);

   BitBlt(hdcTo, 0, 0, Width, Height, hdcFrom, 0, 0, CopyPixelOperation.SourceCopy);
   SelectObject(hdcTo, hLocalBitmap);

   DeleteDC(hdcTo);
   ReleaseDC(hwnd, hdcFrom);

   bmp = Image.FromHbitmap(hBitmap);
   DeleteObject(hBitmap);
   return bmp;
}

此代码是捕获一个名为 MEmu 的 Android 模拟器,它使用 DirectX 来呈现内容。但是这段代码在 Windows 10 更新到 16299 版本后停止工作(之前可以正常工作),它仍然可以在启用 Aero 模式的 Windows 7 上工作。

当我在 Windows 10 Pro v16299.X 中使用此方法时,它只会返回白色图像,或者返回模拟器“加载屏幕”,而不是运行内容。在 Windows 7 上,如果我删除 Aero 模式,它的行为也会相同,捕获“加载屏幕”,因此看起来新 Windows 10 专业版更新中透明度的工作方式发生了某种变化。

我已经尝试了一切,尝试安装一些模块以强制 Aero 模式在 Windows 10 上运行,尝试 PrintWindow 在后台捕获屏幕,但仍然相同。

任何想法可能会发生什么?还是可能的解决方案?或者在最新的 Windows 10 Pro 版本中发生了哪些可能破坏该代码的变化?

谢谢!

【问题讨论】:

  • 16299.64 更改日志显示“Microsoft 图形组件的安全更新”,可能这些更新破坏了 DWM 中的某些内容作为副作用。没有其他 API 可以捕获隐藏的窗口,因此您可以希望 MS 修复它,或者使用 DirectX 挂钩等一些技巧。
  • 仅供参考,它在我们的 Windows 10 Pro 64 位版本 1607 中工作:获取全黑位图。
  • 在调用BitBlt 之后,立即执行以下操作:var error = Marshal.GetLastWin32Error();,如果您得到不同于 0(零)的任何值,请验证错误代码 HERE。为了使其正常工作,您需要在 DllImport 语句中添加 SetLastError = true。这将只给出最后一次 Win32 API 调用的错误,因此您可能需要对每个调用都执行此操作。
  • @IgorM - 至于报告错误的位置 - Windows 10 附带名为“Centrum Feedback”的应用程序,您可以使用它来报告建议/错误。
  • 几个月后问题依然存在,经过一些研究和测试,我和一些朋友找到了一些可能的“解决方案”解决问题HERE,但它仍然不是100%有效,也有API 调用中没有错误,有人在这个问题上运气好吗?

标签: c# windows windows-10


【解决方案1】:

希望这能解决问题。 .net 框架中内置了一种捕获屏幕的方法,该方法可能有效。不确定它是否会捕获 DirectX 内容,但可能值得一试。

请注意,此解决方案捕获当前屏幕,但您可能可以对其进行修改以仅捕获您感兴趣的区域。

我在这里找到了这个解决方案:https://www.c-sharpcorner.com/UploadFile/2d2d83/how-to-capture-a-screen-using-C-Sharp/

private void CaptureMyScreen()
{
      try
      {
           //Creating a new Bitmap object
          Bitmap captureBitmap = new Bitmap(1024, 768, PixelFormat.Format32bppArgb);

         //Bitmap captureBitmap = new Bitmap(int width, int height, PixelFormat);
         //Creating a Rectangle object which will  
         //capture our Current Screen
         Rectangle captureRectangle = Screen.AllScreens[0].Bounds;

         //Creating a New Graphics Object
         Graphics captureGraphics = Graphics.FromImage(captureBitmap);

        //Copying Image from The Screen
        captureGraphics.CopyFromScreen(captureRectangle.Left,captureRectangle.Top,0,0,captureRectangle.Size);

        //Saving the Image File (I am here Saving it in My E drive).
        captureBitmap.Save(@"E:\Capture.jpg",ImageFormat.Jpeg);

        //Displaying the Successfull Result

        MessageBox.Show("Screen Captured");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

【讨论】:

    【解决方案2】:

    对我来说,这适用于 Windows 10 11.02.2021:

    static void hflipAndSwapRandB(unsigned char* data, int w, int h, int dim)
        {
            int y = 0;
            int x = 0;
            int d;
            unsigned char swap = 0;
            int hh = h / 2;
            for (y = 0; y < hh; y++)
            {
                for (x = 0; x < w; x++)
                {
                    for (d = 0; d < dim; d++)
                    {
                        swap = data[y * dim * w + dim * x + d];
                        data[y * dim * w + dim * x + d] = data[(h - 1 - y) * dim * w + dim * x + dim - 1 - d];
                        data[(h - 1 - y) * dim * w + dim * x + dim - 1 - d] = swap;
                    }
                }
            }
        }
    
    static void copyScreen(unsigned char* pixels_out, int x, int y, int width, int height)
    {
        HDC hScreenDC = GetDC(GetDesktopWindow());
        HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
    
        if (width == -1 || height == -1)
        {
            width = GetDeviceCaps(hScreenDC, HORZRES);
            height = GetDeviceCaps(hScreenDC, VERTRES);
        }
    
        HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
        HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
    
        BitBlt(hMemoryDC, x, y, width, height, hScreenDC, x, y, SRCCOPY);
        hBitmap = (HBITMAP)SelectObject(hMemoryDC, hOldBitmap);
        BITMAPINFOHEADER   bi;
    
        bi.biSize = sizeof(BITMAPINFOHEADER);
        bi.biWidth = width-x;
        bi.biHeight = height-y;
        bi.biPlanes = 1;
        bi.biBitCount = 24;
        bi.biCompression = BI_RGB;
        bi.biSizeImage = 0;
        bi.biXPelsPerMeter = 0;
        bi.biYPelsPerMeter = 0;
        bi.biClrUsed = 0;
        bi.biClrImportant = 0;
        GetDIBits(hMemoryDC, hBitmap, 0, height-y, pixels_out, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
        hflipAndSwapRandB(pixels_out, width, height, 3);
    
        DeleteDC(hMemoryDC);
        DeleteDC(hScreenDC);
        DeleteObject(hBitmap);
    }
    

    【讨论】:

      猜你喜欢
      • 2017-09-21
      • 2021-03-20
      • 2016-12-16
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2017-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多