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

如何编程截取Zoom窗口?标准Windows API截图异常问题

如何正确截取Zoom窗口的视频内容?

我需要通过编程截取Zoom窗口,使用标准Windows API实现,但仅能捕获窗口框架,视频区域显示的是窗口后方的内容(测试时后方运行的是Visual Studio)。使用的代码如下:

Hdc hdcWindow = GetWindowDC(hwnd);
Hdc hdcMemDC = CreateCompatibleDC(hdcWindow);

var windowRect = new Rect();
GetWindowRect(hwnd, ref windowRect);
int width = windowRect.Right - windowRect.Left;
int height = windowRect.Bottom - windowRect.Top;

var hbmScreen = CreateCompatibleBitmap(hdcWindow, width, height);
var hOld = SelectObject(hdcMemDC, hbmScreen);

// 尝试过的三种方式
BitBlt(hdcMemDC, 0, 0, width, height, hdcWindow, 0, 0, SRCCOPY);
PrintWindow(hwnd, hdcMemDC, 0);
// SendMessage(hwnd, WM_PRINT, hdcMemDC, (IntPtr)(PRF_CHILDREN | PRF_CLIENT | PRF_NONCLIENT));

// 获取位图
var bmp = System.Drawing.Bitmap.FromHbitmap(hbmScreen);
                
// 资源清理
SelectObject(hdcMemDC, hOld);
DeleteObject(hbmScreen);
DeleteDC(hdcMemDC);
ReleaseDC(hwnd, hdcWindow);

return bmp;

实际运行后,Zoom的标题栏和控件能正常截取,但视频客户区始终显示窗口后方的内容,重启Zoom前每次截图结果一致。推测Zoom采用了非常规窗口机制,求正确的截取方法。


解决方案

Zoom的视频渲染采用了硬件加速的DirectComposition/Direct3D表面,这类内容无法被传统的GDI捕获API(BitBlt/PrintWindow/WM_PRINT)直接捕获,需要使用支持硬件加速内容的捕获方案:

1. 使用Windows.Graphics.Capture API(推荐,Windows 10 1809及以上)

这是微软官方提供的现代捕获API,专门针对硬件加速渲染的窗口/屏幕内容设计,步骤如下:

  • 确保应用声明graphicsCapture权限(UWP应用需在Package.appxmanifest中添加对应权限;Win32应用需通过SetProcessDpiAwarenessContext设置DPI感知,并启用相关权限)
  • 将Zoom窗口的HWND转换为GraphicsCaptureItem
  • 创建捕获会话并监听帧到达事件,获取并处理捕获帧

示例代码:

using Windows.Graphics.Capture;
using Windows.Graphics.DirectX;
using Windows.Graphics.DirectX.Direct3D11;
using System.Runtime.InteropServices;

[ComImport]
[Guid("3628E81B-3CAC-4C60-B7F4-23CE0E0C3356")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IGraphicsCaptureItemInterop
{
    void CreateForWindow(IntPtr window, ref Guid iid, out GraphicsCaptureItem item);
}

// 将HWND转换为GraphicsCaptureItem
public static async Task<GraphicsCaptureItem> GetCaptureItemFromHwnd(IntPtr hwnd)
{
    var interop = GraphicsCaptureItem.As<IGraphicsCaptureItemInterop>();
    Guid graphicsCaptureItemGuid = typeof(GraphicsCaptureItem).GUID;
    interop.CreateForWindow(hwnd, ref graphicsCaptureItemGuid, out var item);
    return item;
}

// 启动Zoom窗口捕获
public static async Task StartZoomCapture(IntPtr zoomHwnd)
{
    var captureItem = await GetCaptureItemFromHwnd(zoomHwnd);
    var captureSession = GraphicsCaptureSession.Create(captureItem);
    
    // 可选:禁用光标捕获
    captureSession.IsCursorCaptureEnabled = false;
    
    // 监听帧到达事件
    captureSession.FrameArrived += (sender, args) =>
    {
        using (var frame = sender.TryGetNextFrame())
        {
            // 将Direct3D表面转换为可处理的图像格式
            // 示例:转换为GDI Bitmap(需Direct3D11设备支持)
            var d3dSurface = frame.Surface;
            // 此处需实现Direct3D到GDI的像素转换逻辑
        }
    };
    
    captureSession.StartCapture();
}

2. 通过DwmGetWindowAttribute获取可视化表面

Zoom窗口的视频区域可能使用了DirectComposition渲染,可以通过DwmGetWindowAttribute获取窗口的可视化表面,再通过Direct3D API读取像素:

  • 调用DwmGetWindowAttribute,传入DWMWA_VISUALIZATION_ATTRIBUTES参数获取表面信息
  • 使用Direct3D设备获取表面的像素数据

3. 临时方案:禁用Zoom硬件加速

如果允许修改Zoom设置,可在Zoom的「设置-视频」中关闭硬件加速选项,之后传统的PrintWindow即可正常捕获视频内容,但会降低Zoom的视频渲染性能。


内容的提问来源于stack exchange,提问作者Joshua Frank

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 13:27:06