A GetWindowRectEx() for Aero and non-resizable windows
Posted: Sun Dec 20, 2009 1:10 am
Under Windows 7 (and Vista too I believe) with Aero enabled, GetWindowRect_ does not include the full non-client area for non-resizable windows.
One way to solve the problem is to call DwmGetWindowAttribute() with #DWMWA_EXTENDED_FRAME_BOUNDS when Aero is enabled.
This code is an example of that and if I didn't do something wrong (!) GetWindowRectEx() should return the right size in any condition (vista/7 with/without aero and winxp or lower).
It's not optimized for efficiency obviously, you can do many of the test at startup and then call the appropriate code in your program, or whatever.
One way to solve the problem is to call DwmGetWindowAttribute() with #DWMWA_EXTENDED_FRAME_BOUNDS when Aero is enabled.
This code is an example of that and if I didn't do something wrong (!) GetWindowRectEx() should return the right size in any condition (vista/7 with/without aero and winxp or lower).
Code: Select all
EnableExplicit
Enumeration
#DWMWA_NCRENDERING_ENABLED = 1
#DWMWA_NCRENDERING_POLICY
#DWMWA_TRANSITIONS_FORCEDISABLED
#DWMWA_ALLOW_NCPAINT
#DWMWA_CAPTION_BUTTON_BOUNDS
#DWMWA_NONCLIENT_RTL_LAYOUT
#DWMWA_FORCE_ICONIC_REPRESENTATION
#DWMWA_FLIP3D_POLICY
#DWMWA_EXTENDED_FRAME_BOUNDS
#DWMWA_HAS_ICONIC_BITMAP
#DWMWA_DISALLOW_PEEK
#DWMWA_EXCLUDED_FROM_PEEK
#DWMWA_LAST
EndEnumeration
Procedure.i IsThemeActive()
; Do not call this function during DllMain or global objects contructors.
Protected *IsThemeActive
Protected iRetVal = 0 ; Themes not active
Protected hDll
If OSVersion() >= #PB_OS_Windows_XP
hDll = OpenLibrary(#PB_Any, "UxTheme.dll")
If hDll
*IsThemeActive = GetFunction(hDll, "IsThemeActive")
If *IsThemeActive
iRetVal = CallFunctionFast(*IsThemeActive) ; #True / #False
EndIf
CloseLibrary(hDll)
EndIf
EndIf
ProcedureReturn iRetVal
EndProcedure
Procedure.i IsAeroActive()
Protected *DwmIsCompositionEnabled
Protected iRetVal = 0 ; Aero is not active
Protected hDll
Protected flgBool
If OSVersion() >= #PB_OS_Windows_Vista
hDll = OpenLibrary(#PB_Any, "dwmapi.dll")
If hDll
*DwmIsCompositionEnabled = GetFunction(hDll, "DwmIsCompositionEnabled")
If *DwmIsCompositionEnabled
If CallFunctionFast(*DwmIsCompositionEnabled, @flgBool) = #S_OK
iRetVal = flgBool ; #True / #False
EndIf
EndIf
CloseLibrary(hDll)
EndIf
EndIf
ProcedureReturn iRetVal
EndProcedure
Procedure GetWindowRectEx (hWnd, *tRECT.RECT)
Protected hDll
Protected iRetVal = 0 ; 0 if fail
Protected *DwmGetWindowAttribute
Protected tRECT.RECT
If OSVersion() >= #PB_OS_Windows_Vista
If IsAeroActive()
hDll = OpenLibrary(#PB_Any, "dwmapi.dll")
If hDll
*DwmGetWindowAttribute = GetFunction(hDll, "DwmGetWindowAttribute")
If *DwmGetWindowAttribute
If CallFunctionFast(*DwmGetWindowAttribute, hWnd, #DWMWA_EXTENDED_FRAME_BOUNDS, *tRECT, SizeOf(RECT)) = #S_OK
iRetVal = 1
EndIf
EndIf
CloseLibrary(hDLL)
EndIf
Else
iRetVal = GetWindowRect_(hWnd, *tRECT) ; 0 if fail
EndIf
Else
iRetVal = GetWindowRect_(hWnd, *tRECT) ; 0 if fail
EndIf
ProcedureReturn iRetVal
EndProcedure
; TEST
Procedure Main()
Protected tRECT.RECT
Debug "Aero = " + Str(IsAeroActive())
Debug "Themes = " + Str(IsThemeActive())
OpenWindow(0, 150,150, 640, 480, "TEST", #PB_Window_SystemMenu)
Debug "GetWindowRectEx = " + Str( GetWindowRectEx (WindowID(0), @tRECT) )
Debug "x = " + Str(tRECT\left)
Debug "y = " + Str(tRECT\top)
Debug "w = " + Str(tRECT\right - tRECT\left)
Debug "h = " + Str(tRECT\bottom - tRECT\top)
Debug "GetWindowRect_ = " + Str( GetWindowRect_ (WindowID(0), @tRECT) )
Debug "x = " + Str(tRECT\left)
Debug "y = " + Str(tRECT\top)
Debug "w = " + Str(tRECT\right - tRECT\left)
Debug "h = " + Str(tRECT\bottom - tRECT\top)
While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
EndProcedure
Main()