How to link exe with "winver = 6.0"? Possible at all?

Windows specific forum
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

How to link exe with "winver = 6.0"? Possible at all?

Post 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?
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: How to link exe with "winver = 6.0"? Possible at all?

Post 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
User avatar
luis
Addict
Addict
Posts: 3895
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: How to link exe with "winver = 6.0"? Possible at all?

Post 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
Last edited by luis on Tue Mar 18, 2014 1:45 pm, edited 1 time in total.
"Have you tried turning it off and on again ?"
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: How to link exe with "winver = 6.0"? Possible at all?

Post by c4s »

I'm going to use that instead. Thanks both of you for the solutions.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Post Reply