Jump to content

making your compiled application DPI Aware


Recommended Posts

What I can say is that DPI awareness is not as simple as just adding a valid manifest and everything will work properly.

A good starting point is https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows

Currently I'm trying to understand how DPI awareness works and how I've to create my GUI incl. child GUIs and what I've to do / call that my code is DPI aware on different operating systems.

In my office I've 3 monitors. 2 of them are external and 1 is from my notebook.

The 2 external are running at 1680x1050 px and the other one at 1600x900 px. Thus the virtual screen size is at 4960x1050 px.

E.g. if I set monitor 1 to 144 DPI, monitor 2 to 168 DPI and monitor 3 to 96 DPI then my test code from above will behave different than setting only one monitor to > 96 DPI. Even only 1 monitor is set to higher DPI it behaves different depending on which monitor will be used.

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

@Shark007 Can you please test this version?

I still used these lines in the manifest

<asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
              <dpiAware>true/pm</dpiAware>
        </asmv3:windowsSettings>
        <asmv3:windowsSettings xmlns="https://schemas.microsoft.com/SMI/2016/WindowsSettings">
              <dpiAwareness>PerMonitorV2, PerMonitor, system</dpiAwareness>
        </asmv3:windowsSettings>
        <asmv3:windowsSettings xmlns="https://schemas.microsoft.com/SMI/2017/WindowsSettings">
              <gdiScaling>true</gdiScaling>
        </asmv3:windowsSettings>
    </asmv3:application>

No _WinAPI_SetDPIAwareness calls, only the DPI awareness from the manifest!

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

The fact that a Manifest written as below works on Windows 10 and 8 in Per Monitor Aware mode
and on Windows 7, (7 only supports System Aware) leads me to assume it is in the best format.

Also know, including gdi scaling (as the 1st line) causes my apps to be Unaware on Windows 8.
This leads me to the conclusion that Windows reads and attempts to connect, from the top down.
Since you manifest has The Windows 8 version before the 10 version (of Per Monitor Aware)
It will use the Windows 8 version on Windows10 systems.

	<asmv3:application>
		<asmv3:windowsSettings>
            	<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
            	<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
		</asmv3:windowsSettings>
	</asmv3:application>

 

They report as Per Monitor Aware on 8 and 10 

Windows 8

Windows8.jpg

Windows 10

Windows10.jpg

Edited by Shark007
Link to comment
Share on other sites

Thanks for testing.

I've modified the manifest to following lines:

<asmv3:application>
        <asmv3:windowsSettings xmlns="https://schemas.microsoft.com/SMI/2016/WindowsSettings">
              <dpiAwareness>PerMonitorV2, PerMonitor, system</dpiAwareness>
        </asmv3:windowsSettings>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
              <dpiAware>true/pm</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>

I tested it using 3 monitors, 175%, 125%, 150% and the main GUI looked ok. The child GUI has no interaction yet, only main GUI where the font size will be reset when GUI is moved to another screen.

I'm wondering why your screenshot on Win10 looks so different...

 

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

To inform, 

I tested this code as standalone (without other entries)

<asmv3:windowsSettings xmlns="https://schemas.microsoft.com/SMI/2016/WindowsSettings">
              <dpiAwareness>PerMonitorV2, PerMonitor, system</dpiAwareness>
        </asmv3:windowsSettings>

and it does not fallback at all. It works on Windows 10 in Per Monitor Aware mode, but on 8 and 7, the apps are unaware

Edited by Shark007
Link to comment
Share on other sites

I changed the manifest to

<asmv3:application>
        <asmv3:windowsSettings xmlns="https://schemas.microsoft.com/SMI/2016/WindowsSettings">
              <dpiAwareness>PerMonitorV2</dpiAwareness>
        </asmv3:windowsSettings>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
              <dpiAware>true/pm</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>

 

How it looks on my Win10 notebook on different monitors with different DPI settings:

 

150%:150.png
125%:125.png
175%:175.png

 

