如何在win32 API中获取所有屏幕的尺寸(RECT)?

6

我正在编写一个应用程序,为测试团队提供帮助。这个应用程序可以让你截取屏幕的任意部分,并将其上传到测试团队服务器,并附上评论。

截图需要选择屏幕上的区域来进行截图。为此,我创建了一个半透明窗口并覆盖整个屏幕。目前我使用GetDesktopWindow()GetWindowRect()来获取屏幕的尺寸,但是在多屏幕环境下这种方法不起作用。

那么如何将一个窗口覆盖在所有可能的屏幕上呢?

屏幕配置可能非常奇特,例如:

     [LCD]
[LCD][LCD][LCD]

4块LCD屏幕 - 顶部一块,底部三块

或者

[LCD]     [LCD]
[LCD][LCD][LCD]
[LCD]     [LCD]

(7块液晶屏幕 - 3块在右边,3块在左边,1块在中间)。

等等。

有人知道我如何将一个窗口覆盖在所有屏幕上吗?当顶部行左右没有屏幕时,在第一个奇特的例子中尺寸会是什么样子呢?

也许我应该为每个液晶屏幕创建一个叠加窗口?

有什么想法吗?

3个回答

9
你可以使用EnumDisplayMonitors函数来实现此功能。以下是一个小类,它会自动构建一个包含系统中所有监视器的向量,并将它们全部合并在一起。
struct MonitorRects
{
    std::vector<RECT>   rcMonitors;
    RECT                rcCombined;

    static BOOL CALLBACK MonitorEnum(HMONITOR hMon,HDC hdc,LPRECT lprcMonitor,LPARAM pData)
    {
        MonitorRects* pThis = reinterpret_cast<MonitorRects*>(pData);
        pThis->rcMonitors.push_back(*lprcMonitor);
        UnionRect(&pThis->rcCombined, &pThis->rcCombined, lprcMonitor);
        return TRUE;
    }

    MonitorRects()
    {
        SetRectEmpty(&rcCombined);
        EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this);
    }
};

如果你只是使用来自rcCombined矩形创建一个大窗口,它将覆盖所有屏幕,“缺失”的部分将被系统自动裁剪。


7
请参考MSDN中关于多显示器的详细信息:
- 多个显示器:Multiple Display Monitors - 虚拟屏幕:Virtual Screen - 多显示器系统指标:Multiple Monitor System Metrics 您可以使用GetSystemMetrics()函数和SM_XVIRTUALSCREENSM_YVIRTUALSCREENSM_CXVIRTUALSCREENSM_CYVIRTUALSCREEN参数来检索包含所有物理屏幕的整个虚拟屏幕的矩形。

SM_CXVIRTUALSCREEN和SM_CYVIRTUALSCREEN似乎只提供主监视器右侧和下方的宽度和高度(从虚拟坐标0,0开始)。如果您有一个位于主监视器左侧的监视器,则SM_XVIRTUALSCREEN将返回虚拟显示原点的正确负值,但是监视器的宽度不会计入SM_CXVIRTUALSCREEN的返回值中(至少在Windows7 SP1上)。 - Bill Brooks
如果是真的,那就是一个bug需要向微软报告,因为它明显违反了文档中的行为规范。 - Remy Lebeau

1
不,那是一个错误。负坐标是设计的一部分,如果用户将监视器移动到主监视器的0,0(顶部,左侧)点之外,这是可以接受的,因此对于超出主监视器边界矩形左侧和顶部的移动的监视器,负坐标将适用。0,0主要点不是虚拟屏幕坐标参考。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接