Tastendruck an Programm senden funktioniert nicht - alternative zu keybd_event?



  • Hallo!

    Mit folgender funktion mochte ich gerne ein Tetris, das in Java programmiert ist, steuern. Es bewegt sich leider nichts. Das richtige Fenster wird jedoch gefunden. Das Fenster ist ein FullScreen.

    void __fastcall TMain::DoMove(int Movement, int Rotation) 
    { 
            HWND hwnd = FindWindow(NULL, "Tetris"); 
            if(hwnd) 
            { 
    
                    SetForegroundWindow(hwnd); 
    
                    if (Movement > 0) 
                    { 
                            for (int i = 0; i < Movement; i++) 
                            { 
                                    keybd_event(VK_RIGHT, 0x27, KEYEVENTF_EXTENDEDKEY | 0, 0); 
                                    keybd_event(VK_RIGHT, 0x27, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); 
                            } 
                    } 
                    else 
                    { 
                            for (int i = 0; i < -Movement; i++) 
                            { 
                                    keybd_event(VK_LEFT, 0x25, KEYEVENTF_EXTENDEDKEY | 0, 0); 
                                    keybd_event(VK_LEFT, 0x25, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); 
                            } 
                    } 
    
                    for (int i = 0; i < Rotation; i++) 
                    { 
                            keybd_event(VK_UP, 0x26, KEYEVENTF_EXTENDEDKEY | 0, 0); 
                            keybd_event(VK_UP, 0x26, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); 
                    } 
            keybd_event(VK_SPACE, 0x20, KEYEVENTF_EXTENDEDKEY | 0, 0); 
            keybd_event(VK_SPACE, 0x20, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); 
            } 
    
    }
    

    Über eine Idee oder ein Vorschlag wie man dieses Problem lösen kann, vielleicht auch "Hardwaremässig eingreifen" da ich das Spiel immer steuern kann, freue ich mich.

    Grüsse





  • hier ist noch eine SendMessage Möglichkeit

    http://www.c-plusplus.net/forum/viewtopic-var-p-is-61995.html



  • Hallo!
    Auch das mit SendMessage() habe ich schon probiert. Das Problem ist, dass ich den richtigen Handle nicht finden kann. Ich habe schon alles ausprobiert. Besser wäre, wenn ich den Tastendruck direkt in den Keyboard Buffer schreiben könnt. Oder irgendwie Global senden und nicht an ein spezifisches Fenster.

    HWND hwnd = FindWindow(NULL, "Tetris"); // Hier sollte ich das richtige Fenster
                                             // finden. Evt. ist es gar kein Fenster
                                             // da das Programm im Vollbild läuft.
    SendMessage(hwnd, WM_SYSKEYDOWN, VK_SPACE, 0);
    SendMessage(hwnd, WM_SYSKEYUP, VK_SPACE, 0);
    

    Besten Dank für die Antwort

    Grüsse

    Ps: Auslesen des Spielfeldes und Setzen des Steines an der richtigen Position funktioniert alles schon. Es ist nur noch das Senden der Befehle das mein Projekt zum Scheitern bringen wird.



  • vielleicht heist das Fenster nicht Tetris.

    Hier ist ein Beitrag, wo beschrieben wird wie man alle Namen von Fenstern einlesen kann.
    Somit könntest du feststellen, ob das Fenster wirklich so heist.... man weis ja nie 🙂

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-148539-and-view-is-previous.html

    hab den Code nicht getestet



  • Hallo!

    Hat auch nicht funktioniert. Ich gebe es auf, habe zu viel Zeit investiert...

    Grüsse



  • Hallo nochmals

    Das Fenster findet er ja. Ich erkenne auch wenn das Programm nicht läuft (FindWindow gibt false zurück). Trotzdem kommen die Befehle nicht an. An andere Programme kann ich die Befehle problemlos senden.

    Grüsse



  • ich programmier normalerweise viel mit java, aber sowas hab ich noch nicht versucht, kann es sein das die java runtime eventuel alle windows signale abblockt oder einfach nur verwirft?
    mach mal java -h oder java -? vielleicht kann man da was einstellen.



  • Hi Wilder

    Hab hier ein Thread gestartet
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-171009.html
    Bin am Schluss selber zu einer Lösung gekommen.
    Am Ende des Thread ist der Link zu X-Spy.
    Also ich sehe das so, wenn dieses Programm dein Java-Steuerelement
    nicht findet, wirst du es wohl nicht ansteuern können.

    Grüsse



  • Hi Steinsoft!

    Das mti dem Spy-Tool hab ich auch schon versucht. Das komische ist, dass ich ein Programm zum ändern der Tastenbelegung als "Brücke" verwenden kann und diese Befehle kommen an.
    Trotzdem danke für den Tip

    Grüsse



  • Hi Wilder

    Eine Frage hab ich noch zu deinem Brücken-programm.
    Ist bei diesem zufällig eine DLL dabei?
    Wenn du es herausfinden kannst, könnte ich mir denken,
    was da vor sich geht.
    Kannst mir auch sagen wie das Brücken-Programm heißt.
    Nur so aus interesse. 🙂

    Grüsse



  • Hi!

    Habe jetzt noch ein Programm mit SourceCode gefunden, aber den verstehe ich nicht ganz. AutoHotKey heisst dieses Programm.

    Grüsse



  • Hi Wilder,

    also der Code von AutoHotKey hats echt in sich. (puhhhhhh...)

    Mal eine Frage gibt es auf der Tetris-Oberfläche ''Bildchen''
    z.B SpeedButton, die keinen Handle besitzen.
    Also Elemente die kein Handle haben können auch nicht
    mit SendMassage(wnd......) angesprochen werden.
    Ich glaube das Programm ermittelt irgendwie die Position des 'Bildchen'.

    Da im AutoHotKey offensichtlich ein Systemweiter MausHook eingebaut ist,
    kann das Programm genau fesellen wann die Maus über der Schaltfläche ist.
    Wenn also die Maus sich genau über dem Bild ist UND die Maustaste gedrückt
    ist wird ein Mausevent zu der MainForm hingeschickt.

    Hier ein Link der vielleicht hilfreich sein kann.
    (Delpie und c++ ist ja nicht sehr verschieden(VCL))

    http://www.delphipraxis.net/topic58281_handle+eines+speedbuttons+einer+fremden+anwendung+ermitteln.html&highlight=winspy

    Grüsse



  • Hallo!

    Ja, der Code ist wirklich nicht einfach zu verstehen, und nur einfach eine Funktion Copy-Paste kann man auch nicht machen. Im Spiel gibt es keine Buttons, ist im Vollbildschirm und wird nur mit der Tastatur bedient (also keine Maus).

    Danke und Gruss



  • Hi,

    Bei meinem BCB5 gibt es ein Tool das nennt sich WinSight32.
    Leider läuft es auf meinem Computer nicht richtig, es blockiert meinen
    ganzen PC. WinSight32 ist auch ein System Spy Programm, wie X-SPY.
    WinSight32 hat noch einen Zusätzliche Aufzeichnungsmöglichkeit.
    und zwar die Botschaftsaufzeichnung von und zu Fenstern.
    Diese Botschafen können mit SendMessage exact an das richtige
    Fenster(FindWondow) und Ebene(FindWindowEx) geschickt werden.

    1. Das Tool müsste man erst richtig einstellen.
    2. Das Tetrisspiel starten und alle Möglichen Tasten drücken (Bootschaften etc. wird aufgezeichnet)
    3. Tetris beenden
    4. alle Botschaften mit SendMessage verschicken

    Hier mal ein Auszug aus der Hilfe:

    Die Ansicht Botschaften zeigt Meldungen über Botschaften an, die von bestimmten Fenstern oder Fensterklassen empfangen werden.
    
    Botschaften vom Typ SendMessage werden zweimal angezeigt: Einmal, wenn Sie abgesendet werden, und einmal, wenn sie empfangen werden.
    
    Botschaften vom Typ DispatchedMessage werden nur einmal angezeigt, da ihr Rückgabewert bedeutungslos ist. Die Ansicht Botschaften soll anzeigen, wie Botschaften in andere Botschaften eingebettet sind.
    
    Das Format für die Botschaften in diesem Fenster lautet:
    
    Handle "Titel"-oder-{Klasse} Botschaft Status ...
    
    Win32-Botschaften
    
    WinSight überprüft, ob die Task, deren Botschaften angezeigt werden, eine Win32-Task ist. Falls dies der Fall ist, wird direkt nach dem Fenster-Handle der Botschaften [Win32] angezeigt. Die Botschaften selbst werden aber im Format von Win16-Botschaften dargestellt.
    
    WS32-Reaktionszeit
    
    WS32.EXE zeigt auch die Symbole + und * an, um folgendes darzustellen:
    
    * bedeutet, daß die WS32.EXE zu langsam ausgeführt wurde, um alle Botschaften zu empfangen.
    	+ bedeutet, daß in einer Hook-Prozedur eine Zeitabschaltung auftrat.
    
    Mit der Einstellung von HookTimeOut in der Datei WinSight.INI (im Windows-Verzeichnis) wird die Zeitabschaltung in Millisekunden für die WinSight-Hook-Prozedur festgelegt. HookTimeOut = 1000 (Vorgabe) legt fest, daß WinSight zwischen Botschaften eine Sekunde unterbricht. Wenn Sie diesen Wert verringern, reagiert WinSight zwar schneller, das Risiko dabei Botschaften zu übergehen, wird aber erhöht. Wird dieser Wert erhöht, verlangsamt sich die Ausführung von WinSight, aber die Chance, daß alle Botschaften empfangen werden, wird erhöht.
    

    hört sich doch gut an oder

    Grüsse



  • Hi Wilder,

    Hab gerade mit JBuilder6 schnell ein Java-Applet
    gebastelt. Hab Key-Event-Handler eingebaut.

    Alle Botschaften wurden mit WinSight abgehört und
    nachgeahmt. Ich bin mir sicher das die Pfeiltasten
    so im Frame ankommen. Es tut sich auf jedenfall was.

    HWND wnd;
    wnd =  FindWindow("SunAwtFrame", "Frame-Titel");
    if (wnd != 0)
    {
     SendMessage(wnd, WM_KEYDOWN,   0x00000026,  0x01480001);
     SendMessage(wnd, WM_USER+0x6C, 0x00000000,  0x08AB3B18);
     SendMessage(wnd, WM_KEYUP,     0x00000026,  0xC1480001);
     SendMessage(wnd, WM_USER+0x6C, 0x00000000,  0x08AB3B18);
    
     SendMessage(wnd, WM_KEYDOWN,   0x00000028,  0x01500001);
     SendMessage(wnd, WM_USER+0x6C, 0x00000000,  0x08AB3B18);
     SendMessage(wnd, WM_KEYUP,     0x00000028,  0xC1500001);
     SendMessage(wnd, WM_USER+0x6C, 0x00000000,  0x08AB3B18);
    
     SendMessage(wnd, WM_KEYDOWN,   0x00000025,  0x014B0001);
     SendMessage(wnd, WM_USER+0x6C, 0x00000000,  0x08AB3B18);
     SendMessage(wnd, WM_KEYUP,     0x00000025,  0xC14B0001);
     SendMessage(wnd, WM_USER+0x6C, 0x00000000,  0x08AB3B18);
     ShowMessage("hallo");
    }
    

    Hier das WinSight log-File (sind alles Hex-Zahlen)

    * WinSight Botschaften verfolgen Wed Jan 24 2007 14:27:55 *
    00122.547 000025:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00122.547 000026:001B00EC "Frame-Titel"  WM_KEYDOWN (10004X) Verarbeitet   wp=00000026  lp=01480001
    00122.547 000027:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00122.547 000028:001B00EC "Frame-Titel"  WM_USER+0x6C (46c04X) Verarbeitet   wp=00000000  lp=08AB3B18
    00122.747 000029:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00122.747 000030:001B00EC "Frame-Titel"  WM_KEYUP (10104X) Verarbeitet   wp=00000026  lp=C1480001
    00122.747 000031:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00122.747 000032:001B00EC "Frame-Titel"  WM_USER+0x6C (46c04X) Verarbeitet   wp=00000000  lp=08AB3B18
    00135.505 000033:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00135.505 000034:001B00EC "Frame-Titel"  WM_KEYDOWN (10004X) Verarbeitet   wp=00000028  lp=01500001
    00135.505 000035:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00135.505 000036:001B00EC "Frame-Titel"  WM_USER+0x6C (46c04X) Verarbeitet   wp=00000000  lp=08AB3B18
    00135.715 000037:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00135.715 000038:001B00EC "Frame-Titel"  WM_KEYUP (10104X) Verarbeitet   wp=00000028  lp=C1500001
    00135.726 000039:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00135.726 000040:001B00EC "Frame-Titel"  WM_USER+0x6C (46c04X) Verarbeitet   wp=00000000  lp=08AB3B18
    00137.328 000041:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00137.328 000042:001B00EC "Frame-Titel"  WM_KEYDOWN (10004X) Verarbeitet   wp=00000025  lp=014B0001
    00137.328 000043:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00137.328 000044:001B00EC "Frame-Titel"  WM_USER+0x6C (46c04X) Verarbeitet   wp=00000000  lp=08AB3B18
    00137.418 000045:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00137.418 000046:001B00EC "Frame-Titel"  WM_KEYUP (10104X) Verarbeitet   wp=00000025  lp=C14B0001
    00137.418 000047:001B00EC "Frame-Titel"  WM_0xC168 (c16804X) Gesendet   wp=00000000  lp=00000000
    00137.418 000048:001B00EC "Frame-Titel"  WM_USER+0x6C (46c04X) Verarbeitet   wp=00000000  lp=08AB3B18
    

    Da sind viele Müll Botschaften dabei 😋
    Ich kann dir nicht sagen ob die Messages so auch bei dir funktionieren

    Grüsse



  • Besten Dank für deine Mühe!

    Irgendwie komme ich nicht klar mit dem Interpretieren der Botschaften und manchmal werden die Botschaften gar nicht aufgezeichnet. Eigentlich möchte ich nur Links, Rechts, Auf und Space an das Java-Spiel Cultris (findest du auf dem Internet) senden.
    Grüsse



  • Hi Wilder,

    Wie heißt den deine Java-Konsole. Ich hab---> jdk1.3.1
    Es kann gut sein das die Botschaftverwaltung anderst
    adressiert wird. Ich schau mir mal das Tetris an.
    Ich hoffe das wir auch davon die selbe Version haben.
    Man weis ja nie. 🙂

    Grüsse



  • Hi Wilder,

    Leider ist meine Grafikkarte nicht dafür geeignet (auch nach Treiber update!).
    Kann also das Spiel nicht starten....(obwohl es mir in den Fingern juckt).

    Also zu WinSight kann ich dir noch ein paar Tipps geben.

    1. die WinSight.INI (im Windows-Verzeichnis) bearbeiten oder anlegegen wie oben in der längsten Zeile beschrieben.
    1.5 WinSight starten
    2. Halt! drücken
    3. Winsight->Fokus folgen (markieren)
    4. Botschaften->Ausgewählte Fenster (markieren)
    5. !!!!!!! Botschaften->Optionen->nur Eingabe (markieren) !!!!!!! sonst wird das lässtig MousMove registriert
    5.5 Botschaft->Optionen->Logfile (markieren) !!!!!! Pfad merken
    5.6 Botschaft->Optionen->Hex (markieren)
    6. Start! drücken
    7. Das Spiel starten (VollBild ok)
    8. Die Windows-Taste auf der Tastur drücken
    9. das Spiel-Fenster unten klicken (--->Fokus folgen .... Ausgewählte-Fenster)
    10. Deine Tasten fürs Spiel drücken
    11. Speil beenden
    12. Halt! drücken !!!!!!
    13. Das Logfile anschauen
    14. und die Message versenden (testen) im gleichen Schema wie oben

    So dann müsste alles auf die Key-strokes des Spiels begrenzt sein.
    1000 Millisekunden in der WinSight.ini müssten reichen.
    Sind ja nur ein paar Keys die abgefangen werden sollen.

    Bin schon gespannt ob es geht.

    Grüsse


Anmelden zum Antworten