Jump to content
Sign in to follow this  
ces1a

Wrong Screen Resolution Displayed by Autoit Macros

Recommended Posts

I recently upgraded my laptop to one with Windows 10 and higher screen resolution.  In the process I found that some of my scripts did not work right when using Autoit's @DesktopWidth and @DesktopHeight macros.  Insteat of 1920 x 1080 resolution Autoit detects 1536 x 864.  Thus, GUIs designed to appear near the right edge of the screen  displayed closer to the horizontal middle of the screen.  I assume others may have the same problem.

A search on this forum and Microsoft Script Center helped me to write the following script that gets the true screen width and height from WMI.

MsgBox(0, '', _GetMonitorInfo())

Func _GetMonitorInfo()
    Local $oWMI, $Listing, $sWidth = 0, $sHeight = 0
    $oWMI = ObjGet("winmgmts:\\" & @ComputerName & "\root\CIMV2")
    If IsObj($oWMI) Then
        $Listing = $oWMI.ExecQuery("SELECT * FROM Win32_DesktopMonitor")
        If IsObj($Listing) Then
            For $oItem In $Listing
                $sHeight = $oItem.ScreenHeight
                $sWidth = $oItem.ScreenWidth
            Next
        EndIf
    EndIf
    Return "Width: " & $sWidth & @CRLF & "Height: " & $sHeight
EndFunc ;_GetMonitorInfo


Hopefully it will benefit others.  I for sure am very happy with all the samples I been able to find here in the past.

Share this post


Link to post
Share on other sites

Have you tried adding:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_HiDpi=Y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

Then when you compile the code this works on W7 and 8 at least Could you try it on your win 10 install 

Edited by Bilgus

Share this post


Link to post
Share on other sites

This can happen when Win10 auto-rescales (see under display settings, I think 125% is default for 1920x1080) to make them easier to read (as hi-res screens make everything that used to look about the right size look tiny now). To make your original script work in full resolution (with macros returning the correct (full) dimensions), while maintaining rescaling for regular programmes, add:

DllCall("User32.dll","bool","SetProcessDPIAware")

This causes the script to take advantage of the full current resolution, but at the cost of its text and graphics appearing smaller than if running rescaled.

Edited by RTFC

Share this post


Link to post
Share on other sites
3 hours ago, RTFC said:

This can happen when Win10 auto-rescales (see under display settings, I think 125% is default for 1920x1080) to make them easier to read (as hi-res screens make everything that used to look about the right size look tiny now). To make your original script work in full resolution (with macros returning the correct (full) dimensions), while maintaining rescaling for regular programmes, add:

DllCall("User32.dll","bool","SetProcessDPIAware")

This causes the script to take advantage of the full current resolution, but at the cost of its text and graphics appearing smaller than if running rescaled.

Hey, Thanks.

Noted This: https://msdn.microsoft.com/en-us/library/windows/desktop/ms633543(v=vs.85).aspx

Note  SetProcessDPIAware is subject to a possible race condition if a DLL caches dpi settings during initialization. For this reason, it is recommended that dpi-aware be set through the application (.exe) manifest rather than by calling SetProcessDPIAware.

 

So it sounds like something like this is in order.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_HiDpi=Y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

If Not (@Compiled ) Then DllCall("User32.dll","bool","SetProcessDPIAware")

 

 

Edited by Bilgus

Share this post


Link to post
Share on other sites

Thanks a lot to everyone.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_HiDpi=Y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

The above lines seem to make my executable unable to run.  I have not figured out why yet.

DllCall("User32.dll","bool","SetProcessDPIAware")

Lets my script run but causes distortion to my labels,

However, looks like this is the right direction to go.

Thanks a million...

 

Share this post


Link to post
Share on other sites

I know turning scaling off would change your labels not sure about the app not running with the manifest entry added though.

I wonder if maybe it has something to do with this: 'SetProcessDPIAware is available for use in the operating systems specified in the Requirements section. It may be altered or unavailable in subsequent versions. Instead, use SetProcessDpiAwareness'

SetProcessDpiAwareness: https://msdn.microsoft.com/en-us/library/windows/desktop/dn302122(v=vs.85).aspx

It seems to have the same caveats as SetProcessDPIAware as in placing in manifest rather than calling the function directly,

it also isn't available till win 8 and later.

