Windows下如何判断窗口句柄所属的显示器(多屏截图场景)
多显示器环境下捕获活动窗口图像的解决方案
你的问题核心是无法定位活动窗口所属的显示器,下面提供两种可靠的解决思路,结合Win32 API和Qt的特性来处理:
方法一:用Qt内置函数直接定位屏幕
Qt的QGuiApplication提供了screenAt()方法,只需传入窗口的任意坐标点(比如窗口左上角),就能直接得到该窗口所在的QScreen对象:
if (auto handle = GetForegroundWindow(); handle != nullptr) { RECT rect; GetWindowRect(handle, &rect); // 传入窗口左上角坐标,获取对应的屏幕 QPoint windowPos(rect.left, rect.top); QScreen* targetScreen = QGuiApplication::screenAt(windowPos); // 如果没找到(极端情况), fallback 到主屏幕 if (!targetScreen) { targetScreen = QGuiApplication::primaryScreen(); } // 捕获窗口图像 auto pixmap = targetScreen->grabWindow(0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); }
方法二:结合Win32 API精准匹配显示器
如果需要更底层的控制,可以用Win32的MonitorFromWindow函数获取窗口对应的显示器句柄,再和Qt的屏幕列表匹配:
#include <Windows.h> #include <QScreen> if (auto handle = GetForegroundWindow(); handle != nullptr) { RECT rect; GetWindowRect(handle, &rect); // 获取窗口所属的显示器句柄 HMONITOR hMonitor = MonitorFromWindow(handle, MONITOR_DEFAULTTONEAREST); MONITORINFO monitorInfo{}; monitorInfo.cbSize = sizeof(MONITORINFO); GetMonitorInfo(hMonitor, &monitorInfo); // 遍历Qt屏幕列表,找到匹配的屏幕 QScreen* targetScreen = nullptr; for (QScreen* screen : QGuiApplication::screens()) { QRect screenRect = screen->geometry(); // 对比显示器的矩形区域,找到匹配项 if (screenRect.left() == monitorInfo.rcMonitor.left() && screenRect.top() == monitorInfo.rcMonitor.top() && screenRect.width() == monitorInfo.rcMonitor.right() - monitorInfo.rcMonitor.left() && screenRect.height() == monitorInfo.rcMonitor.bottom() - monitorInfo.rcMonitor.top()) { targetScreen = screen; break; } } // Fallback到主屏幕 if (!targetScreen) { targetScreen = QGuiApplication::primaryScreen(); } auto pixmap = targetScreen->grabWindow(0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); }
关键说明
screenAt()方法是Qt推荐的简化方式,代码更简洁,适合大多数场景。MonitorFromWindow的MONITOR_DEFAULTTONEAREST参数确保即使窗口跨多个显示器,也能返回最近的那个显示器句柄。- 两种方法都加入了fallback逻辑,避免极端情况下找不到屏幕导致崩溃。
内容的提问来源于stack exchange,提问作者StereoMatching
相关产品推荐
相关产品推荐

