EdWilson Posted June 23, 2019 Posted June 23, 2019 (edited) What is the most elegant way of obtaining the scaling for a monitor? For example, my Surface Pro suggests a scaling of 200, so with a resolution of 2736 x 1824, @DesktopWidth = 1368 (i.e. 2736 / 2). When I want to perform a PixelGetColor I need to multiply the x & y coordinates by the scaling factor. (in this case, 2.0) While I've put together code works for me (no testing on other machines), is there a more elegant way? Something simpler than messing with the manifest? (unless that's way simpler than I think). Thanks, Ed expandcollapse popup#include <WinAPISys.au3> #include <GDIPlus.au3> #include <ScreenCapture.au3> #include <WinAPIHObj.au3> _ConsoleWrite_WithTimeAndCR("Starting") _ConsoleWrite_WithTimeAndCR("_GetDesktopScaling_RoundaboutDraft()=" & _GetDesktopScaling_RoundaboutDraft() & @CRLF) _ConsoleWrite_WithTimeAndCR("_WinAPI_GetSystemMetrics(0)=" & _WinAPI_GetSystemMetrics(0)) ;showing that these do not reflect scaling _ConsoleWrite_WithTimeAndCR("_WinAPI_GetSystemMetrics(1)=" & _WinAPI_GetSystemMetrics(1)) ;showing that these do not reflect scaling _ConsoleWrite_WithTimeAndCR("_WinAPI_GetSystemMetrics(78)=" & _WinAPI_GetSystemMetrics(78)) ;showing that these do not reflect scaling _ConsoleWrite_WithTimeAndCR("_WinAPI_GetSystemMetrics(79)=" & _WinAPI_GetSystemMetrics(79)) ;showing that these do not reflect scaling Func _GetDesktopScaling_RoundaboutDraft() ;~ Purpose is to get the scaling for the primary monitor. Necessary when getting pixel color at certain coordinates. ;~ MS suggests not using an API call to make a thread DPIAware (https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setprocessdpiaware) ;~ I have not found a function to return this (may be missing it). ;~ Have not found it reliably in registry (? is in display adapter info, but that changes from machine to machine). (Have backed up entire reg, changed the setting and immediately backed it up again, then did WinMerge to compare.) ;~ Strategy is to create a window, maximize it while transparent, capture it as an image, get the dimensions, and compare against @DesktopWidth or @DesktopHeight. This takes between .25 and .4 sec to run on one particular Surface. Local $h_GUI_Handle = GUICreate("Window Just For Capture To Determine Scaling") GUISetState(@SW_DISABLE) ; WinSetTrans("Window Just For Capture To Determine Scaling", "", 0) ;prevents an ugly window from appearing. Could mess with controls that are being used when this runs. GUISetState(@SW_MAXIMIZE) ;@SW_MAXIMIZE seems to make the window visible even if it was hidden, or disabled prior. Thus an ugly flash on the screen. Local $h_HBITMAP = _ScreenCapture_CaptureWnd("", $h_GUI_Handle) GUIDelete($h_GUI_Handle) _GDIPlus_Startup() Local $h_GDIObject = _GDIPlus_BitmapCreateFromHBITMAP($h_HBITMAP) Local $i_ImageWidth = _GDIPlus_ImageGetWidth($h_GDIObject) Local $i_ImageHeight = _GDIPlus_ImageGetHeight($h_GDIObject) _GDIPlus_ImageDispose($h_GDIObject) _WinAPI_DeleteObject($h_HBITMAP) _GDIPlus_Shutdown() Local $n_Scaling_W = $i_ImageWidth / @DesktopWidth Local $n_Scaling_H = $i_ImageHeight / @DesktopHeight _ConsoleWrite_WithTimeAndCR("$i_ImageWidth=" & $i_ImageWidth & " $i_ImageHeight=" & $i_ImageHeight) _ConsoleWrite_WithTimeAndCR("@DesktopWidth=" & @DesktopWidth & " @DesktopHeight=" & @DesktopHeight) _ConsoleWrite_WithTimeAndCR("$n_Scaling_W=" & $n_Scaling_W & " $n_Scaling_H=" & $n_Scaling_H) Return Round($n_Scaling_W, 2) EndFunc ;==>_GetDesktopScaling_RoundaboutDraft ; Logging and Console writes Func _ConsoleWrite_WithTimeAndCR($s_ConsoleMessage) ConsoleWrite(@YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & "." & @MSEC & " " & $s_ConsoleMessage & @CRLF) ;If $s_Log_WriteConsoleWrites_To_LogFile = "Y" Then _LogWrite_WithRollCapability($s_ConsoleMessage) EndFunc ;==>_ConsoleWrite_WithTimeAndCR Edited June 23, 2019 by EdWilson
Malkey Posted June 24, 2019 Posted June 24, 2019 I use this. #include <WinAPIGdi.au3> Global $scale = _WinAPI_EnumDisplaySettings('', $ENUM_CURRENT_SETTINGS)[0] / @DesktopWidth ConsoleWrite("Scale = " & _WinAPI_EnumDisplaySettings('', $ENUM_CURRENT_SETTINGS)[0] & " / " & @DesktopWidth & " = " & $scale & @CRLF) ; My laptop returns:- Scale = 1920 / 1536 = 1.25
EdWilson Posted July 7, 2019 Author Posted July 7, 2019 (edited) Perfect, and thank you! (Sorry for the slow reply) Edited July 7, 2019 by EdWilson
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