如何确定窗口是否在屏幕外?

Windows XP及更高版本中,给定一个窗口句柄(HWND),如何判断窗口的位置和大小是否不可恢复地离开窗口? 例如,如果标题栏可用于光标,则窗口可以被拖回到屏幕上。 我需要发现窗口是否实际上可见或至less可以提供给用户。 我想我也需要知道如何检测和响应分辨率的变化,以及如何处理多个显示器。 这似乎是一个相当大的交易。 我正在使用C ++和普通的SDK,所以请限制你的答案,而不是调用C#或类似的平台。

Windows使得在主监视器上确定用户工作区域的大小(即,屏幕上未被任务栏遮挡的区域)的相对简单。 调用SystemParametersInfo函数并为第一个参数( uiAction )指定SPI_GETWORKAREA标志。 pvParam参数应指向RECT结构 ,该结构将以虚拟屏幕坐标接收工作区域的坐标。

一旦获得了描述工作区域的坐标,将它们与应用程序窗口的当前位置进行比较,以确定它是否位于这些边界内就是一件简单的事情。

支持多台显示器的愿望使事情稍微复杂一些。 SystemParametersInfo文档建议您需要调用GetMonitorInfo函数来获取除主GetMonitorInfo以外的监视器的工作区域。 它填充名为MONITORINFOEX的结构,其中包含成员rcWork ,该成员定义了该监视器的工作区域,再次以虚拟屏幕坐标表示为RECT结构。

要做到这一点,您需要枚举用户连接到系统的所有监视器,并使用GetMonitorInfo检索每个GetMonitorInfo的工作区域。

在互联网上有几个这样的例子:

  • MSDN有多个显示设置上的定位对象的示例代码。
  • 如果你使用的是MFC,那么看起来是多显示器支持的一个很好的例子 。
  • 即使你不使用MFC,这篇文章也提到了下面这个链接 , 这个链接看起来像是一个真正的宝石,至于解释在Windows中多个显示器支持是如何工作的,即使它有点老派。 喜欢与否,在Windows的更高版本中,这一点已经发生了变化。

最后,你提到想要检测分辨率的变化。 这比你想象的要简单得多。 如您所知,如果您已经完成了Windows编程,操作系统与您的应用程序进行通信的主要方式是将消息发送到WindowProc函数 。
在这种情况下,您需要监视WM_DISPLAYCHANGE消息 ,该消息在显示分辨率发生变化时发送到所有窗口。 wParam包含以像素为单位的新图像深度; lParam的低位字指定水平分辨率, lParam的高位字指定屏幕的垂直分辨率。

可见性检查非常简单。

 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

UPDATE

正如@Cody Gray指出的,我认为WM_DISPLAYCHANGE比WM_SETTINGCHANGE更合适。 但MFC 9.0库使用WM_SETTINGCHANGE。