简体   繁体   English

BitBlt 屏幕截图在 Windows 10 上不起作用

[英]BitBlt screen capture not working on Windows 10

I'm using this code to capture a process window in the background:我正在使用此代码在后台捕获进程窗口:

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;
}

This code is capture an Android emulator called MEmu, it is using DirectX to render the content.此代码捕获一个名为 MEmu 的 Android 模拟器,它使用 DirectX 来呈现内容。 But this code stopped to work after Windows 10 updated to version 16299 (it was working normally before), it still working on Windows 7 with Aero mode enabled.但是此代码在 Windows 10 更新到版本 16299 后停止工作(之前它可以正常工作),它仍然可以在启用 Aero 模式的 Windows 7 上工作。

When I use this method in the Windows 10 Pro v16299.X it simply return a white image or it returns the emulator "loading screen", not the running content.当我在 Windows 10 Pro v16299.X 中使用此方法时,它只会返回白色图像或返回模拟器“加载屏幕”,而不是正在运行的内容。 On Windows 7, if I remove the Aero mode it will act the same, capturing the "loading screen", so looks like somehow the way the transparency works in the new windows 10 pro update changed.在 Windows 7 上,如果我删除 Aero 模式,它的行为将相同,捕获“加载屏幕”,因此看起来在新的 Windows 10 专业版更新中透明度的工作方式不知何故发生了变化。

I've tried everything, tried install some modules to force Aero Mode to work on Windows 10, tried PrintWindow to capture the screen in the background, but still the same.我已经尝试了一切,尝试安装一些模块以强制 Aero 模式在 Windows 10 上工作,尝试 PrintWindow 在后台捕获屏幕,但仍然相同。

Any ideas what could be happening?任何想法可能会发生什么? Or a possible solution?或者可能的解决方案? Or what changed in this last Windows 10 Pro version that could break that code?或者在最后一个 Windows 10 Pro 版本中发生了什么变化可能会破坏该代码?

Thank you!谢谢!

Hopefully this will solve the problem.希望这将解决问题。 There is a method for capturing the screen that is built in to the .net framework that may work.有一种捕获屏幕的方法,该方法内置于 .net 框架中,可能会起作用。 Not sure if it will capture DirectX content, but it may be worth a try.不确定它是否会捕获 DirectX 内容,但可能值得一试。

Please note that this solution captures the current screen, but you will probably be able to modify it to capture only the area you are interested in.请注意,此解决方案会捕获当前屏幕,但您可能可以对其进行修改以仅捕获您感兴趣的区域。

I found this solution here: https://www.c-sharpcorner.com/UploadFile/2d2d83/how-to-capture-a-screen-using-C-Sharp/我在这里找到了这个解决方案: 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);
    }
}

For me this is working on Windows 10 11.02.2021:对我来说,这适用于 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM