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.