Jump to content

Recommended Posts

Posted (edited)

I'm playing around with the DPI related functions for DPI Awareness Context from UEZ's _WinAPI_DPI.au3 UDF. I need to be able to get the DPI Awareness Context values and make decisions based on those returns.

The part that I don't understand is that the values for these are:

$DPI_AWARENESS_UNAWARE = 0
Global Const $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = $DPI_AWARENESS_UNAWARE - 3
Global Const $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = $DPI_AWARENESS_UNAWARE - 4

So my assumption is that I would get a return of -3 for PMv1 and -4 for PMv2.

But instead, I am getting a return of 18 for PMv1 and 34 for PMv2. I assume that there must be a way to interpret this return to match the initial -3 or -3 that I thought were the values.

If anyone can help me understand this better, I would greatly appreciate it. :)

Here is the script that I am testing:

#include <GUIConstantsEx.au3>

;https://learn.microsoft.com/en-us/windows/win32/api/windef/ne-windef-dpi_awareness
Global Enum $DPI_AWARENESS_INVALID = -1, $DPI_AWARENESS_UNAWARE = 0, $DPI_AWARENESS_SYSTEM_AWARE = 1, $DPI_AWARENESS_PER_MONITOR_AWARE = 2

;https://learn.microsoft.com/en-us/windows/win32/hidpi/dpi-awareness-context
Global Const $DPI_AWARENESS_CONTEXT_UNAWARE = $DPI_AWARENESS_UNAWARE - 1
Global Const $DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = $DPI_AWARENESS_UNAWARE - 2
Global Const $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = $DPI_AWARENESS_UNAWARE - 3
Global Const $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = $DPI_AWARENESS_UNAWARE - 4
Global Const $DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED = $DPI_AWARENESS_UNAWARE - 5

; Per-MonitorV2
;_WinAPI_SetProcessDpiAwarenessContext($DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)

; Per-MonitorV1
_WinAPI_SetProcessDpiAwarenessContext($DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)

Example()

Func Example()
    ; Create a GUI with various controls.
    Local $hGUI = GUICreate("Example", 400, 400)
    Local $idBtn_OK = GUICtrlCreateButton("OK", 310, 370, 85, 25)


    ; Display the GUI.
    GUISetState(@SW_SHOW, $hGUI)

    ConsoleWrite("AwarenessContext from _WinAPI_GetWindowDpiAwarenessContext($hWnd): " & _WinAPI_GetWindowDpiAwarenessContext($hGUI) & @CRLF)
    ConsoleWrite("AwarenessContext from _WinAPI_GetThreadDpiAwarenessContext(): " & _WinAPI_GetThreadDpiAwarenessContext() & @CRLF)

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $idBtn_OK
                ExitLoop

        EndSwitch
    WEnd

    ; Delete the previous GUI and all controls.
    GUIDelete($hGUI)
EndFunc   ;==>Example

; All DPI-related functions below are from UEZ's _WinAPI_DPI.au3 UDF.

