Jump to content

MouseMove and scaling issue


Go to solution Solved by ioa747,

Recommended Posts

I'm trying to move the mouse between three monitors (shaped like an L if that matters). But it's not working because the primary monitor (laptop) has 150% scale. I've seen a couple older posts that try to tackle the issue of mousemove and scaling, but the solutions don't quite tackle the basic compensation issue of a simple mouse move...more like tracking, and I can't really decode what they put together. Has anyone come up with a simple compensation for mousemove with a scaled primary screen?

Link to comment
Share on other sites

I guess I'm missing something and don't see how to implement this. I see how this can help with resolution and monitor count, which I don't have an issue with, but I don't see how this can help with window scaling and mousemove coordinates taking it into consideration.

Link to comment
Share on other sites

No, everything is just off when a monitor has the scale changed. Look at the image. All monitors are 1920 with monitor 1 having a scale of 150%.  If I set MouseMove(2000, 500) the mouse should end up around the green line on monitor 2, but it instead ends up around the blue line. When the scale is at 100% the mouse moves where I expect it to. Some mousemove coordinates wont even move to screen 2 all together even if the coordinates dictate it should be on screen 2.

monitors.png

Link to comment
Share on other sites

  • Solution

can you show the console output from the script i suggested?

indeed, the mouse lives in its world (with a zoom factor of 200% it makes half the journey), while the ToolTip goes normally to its position

however the problem seems to be fixed by using  DPIAwareness.au3  

which I found after digging in  CV  as suggested by @argumentum

 

DPIAwareness.au3

Spoiler
#include-once ; #include "DPIAwareness.au3"

#include <Array.au3>
#include <GUIConstantsEx.au3> ;;; https://www.autoitscript.com/forum/topic/199786-making-your-compiled-application-dpi-aware/?do=findComment&comment=1433365
#include <GDIPlus.au3>
#include <WinAPIGdiDC.au3>
#include <WinAPISysWin.au3>

;~ _GDIPlus_Startup() ; Done in "CV.au3"

; enum _PROCESS_DPI_AWARENESS -> https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).aspx
Global Enum $DPI_AWARENESS_INVALID = -1, $PROCESS_DPI_UNAWARE = 0, $PROCESS_SYSTEM_DPI_AWARE, $PROCESS_PER_MONITOR_DPI_AWARE

Global Enum $Context_UnawareGdiScaled = -5, $Context_PerMonitorAwareV2, $Context_PerMonitorAware, $Context_SystemAware, $Context_Unaware

; 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



Func _WinAPI_SetDPIAwareness($hGUI = 0)
    Switch @OSBuild
        Case 6000 To 9199
            If Not DllCall("user32.dll", "bool", "SetProcessDPIAware") Then Return SetError(1, 0, 0)
            Return 1
        Case 9200 To 13999
            _WinAPI_SetProcessDpiAwareness($PROCESS_PER_MONITOR_DPI_AWARE)
            If @error Then Return SetError(2, 0, 0)
            Return 1
        Case @OSBuild > 13999
            #cs
                Context_Unaware = ((DPI_AWARENESS_CONTEXT)(-1)),
                Context_SystemAware = ((DPI_AWARENESS_CONTEXT)(-2)),
                Context_PerMonitorAware = ((DPI_AWARENESS_CONTEXT)(-3)),
                Context_PerMonitorAwareV2 = ((DPI_AWARENESS_CONTEXT)(-4)),
                Context_UnawareGdiScaled = ((DPI_AWARENESS_CONTEXT)(-5))
            #ce
            _WinAPI_SetProcessDpiAwarenessContext($Context_PerMonitorAwareV2, $hGUI)
            If @error Then Return SetError(3, @error, 0)
            Return 1
    EndSwitch
    Return -1
EndFunc   ;==>_WinAPI_SetDPIAwareness

