c# - 打印窗口闪烁

标签 c# .net winapi

我正在尝试使用我在 PrintWindow 中经常使用的方法来捕获窗口

RECT rc;
GetClientRect(hwnd, out rc); //The process window handler

Bitmap bmp = new Bitmap(rc.right, rc.bottom, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();

PrintWindow(hwnd, hdcBitmap, 1);

gfxBmp.ReleaseHdc(hdcBitmap);
gfxBmp.Dispose();
bmp.Save("test.png");

问题是在这个特定的游戏过程中,当它调用 Printwindow 函数时,窗口很快就会变黑,所以有时保存的图像是全白的。

所以我尝试使用 BitBlt:

Bitmap bmp = new Bitmap(rc.right, rc.bottom, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr dest = gfxBmp.GetHdc();
IntPtr source = GetWindowDC(hwnd);

BitBlt(dest, 0, 0, rc.width, rc.height, source, 0, 0, 13369376);
bmp.Save("test.png");

但是使用上面的代码保存的图像是全黑的。

有什么方法可以防止 PrintWindow 使进程窗口轻弹那个“白层”?如果可能的话,BitBtl 应该为我解决这个问题吧?但是我的代码有什么问题吗?

谢谢

最佳答案

您可以尝试使用此代码,它对我有用。如果您仍然看到黑色图像,可能您必须寻求 DWM 解决方案。

更新:修复了丢失的窗口参数

    public Bitmap CaptureWindowImage(IntPtr hWnd, System.Drawing.Rectangle wndRect)
    {
        IntPtr hWndDc = GetDC(hWnd);
        IntPtr hMemDc = CreateCompatibleDC(hWndDc);
        IntPtr hBitmap = CreateCompatibleBitmap(hWndDc, wndRect.Width, wndRect.Height);
        SelectObject(hMemDc, hBitmap);

        BitBlt(hMemDc, 0, 0, wndRect.Width, wndRect.Height, hWndDc, 0, 0, TernaryRasterOperations.SRCCOPY);
        Bitmap bitmap = Bitmap.FromHbitmap(hBitmap);

        DeleteObject(hBitmap);
        ReleaseDC(hWnd, hWndDc);
        ReleaseDC(IntPtr.Zero, hMemDc);

        return bitmap;
    }

    private enum TernaryRasterOperations : uint
    {
        /// <summary>dest = source</summary>
        SRCCOPY = 0x00CC0020,
        /// <summary>dest = source OR dest</summary>
        SRCPAINT = 0x00EE0086,
        /// <summary>dest = source AND dest</summary>
        SRCAND = 0x008800C6,
        /// <summary>dest = source XOR dest</summary>
        SRCINVERT = 0x00660046,
        /// <summary>dest = source AND (NOT dest)</summary>
        SRCERASE = 0x00440328,
        /// <summary>dest = (NOT source)</summary>
        NOTSRCCOPY = 0x00330008,
        /// <summary>dest = (NOT src) AND (NOT dest)</summary>
        NOTSRCERASE = 0x001100A6,
        /// <summary>dest = (source AND pattern)</summary>
        MERGECOPY = 0x00C000CA,
        /// <summary>dest = (NOT source) OR dest</summary>
        MERGEPAINT = 0x00BB0226,
        /// <summary>dest = pattern</summary>
        PATCOPY = 0x00F00021,
        /// <summary>dest = DPSnoo</summary>
        PATPAINT = 0x00FB0A09,
        /// <summary>dest = pattern XOR dest</summary>
        PATINVERT = 0x005A0049,
        /// <summary>dest = (NOT dest)</summary>
        DSTINVERT = 0x00550009,
        /// <summary>dest = BLACK</summary>
        BLACKNESS = 0x00000042,
        /// <summary>dest = WHITE</summary>
        WHITENESS = 0x00FF0062
    }

    [DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)]
    static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

    [DllImport("gdi32.dll")]
    private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);

    [DllImport("gdi32.dll", SetLastError = true)]
    private static extern IntPtr CreateCompatibleDC(IntPtr hdc);

    [DllImport("gdi32.dll")]
    private static extern bool DeleteObject(IntPtr hObject);

    [DllImport("gdi32.dll")]
    private static extern IntPtr CreateBitmap(int nWidth, int nHeight, uint cPlanes, uint cBitsPerPel, IntPtr lpvBits);

    [DllImport("user32.dll")]
    private static extern IntPtr GetDC(IntPtr hWnd);

    [DllImport("user32.dll")]
    private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

    [DllImport("gdi32.dll")]
    private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);

关于c# - 打印窗口闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38558309/

相关文章:

c++ - Windows 获取卷上所有文件的大小列表

c# - 如何处理一些异步的 TcpClient 响应?

.net - 带边距的分组 WPF ListView 样式问题

c++ - 递归函数中的堆栈溢出

c# - String 、 Int32 等的操作在哪里定义?

c# - .rdlc 报告 - 无法为数据集 'DataSet1' 创建数据读取器

c++ - 在哪个头文件中声明了函数 `_tcscpy_s`?

c# - 如何在不使用系统命名空间的情况下使用字符串

c# - 将自动调整图像大小的 ImageButton

c# - VB.Net - 检查文件是否为 .net 二进制文件