Mausgesten erkennen

  • Hallo liebes Forum,

    Zuerst - schön dass AutoIt.de wieder da ist, habe heute morgen ja schon fast das weinen angefangen, als mir das Plesk-Panel aus dem Firefox entgegensprang :P.

    Nun aber zu meinem Problem: Mich hat mal wieder die Langeweile gepackt, da hab ich meine alten PC Games durchgeguckt. Und siehe da: Black & White! Wie ich dieses Spiel geliebt habe :)

    Also ein bisschen gespielt und dann doch keine Lust mehr gehabt (wie so oft bei mir ^^). Doch die Idee mit den Mausgesten hat mich irgendwie gepackt. Also hab ich gestern abend mal ein bisschen rumprobiert und habe das hier zusammengewurstelt:

    Spoiler anzeigen
    [autoit]


    #include <WindowsConstants.au3>
    #include <GUIConstants.au3>
    #include <ArrayMore.au3>
    #include <Array.au3>
    #include <Misc.au3>
    HotKeySet("{SPACE}","_stop")
    HotKeySet("{TAB}","_recognizePath")

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

    #region - GUI Create
    GUICreate('Mausgesten Manager',120,155,-1,-1,"",$WS_EX_TOPMOST)
    $Button_Go = GUICtrlCreateButton("Start",10,10,100,50)
    $Button_Show = GUICtrlCreateButton("Show",10,70,100,50)
    ;~ $Combo_Geste = GUICtrlCreateCombo("",10,150,100,25)
    GUISetState()
    #endregion
    $record = False
    $drawn = False
    $gesteTaste = "04"
    Dim $Gesten[1] = ["Gesten"]
    Dim $MousePath[1][2]
    $MousePath[0][0] = "x"
    $MousePath[0][1] = "y"
    #region - GUI SelectLoop
    While 1
    $msg = GUIGetMsg()
    Select
    Case $msg = $GUI_EVENT_CLOSE
    Exit
    Case $msg = $Button_Go
    $record = True
    Dim $MousePath[1][2]
    $MousePath[0][0] = "x"
    $MousePath[0][1] = "y"
    _DrawPath()
    Case $msg = $Button_Show
    $MousePosNow = MouseGetPos()

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

    For $i = 1 to UBound($MousePath)-1
    MouseMove($MousePath[$i][0]+$MousePosNow[0],$MousePath[$i][1]+$MousePosNow[1],1)
    Next

    _ArrayDisplay($MousePath)
    EndSelect
    If _IsPressed($gesteTaste) Then _recognizePath()
    WEnd
    #endregion
    Func _stop()
    $record = false
    EndFunc
    Func _recognizePath()
    If IsArray($MousePath) Then
    If UBound($MousePath) > 1 Then

    Local $tol = 150 ; Toleranz in Pixeln.
    Local $pathtol = 0.66
    Local $erfolg = False ; Toleranz bei vergleichen der Arrays

    Do
    Local $MouseStartPos = MouseGetPos()
    Local $MousePosNow = MouseGetPos()
    Local $S = 1
    Dim $MouseDrawnPath[1][2]
    $MouseDrawnPath[0][0] = "X"
    $MouseDrawnPath[0][1] = "Y"
    While _IsPressed($gesteTaste)
    If $MousePosNow[0] <> MouseGetPos(0) OR $MousePosNow[1] <> MouseGetPos(1) Then
    ToolTip("Ich passe auf...")
    _Array2DAdd($MouseDrawnPath,MouseGetPos(0)-$MouseStartPos[0]&"|"&MouseGetPos(1)-$MouseStartPos[1])
    $MousePosNow = MouseGetPos()
    EndIf
    WEnd


    If UBound($MouseDrawnPath) > 1 Then

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

    TrayTip("Ubounds","MousePath: "&UBound($MousePath)&@CRLF&"MouseDrawnPath: "&UBound($MouseDrawnPath),1)
    If Ubound($MouseDrawnPath) > UBound($MousePath) Then
    For $i = 1 to UBound($MousePath)-1
    If Not (($MouseDrawnPath[$i][0] <= $MousePath[$i][0] + $tol) AND ($MouseDrawnPath[$i][0] >= $MousePath[$i][0] - $tol)) AND (($MouseDrawnPath[$i][1] <= $MousePath[$i][1] + $tol) AND ($MouseDrawnPath[$i][1] >= $MousePath[$i][1] - $tol)) Then
    If $i/Ubound($MousePath) > $pathtol Then
    MsgBox("","","Mausgeste zu "&Floor(($i/Ubound($MousePath))*100)&"% erkannt!"&@CRLF&" Dies wird als Erfolg gewertet.",5)
    ExitLoop
    Else
    MsgBox("","","Mausgeste nicht erkannt! Fehler bei "&$i,1)
    $drawn = True
    ExitLoop
    EndIf
    Else
    If $i = UBound($MousePath)-1 Then
    MsgBox(64,"Success!!!","Gratulation ! Die mausgeste konnte erkannt werden.")
    $drawn = True
    ExitLoop
    EndIf
    EndIf
    Next
    ElseIf Ubound($MouseDrawnPath) <= UBound($MousePath) Then
    For $i = 1 to UBound($MouseDrawnPath)-1
    If Not (($MouseDrawnPath[$i][0] <= $MousePath[$i][0] + $tol) AND ($MouseDrawnPath[$i][0] >= $MousePath[$i][0] - $tol)) AND (($MouseDrawnPath[$i][1] <= $MousePath[$i][1] + $tol) AND ($MouseDrawnPath[$i][1] >= $MousePath[$i][1] - $tol)) Then
    If $i/Ubound($MousePath) > $pathtol Then
    MsgBox("","","Mausgeste zu "&Floor(($i/Ubound($MousePath))*100)&"% erkannt!"&@CRLF&" Dies wird als Erflog gewertet.",5)
    ExitLoop
    Else
    MsgBox("","","Mausgeste nicht erkannt! Fehler bei "&$i,1)
    $drawn = True
    ExitLoop
    EndIf
    Else
    If $i = UBound($MousePath)-1 Then
    MsgBox(64,"Success!!!","Gratulation ! Die mausgeste konnte erkannt werden.")
    $drawn = True
    ExitLoop
    EndIf
    EndIf
    Next
    EndIf
    EndIf
    ;~ If $drawn = True Then ExitLoop
    ToolTip("")
    Until Not _IsPressed($gesteTaste)
    EndIf
    EndIf
    EndFunc
    Func _DrawPath()
    Local $MouseStartPos = MouseGetPos()
    Local $MousePosNow = MouseGetPos()
    While $record
    If $MousePosNow[0] <> MouseGetPos(0) OR $MousePosNow[1] <> MouseGetPos(1) Then
    _Array2DAdd($MousePath,MouseGetPos(0)-$MouseStartPos[0]&"|"&MouseGetPos(1)-$MouseStartPos[1])
    $MousePosNow = MouseGetPos()
    EndIf
    WEnd
    EndFunc

    [/autoit]

    Leider funktioniert das ganze mehr schlecht als recht. Die Gesten müssen (fast) genauso gezeichnet werden wie sie aufgenommen wurden. Variable Größen oder zu starke Abweichungen von der orginalen Geste laufen darauf hinaus, dass die Geste nicht erkannt wird.
    Ich habe das ganze bereits mit dem oben gezeigten Script probiert, sowie einer Version, die immer die Positionsänderung zur letzen Position aufzeichnet.

    Spoiler anzeigen
    [autoit]

    #include <WindowsConstants.au3>
    #include <GUIConstants.au3>
    #include <ArrayMore.au3>
    #include <Array.au3>
    #include <Misc.au3>
    HotKeySet("{SPACE}","_stop")
    HotKeySet("{TAB}","_recognizePath")

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

    #region - GUI Create
    GUICreate('Mausgesten Manager',120,155,-1,-1,"",$WS_EX_TOPMOST)
    $Button_Go = GUICtrlCreateButton("Start",10,10,100,50)
    $Button_Show = GUICtrlCreateButton("Show",10,70,100,50)
    ;~ $Combo_Geste = GUICtrlCreateCombo("",10,150,100,25)
    GUISetState()
    #endregion
    $record = False
    $drawn = False
    $gesteTaste = "04"
    Dim $Gesten[1] = ["Gesten"]
    Dim $MousePath[1][2]
    $MousePath[0][0] = "x"
    $MousePath[0][1] = "y"
    #region - GUI SelectLoop
    While 1
    $msg = GUIGetMsg()
    Select
    Case $msg = $GUI_EVENT_CLOSE
    Exit
    Case $msg = $Button_Go
    $record = True
    Dim $MousePath[1][2]
    $MousePath[0][0] = "x"
    $MousePath[0][1] = "y"
    _DrawPath()
    Case $msg = $Button_Show
    $MousePosNow = MouseGetPos()

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

    For $i = 1 to UBound($MousePath)-1
    $MousePosNow = MouseGetPos()
    MouseMove($MousePath[$i][0]+MouseGetPos(0),$MousePath[$i][1]+MouseGetPos(1),1)

    Next

    _ArrayDisplay($MousePath)
    EndSelect
    If _IsPressed($gesteTaste) Then _recognizePath()
    WEnd
    #endregion
    Func _stop()
    $record = false
    EndFunc
    Func _recognizePath()
    If IsArray($MousePath) Then
    If UBound($MousePath) > 1 Then

    Local $tol = 150 ; Toleranz in Pixeln.
    Local $erfolg = False
    Local $pathtol = 0.66 ; Toleranz bei vergleichen der Arrays

    While _IsPressed($gesteTaste)
    Local $MouseStartPos = MouseGetPos()
    Local $MousePosNow = MouseGetPos()
    Local $S = 1
    Dim $MouseDrawnPath[1][2]
    $MouseDrawnPath[0][0] = "X"
    $MouseDrawnPath[0][1] = "Y"
    While _IsPressed($gesteTaste)
    If $MousePosNow[0] <> MouseGetPos(0) OR $MousePosNow[1] <> MouseGetPos(1) Then
    ToolTip("Ich passe auf...")
    _Array2DAdd($MouseDrawnPath,MouseGetPos(0)-$MouseStartPos[0]&"|"&MouseGetPos(1)-$MouseStartPos[1])
    $MousePosNow = MouseGetPos()
    EndIf
    WEnd


    If UBound($MouseDrawnPath) > 1 Then

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


    If Ubound($MouseDrawnPath) > UBound($MousePath) Then
    For $i = 1 to UBound($MousePath)-1
    If Not (($MouseDrawnPath[$i][0] <= $MousePath[$i][0] + $tol) AND ($MouseDrawnPath[$i][0] >= $MousePath[$i][0] - $tol)) AND (($MouseDrawnPath[$i][1] <= $MousePath[$i][1] + $tol) AND ($MouseDrawnPath[$i][1] >= $MousePath[$i][1] - $tol)) Then
    MsgBox("","","Mausgeste nicht erkannt! Fehler bei "&$i,1)
    _ArrayDisplay($MouseDrawnPath)
    $drawn = True
    ExitLoop
    Else
    If $i = UBound($MousePath)-1 Then
    MsgBox(64,"Success!!!","Gratulation ! Die mausgeste konnte erkannt werden.")
    $drawn = True
    ExitLoop
    EndIf
    EndIf
    Next
    ElseIf Ubound($MousePath) > UBound($MouseDrawnPath) Then
    For $i = 1 to UBound($MouseDrawnPath)-1
    If Not (($MouseDrawnPath[$i][0] <= $MousePath[$i][0] + $tol) AND ($MouseDrawnPath[$i][0] >= $MousePath[$i][0] - $tol)) AND (($MouseDrawnPath[$i][1] <= $MousePath[$i][1] + $tol) AND ($MouseDrawnPath[$i][1] >= $MousePath[$i][1] - $tol)) Then
    If $i/Ubound($MousePath) > $pathtol Then
    MsgBox("","","Mausgeste zu "&Floor(($i/Ubound($MousePath))*100)&"% erkannt!"&@CRLF&" Dies wird als Erfolg gewertet.",5)
    ExitLoop
    Else
    MsgBox("","","Mausgeste nicht erkannt! Fehler bei "&$i,1)
    $drawn = True
    ExitLoop
    EndIf
    Else
    If $i = UBound($MousePath)-1 Then
    MsgBox(64,"Success!!!","Gratulation ! Die mausgeste konnte erkannt werden.")
    $drawn = True
    ExitLoop
    EndIf
    EndIf
    Next
    EndIf
    EndIf
    If $drawn = True Then ExitLoop
    ToolTip("")
    WEnd
    EndIf
    EndIf
    EndFunc
    Func _DrawPath()
    Local $MouseStartPos = MouseGetPos()
    Local $MousePosNow = MouseGetPos()
    While $record * sleep(10)
    If $MousePosNow[0] <> MouseGetPos(0) OR $MousePosNow[1] <> MouseGetPos(1) Then
    _Array2DAdd($MousePath,MouseGetPos(0)-$MousePosNow[0]&"|"&MouseGetPos(1)-$MousePosNow[1])
    $MousePosNow = MouseGetPos()
    EndIf
    WEnd
    EndFunc

    [/autoit]

    Das funktioniert allerdings noch seltener, also hab ich das Konzept direkt wieder übern Haufen geworfen und arbeite mit Version 1 weiter. Oben genannte Probleme konnte ich schon eindämmen indem ich verschiedene Toleranzen eingebaut habe. Aber gefallen tut mir das ganze immer noch nicht. Wenn also jemand Ideen hat wie man das verbessern kann - Immer her damit! Ich bin für jeden Schubser in die richtige Richtung dankbar.


    Bevor ichs vergesse: Ihr nehmt eine Geste auf indem ihr auf Start drückt, und beendet die Aufnahme mit der Leertaste. Mit Show könnt ihr euch die aufgenommene Geste noch einmal anzeigen lassen.

  • Mausgesten war einmal das Thema eines Wettbewerbs hier. Wäre schön wenn es mal wieder so einen Wettbewerb für Anfänger gäbe.

  • Ich hab mal etwas in der Art gemacht, habe es mal schnell nachempfunden weil ich das Original nicht
    gefunden habe, also nicht meckern wegen Stil oder Optik etc.

    Spoiler anzeigen
    [autoit]


    #include <Misc.au3>

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

    HotKeySet( "^{a}", "a") ; <-- Aufzeichnen
    HotKeySet( "^{s}", "s") ; <-- Abspielen

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

    Global $a_x[2], $a_y[2]

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

    While 1
    Sleep(200)
    WEnd

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

    Func a()
    Local $z = 1, $merker = 0
    $dll = DllOpen("user32.dll")
    ReDim $a_x[2], $a_y[2] ; <-- Löschen des Array
    While 1
    While _IsPressed("01", $dll) ; <-- solange Taste gedrückt ist
    $merker = 1
    $pos = MouseGetPos()
    $a_x[$z] = $pos[0]
    $a_y[$z] = $pos[1]
    $z +=1
    ReDim $a_x[$z+1], $a_y[$z+1]
    Sleep(100)
    WEnd
    If $merker = 1 Then ; <-- wenn Taste gedrückt war
    DllClose($dll)
    Return
    EndIf
    WEnd
    EndFunc

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

    Func s()
    For $z = 1 To UBound($a_x) - 2
    MouseMove($a_x[$z], $a_y[$z], 15)
    next
    EndFunc

    [/autoit]

    Hilft das vielleicht?

  • Sorry. Werde ich in Zukunft versuchen zu vermeiden ;) Da waren doch noch so viele andere, warum musstest du auch ausgerechnet meins öffnen ;( Das macht mich jezt auch traurig, dass ich dir den Spaß verdorben habe.

  • Naja deins hat halt gewonnen ^^ ich war ja quasi dazu gezwungen das aufzumachen :P

    Finds aber sehr nice gelöst, ich bin grade dabei mich durchzuarbeiten aber das wird noch ein bisschen dauern ^^
    Ein paar der Funktionen die du verwendest hab ich mir auch so in etwa vorgestellt, zb das Zeichnen der Geste mit GDIPlus oder die berechnung der akutellen "Richtung" - leider wusste ich nicht wie ich das anstellen soll...

  • Hi, hab mir grad auch mal die Programme angeguckt, und die sind alle wirklich sehr gut (hätte nie auch nur annähernd sowas geschafft ^^ ), und das von Progandy hab ich direkt mal in Autostart gelegt :D total praktisch, weiter so :thumbup: