2011-01-13 23 views
9

En Windows XP y superior, dado un identificador de ventana (HWND), ¿cómo puedo saber si la posición y el tamaño de la ventana dejan la ventana irremediablemente fuera de la pantalla? Por ejemplo, si la barra de título está disponible para el cursor, entonces la ventana puede arrastrarse hacia atrás en la pantalla. Necesito descubrir si la ventana es de hecho visible o al menos disponible para el usuario. Creo que también necesito saber cómo detectar y responder a los cambios de resolución y cómo lidiar con múltiples monitores. Esto parece bastante importante. Estoy usando C++ y el SDK normal, así que limite sus respuestas a esa plataforma en lugar de invocar C# o similar.¿Cómo puedo determinar si una ventana está fuera de la pantalla?

Respuesta

15

Windows hace que sea relativamente simple determinar el tamaño del área de trabajo de un usuario en el monitor principal (es decir, el área de la pantalla no oscurecida por la barra de tareas). Llame al SystemParametersInfo function y especifique SPI_GETWORKAREA para el primer parámetro (uiAction). El parámetro pvParam debe apuntar a un RECT structure que recibirá las coordenadas del área de trabajo en coordenadas de pantalla virtual.

Una vez que tenga las coordenadas que describen el área de trabajo, es una simple cuestión de compararlas con la posición actual de la ventana de su aplicación para determinar si se encuentra dentro de esos límites.


El deseo de admitir monitores múltiples hace las cosas un poco más complicadas. La documentación para SystemParametersInfo sugiere que necesita llamar al GetMonitorInfo function en su lugar para obtener el área de trabajo de un monitor que no sea el primario. Llena una estructura llamada MONITORINFOEX que contiene el miembro rcWork que define el área de trabajo de ese monitor, nuevamente expresada en coordenadas de pantalla virtual como una estructura RECT.

Para hacerlo bien, deberá enumerar todos los monitores que un usuario ha conectado al sistema y recuperar el área de trabajo de cada uno que use GetMonitorInfo.

Hay algunas muestras de este que se encuentran en torno a Internet:

  • MSDN tiene un código de ejemplo para Positioning Objects on a Multiple Display Setup.
  • Si está utilizando MFC, esto es lo que parece ser an excellent example de compatibilidad con monitores múltiples.
  • Incluso si no está utilizando MFC, ese artículo hace referencia al the following link que parece ser una verdadera joya en cuanto a explicar cómo funcionan los múltiples soportes de monitor en Windows, incluso si es un poco vieja escuela. Nos guste o no, muy poco de esto ha cambiado en versiones posteriores de Windows.


Finalmente, usted mencionó querer detectar cambios de resolución. Esto es mucho más simple de lo que probablemente imaginaste. Como sabe, si ha realizado alguna programación de Windows, la forma principal en que el sistema operativo se comunica con su aplicación es enviando mensajes a su WindowProc function.
En este caso, querrá ver el WM_DISPLAYCHANGE message, que se envía a todas las ventanas cuando la resolución de la pantalla ha cambiado. El wParam contiene la nueva profundidad de imagen en bits por píxel; la palabra de orden inferior lParam especifica la resolución horizontal y la palabra de orden superior lParam especifica la resolución vertical de la pantalla.

+0

Gracias, eso es un excelente comienzo. No puedo creer que no haya encontrado antes SystemParametersInfo. Todavía estoy atascado con el problema de si la barra de título es visible o no, y qué sucede si la resolución cambia. – hatcat

+0

@hatcat: No hay razón para castigarte; la API de Windows es grande y nadie sabe todo. No estoy seguro de cómo todavía podría estar atascado en la visibilidad de la barra de título. Verifique si la región de su ventana que contiene la barra de título se encuentra dentro del área de trabajo de la pantalla que obtuvo usando cualquiera de las funciones descritas anteriormente. Y me olvidé de detectar cambios de resolución; Actualizaré mi respuesta. –

+0

¡Gracias! He estado programando Windows desde 1992, lo creas o no. Creo que lo más difícil es saber qué funcionalidad ha sido reemplazada y cuándo, y si debes o no quedarte con lo que sabes. La parte de la barra de título tenía más que ver con recuperar esa región para poder probarla. Voy a comprobar los diez píxeles superiores y los diez píxeles laterales, eso debería ser suficiente. – hatcat

1

La comprobación de la visibilidad es realmente fácil.

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); 

No tiene que usar RectInRegion, lo usé para acortar el código.

La visualización, la supervisión del cambio de resolución también es fácil si maneja el mensaje WM_SETTINGCHANGE.

http://msdn.microsoft.com/en-us/library/ms725497(v=vs.85).aspx

ACTUALIZACIÓN

Como se señaló @Cody gris, creo WM_DISPLAYCHANGE es más apropiado que WM_SETTINGCHANGE. Pero la biblioteca MFC 9.0 utiliza WM_SETTINGCHANGE.

Cuestiones relacionadas