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支持将窗口缩略图绘制到非顶级窗口,灵活性更强,适合需要特效或复杂布局的场景:
- 初始化
IDCompositionDevice和关联到子窗口的IDCompositionTarget - 创建
IDCompositionVisual并绑定源窗口缩略图 - 将视觉对象添加到目标并提交更新
该方案代码量较大,但能更好地适配子窗口场景。
内容的提问来源于stack exchange,提问作者Cesar
相关产品推荐
相关产品推荐

