Wie sendet man einen Joystick-Button?

  • Guten Tag zusammen,

    seit einiger Zeit bin ich Besitzer eines einfachen Gamepads. Bei den meisten Spielen kann ich die Tasten nach meinen Wünschen belegen. (Das Gamepad ähnelt einem Playstation Controller, leider sind ständig Tasten vertauscht.)

    Jetzt habe ich ein Spiel erwischt, bei dem ich den Controller nicht neu belegen kann. Einige Tasten sind vertauscht. Die Start Taste hat momentan überhaupt keine Funktion. Ich habe auch schon nach .ini's für Controller Input Ausschau gehalten, ohne Erfolg.

    Ein Beispiel: Button Select entspricht derzeit Button Start. Das Menü wird also bei Druck auf Select geöffnet und bei Druck auf Start passiert nichts.

    Nun möchte ich gerne über ein Script erreichem, dass z.B. Button Start -> Button Select entspricht.

    Die _Joystick.au3 von Ejoc - diese bekommt die gets über die Winmm.dll - gibt mir Informationen über gedrückte Buttons. Ich habe z.B. einen Knopft mit einer Media-Taste belegt, die dafür sorgt, dass das Aktuelle Lied im Audio-Player übersprungen wird. Ich schaffe es also Virtual-Key Codes und normale send's auszuführen.

    Spoiler anzeigen
    [autoit]

    $leftstick = 0
    while 1
    $coord=_GetJoy($joy,0)
    If $coord[7] = "1024" Then
    $leftstick = 1
    EndIf
    If $coord[7] <> "1024" Then
    if $leftstick = 1 Then
    _Send_Virtual_Key(0xB0)
    $leftstick = 0
    EndIf
    EndIf
    WEnd
    $lpJoy=0 ; Joyclose

    [/autoit]

    1024 = linker Analogstick
    256 = Select-Taste
    512 = Start-Taste
    0xB0 = Virtual Key für die "Next Track" Taste

    von Melba23:

    [autoit]

    Func _Send_Virtual_Key($iCode)
    If Not IsInt($iCode) Then Return
    DllCall('user32.dll', 'int', 'keybd_event', 'int', $iCode, 'int', 0, 'int', 0, 'ptr', 0)
    DllCall('user32.dll', 'int', 'keybd_event', 'int', $iCode, 'int', 0, 'int', 2, 'ptr', 0)
    EndFunc

    [/autoit]

    Aber wie kann ich einen "Joystick send" ausführen?

    Ich quäle mich damit seit Tagen. Ich habe bereits sämtliche autoit.de und autoitscript.com Posts über Joysticks gelesen.

    Eine Lösung würde mich defenitiv glücklich machen.

    2 Mal editiert, zuletzt von Mortal (1. September 2013 um 14:58)

  • Hi,

    Zitat

    Die _Joystick.au3 von Ejoc - diese bekommt die gets über die Winmm.dll - gibt mir Informationen über gedrückte Buttons.

    und was sagt diese dll zu deinen gedrückten Buttons?

    Zitat

    $coord=_GetJoy($joy,0)

  • Zitat

    und was sagt diese dll zu deinen gedrückten Buttons?


    Jede Taste bekommt einen Wert zugewiesen.
    Wenn ich start drücke gibt sie "512" zurück.
    Bei Select gibt sie "256" zurück. usw.

    Zitat

    $coord=_GetJoy($joy,0)


    $coord[7] -> gibt die Tasten des Controllers zurück.
    $coord[6] -> gibt die Tasten des Steuerkreuzes zurück.
    $coord[0] - $coord[5] -> gibt die Position der Analogsticks zurück.

    Spoiler anzeigen
    [autoit]

    ;____________________________________________________________________
    ; Original program by Ejoc ;
    ;____________________________________________________________________
    Local $joy,$coor,$h,$s,$msg
    $joy = _JoyInit()

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

    $leftstick = 0
    while 1
    $coord=_GetJoy($joy,0)
    If $coord[7] = "1024" Then
    $leftstick = 1
    EndIf
    If $coord[7] <> "1024" Then
    if $leftstick = 1 Then
    _Send_Virtual_Key(0xB0)
    $leftstick = 0
    EndIf
    EndIf
    WEnd
    $lpJoy=0 ; Joyclose

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

    Func _Send_Virtual_Key($iCode)
    If Not IsInt($iCode) Then Return
    DllCall('user32.dll', 'int', 'keybd_event', 'int', $iCode, 'int', 0, 'int', 0, 'ptr', 0)
    DllCall('user32.dll', 'int', 'keybd_event', 'int', $iCode, 'int', 0, 'int', 2, 'ptr', 0)
    EndFunc

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

    ;======================================
    ; _JoyInit()
    ;======================================
    Func _JoyInit()
    Local $joy
    Global $JOYINFOEX_struct = "dword[13]"
    $joy=DllStructCreate($JOYINFOEX_struct)
    if @error Then Return 0
    DllStructSetData($joy, 1, DllStructGetSize($joy), 1);dwSize = sizeof(struct)
    DllStructSetData($joy, 1, 255, 2) ;dwFlags = GetAll
    return $joy
    EndFunc
    ;======================================
    ; _GetJoy($lpJoy,$iJoy)
    ; $lpJoy Return from _JoyInit()
    ; $iJoy Joystick # 0-15
    ; Return Array containing X-Pos, Y-Pos, Z-Pos, R-Pos, U-Pos, V-Pos,POV
    ; Buttons down
    ;
    ; *POV This is a digital game pad, not analog joystick
    ; 65535 = Not pressed
    ; 0 = U
    ; 4500 = UR
    ; 9000 = R
    ; Goes around clockwise increasing 4500 for each position
    ;======================================
    Func _GetJoy($lpJoy,$iJoy)
    Local $coor,$ret
    Dim $coor[8]
    DllCall("Winmm.dll","int","joyGetPosEx", _
    "int",$iJoy, _
    "ptr",DllStructGetPtr($lpJoy))
    if Not @error Then
    $coor[0] = DllStructGetData($lpJoy,1,3)
    $coor[1] = DllStructGetData($lpJoy,1,4)
    $coor[2] = DllStructGetData($lpJoy,1,5)
    $coor[3] = DllStructGetData($lpJoy,1,6)
    $coor[4] = DllStructGetData($lpJoy,1,7)
    $coor[5] = DllStructGetData($lpJoy,1,8)
    $coor[6] = DllStructGetData($lpJoy,1,11)
    $coor[7] = DllStructGetData($lpJoy,1,9)
    EndIf
    return $coor
    EndFunc

    [/autoit]

    Einmal editiert, zuletzt von Mortal (1. September 2013 um 14:57)

  • Hi,

    Zitat

    Jede Taste bekommt einen Wert zugewiesen.
    Wenn ich start drücke gibt sie "512" zurück.
    Bei Select gibt sie "256" zurück. usw.

    Wo ist dann das Problem? Denn du sagtest doch

    Zitat

    Ich schaffe es also Virtual-Key Codes und normale send's auszuführen.

    Dann solltest du doch nur noch die Abfrage ändern, oder täusche ich mich?

    [autoit]


    $select= ;hier gehört der Tastaturscancode für den Selectbutton hin
    If $coord[7] = "512" Then ;wenn "Start"-Button vom Gamepad gedrückt
    _Send_Virtual_Key($select) ;dann Tastaturkommando an Spiel schicken
    EndIf

    [/autoit]


    Wenn es eine Taste gibt, mit der du im Spiel "Select" auswählen kannst, dann findest du ggf Scancodes hier oder hier
    Eine kurze Liste der Tastaturscancodes findet man auch in der AutoIt-Hilfe zu

    [autoit]

    _IsPressed()

    [/autoit]

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    5 Mal editiert, zuletzt von Andy (1. September 2013 um 12:27)

  • Danke für deine Bemühung.
    Tatsächlich würde ich damit das Problem mit der Select-Taste beheben können.
    Leider diente die Select-Taste nur als Beispiel.
    Es gibt dennoch ein paar Tasten, die vertauscht sind. Für diese Tasten gibt es keinen "Alternativ-Key" am Keyboard oder an der Maus.

    Ich habe gestern noch ein paar interessante Posts gefunden. Geholfen haben sie mir nicht wirklich, denn man braucht dafür einen XBox360 Controller. (Wenn ich den hätte wären bestimmt auch keine Tasten vertauscht.)
    Jedenfalls haben es dort Leute geschafft über ein Script "gets" und "sends" über die "xinput.dll" zu bekommen/ senden.

    Grüße

  • Hi,

    Zitat

    Es gibt dennoch ein paar Tasten, die vertauscht sind. Für diese Tasten gibt es keinen "Alternativ-Key" am Keyboard oder an der Maus.

    OK, mir wäre das ehrlich gesagt auch viel zu viel Aufwand!
    Als jemand, der mit einem Lötkolben in der Hand grossgeworden ist, würde ich die "softwareseitige" Umbelegung von Tasten sowieso erst als letzte Lösung wählen...
    Mach den Controller auf, und löte mit einigen cm Fädeldraht die Schalter wie gewünscht um!
    Das ist in nichtmal 20 Minuten erledigt. Ich will nicht wissen wieviel Zeit und Energie und Frust deinerseits in die Suche nach einer Softwarelösung geflossen sind...

  • Zitat

    Ich will nicht wissen wieviel Zeit und Energie und Frust deinerseits in die Suche nach einer Softwarelösung geflossen sind...


    Ja ich habe schon "zuviel" Zeit investiert. Aber dieses Gefühl, wenn man solch ein Problem dann doch löst.... dafür lohnt es sich.

    Zitat

    Mach den Controller auf, und löte mit einigen cm Fädeldraht die Schalter wie gewünscht um!


    [duck]Ich möchte die Tasten nicht umlöten.[/duck]
    Ich benutze hier die guten alten Playstation2 Gamepads. Ich habe einen USB-Adapter, der es mir ermöglicht 2 Playstation-Controller anzuschließen.
    Wenn ich die Schalter jetzt umlöte, dann kann ich prinzipiell den Ein/Aus-Schalter der Playstation2 entlöten.

    Natürlich... die Playstation2 ist schon uralt, dennoch bekomme ich manchmal Lust auf ein altes Spiel.

    Ein Playstation2 Emulator würde da auch keine Abhilfe schaffen.
    Ja ich habe wohl ne Schraube locker. Aber ich dachte, dass Autoit alle Inputs auslesen und senden kann.

    Danke für deine guten Ideen.
    Ich muss es irgendwie softwaretechnisch schaffen.

    Zitat

    Ich habe gestern noch ein paar interessante Posts gefunden. Geholfen haben sie mir nicht wirklich, denn man braucht dafür einen XBox360 Controller. (Wenn ich den hätte wären bestimmt auch keine Tasten vertauscht.)
    Jedenfalls haben es dort Leute geschafft über ein Script "gets" und "sends" über die "xinput.dll" zu bekommen/ senden.


    Gibt es vielleicht eine möglichkeit den Xbox360 Controller Treiber zu installieren oder den Treiber vorzugaukeln?

    ______ Nachtrag ______
    Mich hat der Ehrgeiz gepackt. Ich bin ein ganzes Stück weiter gekommen.
    Für weitere schwierigkeiten befinde ich mich jetzt wahrscheinlich im falschen Forum.
    Falls es dennoch jemanden gibt, der einen "button-press" senden kann.
    Dann hinterlasse eine Nachricht.

    Danke an Andy, war eine nette Konversation.

    Einmal editiert, zuletzt von Mortal (1. September 2013 um 14:52)

  • Nun gut, du hast es nicht anders gewollt!

    Zitat

    Ja ich habe wohl ne Schraube locker.

    Damit fängt alles an :thumbup:

    Die Buttons auf dem Controller kannst du per AutoIt alle abfragen!?
    Dann kommt es "nur" noch darauf an, dem Spiel des "richtigen" Tastaturcode zu senden. IdR. emulieren die am USB-Port angestöpselten Devices eine Tastatur, dass ist Programmintern am einfachsten abzufangen (Standard-Library)

    Schreib dir ein Script, welches alle ausser den dir schon bekannten Tastaturcodes (wichtig!) per

    [autoit]

    _Send_Virtual_Key($iCode)

    [/autoit]

    an das Programm sendet.
    Wenn sich dort dann auf dem Bildschirm "etwas tut", dann hast du einen Treffer gelandet.

    Ich wollte jetzt aufs Re-engeneering per Debugger in den Tiefen der Treiber abschwenken, aber es gibt noch eine einfachere Möglichkeit, den "Mouseklick".
    Mit der Abfrage des Controllerstatus bekommst du auch die Position des "virtuellen Mauszeigers".
    Diese Position könntest du dazu benutzen mit einem

    [autoit]

    mouseclick()

    [/autoit]

    das Drücken der Taste auf dem Gamepad zu emulieren.

    Zitat

    Für weitere schwierigkeiten befinde ich mich jetzt wahrscheinlich im falschen Forum.

    sagt wer? Frag einfach, im schlimmsten Fall bekommst du keine Antwort^^

  • Ich schaffe es nicht eine Schleife zu erstellen, da ich den Hex-Code in dieser Form brauche: 0x%%
    Ich wollte für jeden lauf durch die Schleife den Hex-Code um eins erhöhen.

    So sollte es aussehen: 0xB0, 0xB1, 0xB2...
    So sieht es aus: B0, B1, B2 ...

    "0x" vor die Hex-Zahl zu setzen nützt natürlich auch nichts, da es dadurch ein String wird.
    Nett wäre ein Befehl, wie _HexTo0xHex() :D

    Natürlich könnte ma es auch sofort über die Funktion bearbeiten, dass der $iCode von Haus aus 0x enthält.

    [autoit]

    Func _Send_Virtual_Key($iCode)
    If Not IsInt($iCode) Then Return
    DllCall('user32.dll', 'int', 'keybd_event', 'int', $iCode, 'int', 0, 'int', 0, 'ptr', 0)
    DllCall('user32.dll', 'int', 'keybd_event', 'int', $iCode, 'int', 0, 'int', 2, 'ptr', 0)
    EndFunc

    [/autoit]


    Bitte helfen.

  • Ich schaffe es nicht eine Schleife zu erstellen, da ich den Hex-Code in dieser Form brauche: 0x%%
    Ich wollte für jeden lauf durch die Schleife den Hex-Code um eins erhöhen.

    So sollte es aussehen: 0xB0, 0xB1, 0xB2...
    So sieht es aus: B0, B1, B2 ...

    "0x" vor die Hex-Zahl zu setzen nützt natürlich auch nichts, da es dadurch ein String wird.
    Nett wäre ein Befehl, wie _HexTo0xHex() :D


    Dafür gibt es Dec. Du kannst in deiner Schleife aber auch gleich Dezimalzahlen benutzen, das sollte leichter sein.

  • Ach wie peinlich :pinch:

    Danke funktioniert natürlich auch mit Dezimalzahlen.

    ____

    Ich habe jetzt 3000 vKeys getestet. Keiner davon war ein Controller-Button.

    Einmal editiert, zuletzt von Mortal (1. September 2013 um 20:04)

  • Hi,
    beim Keyboard-Event nicht vergessen, sämtliche Status der Tastaur mit jeder Tastenkombi zu erfassen!
    Also sowohl ALT, SHIFT, STRG als auch sämtliche Kombinationen damit^^

    Das geht zur Not auch mit

    [autoit]

    Send()

    [/autoit]
  • Funktioniert leider auch nicht.
    -> Shift + vKey, Alt + vKey, Strg + vKey, Shift + Alt + vKey, Shift + Strg + Alt + vKey

    Ich glaube, dass es über die xinput.dll zu realisieren wäre, wenn ich einen Xbox Controller hätte.

    Spoiler anzeigen

    http://www.autoitscript.com/forum/topic/20161-xinput-udf/
    http://www.autoitscript.com/forum/topic/21…360-controller/
    http://msdn.microsoft.com/en-us/library/…v=vs.85%29.aspx Klingt interessant, bin jetzt aber zu müde.
    Ich habe es unter anderem mit diesen Scripts versucht. Erfolglos! Die dll aus xwrap.zip wurde über regsvr32 registriert.


    Wenn Windows nur glauben würde, dass ich einen Xbox - Controller habe. Die Registry jedenfalls glaubt es.

    Es gibt auch xbox360 Controller Emulatoren. Diese erstellen mir eine xinput.dll im Ordner des Emulators.
    Durch XInputTest.exe sehe ich, dass die Button-Sends meines Gamepads erkannt werden..
    Die UDFs hingegen können mit dieser erstellten dll nicht arbeiten. Sie funktionieren scheinbar nur mit der originalen aus sys32 dir. (Habe die erstellte xinput.dll mit der UDF öffnen lassen. -> Fehlermeldung. Wenn die sys32 xinput.dll mit der UDF geöffnet wird gibt es keine Fehlermeldung, jedoch empfängt die UDF keine sends. - Hätte ich einen XBox360 Controller hätte ich testen können, ob es überhaupt funktioniert, selbst wenn man solch einen Controller hat... ich gehe jetzt einfach mal davon aus.)

    Fazit: Die dll im sys32 Ordner erkennt meinen Joystick scheinbar nicht als XBox-Controller. Auch wenn mein Controller in der Registry ein XBox-Controller zu sein scheint.
    Das ist wirklich eine sehr harte Nuss.

    2 Mal editiert, zuletzt von Mortal (2. September 2013 um 04:35)

  • Zitat

    Durch XInputTest.exe sehe ich, dass die Button-Sends meines Gamepads erkannt werden..
    Die UDFs hingegen können mit dieser erstellten dll nicht arbeiten. Sie funktionieren scheinbar nur mit der originalen aus sys32 dir. (Habe die erstellte xinput.dll mit der UDF öffnen lassen. -> Fehlermeldung. Wenn die sys32 xinput.dll mit der UDF geöffnet wird gibt es keine Fehlermeldung, jedoch empfängt die UDF keine sends. - Hätte ich einen XBox360 Controller hätte ich testen können, ob es überhaupt funktioniert, selbst wenn man solch einen Controller hat... ich gehe jetzt einfach mal davon aus.)

    schick mal biite die dll, mit der das Send funktionieren würde. Also jene, mit denen die UDF nicht funktioniert.
    Nur weil dll´s die selben Namen haben heisst das nicht, dass der Inhalt gleich ist, bzw. die Funktionen identisch aufgerufen werden.

  • Zitat

    Versuch es mal mit der Software Xpadder :)
    Die nutze ich selber um alle Games mit dem Controller zu zocken :P

    (Habe mir jetzt nicht den ganzen Thread durchgelesen)


    Danke, das Programm gefällt mir soweit ganz gut.

    Vor ein paar Tagen hätte mir diese Software wahrscheinlich gereicht...

    Soweit ich gesehen habe kann ich bei dieser Software keine Kombination erstellen.
    Damit ist folgendes gemeint, wenn Taste1 gedrückt wird dann soll das Programm Taste1 + Taste2 senden. (Taste = Button am Controller)
    Xpadder könnte folgendes -> Taste1 wird gedrückt, Xpadder sendet Taste1 + Key/Mouse. Diese Funktion könnte meine jetzige UDF auch.

    Derweil bin ich aber sehr bemüht Button-sends über autoit zu realisieren.