100%: 100.png
 

 

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

@UEZ In my travels, some information you may find interesting.

To enable support for Mixed-Mode High DPI scaling, you can set the following AppContext switch in the manifest.

<runtime>
   <AppContextSwitchOverrides value = "Switch.System.Windows.DoNotScaleForDpiChanges=false; Switch.System.Windows.DoNotUsePresentationDpiCapabilityTier2OrGreater=false"/>
</runtime>

Documentation

Edited by Shark007
Link to comment
Share on other sites

10 hours ago, Shark007 said:

@UEZ In my travels, some information you may find interesting.

To enable support for Mixed-Mode High DPI scaling, you can set the following AppContext switch in the manifest.


<runtime>
   <AppContextSwitchOverrides value = "Switch.System.Windows.DoNotScaleForDpiChanges=false; Switch.System.Windows.DoNotUsePresentationDpiCapabilityTier2OrGreater=false"/>
</runtime>

Documentation

When I add these lines than the exe cannot be started!

Error message:

The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.

 

I was able to reproduce your screens when I changed by main screen to 175%.

 

Can you test the executables in the 7-Zip archive please?

 

 

 

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

2 minutes ago, Deye said:

UEZ

when you start one at 175% then change the settings to 100% and start another they are not the same sizes

also the text with the one that started on 175% becomes too small to read ..

If you mean the child GUI with the bitmap then you are right as the 2nd (child) GUI has no awareness code.

When the result is as expected than I will release the code.

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

	<configuration>
		<windows>
			<runtime>
   				<AppContextSwitchOverrides value = "Switch.System.Windows.DoNotScaleForDpiChanges=false; Switch.System.Windows.DoNotUsePresentationDpiCapabilityTier2OrGreater=false"/>
			</runtime>
		</windows>
	</configuration>

	<asmv3:application>
		<asmv3:windowsSettings>
			<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
			<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
		</asmv3:windowsSettings>
	</asmv3:application>

@UEZ OK, I got this working. i'm laughing at myself at this point. But this works and is reproducible

Edited by Shark007
Link to comment
Share on other sites

@Shark007 For me it is still not working - getting the same error message!

Regarding Win8 -> the function _WinAPI_GetDpiForWindow() requires Win10 v1607+. I've added another GDI+ function to get the DPI which should work, too.

Can you test please?

 

Here the code:

;Coded by UEZ build 2023-07-21 beta
#include <Array.au3>
#AutoIt3Wrapper_Res_HiDpi=y

#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPIGdiDC.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>


#Region $DPI_AWARENESS_CONTEXT
;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
#EndRegion $DPI_AWARENESS_CONTEXT

; enum _MONITOR_DPI_TYPE
Global Enum $MDT_EFFECTIVE_DPI = 0, $MDT_ANGULAR_DPI, $MDT_RAW_DPI
Global Const $MDT_DEFAULT = $MDT_EFFECTIVE_DPI


Global Const $WM_DPICHANGED = 0x02E0, $WM_DPICHANGED_BEFOREPARENT = 0x02E2, $WM_DPICHANGED_AFTERPARENT = 0x02E3, $WM_GETDPISCALEDSIZE = 0x02E4

Global $dpiScaledX, $dpiScaledY, $aCtrlFS[5][2], $hGUI, $hGUI_child, $g_iDPI_ratio2, $iLable_child, $iPic_child, $sImage = "c:\Program Files (x86)\AutoIt3\Examples\GUI\Merlin.gif"
Global $hDLL = DllOpen("user32.dll")

Example1()

DllClose($hDLL)

