Page 1 of 1
How to link exe with "winver = 6.0"? Possible at all?
Posted: Mon Mar 17, 2014 1:29 pm
by c4s
A short introduction:
I just noticed that GetWindowRect_() returns a wrong (too small) value if the #PB_Window_SizeGadget flag (aka. #WS_SIZEBOX) isn't set. Yeah I'm a little late with this but I found out that it has to do with the
new rendering introduced in Windows Vista - the problem still exists in Windows 8.1 though.
Solution:
Greg Schechter from Microsoft wrote:However, there's been a recent change in the system which will be coming out in Vista RC1 that will return the correct rendered value from GetWindowRect() for executables that are linked with "winver = 6.0". This allows new and newly-linked applications to get the "correct" values from GetWindowRect().
Question:
So, how can I link my executable with "winver = 6.0"? Is this even possible with PureBasic?
Re: How to link exe with "winver = 6.0"? Possible at all?
Posted: Tue Mar 18, 2014 8:53 am
by Danilo
WINVER is a Define in the windows headers files, and GetWindowRect_() is the same on all platforms.
I think it is best to just use the available solutions to the problem:
Code: Select all
Prototype proto_DwmGetWindowAttribute(hWnd, dwAttribute.l, *pvAttribute, cbAttribute.l)
#DWMWA_EXTENDED_FRAME_BOUNDS = 9
Procedure GetWindowRect_VistaSeven(hWnd, *rect.RECT)
Protected lib
Protected DwmGetWindowAttribute.proto_DwmGetWindowAttribute
If hWnd And *rect
; OSVersion >= #PB_OS_Windows_Vista And >= #PB_OS_Windows_Server_2008
If OSVersion() >= #PB_OS_Windows_Vista
lib = OpenLibrary(#PB_Any, "dwmapi.dll")
If lib
DwmGetWindowAttribute = GetFunction(lib,"DwmGetWindowAttribute")
If DwmGetWindowAttribute
If DwmGetWindowAttribute(hWnd,#DWMWA_EXTENDED_FRAME_BOUNDS,*rect,SizeOf(RECT)) = #S_OK
CloseLibrary(lib)
ProcedureReturn #True
EndIf
EndIf
CloseLibrary(lib)
EndIf
EndIf
ProcedureReturn GetWindowRect_(hWnd,*rect)
EndIf
EndProcedure
Macro GetWindowRect_(hWnd, rect)
GetWindowRect_VistaSeven(hWnd,rect)
EndMacro
;---------------------------------------------
OpenWindow(0,0,0,800,600,"Title",#PB_Window_TitleBar|#PB_Window_ScreenCentered)
GetWindowRect_(WindowID(0),@rect.RECT)
Debug rect\left
Debug rect\top
Debug rect\right - rect\left
Debug rect\bottom - rect\top
Debug "-------------------"
UndefineMacro GetWindowRect_
GetWindowRect_(WindowID(0),@rect.RECT)
Debug rect\left
Debug rect\top
Debug rect\right - rect\left
Debug rect\bottom - rect\top
Re: How to link exe with "winver = 6.0"? Possible at all?
Posted: Tue Mar 18, 2014 12:05 pm
by luis
At the time I did something a lot similar to Danilo's code, only difference I see at a glance is I used a wrapper called GetWindowRectEx() with a fallback to GetWindowRect_().
I'm posting it anyway even if almost identical, it gives the same results on my Win7 x64 + Aero.
Code: Select all
Enumeration ; GetWindowRectEx()
#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 IsAeroActive()
; [DESC]
; Check if Aero is currently enabled.
;
; [RETURN]
; #True or #False.
;
; [NOTES]
; Aero is available on Vista and Windows 7. Windows 8 doesn't have it.
Protected *DwmIsCompositionEnabled
Protected iRetVal, hDll, iBool
If OSVersion() >= #PB_OS_Windows_Vista
hDll = OpenLibrary(#PB_Any, "dwmapi.dll")
If hDll
*DwmIsCompositionEnabled = GetFunction(hDll, "DwmIsCompositionEnabled")
If *DwmIsCompositionEnabled
If CallFunctionFast(*DwmIsCompositionEnabled, @iBool) = #S_OK
iRetVal = iBool ; #True / #False
EndIf
EndIf
CloseLibrary(hDll)
EndIf
EndIf
ProcedureReturn iRetVal
EndProcedure
Procedure GetWindowRectEx (hWnd, *tRECT.RECT)
; [DESC]
; Get the windows boundaries as GetWindowRect() does but it supports AERO too.
;
; [INPUT]
; hWnd : Handle of the window.
;
; [OUTPUT]
; *tRECT : Pointer to a RECT structure which will contain the bounding coordinates.
;
; [RETURN]
; NONE
;
; [NOTES]
; Under Vista/Win7 GetWindowRect() will return a misleading set of values that do not account for the
; extra padding of "glass" pixels Aero applies to the window.
; This appears to happen even in Aero Basic (without Glass) to retain sizing consistency.
; The workaround seems to be to dynamically bind to dwmapi.dll, use GetProcAddress() to obtain the
; DwmGetWindowAttribute() function, and call it with the DWMWA_EXTENDED_FRAME_BOUNDS argument to request
; the genuine window frame dimensions.
Protected hDll, iDwmUsed
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
iDwmUsed = 1
EndIf
EndIf
CloseLibrary(hDLL)
EndIf
EndIf
EndIf
If iDwmUsed = 0 ; fallback
GetWindowRect_(hWnd, *tRECT)
EndIf
EndProcedure
OpenWindow(0,0,0,800,600,"Title",#PB_Window_TitleBar|#PB_Window_ScreenCentered)
GetWindowRectEx (WindowID(0),@rect.RECT)
Debug rect\left
Debug rect\top
Debug rect\right - rect\left
Debug rect\bottom - rect\top
EDIT: fixed typo
Re: How to link exe with "winver = 6.0"? Possible at all?
Posted: Tue Mar 18, 2014 12:27 pm
by c4s
I'm going to use that instead. Thanks both of you for the solutions.