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

DwmRegisterThumbnail用于子窗口失效,求解决方案及替代API

问题:DwmRegisterThumbnail无法在子窗口中显示缩略图

我使用Windows API的DwmRegisterThumbnail将window1的画面投射到window2中,但当window2被设置为其他窗口的子窗口后,投射画面消失。查阅文档发现:目标窗口句柄为非顶级窗口时,DwmRegisterThumbnail会返回E_INVALIDARG错误。

相关代码如下:

HWND dest = (HWND)this->winId();
HWND source = ...
hr = DwmRegisterThumbnail(dest, source, &thumbnail_id);
DWORD err = GetLastError();
qDebug() << "hr: " << hr;

if (SUCCEEDED(hr) && NULL != thumbnail_id)
{
    prop.dwFlags = DWM_TNP_RECTDESTINATION | DWM_TNP_RECTSOURCE | DWM_TNP_OPACITY
        | DWM_TNP_VISIBLE | DWM_TNP_SOURCECLIENTAREAONLY;
    prop.rcSource = { 0, 0, 1200, 600 };
    prop.rcDestination = { 0, 0, 1200, 600 };
    prop.opacity = 255;
    prop.fVisible = TRUE;
    prop.fSourceClientAreaOnly = FALSE;

    hr = DwmUpdateThumbnailProperties(thumbnail_id, &prop);

    qDebug() << "hr: " << hr;
}

我还尝试使用QDockWidget,但仅在小部件未停靠到MainWindow时画面可见,一旦停靠就消失。请问有没有办法实现将画面投射到子窗口?或者是否有其他可用的Windows API?


可行方案

方案1:用顶级窗口作为缩略图容器,再挂载为子窗口

既然DwmRegisterThumbnail仅支持顶级窗口,可创建一个无边框顶级窗口承载缩略图,再通过SetParent将其挂载到目标子窗口容器中,同步位置和大小使其看起来像原生子部件:

// 创建无边框的顶级承载窗口
HWND thumbHost = CreateWindowEx(0, L"STATIC", L"", WS_POPUP | WS_VISIBLE, 
                                0, 0, 1200, 600, NULL, NULL, GetModuleHandle(NULL), NULL);
// 注册缩略图到承载窗口
hr = DwmRegisterThumbnail(thumbHost, source, &thumbnail_id);
// 将承载窗口挂载到目标子窗口
SetParent(thumbHost, dest);
// 同步承载窗口与目标子窗口的客户端区域大小
RECT clientRect;
GetClientRect(dest, &clientRect);
SetWindowPos(thumbHost, NULL, 0, 0, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top, SWP_NOZORDER);

方案2:手动捕获源窗口画面并绘制

跳过DWM缩略图机制,直接在子窗口的绘制事件中捕获源窗口画面并手动绘制:

void MyWidget::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);
    if (!source) return;

    HDC hdcSource = GetDC(source);
    HDC hdcDest = GetDC((HWND)winId());
    RECT srcRect;
    GetClientRect(source, &srcRect);
    // 捕获源窗口客户端区域画面
    PrintWindow(source, hdcSource, PW_CLIENTONLY);
    // 将画面绘制到当前子窗口
    BitBlt(hdcDest, 0, 0, srcRect.right, srcRect.bottom, hdcSource, 0, 0, SRCCOPY);

    ReleaseDC(source, hdcSource);
    ReleaseDC((HWND)winId(), hdcDest);
}

注意:PrintWindow对部分硬件加速窗口捕获效果不佳,可替换为GDI+或DXGI截屏方案。

方案3:使用DirectComposition API

DirectComposition支持将窗口缩略图绘制到非顶级窗口,灵活性更强,适合需要特效或复杂布局的场景:

  1. 初始化IDCompositionDevice和关联到子窗口的IDCompositionTarget
  2. 创建IDCompositionVisual并绑定源窗口缩略图
  3. 将视觉对象添加到目标并提交更新

该方案代码量较大,但能更好地适配子窗口场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:10:38