c# - BitBlt 屏幕捕获在 Windows 10 上不起作用

标签 c# windows windows-10

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

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 Pro 更新中的工作方式发生了变化。

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

你知道会发生什么吗?或者一个可能的解决方案?或者最后一个 Windows 10 专业版中发生了什么变化可能会破坏该代码?

谢谢!

最佳答案

对我来说,这适用于 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);
}

关于c# - BitBlt 屏幕捕获在 Windows 10 上不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47801997/

相关文章:

c# - .Net 内存跟踪中的 "TargetCore"是什么?

c# - 需要一种方法来获取当前请求 URL 以在 Multi-Tenancy 应用程序中配置数据库上下文

c# - 如何在给定自引用表中的以下路由别名的情况下获取最后一个类别

windows - 在 Windows 上使用 SonarQube 和备用 IP 地址会出现绑定(bind)错误

Windows 10 : how to prevent switching or closing an application

c# - 依赖注入(inject)如何帮助对象组合?

c - 虚拟分配粒度和页面大小

c# - 如何在 Windows 10 中运行 Visual Studio 创建的 C# exe 文件?

python - 如何授予应用程序(而非用户本身)对文件夹和文件的权限

windows - 在 cmake 中强制构建 x64 位