You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#使用PrintWindow捕获隐藏/非活跃游戏窗口异常问题求助

解决方案

问题根源

现代游戏大多使用DirectX/OpenGL等硬件加速技术渲染画面,这些画面直接输出到显卡帧缓冲区,而非通过GDI绘制链路。PrintWindow默认调用只能捕获GDI绘制的内容,因此无法获取游戏的实际渲染画面。


方法1:使用PrintWindow的全屏渲染标志

尝试调用PrintWindow时传入PW_RENDERFULLCONTENT(值为0x00000002),该标志会强制窗口渲染完整内容,对部分支持此机制的游戏有效。

修改代码步骤:

  1. 添加常量定义:
private const uint PW_RENDERFULLCONTENT = 0x00000002;
  1. 修改PrintWindow调用:
PrintWindow(handle, hdcBitmap, PW_RENDERFULLCONTENT);

方法2:使用Windows Graphics Capture API(推荐Win10及以上系统)

这是微软针对现代应用和硬件加速窗口设计的官方捕获方案,支持捕获非活跃、被遮挡的窗口,无需特殊权限,兼容性更好。

示例代码核心逻辑:

using Windows.Graphics.Capture;
using Windows.Graphics.DirectX;
using Windows.Graphics.DirectX.Direct3D11;
using System.Drawing;
using System.Drawing.Imaging;

public static async Task<Bitmap> CaptureGameWindowAsync(IntPtr hwnd)
{
    // 通过窗口句柄获取捕获项
    var captureItem = GraphicsCaptureItem.TryCreateFromWindowId(Win32Interop.GetWindowIdFromWindow(hwnd));
    if (captureItem == null) return null;

    // 创建Direct3D设备
    var d3dDevice = Direct3D11Helper.CreateDevice();
    // 创建帧池
    var framePool = Direct3D11CaptureFramePool.Create(
        d3dDevice,
        DirectXPixelFormat.B8G8R8A8UIntNormalized,
        1,
        captureItem.Size);

    // 创建捕获会话并启动
    var captureSession = framePool.CreateCaptureSession(captureItem);
    captureSession.StartCapture();

    // 获取捕获帧
    var captureFrame = await framePool.TryGetNextFrameAsync();
    if (captureFrame == null)
    {
        captureSession.Dispose();
        framePool.Dispose();
        return null;
    }

    // 将Direct3D表面转换为Bitmap
    var bitmap = BitmapFromDirect3DSurface(captureFrame.Surface);
    
    // 释放资源
    captureFrame.Dispose();
    captureSession.Dispose();
    framePool.Dispose();

    return bitmap;
}

// 辅助方法:将Direct3D Surface转换为GDI Bitmap
public static Bitmap BitmapFromDirect3DSurface(IDirect3DSurface surface)
{
    using (var stream = new InMemoryRandomAccessStream())
    {
        var encoder = BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream).AsTask().Result;
        encoder.SetSoftwareBitmap(SoftwareBitmap.CreateCopyFromSurface(surface, BitmapAlphaMode.Premultiplied)).AsTask().Wait();
        encoder.FlushAsync().AsTask().Wait();

        stream.Seek(0);
        return new Bitmap(stream.AsStream());
    }
}

注:需要项目支持.NET 5+或添加WinRT包引用,具体可参考微软官方文档。


方法3:Direct3D钩子捕获(进阶方案)

对于不支持Windows Graphics Capture的老旧游戏,可以通过钩子IDXGISwapChain::Present方法拦截游戏的帧渲染,直接从显卡获取帧数据。这种方法需要深入掌握Direct3D编程知识,适合对性能要求较高的场景。


内容的提问来源于stack exchange,提问作者Сергей

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 21:14:50