Windows很容易确定用户在主显示器上的工作区大小(即屏幕不被任务栏遮挡的区域)。调用SystemParametersInfo
函数并指定第一个参数(uiAction
)为SPI_GETWORKAREA
标志。其中pvParam
参数应指向接收虚拟屏幕坐标下工作区坐标的RECT
结构。
一旦您获得了描述工作区的坐标,只需将其与您的应用程序窗口的当前位置进行比较,以确定它是否落在这些范围内。
支持多个监视器需要考虑到更多因素。文档建议调用GetMonitorInfo
函数获取除主监视器外其他监视器的工作区,该函数会填充名为MONITORINFOEX
的结构体,其中包含成员rcWork
,该成员定义该监视器的工作区,同样以RECT
结构体表示虚拟屏幕坐标。
要做到这一点,您需要枚举用户连接到系统的所有监视器,并使用GetMonitorInfo
检索每个监视器的工作区。
在互联网上有一些此类示例:
最后,您提到想要检测分辨率更改。这比您想象的要简单得多。如果您已经进行了任何Windows编程,那么操作系统与您的应用程序之间的主要通信方式是通过向您的WindowProc
函数发送消息。
在这种情况下,您将需要监视WM_DISPLAYCHANGE
消息,该消息会在显示器分辨率更改时发送给所有窗口。 wParam
包含新的图像深度(每像素位数);lParam
的低位字包含屏幕的水平分辨率,高位字则指定垂直分辨率。
POINT p;
p.x = x;
p.y = y;
HMONITOR hMon = MonitorFromPoint(p, MONITOR_DEFAULTTONULL);
if (hMon == NULL) {
// point is off screen
}
可见性检查非常简单。
RECT rtDesktop, rtView;
GetWindowRect( GetDesktopWindow(), &rtDesktop );
GetWindowRect( m_hWnd, &rtView );
HRGN rgn = CreateRectRgn( rtDesktop.left, rtDesktop.top, rtDesktop.right, rtDesktop.bottom );
BOOL viewIsVisible = RectInRegion( rgn, &rtView );
DeleteObject(rgn);
http://msdn.microsoft.com/en-us/library/ms725497(v=vs.85).aspx
更新
正如 @Cody Gray 所指出的,我认为 WM_DISPLAYCHANGE 比 WM_SETTINGCHANGE 更加合适。但是 MFC 9.0 库使用了 WM_SETTINGCHANGE。
GetSystemMetrics
函数来确定实际大小时。要获取窗口标题栏的高度(以像素为单位),请在nIndex
参数中指定SM_CYCAPTION
。要获取窗口边框的宽度(以像素为单位),请指定SM_CXBORDER
,要获取窗口边框的高度(以像素为单位),请指定SM_CYBORDER
。 - Cody Gray