;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setprocessdpiawarenesscontext
Func _WinAPI_SetProcessDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value)
    Local $aResult = DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1703+ / Windows Server 2016+
    If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0)
    If Not $aResult[0] Then Return SetError(2, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_SetProcessDpiAwarenessContext

;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdpiawarenesscontext
Func _WinAPI_GetWindowDpiAwarenessContext($hWnd)
    Local $aResult = DllCall("user32.dll", "uint", "GetWindowDpiAwarenessContext", "hwnd", $hWnd) ;requires Win10 v1607+ / no server support
    If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0)
    If Not $aResult[0] Then Return SetError(2, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_GetWindowDpiAwarenessContext

;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getthreaddpiawarenesscontext
Func _WinAPI_GetThreadDpiAwarenessContext()
    Local $aResult = DllCall("user32.dll", "uint", "GetThreadDpiAwarenessContext") ;requires Win10 v1607+ / no server support
    If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0)
    If Not $aResult[0] Then Return SetError(2, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_GetThreadDpiAwarenessContext

 

Edited by WildByDesign
typo
  • WildByDesign changed the title to Understanding return values from DPI Awareness Context
  • Solution
Posted
#include <GUIConstantsEx.au3>

; Enums: Returned by _WinAPI_GetAwarenessFromDpiAwarenessContext
Global Enum $DPI_AWARENESS_INVALID = -1, _
            $DPI_AWARENESS_UNAWARE = 0, _
            $DPI_AWARENESS_SYSTEM_AWARE = 1, _
            $DPI_AWARENESS_PER_MONITOR_AWARE = 2

; Pseudo-Handles: Used to set or test against specific DPI contexts
Global Const $DPI_AWARENESS_CONTEXT_UNAWARE             = Ptr(-1)
Global Const $DPI_AWARENESS_CONTEXT_SYSTEM_AWARE        = Ptr(-2)
Global Const $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE    = Ptr(-3)
Global Const $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = Ptr(-4)
Global Const $DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED    = Ptr(-5)

; Set DPI Awareness to Per-Monitor V2
_WinAPI_SetProcessDpiAwarenessContext($DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)

Local $hGUI = GUICreate("DPI Test", 400, 300)
Local $hContext = _WinAPI_GetWindowDpiAwarenessContext($hGUI)

; Display the user-friendly name of the context
ConsoleWrite("DPI Context Name: " & _GetDpiAwarenessContextName($hContext) & @CRLF)

; Check specifically if it is PMv2 using AreDpiAwarenessContextsEqual
If _WinAPI_AreDpiAwarenessContextsEqual($hContext, $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) Then
    ConsoleWrite("Decision: Window is running in Per-Monitor V2 mode." & @CRLF)
EndIf


; ==============================================================================
; Helper Function to Convert Any Handle to a Friendly String
; ==============================================================================
Func _GetDpiAwarenessContextName($hContext)
    If _WinAPI_AreDpiAwarenessContextsEqual($hContext, $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) Then Return "Per-Monitor Aware V2"
    If _WinAPI_AreDpiAwarenessContextsEqual($hContext, $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)    Then Return "Per-Monitor Aware V1"
    If _WinAPI_AreDpiAwarenessContextsEqual($hContext, $DPI_AWARENESS_CONTEXT_SYSTEM_AWARE)         Then Return "System Aware"
    If _WinAPI_AreDpiAwarenessContextsEqual($hContext, $DPI_AWARENESS_CONTEXT_UNAWARE)              Then Return "Unaware"
    If _WinAPI_AreDpiAwarenessContextsEqual($hContext, $DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED)    Then Return "Unaware (GDI Scaled)"
    Return "Unknown Context"
EndFunc   ;==>_GetDpiAwarenessContextName


; ==============================================================================
; WinAPI Wrappers
; ==============================================================================

; https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-aredpiawarenesscontextsequal
Func _WinAPI_AreDpiAwarenessContextsEqual($hContextA, $hContextB)
    Local $aResult = DllCall("user32.dll", "bool", "AreDpiAwarenessContextsEqual", "handle", $hContextA, "handle", $hContextB)
    If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, False)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_AreDpiAwarenessContextsEqual

Func _WinAPI_SetProcessDpiAwarenessContext($hDpiContext)
    Local $aResult = DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", "handle", $hDpiContext)
    If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, False)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_SetProcessDpiAwarenessContext

Func _WinAPI_GetWindowDpiAwarenessContext($hWnd)
    Local $aResult = DllCall("user32.dll", "handle", "GetWindowDpiAwarenessContext", "hwnd", $hWnd)
    If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_GetWindowDpiAwarenessContext

Do not test $hContext = -3 or $hContext = 18. Use _WinAPI_AreDpiAwarenessContextsEqual($hContext, $DPI_AWARENESS_CONTEXT_...) to reliably check for PMv1 vs PMv2.

Hope this clarifies 🤔

 

 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting  image.gif.922e3a93535f431de08b31ee669cc446.gif
autoit_scripter_blue_userbar.png

Posted
7 hours ago, argumentum said:

Do not test $hContext = -3 or $hContext = 18. Use _WinAPI_AreDpiAwarenessContextsEqual($hContext, $DPI_AWARENESS_CONTEXT_...) to reliably check for PMv1 vs PMv2.

Hope this clarifies 🤔

Your answer clarifies to perfection. This is exactly what I needed. Thank you so much. :)

I needed this for the PMv2 UDF, but it turns out that I also likely need this for GUIDarkTheme UDF as well because knowing which DPI awareness context makes a big difference. PMv2 automatically scales non-client area (menubar, etc.) and common controls (statusbar, etc.) Therefore I need to not scale specific parts under PMv2, while under other DPI awareness contexts I will need to scale those.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...