MouseGetPos - relativ + Berücksichtigung Caption

    • Offizieller Beitrag

    Hi,
    da MouseGetPos uns mit der Standard Opt('MouseCoordMode') die absoluten Koordinaten liefert und ich i.A. nicht für das ganze Skript den Modus ändern möchte, habe ich mal die Schritte (Mode wechseln, Koordinaten ermitteln, zurück zu altem Mode) in einer Funktion zusammengefasst mit einem optionalen Parameter zur Berücksichtigung (einer evtl. vorhandenen) Titelleiste. Denn das Fenster beginnt für die relativen Koordinaten am Fensterrand.
    Falls ein randloser Style verwendet wird, gibt es hier kleine Differenzen. Da ich die Positionsabfrage aber selten pixelgenau benötige, ist das wenig dramatisch.
    Syntax (und Rückgabe) identisch zu MouseGetPos, zusätzlicher Parameter True/False für Titelhöhe berücksichtigen.
    Falls es wer braucht:

    Spoiler anzeigen
    [autoit]

    Func _MouseGetPosRel($i=-1, $fAddTitleHeight=False)
    Local $ret, $iTitleHeight = 0, $iBorder
    If $fAddTitleHeight Then
    ; === Höhe Caption
    $ret = DllCall("user32.dll", "long", "GetSystemMetrics", "long", 4)
    $iTitleHeight = $ret[0]
    EndIf
    ; === Höhe Border
    $ret = DllCall("user32.dll", "long", "GetSystemMetrics", "long", 6)
    $iBorder = $ret[0]
    If $fAddTitleHeight Then $iTitleHeight += 2*$iBorder
    Local $old = Opt('MouseCoordMode', 0)
    Local $aM = MouseGetPos()
    Opt('MouseCoordMode', $old)
    Switch $i
    Case 0
    Return $aM[0] -$iBorder
    Case 1
    Return $aM[1] -$iTitleHeight
    Case Else
    $aM[0] -= $iBorder
    $aM[1] -= $iTitleHeight
    Return $aM
    EndSwitch
    EndFunc

    [/autoit]

    Es funktioniert für XP, aber wie ich schon gehört habe, liefert Systemmetrics bei Win7 wohl fehlerhafte Werte. Könnt ihr ja testen.

  • Wenn man die Mausposition relativ zur Clientarea eines Fensters benötigt, dann ist diese Funktion ganz hilfreich (funktioniert unabhängig von MouseCoordMode)
    Gibt man kein Fensterhandle an, dann werden absolute Bildschirmkooordinaten zurückgegeben

    Spoiler anzeigen
    [autoit]

    #include <WinAPI.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("Test", 400, 300)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    While GUIGetMsg() <> -3
    ;$aPos = _MouseGetPos()
    $aPos = _MouseGetPos($hGui)
    ;$aPos = _MouseGetPos(WinGetHandle("Rechner"))
    ToolTip($aPos[0] & " " & $aPos[1])
    Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _MouseGetPos($hWnd = 0)
    Local $tPoint = DllStructCreate("long X;long Y")
    Local $aResult = DllCall("user32.dll", "bool", "GetCursorPos", "ptr", DllStructGetPtr($tPoint))
    If @error Then Return SetError(@error, @extended, 0)
    If $hWnd Then _WinAPI_ScreenToClient($hWnd, $tPoint)
    Local $aReturn[2]
    $aReturn[0] = DllStructGetData($tPoint, 1)
    $aReturn[1] = DllStructGetData($tPoint, 2)
    Return $aReturn
    EndFunc ;==>_MouseGetPos

    [/autoit]
  • Was spricht denn eigentlich gegen

    [autoit]

    Opt('MouseCoordMode', 2)

    [/autoit]


    Dann könnte man das in einer solchen Funktion kapseln:

    _MouseGetPosCoordMode()
    [autoit]

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _MouseGetPosCoordMode
    ; Description ...: Liefert die Mausposition für einen vorgegebenen CoordMode.
    ; Syntax.........: _MouseGetPosCoordMode([$iDimension[, $iCoordMode]])
    ; Parameters ....: $iDimension - Gültige Dimension (vgl. Hilfe zu MouseGetPos())
    ; |Default : Array mit X-Position in Array[0] und Y-Position in Array[1]
    ; |0 : X-Position als Integer
    ; |1 : Y-Position als Integer
    ; $iCoordMode - Gültiger CoordMode (vgl. Hilfe zu Opt('MouseCoordMode'))
    ; |Default : Aktuell im Skript eingestellter Wert
    ; |0 : Relative Position im aktiven Fenster
    ; |1 : Absolute Position auf dem Bildschirm
    ; |2 : Relative Position im Clientbereich des aktiven Fensters
    ; Return values .: Erfolg - Position in Pixeln im gewünschten Format (s.o.)
    ; Fehler - 0, @error = 1, @extended enthält die Position des fehlerhaften Parameters
    ; Author ........: http://www.autoit.de
    ; Modified.......:
    ; Remarks .......:
    ; Related .......:
    ; Link ..........:
    ; Example .......: Nein
    ; ===============================================================================================================================
    Func _MouseGetPosCoordMode($iDimension = Default, $iCoordMode = Default)
    If $iCoordMode = Default Then $iCoordMode = Opt('MouseCoordMode')
    Switch $iCoordMode
    Case 0, 1, 2
    Local $MCM = Opt('MouseCoordMode', $iCoordMode)
    Local $aPos = MouseGetPos()
    Opt('MouseCoordMode', $MCM)
    Case Else
    Return SetError(1, 2, 0)
    EndSwitch
    Switch $iDimension
    Case Default
    Return $aPos
    Case 0
    Return $aPos[0]
    Case 1
    Return $aPos[1]
    Case Else
    Return SetError(1, 1, 0)
    EndSwitch
    EndFunc

    [/autoit]


    Hier noch was zum Spielen:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Dim $Text = " Clientbereich: 310 x 210" & @CRLF & _
    " Linke obere Ecke des Kastens: 20 - 20" & @CRLF & _
    " Aktuelle Mauskoordinaten per Linksklick abfragen!"
    $hGUI = GUICreate("GUI", 310, 210, -1, -1)
    GUICtrlCreateLabel($Text, 20, 20, 270, 50, $WS_BORDER)
    GUICtrlCreateLabel("_MouseGetPosRel:", 20, 90, 150, 20)
    $Out1 = GUICtrlCreateLabel("", 190, 90, 100, 20)
    GUICtrlCreateLabel("_MouseGetPosCoordMode:", 20, 130, 150, 20)
    $Out2 = GUICtrlCreateLabel("", 190, 130, 100, 20)
    GUICtrlCreateLabel("MouseGetPos - WinGetPos:", 20, 170, 150, 20)
    $Out3 = GUICtrlCreateLabel("", 190, 170, 100, 20)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    While True
    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
    ExitLoop
    Case $GUI_EVENT_PRIMARYDOWN
    $aPos1 = _MouseGetPosRel(-1, 1)
    $aPos2 = _MouseGetPosCoordMode(Default, 2)
    $aPos3 = WinGetPos($hGUI)
    $aPos4 = MouseGetPos()
    GUICtrlSetData($Out1, $aPos1[0] & " - " & $aPos1[1])
    GUICtrlSetData($Out2, $aPos2[0] & " - " & $aPos2[1])
    GUICtrlSetData($Out3, ($aPos4[0] - $apos3[0]) & " - " & ($aPos4[1] - $aPos3[1]))
    EndSwitch
    WEnd
    Exit

    [/autoit] [autoit][/autoit] [autoit]

    Func _MouseGetPosCoordMode($iDimension = Default, $iCoordMode = Default)
    If $iCoordMode = Default Then $iCoordMode = Opt('MouseCoordMode')
    Switch $iCoordMode
    Case 0, 1, 2
    Local $MCM = Opt('MouseCoordMode', $iCoordMode)
    Local $aPos = MouseGetPos()
    Opt('MouseCoordMode', $MCM)
    Case Else
    Return SetError(1, 2, 0)
    EndSwitch
    Switch $iDimension
    Case Default
    Return $aPos
    Case 0
    Return $aPos[0]
    Case 1
    Return $aPos[1]
    Case Else
    Return SetError(1, 1, 0)
    EndSwitch
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _MouseGetPosRel($i=-1, $fAddTitleHeight=False)
    Local $ret, $iTitleHeight = 0, $iBorder
    If $fAddTitleHeight Then
    ; === Höhe Caption
    $ret = DllCall("user32.dll", "Int", "GetSystemMetrics", "Int", 4)
    $iTitleHeight = $ret[0]
    EndIf
    ; === Höhe Border
    $ret = DllCall("user32.dll", "Int", "GetSystemMetrics", "Int", 7)
    $iBorder = $ret[0]
    If $fAddTitleHeight Then $iTitleHeight += 2*$iBorder
    Local $old = Opt('MouseCoordMode', 0)
    Local $aM = MouseGetPos()
    Opt('MouseCoordMode', $old)
    Switch $i
    Case 0
    Return $aM[0] -$iBorder
    Case 1
    Return $aM[1] -$iTitleHeight
    Case Else
    $aM[0] -= $iBorder
    $aM[1] -= $iTitleHeight
    Return $aM
    EndSwitch
    EndFunc

    [/autoit]
    • Offizieller Beitrag

    Habe noch 'nen Fehler entdeckt. Ich war der irrigen Meinung, Caption wird von zwei Border umschlossen. Ist tatsächlich nur einmal.
    Folgende Codezeile:

    [autoit]

    If $fAddTitleHeight Then $iTitleHeight += 2*$iBorder

    [/autoit]

    muß also richtig heißen:

    [autoit]

    If $fAddTitleHeight Then $iTitleHeight += $iBorder

    [/autoit]

    Dann paßt es auch.