WildByDesign Posted 8 hours ago Posted 8 hours ago (edited) Per-Monitor v2 DPI Awareness Scaling Test: Have this GUI running and test by changing your DPI scaling settings from: Settings app > System > Display > Scale Work in progress, but might become more interesting. Possible UDF if everything goes well. expandcollapse popup#include <GuiEdit.au3> #include <FontConstants.au3> #include <WindowsNotifsConstants.au3> #include <WinAPISysWin.au3> #include <WinAPIGdi.au3> #include <GUIConstantsEx.au3> #include <AutoItConstants.au3> #include <StructureConstants.au3> ; Apply PER_MONITOR_AWARE_V2 DPI Awareness DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext", "int_ptr", -4) Global $g_iScale = 1 Global $g_hCtrlFont = 0 Global Const $fDefFontSize = 8.5, $fDefPixel = $fDefFontSize * 96 / 72 Global Const $WM_DPICHANGED = 0x02E0 Global Const $WM_GETDPISCALEDSIZE = 0x02E4 Global Const $WM_DPICHANGED_BEFOREPARENT = 0x02E2 Global Const $WM_DPICHANGED_AFTERPARENT = 0x02E3 OnAutoItExitRegister("_Cleanup") Example() Func Example() Local $iCtrlSpaceV = 15 Local $sAppName = "Testing PerMonitorV2 DPI" Local $hGUI = GUICreate($sAppName, 440, 340, -1, -1) Local $idTestName = GUICtrlCreateLabel("Test Name:", 15, 20, -1, -1) Local $aPos = ControlGetPos($hGUI, "", $idTestName) Local $iPrev = $aPos[1] + $aPos[3] + $iCtrlSpaceV Local $idTestInput = GUICtrlCreateInput("Test Input", 15, $iPrev, 300, 24) Local $aPos = ControlGetPos($hGUI, "", $idTestInput) Local $iPrev = $aPos[1] + $aPos[3] + $iCtrlSpaceV Local $idCheckbox1 = GUICtrlCreateCheckbox("Test Checkbox1 ", 15, $iPrev) Local $aPos = ControlGetPos($hGUI, "", $idCheckbox1) Local $iPrev = $aPos[1] + $aPos[3] + $iCtrlSpaceV Local $idCheckbox2 = GUICtrlCreateCheckbox("Test Checkbox2 ", 15, $iPrev) Local $aPos = ControlGetPos($hGUI, "", $idCheckbox2) Local $iPrev = $aPos[1] + $aPos[3] + $iCtrlSpaceV _GUICtrlEdit_Create($hGUI, "This is a test" & @CRLF & "Another Line", 15, $iPrev, 394, 80) $g_iScale = _WinAPI_GetDPIForWindow($hGUI) / 96 If @error Then $g_iScale = 1 GUISetState(@SW_SHOW, $hGUI) GUIRegisterMsg($WM_DPICHANGED, _WM_DPICHANGED) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd GUIDelete($hGUI) EndFunc ;==>Example Func _WM_DPICHANGED($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam, $lParam Local Static $iInitDPI = $g_iScale Local Static $iPrevDPI = $g_iScale ; Obtain new DPI values Local $iDPI = _WinAPI_LoWord($wParam) Local $iNewDPI = _WinAPI_LoWord($wParam) / 96 Local $hFont = $g_hCtrlFont ; Create new scaled font $g_hCtrlFont = _WinAPI_CreateFont(-Round($fDefPixel * $iNewDPI), 0, 0, 0, $FW_NORMAL, False, False, False, _ $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $PROOF_QUALITY, $DEFAULT_PITCH, "Segoe UI") ; Lock window drawing for smoother transition _WinAPI_LockWindowUpdate($hWnd) ; Enumerate child windows for sizing adjustments Local $aCtrls = _WinAPI_EnumChildWindows($hWnd, False) Local $hCtrl, $sClass, $aPos, $tPoint, $iX, $iY, $iW, $iH, $iOrigDPI If IsArray($aCtrls) Then For $i = 1 To $aCtrls[0][0] $hCtrl = $aCtrls[$i][0] $sClass = $aCtrls[$i][1] $aPos = WinGetPos($hCtrl) $tPoint = DllStructCreate("int X;int Y") DllStructSetData($tPoint, "X", $aPos[0]) DllStructSetData($tPoint, "Y", $aPos[1]) ; Convert screen coordinates to client _WinAPI_ScreenToClient($hWnd, $tPoint) $iX = DllStructGetData($tPoint, "X") $iY = DllStructGetData($tPoint, "Y") $iW = _WinAPI_GetWindowWidth($hCtrl) $iH = _WinAPI_GetWindowHeight($hCtrl) ; Divide value by previous DPI factor to get original size, then multiply by new DPI factor (rounded to nearest .5) $iX = Round((($iX / $iPrevDPI) * $iNewDPI) / 0.5) * 0.5 $iY = Round((($iY / $iPrevDPI) * $iNewDPI) / 0.5) * 0.5 $iW = Round((($iW / $iPrevDPI) * $iNewDPI) / 0.5) * 0.5 $iH = Round((($iH / $iPrevDPI) * $iNewDPI) / 0.5) * 0.5 ; Set new position/sizes for control Local $iCtrlID = _WinAPI_GetDlgCtrlID($hCtrl) If $iCtrlID < 10000 Then GUICtrlSetResizing($iCtrlID, $GUI_DOCKLEFT + $GUI_DOCKTOP + $GUI_DOCKWIDTH + $GUI_DOCKHEIGHT) GUICtrlSetPos($iCtrlID, $iX, $iY, $iW, $iH) ; working for GUICtrlCreate* controls only ElseIf $iCtrlID >= 10000 Then ControlMove($hWnd, "", $iCtrlID, $iX, $iY, $iW, $iH) ; working for UDF-created controls only ElseIf Not $iCtrlID Then ; probably custom SysLink or something which has no CtrlID ; can't move without CtrlID ; only need to modify X here EndIf ; Set new scaled font to each control _SendMessage($hCtrl, $WM_SETFONT, $g_hCtrlFont, True) Next EndIf ; Resize GUI window Local $tRECT = DllStructCreate($tagRECT, $lParam) Local $iX = $tRECT.left, $iY = $tRECT.top, $iW = $tRECT.right - $iX, $iH = $tRECT.bottom - $iY _WinAPI_SetWindowPos($hWnd, 0, $iX, $iY, $iW, $iH, BitOR($SWP_NOZORDER, $SWP_NOACTIVATE)) ; ; IMPORTANT: Desperately need a GUICtrlGetResizing() function to restore original control resizing behavior ; ; Update previous DPI with the now current DPI $iPrevDPI = $iNewDPI _WinAPI_LockWindowUpdate(0) ; Delete previous font If $hFont Then _WinAPI_DeleteObject($hFont) Return 0 EndFunc ;==>_WM_DPICHANGED Func _Cleanup() _WinAPI_DeleteObject($g_hCtrlFont) EndFunc Func _WinAPI_GetDPIForWindow($hWnd) ; UEZ Local $aResult = DllCall('user32.dll', "uint", "GetDpiForWindow", "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_GetDPIForWindow Edited 8 hours ago by WildByDesign
argumentum Posted 7 hours ago Posted 7 hours ago 27 minutes ago, WildByDesign said: Work in progress, Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now