2010-07-07 10 views
12

El problema real que estoy tratando de resolver es, quiero averiguar automáticamente el tamaño de los márgenes alrededor de Windows. Si puede encontrar una mejor manera, por favor responda eso en lugar de esto.GetWindowRect demasiado pequeño en Windows 7

Para hacer esto, decidí tomar una captura de pantalla de una ventana de prueba y medir los márgenes. Esto es bastante simple, ya que espero que los márgenes nunca sean de color rosa brillante, pero admito que es un truco. Uso GetWindowRect (py) para obtener el cuadro delimitador y PIL para tomar una captura de pantalla y recortarla en el cuadro delimitador. El problema es que mientras la cosecha funciona correctamente, el cuadro delimitador es not accurate. La "herramienta de recorte" de Windows 7 obtiene el correct dimensions. ¿Cómo puedo hacer lo mismo?

Respuesta

16

Mis primeros pensamientos se enumeran a continuación, pero si, como usted dice, está seguro de que GetWindowRect está devolviendo valores incorrectos, consulte RESOLUCIÓN más abajo.


"¿Qué pasa con GetSystemMetrics(SM_CXBORDER) y GetSystemMetrics(SM_CYBORDER)?

El método que utiliza parece una manera muy indirecta de hacerlo y, si se puede llamar GetWindowRect(), estoy bastante seguro de que puede llamar GetSystemMetrics() también.

otra posibilidad es utilizar GetWindowRect para obtener todo el rectángulo delimitador de la ventana y GetClientRect para obtener el rectángulo delimitador para el área de cliente (no frontera).

Este debería darle algo así como (100,200),(1000,900) y (112,227),(988,888), respectivamente, y se puede trabajar en el borde superior como 227-200, inferior como 900-888, izquierda y derecha como 112-100 como 900-888 (27,12,12,12).


RESOLUCIÓN:

Un poco de investigación se convierte en imagen this. Es un hilo de 2006 que indica que es posible que no obtenga los valores correctos en GetWindowsRect. El hilo que me señaló a este declaró:

Aplicaciones en Vista que no están vinculados con WINVER = 6 recibirá un juego engañoso de los valores aquí, que no tienen en cuenta el acolchado extra de "cristal" píxeles Vista Aero se aplica a la ventana. Esto parece suceder incluso en Aero Basic (sin Glass) para retener la consistencia del tamaño. La solución alternativa (si no desea configurar WINVER = 6) parece ser vincular dinámicamente a dwmapi.dll y usar GetProcAddress() para obtener la función DwmGetWindowAttribute() y llamarlo con el argumento DWMWA_EXTENDED_FRAME_BOUNDS para solicitar la ventana genuina dimensiones del marco.

Así que, básicamente, usar algo como (puede que tenga que utilizar ctypes hacer esto desde Python):

RECT r; 
HRESULT stat = DwmGetWindowAttribute (
    hwnd, 
    DWMWA_EXTENDED_FRAME_BOUNDS, 
    &r, 
    sizeof(r)); 

y que debería darle el rectángulo de delimitación correcta.

+0

Bueno, devuelve 1. 1 no es el ancho de ninguno de los bordes en esa ventana. Estoy bastante seguro de que los valores que quiero para esa ventana son 8 y 30. –

+0

¿Cómo se obtienen 8 y 30? El marco de aspecto correcto parece tener el mismo ancho en la parte inferior que en los laterales. – paxdiablo

+0

Me importa la parte superior, también. –

1

primera, que llame a GetClientRect retrive rectángulo de cliente R1, luego llamar a AdjustWindowRectEx para calcular los límites precisos de acuerdo a R1.

0

GetWindowRect devuelve los valores correctos, pero para el manejo explícito de la ventana. Use GetParent function para obtener el control de la ventana principal, mientras GetWindoWRect devuelve para usted el valor de retorno RECT o GetParent máximo es NULL.

+3

El OP ya * está * hablando de una ventana de nivel superior aquí. – BrendanMcK

3

Sé que es un tema viejo. Pero me costó un poco buscar y pasé por el dolor de ctypes para obtener la solución de paxdiablo trabajando en Python. Sólo quería compartir ejemplo de código de trabajo para wxPython:

try: 
    f = ctypes.windll.dwmapi.DwmGetWindowAttribute 
except WindowsError: 
    f = None 
if f: # Vista & 7 stuff 
    rect = ctypes.wintypes.RECT() 
    DWMWA_EXTENDED_FRAME_BOUNDS = 9 
    f(ctypes.wintypes.HWND(self.GetHandle()), 
     ctypes.wintypes.DWORD(DWMWA_EXTENDED_FRAME_BOUNDS), 
     ctypes.byref(rect), 
     ctypes.sizeof(rect) 
    ) 
    size = (rect.right - rect.left, rect.bottom - rect.top)   
else:  
    size = self.GetSize() 
1

GetWindowRect en Windows 7 parece no incluir el derecho y los bordes del marco de ventana inferior (al menos con el tema Aero yo sepa), si se creó la ventana sin el estilo WS_SIZEBOX (es decir, desea una ventana no dimensionable).

El problema es que WS_SIZEBOX es lo mismo que WS_THICKFRAME, y en Aero, las ventanas tienen la estructura gruesa, independientemente de si pueden cambiar de tamaño o no. Pero la función GetWindowRect piensa que una ventana que no se puede redimensionar es más delgada.

¿La solución? Puede crear la ventana con WS_SIZEBOX, llamar a GetWindowRect, luego usar SetWindowLongPtr (GWL_STYLE, ...) para desactivar WS_SIZEBOX, pero esto creará un borde blanco feo dentro del área del cliente.

En su lugar, deje WS_SIZEBOX habilitado, y simplemente devuelva el mismo valor para ptMinTrackSize y ptMaxTraceSize en la estructura MINMAXINFO al responder al mensaje WM_GETMINMAXINFO. Esto evitará que la ventana se pueda redimensionar y GetWindowRect devolverá los datos correctos. El único inconveniente es que el cursor del mouse cambiará a un cursor de cambio de tamaño cuando el puntero del mouse va sobre el marco de la ventana, pero es el menor de los males hasta ahora.

Cuestiones relacionadas