DLLs sind kompliziert...

  • ... zumindestens für mich!

    Vielleicht kann mir ja jemand dabei helfen:
    Ich stehe mit den DLLs etwas auf Kriegsfuss.
    Das liegt vielleicht auch daran, dass ich eigentlich kein Programmierer bin und das ziemlich kompliziert finde!

    Ich möchte mit der Funktion MonitorFromPoint aus der User32.dll ein handle zurückbekommen, welches sich auf den Monitor bezieht, wo sich die Maus gerade befindet.
    Dann möchte ich damit die Monitornummer zurückbekommen, auf welchem sich die Maus gerade befindet.

    Angefangen habe ich damit:

    [autoit]

    Local $Struct, $ptrStruct, $Ret

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

    $Struct = DllStructCreate("long;long")
    DllStructSetData($Struct, 1, MouseGetPos(0))
    DllStructSetData($Struct, 2, MouseGetPos(1))
    $ptrStruct = DllStructGetPtr($Struct)

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

    $Ret = DllCall("User32.dll", "handle", "MonitorFromPoint", "ptr", $ptrStruct, "dword", 0)
    MsgBox(0,"",$Ret)

    [/autoit]

    Doch leider stürzt mir bei der zweitletzten Zeile AutoIt ab. Was könnte der Fehler in dieser Zeile sein?
    Die Dokumentation zu dieser Funktion in der User32.dll findet ihr hier

    Und wie könnte ich danach mit diesem Handle weiterarbeiten, wenn es mal läuft?

    Für Ideen wäre ich dankbar!
    Gruss
    Veronesi

    Einmal editiert, zuletzt von veronesi (27. Mai 2010 um 20:43)

  • Wie wärs wenn dus so machst:

    [autoit]

    Func GetScreen()
    $a=MousegetPos()
    If $a[2] > @DesktopHeight or $a[2] < 0 Then
    Return 2
    Endif
    If $a[1] > @DesktopWidth or $a[1] < 0 Then
    Return 2
    Endif
    Return 1
    Endfunc

    [/autoit]


    mfg Ubuntu

    Ps: Ungetestet

  • Hallo Ubuntu,

    vielen Dank.
    Doch dies funktioniert doch "nur" bei max. 2 Monitoren! Oder?
    Ich habe hier 8 Monitore gleichzeitig....

    Ich möchte schlussendlich herausfinden, auf welchem Bildschirm die Maus ist. Dann könnte ich mit der folgenden Funktion alle geöffneten Fenster auf dem Monitor anordnen, wo die Maus ist!
    _TileWindows()

    Spoiler anzeigen
    [autoit]

    #include-once
    #include "Func_GetMonitorInfo.au3"
    #include "Func_GetMouseInfo.au3"

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

    Func _TileWindows()
    ;Tile Windows on that screen where the mouse is!
    ;Call: _TileWindows()

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

    Local $MonNr, $Left, $Top, $Right, $Bottom, $tStruct, $Rect, $aTmp[32][32]
    $MonNr = _GetMouseInfo()
    $aTmp = _GetMonitorInfo()

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

    $Left = $aTmp[$MonNr][2]
    $Top = $aTmp[$MonNr][3]
    $Right = $aTmp[$MonNr][0]
    $Bottom = $aTmp[$MonNr][1]

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

    $tStruct = DllStructCreate("int[4]") ;4 points of values that are integers
    DllStructSetData($tStruct, 1, $Left, 1)
    DllStructSetData($tStruct, 1, $Top, 2)
    DllStructSetData($tStruct, 1, $Right, 3)
    DllStructSetData($tStruct, 1, $Bottom, 4)
    $Rect = DllStructGetPtr($tStruct) ;Now $rect holds our left/top/right/bottom values in a type of array basically

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

    DllCall("user32.dll", "int", "TileWindows", "int", 0, "int", 0, "Ptr", $Rect, "int", 0, "int", 0)
    EndFunc

    [/autoit]


    _GetMonitorInfo()
    (Leider stimmen hier die Monitor-Nummern nicht mit den Nummern von Windows überein. Das wäre eigentlich schon alles was ich bräuchte! Wenn diese Funktion die korrekten
    Monitor-Nummern - so wie Windows sie vergibt - zurückgeben würde, dann wäre alles o.k.)

    Spoiler anzeigen
    [autoit]

    #include-once

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

    Func _GetMonitorInfo()
    ;Returns some informations about your screens
    ;Call: _GetMonitorInfo()
    ;Return: Array With
    ;[0][0] Nr of Monitors
    ;[1][0] X Resolution of Monitor 1
    ;[1][1] Y Resolution of Monitor 1
    ;[1][2] X Position of Monitor 1
    ;[1][3] Y Position of Monitor 1

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

    ;[2][0] X Resolution of Monitor 2
    ;[2][1] Y Resolution of Monitor 2
    ;[2][2] X Position of Monitor 2
    ;[2][3] Y Position of Monitor 2
    ;......

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

    Local $NrOfMonitors, $ResolutionX[32], $ResolutionY[32], $PositionX[32], $PositionY[32], $Ret
    Local $cbMonitorEnumProc = DllCallbackRegister("MonitorEnumProc", "ubyte", "ptr;ptr;ptr;int")

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

    If @error Then Return SetError(1, 0, False)
    Local $strctCount = DllStructCreate("uint Count;uint Width[12];uint Height[12];int left[12];int top[12]")
    If @error Then Return SetError(2, @error, False)
    Local $iCount

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

    DllStructSetData($strctCount, "Count", 0)

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

    $Ret = DllCall("User32.dll", "ubyte","EnumDisplayMonitors","ptr", 0,"ptr", 0, "ptr", DllCallbackGetPtr($cbMonitorEnumProc), "ptr", DllStructGetPtr($strctCount))
    If @error Or $Ret[0] = 0 Then Return SetError(3, @error, False)

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

    DllCallbackFree($cbMonitorEnumProc)

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

    $iCount = Int(DllStructGetData($strctCount, "Count"))

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

    Local $aMonitors[$iCount+1][4] = [[$iCount]]

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

    For $i = 1 To $iCount
    $aMonitors[$i][0] = Int(DllStructGetData($strctCount, "Width",$i))
    $aMonitors[$i][1] = Int(DllStructGetData($strctCount, "Height",$i))
    $aMonitors[$i][2] = Int(DllStructGetData($strctCount, "left",$i))
    $aMonitors[$i][3] = Int(DllStructGetData($strctCount, "top",$i))
    Next

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

    $strctCount = 0
    Return $aMonitors
    EndFunc

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

    Func MonitorEnumProc($hMonitor, $hdcMonitor, $lprcMonitor, $dwData)
    Local $strctRECT = DllStructCreate("long left;long top;long right;long bottom", $lprcMonitor)
    Local $strctCount = DllStructCreate("uint Count;uint Width[12];uint Height[12];int left[12];int top[12]", $dwData)
    Local $iNumber = DllStructGetData($strctCount, "Count")
    Local $Height = Int(DllStructGetData($strctRECT, "bottom"))-Int(DllStructGetData($strctRECT, "top"))
    Local $Width = Int(DllStructGetData($strctRECT, "right"))-Int(DllStructGetData($strctRECT, "left"))

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

    DllStructSetData($strctCount, "Width", $Width, $iNumber+1)
    DllStructSetData($strctCount, "Height", $Height, $iNumber+1)
    DllStructSetData($strctCount, "left", Int(DllStructGetData($strctRECT, "left")), $iNumber+1)
    DllStructSetData($strctCount, "top", Int(DllStructGetData($strctRECT, "top")), $iNumber+1)
    DllStructSetData($strctCount, "Count", $iNumber+1)
    Return True
    EndFunc

    [/autoit]


    _GetMouseInfo()

    Spoiler anzeigen
    [autoit]

    #include-once
    #include "Func_GetMonitorInfo.au3"
    Func _GetMouseInfo()
    ;Returns the screen number on which the actual mouse cursor is
    ;Call: _GetMouseInfo()

    Local $aTmp[32][32], $MousePos, $NrOfScreens, $i
    $MousePos = MouseGetPos()
    $aTmp = _GetMonitorInfo()
    If @error <> 0 Then Return 1 ;If any error found Return Screen Number 1
    $NrOfScreens = $aTmp[0][0]
    For $i = 1 To $NrOfScreens
    If $MousePos[0] >= $aTmp[$i][2] AND ($MousePos[0] <= $aTmp[$i][2] + $aTmp[$i][0]) AND $MousePos[1] >= $aTmp[$i][3] AND ($MousePos[1] <= $aTmp[$i][3] + $aTmp[$i][1]) Then Return $i
    ;Checks on which Screen the Mousecursor is
    Next
    EndFunc

    [/autoit]


    Trotzdem danke!

    3 Mal editiert, zuletzt von veronesi (27. Mai 2010 um 15:55)

  • Das liegt definitiv nicht daran.
    Da stürzt das script nicht mit fehlermeldungen ab, sonder die autoit.exe hängt sich auf...

    Edit: und zwar genau beim DllCall aufruf...

    Spoiler anzeigen

    Grundkenntnisse in: C++, JavaScript
    Sehr gute Kenntnisse: PHP, JAVA, C und näturlich AutoIt


    Klaviatur, Anhang UDF, GDI+ Mühle

    Zitat

    "Wenn einen um 20h der Pizzadienst anruft und fragt, ob man's nur vergessen hat und ob man das gleiche
    möchte wie immer -- dann sollte man sein Bestellverhalten evtl überdenken"

  • Daran liegts bestimmt nicht...
    Das ist der DllCall Aufruf...

    Spoiler anzeigen

    Grundkenntnisse in: C++, JavaScript
    Sehr gute Kenntnisse: PHP, JAVA, C und näturlich AutoIt


    Klaviatur, Anhang UDF, GDI+ Mühle

    Zitat

    "Wenn einen um 20h der Pizzadienst anruft und fragt, ob man's nur vergessen hat und ob man das gleiche
    möchte wie immer -- dann sollte man sein Bestellverhalten evtl überdenken"

  • Die Funktion hat ganz blöde Parameter:

    [autoit]

    $pos = MouseGetPos()
    $Ret = DllCall("User32.dll", "handle", "MonitorFromPoint", "uint64", _InlinePoint($pos[0], $pos[1]) , "dword", 0)
    MsgBox(0,"",$Ret[0])

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

    Func _InlinePoint($iX, $iY)
    ; ProgAndy
    Local $point = DllStructCreate("long[2]")
    DllStructSetData($point, 1, $iX, 1)
    DllStructSetData($point, 1, $iY, 2)
    Return DllStructGetData(DllStructCreate("uint64", DllStructGetPtr($point)), 1)
    EndFunc

    [/autoit]

    Edit: Marthog: So geht es auch...

  • Vielen Dank Euch beiden!
    Es funktioniert beides!

    Da die Funktion jedoch einen "Point Structure" erwartet, bevorzuge ich die Variante von Progandy, weil "bloss" ein Parameter für diesen Point übergeben wird. Aber das von Marthog geht trotzdem auch!

    Interessanterweise habe ich gemerkt, dass ich nur mein "ptr" in "uint64" ändern muss, dann läuft es!

    Spoiler anzeigen
    [autoit]

    Local $Struct, $ptrStruct, $Ret

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

    $Struct = DllStructCreate("long;long")
    DllStructSetData($Struct, 1, MouseGetPos(0))
    DllStructSetData($Struct, 2, MouseGetPos(1))
    $ptrStruct = DllStructGetPtr($Struct)

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

    $Ret = DllCall("User32.dll", "handle", "MonitorFromPoint", "uint64", $ptrStruct, "dword", 0)

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

    MsgBox(0,"",$Ret)

    [/autoit]

    Gut, die MessageBox liefert ein Leerstring zurück, doch ich denke, dass kann die gar nicht anzeigen - ein Handle!

    Nun geht's aber weiter! Wie könnte ich mit diesem Handle auf den Monitor die korrekte Monitornummer herausfinden?

  • Also auf das wäre ich jetzt nie gekommen!
    Woher hast Du das? Diese MSDN Dokus verstehe ich nicht!

    Nun zeige ich mit _ArrayDisplay($Ret) das ganze Array an.
    Jedoch kann ich damit nichts anfangen! Egal auf welchem Bildschirm der Mauszeiger sich befindet, ich bekomme für [0] und [2] immer die gleichen Werte. Für [1] bekomme ich immer einen anderen Wert, der ist jedoch auch unterschiedlich, wenn ich die Maus nicht bewege!

    Was könnte dies nun sein?

    Zudem steht in der MSDN Doku man müsse "MONITOR_DEFAULTTONEAREST" nehmen. Ich habe einfach mal angenommen, das ist 0 (deshalb die 0 am Ende des DllCalls)

  • Zitat aus der deutschen Hilfe:

    Zitat

    Wenn der Funktionsaufruf scheitert, wird @error auf 1 gesetzt. Ansonsten wird ein Array mit dem Rückgabewert der Funktion und einer Kopie aller Parameter (inklusive derer, die die Funktion möglicherweise verändert hat) zurückgegeben.
    $return[0] = Rückgabewert der Funktion
    $return[1] = Param1
    $return[2] = Param2
    ...
    $return[n] = Paramn

    DllCall

    Spoiler anzeigen

    Grundkenntnisse in: C++, JavaScript
    Sehr gute Kenntnisse: PHP, JAVA, C und näturlich AutoIt


    Klaviatur, Anhang UDF, GDI+ Mühle

    Zitat

    "Wenn einen um 20h der Pizzadienst anruft und fragt, ob man's nur vergessen hat und ob man das gleiche
    möchte wie immer -- dann sollte man sein Bestellverhalten evtl überdenken"

  • Ich sagte es doch: Die DLLs sind kompliziert.

    Ich komme hier einfach nicht mehr weiter:

    [autoit]

    Local $Struct, $StructData, $hScreen

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

    $Struct = DllStructCreate("long;long")
    DllStructSetData($Struct, 1, MouseGetPos(0))
    DllStructSetData($Struct, 2, MouseGetPos(1))
    $StructData = DllStructGetData(DllStructCreate("uint64", DllStructGetPtr($Struct)), 1)

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

    $hScreen = DllCall("User32.dll", "handle", "MonitorFromPoint", "uint64", $StructData, "dword", "Monitor_DefaultToNearest")
    $test = DllCall("User32.dll", "ptr", "GetMonitorInfo", "handle", $hScreen)

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

    ;~ MsgBox(0,"",$test)

    [/autoit]

    Das Handle kann ich nun mit Eurer Hilfe korrekt bestimmen.
    Doch bereits beim nächsten DllCall wieder ein Absturz!
    Das kann doch nicht so kompliziert sein!