Func Example1() ;thanks to alpines for the main GUI layout
    If _WinAPI_SetDPIAwareness($DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) = -1 Then Exit MsgBox(16, "ERROR", "Cannot set DPI awareness!", 10)

    Local $iDPI
    If @OSBuild < 14393 Then
        $iDPI = _GDIPlus_GraphicsGetDPIRatio()
    Else
        Local $hGUI_dummy = GUICreate("", 1, 1, 0, 0)
        $iDPI = _WinAPI_GetDpiForWindow($hGUI_dummy)
        GUIDelete($hGUI_dummy)
    EndIf

    Local $iDPI_ratio = $iDPI / 96
    $g_iDPI_ratio2 = 96 / $iDPI

    $hGUI = GUICreate("Example 1", 314 * $iDPI_ratio, 130 * $iDPI_ratio, -1, 10)
    GUISetFont(12 * $iDPI_ratio, 400, 0, "Times New Roman")

    $aCtrlFS[0][0] = GUICtrlCreateLabel("Label1", 16 * $iDPI_ratio, 16 * $iDPI_ratio, 40 * $iDPI_ratio, 21 * $iDPI_ratio)
    $aCtrlFS[0][1] = 10
    GUICtrlSetBkColor(-1, 0x3399FF)
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

    $aCtrlFS[1][0] = GUICtrlCreateLabel("Label2", 64 * $iDPI_ratio, 16 * $iDPI_ratio, 40 * $iDPI_ratio, 21 * $iDPI_ratio)
    $aCtrlFS[1][1] = 10
    GUICtrlSetBkColor(-1, 0x3399FF)
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

    $aCtrlFS[2][0] = GUICtrlCreateLabel("Label3", 112 * $iDPI_ratio, 16 * $iDPI_ratio, 40 * $iDPI_ratio, 21 * $iDPI_ratio)
    $aCtrlFS[2][1] = 10
    GUICtrlSetBkColor(-1, 0x3399FF)
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

    $aCtrlFS[3][0] = GUICtrlCreateInput("Input1", 160 * $iDPI_ratio, 16 * $iDPI_ratio, 137 * $iDPI_ratio, 22 * $iDPI_ratio)
    $aCtrlFS[3][1] = 10
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

    $aCtrlFS[4][0] = GUICtrlCreateButton("Close", 16 * $iDPI_ratio, 48 * $iDPI_ratio, 283 * $iDPI_ratio, 65 * $iDPI_ratio)
    $aCtrlFS[4][1] = 16
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

    $hGUI_child = GUICreate("Child", 320 * $iDPI_ratio, 260 * $iDPI_ratio, -1, -1, -1, -1, $hGUI)
    GUISetBkColor(0xFFFFFF)
    $iLable_child = GUICtrlCreateLabel("Label11", 16, 16, 288 * $iDPI_ratio, 168 * $iDPI_ratio)
    GUICtrlSetFont(-1, 65, 400, 0, "Times New Roman", 5)
    $iPic_child = GUICtrlCreatePic($sImage, 0, 160 * $iDPI_ratio, 68 * $iDPI_ratio, 71 * $iDPI_ratio)

    ResizeFont($hGUI)

    GUISetState(@SW_SHOW, $hGUI)
    GUISetState(@SW_SHOW, $hGUI_child)

    GUIRegisterMsg($WM_DPICHANGED_BEFOREPARENT, "WM_DPICHANGED") ;requires Win 8.1+ / Server 2012 R2+
;~  GUIRegisterMsg($WM_GETDPISCALEDSIZE, "WM_GETDPISCALEDSIZE")

    While True
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $aCtrlFS[4][0]
                GUIDelete($hGUI)
                ExitLoop
        EndSwitch
    WEnd
EndFunc   ;==>Example1

Func ResizeFont($hWnd)
    Local $iDPI = _WinAPI_GetDpiForWindow($hWnd), $dpi_ratio = $iDPI / 96
    Switch $hWnd
        Case $hGUI
            Local $i
            For $i = 0 To UBound($aCtrlFS) - 1
                GUICtrlSetFont($aCtrlFS[$i][0], $aCtrlFS[$i][1] * $dpi_ratio * $g_iDPI_ratio2, 400, 0, "Times New Roman", 5)
            Next
        Case $hGUI_child
            GUICtrlSetFont($iLable_child, 65 * $dpi_ratio * $g_iDPI_ratio2, 400, 0, "Times New Roman", 5)
    EndSwitch