Func _WinAPI_SetProcessDpiAwareness($DPIAware) ;https://docs.microsoft.com/en-us/windows/desktop/api/shellscalingapi/nf-shellscalingapi-setprocessdpiawareness
    Local $aResult = DllCall("Shcore.dll", "long", "SetProcessDpiAwareness", "int", $DPIAware)
    If @error Then Return SetError(1, 0, 0)
    #forceref $aResult
    Return 1
EndFunc   ;==>_WinAPI_SetProcessDpiAwareness

Func _WinAPI_SetProcessDpiAwarenessContext($DPIAwareContext = $Context_PerMonitorAware, $hGUI = 0, $iMode = 3) ;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setprocessdpiawarenesscontext
    $DPIAwareContext = ($DPIAwareContext < -5) ? -5 : ($DPIAwareContext > -1) ? -1 : $DPIAwareContext
    $iMode = ($iMode < 1) ? 1 : ($iMode > 3) ? 3 : $iMode
    Local $aResult, $aResult1, $aResult2, $aResult31, $aResult32
    Switch $iMode
        Case 1
            Local $hDC = _WinAPI_GetDC($hGUI)
            $aResult1 = DllCall("user32.dll", "int", "GetDpiFromDpiAwarenessContext", "ptr", $hDC)
            If @error Or Not IsArray($aResult1) Then Return SetError(11, 0, 0)
            _WinAPI_ReleaseDC(0, $hDC)
            $aResult = DllCall("user32.dll", "Bool", "SetProcessDpiAwarenessContext", "int", $aResult1[0] + $DPIAwareContext)
            If @error Or Not IsArray($aResult) Then Return SetError(12, 0, 0)
        Case 2
;~          If Not $hGUI Then $hGUI = WinGetHandle(AutoItWinGetTitle())
            $aResult2 = DllCall("user32.dll", "int", "GetWindowDpiAwarenessContext", "ptr", $hGUI)
            If @error Or Not IsArray($aResult2) Then Return SetError(21, 0, 0)
            $aResult = DllCall("user32.dll", "Bool", "SetProcessDpiAwarenessContext", "int", $aResult2[0] + $DPIAwareContext)
            If @error Or Not IsArray($aResult) Then Return SetError(22, 0, 0)
        Case 3
            $aResult31 = DllCall("user32.dll", "ptr", "GetThreadDpiAwarenessContext")
            If @error Or Not IsArray($aResult31) Then Return SetError(31, 0, 0)
            $aResult32 = DllCall("user32.dll", "int", "GetAwarenessFromDpiAwarenessContext", "ptr", $aResult31[0])
            If @error Or Not IsArray($aResult32) Then Return SetError(32, 0, 0)
            $aResult = DllCall("user32.dll", "Bool", "SetThreadDpiAwarenessContext", "int", $aResult32[0] + $DPIAwareContext)
            If @error Or Not IsArray($aResult) Then Return SetError(33, 0, 0)
    EndSwitch

    Return 1
EndFunc   ;==>_WinAPI_SetProcessDpiAwarenessContext

 

 

Example

; https://www.autoitscript.com/forum/topic/210653-mousemove-and-scaling-issue/#comment-1522551

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#include <WindowsConstants.au3>
#include <WinAPIGdi.au3>
#include "DPIAwareness.au3"

_WinAPI_SetDPIAwareness()

Global $hGui = GUICreate('Au3Gui', 500, 500, -1, -1, $WS_OVERLAPPEDWINDOW)
WinSetTrans($hGui, '', 100)
Global $Label1 = GUICtrlCreateLabel("", 200, 200, 300, 300)
GUICtrlSetFont(-1, 200, 900, 0, "MS Sans Serif")
GUISetState(@SW_SHOW, $hGui)

Global $aMon = _GetMonitorsArray()

