在Windows XP及更高版本中,给定一个窗口句柄(HWND),如何判断窗口位置和大小是否会使窗口无法恢复到屏幕外?例如,如果标题栏可用于光标,则可以将窗口拖回屏幕。我需要发现窗口是否实际可见或至少对用户可用。我想我还需要知道如何检测和响应分辨率变化以及如何处理多个监视器。这似乎是一个相当大的交易。我正在使用C ++和常规SDK,因此请限制您对该平台的回答,而不是调用C#或类似的。
答案 0 :(得分:18)
Windows使得在主监视器上确定用户工作区域的大小(即,未被任务栏遮挡的屏幕区域)变得相对简单。调用 SystemParametersInfo
function并为第一个参数(SPI_GETWORKAREA
)指定 uiAction
标志。 pvParam
参数应指向RECT
structure,它将在虚拟屏幕坐标中接收工作区域的坐标。
一旦你获得了描述工作区域的坐标,就可以将它们与应用程序窗口的当前位置进行比较,以确定它是否位于这些边界内。
支持多个监视器的愿望使事情稍微复杂一些。 SystemParametersInfo
的文档建议您需要调用GetMonitorInfo
function来获取除主数据库之外的监视器的工作区域。它填充了一个名为MONITORINFOEX
的结构,其中包含定义该监视器工作区域的成员rcWork
,再次以虚拟屏幕坐标表示为RECT
结构。
要做到这一点,您需要枚举用户连接到系统的所有监视器,并使用GetMonitorInfo
检索每个监视器的工作区域。
互联网上有一些这样的样本:
最后,您提到要检测分辨率更改。这比你想象的要简单得多。如您所知,如果您已完成任何Windows编程,则操作系统与您的应用程序通信的主要方式是向WindowProc
function发送消息。
在这种情况下,您需要注意WM_DISPLAYCHANGE
message,当显示分辨率发生变化时,会发送到所有窗口。 wParam
包含每像素位数的新图像深度; lParam
的低位字指定水平分辨率,lParam
的高位字指定屏幕的垂直分辨率。
答案 1 :(得分:3)
您可以使用MonitorFromRect或MonitorFromPoint检查窗口的左上角或右下角是否包含在任何显示器中(屏幕外)。
POINT p;
p.x = x;
p.y = y;
HMONITOR hMon = MonitorFromPoint(p, MONITOR_DEFAULTTONULL);
if (hMon == NULL) {
// point is off screen
}
答案 2 :(得分:0)
可见性检查非常简单。
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);
您不必使用RectInRegion,我用它来缩短代码。
如果您处理WM_SETTINGCHANGE消息,显示,分辨率更改监控也很容易。
http://msdn.microsoft.com/en-us/library/ms725497(v=vs.85).aspx
<强>更新强>
正如@Cody Gray所说,我认为WM_DISPLAYCHANGE比WM_SETTINGCHANGE更合适。但是MFC 9.0库使用了WM_SETTINGCHANGE。