EndFunc   ;==>ResizeFont

Func _WinAPI_FindWindowEx($hWndParent, $hWndChildAfter = 0, $sClassName = "", $sWindowName = "")
    Local $aResult = DllCall($hDLL, "hwnd", "FindWindowEx", "hwnd", $hWndParent, "hwnd", $hWndChildAfter, "wstr", $sClassName, "wstr", $sWindowName)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_FindWindowEx

#Region WinAPI DPI
;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isvaliddpiawarenesscontext
Func _WinAPI_IsValidDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value)
    Local $aResult = DllCall($hDLL, "bool", "IsValidDpiAwarenessContext", "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1607+ / no server support
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_IsValidDpiAwarenessContext

;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-logicaltophysicalpointforpermonitordpi
Func _WinAPI_LogicalToPhysicalPointForPerMonitorDPI($hWnd)
    Local $tPOINT = DllStructCreate($tagPOINT)
    Local $aResult = DllCall($hDLL, "bool", "LogicalToPhysicalPointForPerMonitorDPI", "hwnd", $hWnd, "struct*", $tPOINT) ;requires Win 8.1+ / no server support
    If @error Then Return SetError(@error, @extended, 0)
    Return $tPOINT
EndFunc   ;==>_WinAPI_LogicalToPhysicalPointForPerMonitorDPI

;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-physicaltologicalpointforpermonitordpi
Func _WinAPI_PhysicalToLogicalPointForPerMonitorDPI($hWnd)
    Local $tPOINT = DllStructCreate($tagPOINT)
    Local $aResult = DllCall($hDLL, "bool", "PhysicalToLogicalPointForPerMonitorDPI", "hwnd", $hWnd, "struct*", $tPOINT) ;requires Win 8.1+ / no server support
    If @error Then Return SetError(@error, @extended, 0)
    Return $tPOINT
EndFunc   ;==>_WinAPI_PhysicalToLogicalPointForPerMonitorDPI


;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow
Func _WinAPI_GetDpiForWindow($hWnd)
    Local $aResult = DllCall($hDLL, "uint", "GetDpiForWindow", "hwnd", $hWnd) ;requires Win10 v1607+ / no server support
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_GetDpiForWindow

;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforsystem
Func _WinAPI_GetDpiForSystem()
    Local $aResult = DllCall($hDLL, "uint", "GetDpiForSystem") ;requires Win10 v1607+ / no server support
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_GetDpiForSystem

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

;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpifromdpiawarenesscontext
Func _WinAPI_GetDpiFromDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value)
    Local $aResult = DllCall($hDLL, "int", "GetDpiFromDpiAwarenessContext", "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1803+ / Windows Server 2016+
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_GetDpiFromDpiAwarenessContext

;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiawarenesscontextforprocess
Func _WinAPI_GetDpiAwarenessContextForProcess($hProcess)
    Local $aResult = DllCall($hDLL, "int", "GetDpiAwarenessContextForProcess", "handle", $hProcess) ;requires Win10 v1803+ / Windows Server 2016+
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_GetDpiAwarenessContextForProcess

;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemdpiforprocess
Func _WinAPI_GetSystemDpiForProcess($hProcess)
    Local $aResult = DllCall($hDLL, "uint", "GetSystemDpiForProcess", "handle", $hProcess) ;requires Win10 v1803+ / Windows Server 2016+
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_GetSystemDpiForProcess

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


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

;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setthreaddpiawarenesscontext
Func _WinAPI_SetThreadDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value)
    Local $aResult = DllCall($hDLL, "bool", "SetThreadDpiAwarenessContext", "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1703+ / Windows Server 2016+
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_SetThreadDpiAwarenessContext

;https://learn.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-setprocessdpiawareness
Func _WinAPI_SetProcessDpiAwareness($PROCESS_DPI_AWARENESS = $DPI_AWARENESS_PER_MONITOR_AWARE) ;https://docs.microsoft.com/en-us/windows/desktop/api/shellscalingapi/nf-shellscalingapi-setprocessdpiawareness
    Local $iResult = DllCall("Shcore.dll", "long", "SetProcessDpiAwareness", "int", $PROCESS_DPI_AWARENESS) ;requires Win 8.1+ / Server 2012 R2+
    If @error Or $iResult Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_WinAPI_SetProcessDpiAwareness


;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-adjustwindowrectexfordpi
Func _WinAPI_AdjustWindowRectExForDpi($dpi, $dwStyle, $dwExStyle, $bMenu = False)
    Local $tRECT = DllStructCreate($tagRECT)
    Local $aResult = DllCall($hDLL, "bool", "AdjustWindowRectExForDpi", "struct*", $tRECT, "dword", $dwStyle, "bool", $bMenu, "dword", $dwExStyle, "uint", $dpi) ;requires Win10 v1607+ / no server support
    If @error Then Return SetError(@error, @extended, 0)
    Return $tRECT
EndFunc   ;==>_WinAPI_AdjustWindowRectExForDpi
#EndRegion WinAPI DPI

Func _GDIPlus_GraphicsGetDPIRatio($iDPIDef = 96)
    _GDIPlus_Startup()
    Local $hGfx = _GDIPlus_GraphicsCreateFromHWND(0)
    If @error Then Return SetError(1, @extended, 0)
    Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetDpiX", "handle", $hGfx, "float*", 0)
    If @error Then Return SetError(2, @extended, 0)
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_Shutdown()
    Return $aResult[2]
EndFunc   ;==>_GDIPlus_GraphicsGetDPIRatio

Func _WinAPI_GetDpiForPrimaryMonitor($dpiType = $MDT_DEFAULT, $hMOnitor = 0, $iDPIDef = 96) ;https://learn.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-getdpiformonitor
    If $hMOnitor = 0 Then
        Local $aMonitors = _WinAPI_EnumDisplayMonitors()
        If @error Then Return SetError(1, 0, 0)
        Local $i
        For $i = 1 To $aMonitors[0][0]
            If _WinAPI_GetMonitorInfo($aMonitors[$i][0])[2] = 1 Then
                $hMOnitor = $aMonitors[$i][0]
                ExitLoop
            EndIf
        Next
    EndIf
    Local $tX = DllStructCreate("uint x"), $tY = DllStructCreate("uint y")
    Local $aRet = DllCall("Shcore.dll", "long", "GetDpiForMonitor", "long", $hMOnitor, "int", $dpiType, "struct*", $tX, "struct*", $tY)
    If @error Or Not IsArray($aRet) Then Return SetError(2, 0, 0)
    Local $aDPI[2] = [$iDPIDef / $tX.x, $tX.x / $iDPIDef]
    Return $aDPI
EndFunc   ;==>_WinAPI_GetDpiForPrimaryMonitor


Func WM_GETDPISCALEDSIZE($hWnd, $iMsg, $wParam, $lParam)
    Local $tSize = DllStructCreate($tagSIZE, $lParam)
    Return True
EndFunc   ;==>WM_GETDPISCALEDSIZE

Func WM_DPICHANGED($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg, $wParam
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $lParam = ' & $lParam & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    Local $tRECT = DllStructCreate($tagRECT, $lParam)
    Local $iX = $tRECT.left, $iY = $tRECT.top, $iW = $tRECT.right - $iX, $iH = $tRECT.bottom - $iY
    ;requires Win10 v1607+ / no server support
    DllCall($hDLL, "bool", "AdjustWindowRectExForDpi", "struct*", $tRECT, "dword", BitOR($WS_BORDER, $WS_CAPTION, $WS_CLIPSIBLINGS, $WS_GROUP, $WS_POPUP, $WS_SYSMENU, $WS_VISIBLE), "bool", False, "dword", $WS_EX_WINDOWEDGE, "uint", _WinAPI_HiWord($wParam))
    _WinAPI_SetWindowPos($hWnd, 0, $iX, $iY, $iW, $iH, BitOR($SWP_NOZORDER, $SWP_NOACTIVATE))
    ResizeFont($hWnd)
    Local Const $iDPI = _WinAPI_GetDpiForWindow($hWnd), $dpi_ratio = $iDPI / 96, $dpi_ratio2 = 96 / $iDPI
    Local $aPos = ControlGetPos($hWnd, "", $iPic_child)
    If UBound($aPos) = 4 Then
        _WinAPI_MoveWindow(GUICtrlGetHandle($iPic_child), $aPos[0] * $dpi_ratio2 * $g_iDPI_ratio2, $aPos[1] * $dpi_ratio2 * $g_iDPI_ratio2, $aPos[2] * $dpi_ratio * $g_iDPI_ratio2, $aPos[3] * $dpi_ratio * $g_iDPI_ratio2)
        GUICtrlSetImage($iPic_child, $sImage)
    EndIf
    $tRECT = 0
    Return 1
EndFunc   ;==>WM_DPICHANGED


Func _WinAPI_SetDPIAwareness($DPIAwareContext = $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, $iMode = 1)
    Switch @OSBuild
        Case 6000 To 9199
            If Not DllCall($hDLL, "bool", "SetProcessDPIAware") Then Return SetError(1, 0, 0) ;requires Vista+ / Server 2008+
            Return 1
        Case 9200 To 13999
            _WinAPI_SetProcessDpiAwareness($DPIAwareContext) ;requires Win 8.1+ / Server 2012 R2+
            If @error Then Return SetError(2, @error, 0)
            Return 1
        Case @OSBuild > 13999
            _WinAPI_SetProcessDpiAwarenessContext_int($DPIAwareContext, $iMode)
            If @error Then Return SetError(3, @error, 0)
            Return 1
    EndSwitch
    Return -1
EndFunc   ;==>_WinAPI_SetDPIAwareness

Func _WinAPI_SetProcessDpiAwarenessContext_int($DPIAwareContext = $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, $iMode = 1)
    $DPIAwareContext = ($DPIAwareContext < -5) ? -5 : ($DPIAwareContext > -1) ? -1 : $DPIAwareContext
    $iMode = ($iMode < 1) ? 1 : ($iMode > 2) ? 2 : $iMode
    Switch $iMode
        Case 1
            _WinAPI_SetProcessDpiAwarenessContext($DPIAwareContext)
            If @error Then Return SetError(1, 0, 0)
        Case 2
            ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setprocessdpiawarenesscontext
            _WinAPI_SetThreadDpiAwarenessContext($DPIAwareContext) ;requires Win10 v1607+ / no server support
            If @error Then Return SetError(2, 0, 0)
    EndSwitch

    Return 1
EndFunc   ;==>_WinAPI_SetProcessDpiAwarenessContext_int

 

_WinAPI_SetDPIAwareness.zip

Edited by UEZ
Update

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Working with Windows... more aaarrrggg  because I can no longer reproduce good results with the manifest editing.

Moving on... Windows 10, screen shots are the same... Windows 8...

8.jpg

I see an awesome UDF coming out soon'ish.  Good work UEZ!

Edited by Shark007
Link to comment
Share on other sites

8 hours ago, Deye said:

UEZ

when you start one at 175% then change the settings to 100% and start another they are not the same sizes

also the text with the one that started on 175% becomes too small to read ..

@Deye This is the reason why there is a warning when you change resolutions that some apps may not appear correctly until you log off and back in again. I'm pretty sure this statement is addressing DPI Aware applications specifically.

Edited by Shark007
Link to comment
Share on other sites

35 minutes ago, Shark007 said:

@UEZ To inform, I had other testing to do in Win7 and before I left, I tested your latest iteration there too .It is set to 125% and and all was well!

Cool, thanks for testing. :)

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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
 Share

×
×
  • Create New...