If IsArray($aMon) Then

    #Region ===( test1 )===
    For $i = 1 To $aMon[0][0]
        WinMove($hGui, "", $aMon[$i][1], $aMon[$i][2], $aMon[$i][3], $aMon[$i][4])
        GUISetState(@SW_MAXIMIZE, $hGui)
        GUICtrlSetData($Label1, $i)

        ConsoleWrite("  index: " & $i & @CRLF)
        ConsoleWrite("- [0]=handle=" & $aMon[$i][0] & @CRLF)
        ConsoleWrite("- [1]=left=" & $aMon[$i][1] & @CRLF)
        ConsoleWrite("- [2]=top=" & $aMon[$i][2] & @CRLF)
        ConsoleWrite("- [3]=width=" & $aMon[$i][3] & @CRLF)
        ConsoleWrite("- [4]=height=" & $aMon[$i][4] & @CRLF)
        ConsoleWrite("" & @CRLF)

        _GetMonitorInfo($hGui)

        Sleep(2000)
    Next

    GUIDelete($hGui)
    #EndRegion ===( test1 )===

    #Region ===( test2 )===
    Global $iX, $iY
    For $i = 1 To $aMon[0][0]

        ;the start point
        $iX = $aMon[$i][1]
        $iY = $aMon[$i][2]

        ;plus the midle point
        $iX += $aMon[$i][3] / 2
        $iY += $aMon[$i][4] / 2

        ConsoleWrite($iX & ", " & $iY & @CRLF)

        ToolTip("Mouse x, y:" & @CRLF & $iX & ", " & $iY, $iX, $iY, "midle point:", 1, 3)
        MouseMove($iX, $iY, 70)

        Global $aPos = MouseGetPos()
        ConsoleWrite("MouseGetPos x, y:" & $aPos[0] & ", " & $aPos[1] & @CRLF)

        Sleep(3000)
        ToolTip("")

    Next
    #EndRegion ===( test2 )===

EndIf

;----------------------------------------------------------------------------------------
Func _GetMonitorInfo($hWindow)
    Local $hMonitor = _WinAPI_MonitorFromWindow($hWindow, $MONITOR_DEFAULTTONULL)
    Local $aData = _WinAPI_GetMonitorInfo($hMonitor)
    ConsoleWrite('MonitorInfo **********************' & @CRLF)
    If Not @error Then
        ConsoleWrite('Handle:      ' & $hMonitor & @CRLF)
        ConsoleWrite('Rectangle:   ' & DllStructGetData($aData[0], 1) & ', ' & DllStructGetData($aData[0], 2) & ', ' & DllStructGetData($aData[0], 3) & ', ' & DllStructGetData($aData[0], 4) & @CRLF)
        ConsoleWrite('Work area:   ' & DllStructGetData($aData[1], 1) & ', ' & DllStructGetData($aData[1], 2) & ', ' & DllStructGetData($aData[1], 3) & ', ' & DllStructGetData($aData[1], 4) & @CRLF)
        ConsoleWrite('Primary:     ' & $aData[2] & @CRLF)
        ConsoleWrite('Device name: ' & $aData[3] & @CRLF)
        ConsoleWrite("**********************************" & @CRLF & @CRLF)

    EndIf
EndFunc   ;==>_GetMonitorInfo
;----------------------------------------------------------------------------------------
Func _GetMonitorsArray()
    Local $aPos, $aData = _WinAPI_EnumDisplayMonitors()
    If IsArray($aData) Then
        ReDim $aData[$aData[0][0] + 1][5]
        For $i = 1 To $aData[0][0]
            $aPos = _WinAPI_GetPosFromRect($aData[$i][1])
            For $j = 0 To 3
                $aData[$i][$j + 1] = $aPos[$j]
            Next
        Next
    EndIf
    Return $aData
EndFunc   ;==>_GetMonitorsArray
;----------------------------------------------------------------------------------------

 

;comment /  uncomment  the _WinAPI_SetDPIAwareness() func to see  the different

Edited by ioa747
Correction

I know that I know nothing

Link to comment
Share on other sites

  • 1 month later...

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...