Perhaps W10 won't work with the older function in the manifest which I find odd. If so,  I think additions to the manifest or logic would be something that would have to be updated in the Autoit  Res_HiDpi Pragma

Maybe someone more knowledgeable with aut2Exe  would be able to inform us on that.

For the time being maybe you should use either your current function or maybe do something like this:

If @OsType="WIN_10" Then
    DllCall("Shcore.dll","long","PROCESS_DPI_AWARENESS",1) 
Else
    DllCall("User32.dll","bool","SetProcessDPIAware") 
EndIf
;hResult is 32bit

;PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE  = 2

Not sure if I got that dll call right I'm not near a PC to test atm.

Also, Not necessarily directed at you:
I'm unsure how likely it is that a Dll would cache the dpi data.

Would the Dll be something called by Autoit or the OS. 

What exact situation would result in this Race Condition and what are the consequences?

Be something to look into as the MSDN page is kind of vague.

Edited by Bilgus
changed return type on Shcore.dll to long

Share this post


Link to post
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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By nacerbaaziz
      hello autoit team
      please i need your help today
      am trying to make the list of features in list view and control it
      am using the dism command line to read output
      i've made the code
      but i found some problems
      what i need is the list of features in 2d array
      $array[$n][0]= name $array[$i][1] = state
      when i tested the code
      it give me some results that i don't need to it e.g
      ------ ------  | --------
      or
      name       | state
      i need just the list of features and there state
      please help me to do that
      here is my example
      #RequireAdmin #NoTrayIcon #include <AutoItConstants.au3> Wow64EnableWow64FsRedirection(false) _Windows_Get_Features() func _Windows_Get_Features() local $a_FeaturesArray[1][2] $a_FeaturesArray[0][0] local $i_Dism_Run = Run("DISM /online /english /get-features /format:table", "", @sw_hide, BitOR($STDERR_CHILD, $STDOUT_CHILD)) local $s_OutputDism = "", $a_OutPutDism While 1 $s_OutputDism = StdoutRead($i_Dism_Run) If @error Then exitLoop if ($s_OutputDism = "") or (StringRegExp($s_OutputDism, "^((\-){1,})?(?:\s)\|?(?:\s)((\-){1,})$", 0) = 1) then ContinueLoop if (StringRegExp($s_OutputDism, "((([\s\d\-\+\_\,]{1})\|([\s\d\-\+\_\,]{1})){1,})", 0) = 1) then $a_OutPutDism = StringSplit($s_OutputDism, @lf) for $i = 1 to $a_OutPutDism[0] if msgBox(1, $i, $a_OutPutDism[$i]) = 1 then exitLoop next endIf Wend endFunc func Wow64EnableWow64FsRedirection($b_Enabled) local $h_OpenFS = DLLOpen("kernel32.dll") local $Return = DllCall($h_OpenFS, "boolean", "Wow64EnableWow64FsRedirection", "boolean", $b_Enabled) if @error then DLLClose($h_OpenFS) Return SetError(@error, @extended, -1) else DLLClose($h_OpenFS) Return $Return[0] endIf endFunc  
    • By nacerbaaziz
      question about _WinAPI_CreateWindowEx
      good morning
      welcome autoit team
      please i need your help
      i've searched a lot about how to use the _WinAPI_CreateWindowEx
      finally i found an example
      but i found some problem i hope you can help me
      firstly, i want to set the controls focussable with the keyboard input
      i already used the ws_tabStop but it did not work with me.
      secondly, i want to set some access keys linked with the window
      such as control+o enable the open button and control+f4 exit the app
      note: i need a local access keys and not a global hotkeys
      such as GUISetAccelerators
      finaly, before i will put the code here i must clarify a few things.
      1. you will ask me why you don't use the GUICreate function
      here i'll tell you that it as dialog and It is a little heavy in motion with screen readers.
      the screen readers for blind has some function that work with dialogs and others work with full windows style
      2. you will ask me why you didn't search the net for that?
      i will tell you that all examples that i found in the internet with pdfs and Picture books.
      i found some examples in microsoft but it with cpp.
      ok here is the code
      i hope you can help me to do what i want
      thank you in advance
       
      ; Small AutoIt Application that uses Windows API ; Written by Yuraj #NoTrayIcon #include <_RegisterClassEx.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> #include <ButtonConstants.au3> #include <EditConstants.au3> #include <FontConstants.au3> AutoItSetOption("MustDeclareVars", 1) ; Window definitions Const $WinWidth = 370 Const $WinHeight = 350 Const $WinXPos = (@DesktopWidth / 2) - ($WinWidth / 2) Const $WinYPos = (@DesktopHeight / 2) - ($WinHeight / 2) Const $WinTitle = "Win32 Application - Text reader" Const $WinClass = "mainapp" Const $WinIcon = _WinAPI_LoadIcon(_WinAPI_GetModuleHandle("shell32.dll"), 13) ; Windows handles Global $hwnd, $edit1, $btn1, $btn2 ; Fonts Global $fnt1 ; Register class, Create the window Local $retVal = __WinAPI_RegisterClassEx($WinClass, "WindowCallback", $WinIcon, 0, _WinAPI_GetSysColor($COLOR_BTNFACE), BitOR($CS_DEFAULTSTYLE, $CS_DROPSHADOW)) ; If $retVal == 0 Then ; If registerclass fails MsgBox(16, "Error", "Error while registering window class!") Exit EndIf ; Create windows/controls $hwnd = _WinAPI_CreateWindowEx($WS_EX_STATICEDGE, $WinClass, $WinTitle, BitOR($WS_OVERLAPPED,$WS_SYSMENU, $WS_MINIMIZEBOX, $WS_GROUP, $WS_DLGFRAME), $WinXPos, $WinYPos, $WinWidth, $WinHeight, 0) $btn1 = _WinAPI_CreateWindowEx(0, "button", "Open file ...", BitOR($WS_VISIBLE, $WS_CHILD, $WS_TABSTOP, $WS_CLIPCHILDREN), 25, 270, 100, 30,$hwnd) $btn2 = _WinAPI_CreateWindowEx(0, "Button", "Exit", BitOR($WS_VISIBLE, $WS_CHILD, $WS_TABSTOP, $WS_CLIPCHILDREN), 235, 270, 100, 30, $hwnd) $edit1 = _WinAPI_CreateWindowEx(0, "edit", "text", BitOR($WS_VISIBLE, $WS_CHILD, $WS_VSCROLL, $ES_AUTOVSCROLL, $es_readOnly, $WS_TABSTOP), 5, 5, $WinWidth - 15, $WinHeight - 100, $hwnd) ; Set controls identifiers _WinAPI_SetWindowLong($btn1,$GWL_ID,150) _WinAPI_SetWindowLong($btn2,$GWL_ID,160) ; Set (controls) fonts $fnt1 = _CreateFont("MS Sans Serif", 15) _WinAPI_SetFont($btn1, $fnt1) _WinAPI_SetFont($btn2, $fnt1) _WinAPI_SetFont($edit1, $fnt1) ; Set focus to edit _WinAPI_SetFocus($edit1) ; Show window _WinAPI_ShowWindow($hwnd) _WinAPI_UpdateWindow($hwnd) ; Main loop that keep application opened While 1 Sleep(100) WEnd ;=================================================================; ; WINDOW CALLBACK ... ;=================================================================; Func WindowCallback($_hwnd, $iMsg, $wParam, $lParam) Local $iNC, $iID Switch $iMsg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Case $WM_CLOSE ; Show message on closing If MsgBox(48 + 4, $WinTitle, "Do you want really exit?", 0, $hwnd) <> 6 Then Return 0 ; Call destructor and then exit main thread FinalizeApp() Exit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Case $WM_COMMAND $iNC = _WinAPI_HiWord($wParam) $iID = _WinAPI_LoWord($lParam) Switch $iNC Case $BN_CLICKED ; When is control clicked Switch _WinAPI_GetDlgCtrlID($iID) Case _WinAPI_GetDlgCtrlID($btn1) BtnOpenFileClick() Case _WinAPI_GetDlgCtrlID($btn2) BtnExitClick() EndSwitch EndSwitch ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EndSwitch Return _WinAPI_DefWindowProc($_hwnd, $iMsg, $wParam, $lParam) EndFunc ;==>WindowCallback Func FinalizeApp() _WinAPI_DeleteObject($fnt1) _WinAPI_DestroyWindow($hwnd) __WinAPI_UnregisterClass($WinClass) EndFunc ;==>FinalizeApp Func _CreateFont($fontName, $height = 16, $style = $FW_NORMAL, $italic = False, $underline = False, $strikeout = False) Local $hFont = _WinAPI_CreateFont($height, 0, 0, 0, $style, $italic, $underline, $strikeout, $DEFAULT_CHARSET, _ $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, $DEFAULT_PITCH, $fontName) Return $hFont EndFunc ;==>_CreateFont ;=================================================================; ; WINDOW EVENTS ;=================================================================; Func BtnOpenFileClick() Local $ret = _WinAPI_GetOpenFileName("", "Text files (*.txt)|All files (*.*)", ".", "", "", 1, 0, 0, $hwnd) If ($ret[0] > 0) Then Local $path = $ret[1] & "\" & $ret[2] Local $file = _WinAPI_CreateFile($path, 2, 2) Local $buf = DllStructCreate("byte[" & _WinAPI_GetFileSizeEx($file) & "]") Local $i = 0 _WinAPI_ReadFile($file, DllStructGetPtr($buf), _WinAPI_GetFileSizeEx($file), $i) ; Close file handle _WinAPI_CloseHandle($file) _WinAPI_SetWindowText($edit1, BinaryToString(DllStructGetData($buf, 1))) EndIf EndFunc ;==>BtnOpenFileClick Func BtnExitClick() FinalizeApp() Exit EndFunc ;==>BtnExitClick  
      _RegisterClassEx.au3
    • By Saravanan2213
      Hi everyone,
      i just need your help. i have script for cleaning browsing history and other unwanted file but the problem is i don't want to see the GUI i have attached below. It should not show anything on the screen. is it possible to do it in autoit. thanks in advance.
       
      So for i have tried flag
      Run("rundll32.exe InetCpl.cpl,ClearMyTracksByProcess 255", "", @SW_HIDE)
      @SW_DISABLE
       
      Looking forward your help.........

    • By Kelvin44
      WiFi Disconnects Automatically Windows 10 / 8 / 7 Laptop. This video guide very help to me
    • By PeterVerbeek
      Hi Guys,
      I've noticed that the SoundGetWaveVolume UDF in an older topic isn't working on Windows Vista, 7, 8, 8.1 and 10. It's probably a Windows XP UDF. The UDF below does work. It successfully returns the volume set by SoundSetWaveVolume. It might need checking by the AutoIt community for some synthax finetuning.
      ; #FUNCTION# ==================================================================================================================== ; Name...........: _SoundGetWaveVolume ; Description....: Returns app volume of script, Windows Vista, 7, 8, 10 only ; Syntax.........: _SoundGetWaveVolume([$iValueOnError = -1]) ; Parameters.....: $iValueOnError - Value to return when an error occurs ; Return values..: App volume of script or $iValueOnError at an error ; Error values...: @error = 1 - Unable to create Struct ; @error = 2 - Dll file not found ; @error = 3 - Wrong call so not on Windows Vista, 7, 8 or 10 ; @error = 4 - Internal error, array not returned ; @error = 5 - Volume wasn't received ; @error = 6 - Volume couldn't read ; Author.........: Peter Verbeek ; Modified.......: ; =============================================================================================================================== Func _SoundGetWaveVolume($iValueOnError = -1) Local $LPDWORD,$aMMRESULT,$iVolume $LPDWORD = DllStructCreate("dword") If @error <> 0 Then SetError(1) ; 1 = unable to create Struct Return $iValueOnError EndIf ; get app volume of this script $aMMRESULT = DllCall("winmm.dll","uint","waveOutGetVolume","ptr",0,"long_ptr",DllStructGetPtr($LPDWORD)) Switch @error Case 1 SetError(2) ; 2 = dll file not found Return $iValueOnError Case 2,3,4,5 SetError(3) ; 3 = wrong call so not on Windows Vista, 7, 8 or 10 Return $iValueOnError EndSwitch If not IsArray($aMMRESULT) Then SetError(4) ; 4 = internal error, array not returned Return $iValueOnError EndIf If $aMMRESULT[0] <> 0 Then SetError(5) ; 5 = volume wasn't received Return $iValueOnError EndIf $iVolume = DllStructGetData($LPDWORD,1) If @error <> 0 Then SetError(6) ; 6 = volume couldn't read Return $iValueOnError EndIf Return Round(100*$iVolume/4294967295) ; return in range 0 to 100 as SoundSetWaveVolume() EndFunc  
×
×
  • Create New...