SendMessage zu Directx Games
-
Hallo, ich habe das Problem das Keys die ich mit SendMessage an Spiele Fenster schicke nicht ankommen. Mir wurde gesagt das es nur mit DirecktInput gehen würde ? Habe leider keine Ahnung was das sein soll geschweige denn wie man sowas einbaut.
Der " W " Key müsste den Charakter bewegen macht er aber nicht.
Hier mal der Code:
#include <iostream> #include <windows.h> using namespace std; DWORD WINAPI GetLastError(void); int main() { HWND hwnd; hwnd = FindWindow (NULL, "Minecraft"); if (!hwnd) { cout << "Das Fenster 'Minecraft' konnte nicht gefunden werden." << endl; } else { cout << "Fenster Gefunden !" << endl; cout << "WindowHandle: " << hwnd << 'n' << endl; GetLastError(); cout << "Error: " << GetLastError() << endl; } int i = 0; while (i < 1) { SendMessage(hwnd, WM_KEYDOWN, NULL, 'w'); } return 0; }
-
Du musst DInput hooken und dann das W senden.
-
Minecraft verwendet kein DirectX, sondern OpenGL mit Java
greetz KN4CK3R
-
Zunächst mal verwendet Minecraft kein DirectX...
Desweiteren schickt man Tastendrücke nicht per SendMessage an Spiele,
da Spiele dazu neigen, den Tastaturstatus abzufragen, anstatt auf Nachrichten zu warten. Deine Nachricht kommt also an, das Spiel ignoriert sie aber und pollt in jedem Schleifendurchlauf den Tastaturstatus neu.
Was du brauchst ist SendInput.
-
Zieh dir doch einfach den dekompilierten Minecraft Source aus dem internet und bau ne Key-Lock-Taste ein.
-
Dieser Thread wurde von Moderator/in Marc++us aus dem Forum C++ (auch C++0x, bzw. C++11) in das Forum WinAPI verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Dazu sage ich nur eines:
Finger weg von Tastatur- und Maus-Simulation mittels SendMessage()Nimm bitte stattdessen SendInput(), dafür ist die Funktion gedacht!
Siehe auch "Tasteneingabe an Spiel senden" http://www.c-plusplus.net/forum/289087
Dort habe ich auch ein Link angegeben, wo Martin Richter erklärt warum SendInput() die bessere Wahl ist.HTH,
Martin
-
@Mmacher: +1
-
Danke für die vielen antworten leider bin ich mit dem SendInput total überfordert und das auf der MSDN seite versteh ich nur teilweise, ich "programmiere" auch erst seit kurzem.
Ich habe es jetzt erstmal mit
{ SetForegroundWindow(hwnd); keybd_event(VK_SPACE, 0, 0, 0); Sleep(100); keybd_event(VK_SPACE, 0, KEYEVENTF_KEYUP, 0); Sleep(2000); i++; }
getestet funktioniert auch (der charakter springt) allerdings ist das mit dem Foreground dann doch mies. Hätte nicht gedacht das es für so ein paar eingaben dann doch schon soviel know how erfordert.
-
gehört halt dazu, dass man sich erkundigt, welche Voraussetzungen manche Funktion benötigen. Du erwartest ja von einem Auto auch (noch) nicht, dass es losfährt sobald du dich reinsetzt.
Der Link von Mmacher zeigt auf Codeschnipsel zu SendInput, ist auch nicht schwerer wie keybd_event, nur eine andere Form.greetz KN4CK3R
-
Hey, die Codeschnipsel hab ich mir schon angeguckt ich hab echt lange versucht hin und her kriegs aber nicht hin ich bekomm immer not declared errors, obwohl ich alles included hab was auch sonst bei den anderen included ist..
C:\Programmieren\SendKey\SendInput().cpp||In function 'int main(int, char**)':| C:\Programmieren\SendKey\SendInput().cpp|29|error: 'INPUT' was not declared in this scope| C:\Programmieren\SendKey\SendInput().cpp|29|error: expected ';' before 's_input'| C:\Programmieren\SendKey\SendInput().cpp|31|error: 's_input' was not declared in this scope| C:\Programmieren\SendKey\SendInput().cpp|31|error: 'INPUT_KEYBOARD' was not declared in this scope| C:\Programmieren\SendKey\SendInput().cpp|37|error: 'SendInput' was not declared in this scope| ||=== Build finished: 5 errors, 0 warnings ===|
Hier der Code mit dem ich das getestet habe:
#include <iostream> #include <windows.h> using namespace std; int main (int argc, char* argv[]) { HWND hwnd; DWORD dwPid; //Prozess ID des Targets HWND hwGamewindow;//Fenstername des Targets HANDLE hProcess; //ID nach dem Öffnen des Prozesses hwnd = FindWindow (NULL, "Minecraft"); if (!hwnd) { cout << "Das Fenster 'Minecraft' konnte nicht gefunden werden." << endl; } else { cout << "Fenster Gefunden !" << endl; cout << "WindowHandle: " << hwnd << 'n' << endl; } int i = 0; while(i<3) { Sleep(1000); INPUT s_input; s_input.type = INPUT_KEYBOARD; s_input.ki.wVk = VK_RETURN; s_input.ki.wScan = 28; s_input.ki.dwFlags = 0; s_input.ki.time = 0; s_input.ki.dwExtraInfo = 0; SendInput( 1, &s_input, sizeof( INPUT ) ); //Tastendruck "ENTER" simulieren. } }
-
Hallo, versuch mal:
#include <windows>
#include <iostream>
using namespace std;Und schau dir den Quelltext mal an, kann sein das du AttachThreadInput verwenden musst.
Du musst in dem Quelltext halt noch angeben das die Taste auch wieder los gelassen werden soll.
[Ansonsten wenn es dir nicht um den Lerneffekt geht nimm einfach AutoIT dann biste warscheinlich in 10 Minuten fertig. ^^]
#include <windows> #include <iostream> using namespace std; int main(int argc, char* argv[]) { bool terminate = false; COLORREF ref; Sleep(3000); UINT key; HWND hwnd; HWND foc; DWORD getThreadID; DWORD getThreadProcessID; bool Attach; hwnd = FindWindow (0,"Guild Wars"); if ( hwnd == 0 ) { cout<<"FindWindow error code:"<<GetLastError(); } HDC hdc = GetDC(0); getThreadID = GetCurrentThreadId(); getThreadProcessID = GetWindowThreadProcessId(hwnd,0); Attach = AttachThreadInput( getThreadID , getThreadProcessID , true ); if ( Attach == 0) { cout<<"AttachThreadInput error code: "<<GetLastError()<<endl; system("PAUSE"); } while ( terminate == false) { ref = GetPixel( hdc, 424, 93 ); if (ref == 0xDAE7A1) { key = MapVirtualKey( 0x31,0 ); INPUT data; data.type = INPUT_KEYBOARD; data.ki.wVk = 0x31; data.ki.wScan = key; data.ki.dwFlags = 0; data.ki.time =0; data.ki.dwExtraInfo = 0; SendInput (1 , &data, sizeof(data)); } if (GetAsyncKeyState(VK_ESCAPE) ==-32767) { AttachThreadInput( getThreadID , getThreadProcessID , false ); terminate = true; } } return 0; }
-
Hey,
#include <windows>
Funktioniert nicht bei mir nur mit einem .h dahinter, der code den du gepostet hast spuckt bei mir 36 Errors aus, wenn ich den code mit
#include <windows.h>
nutze sinds halt genau die gleichen 5 wie bei meinem Code.
Edit: ich nutze Code::Blocks 10.05
Edit2: Von AutoIt halte ich nichts, ich möchte die sachen schon selber schreiben und verstehen können ich möchte bis ende des Jahres ein kleines Projekt fertigstellen können.
-
Kleiner Tipp: benutz Visual C++ 2010 Express...
Ist kostenlos und da funktioniert es. (mit windows.h)
Beim MinGW musst du leider damit rechnen, dass evtl die Windows Header nicht ganz so vollständig sind wie die von Microsoft.
-
DrakoXP schrieb:
Kleiner Tipp: benutz Visual C++ 2010 Express...
Ist kostenlos und da funktioniert es. (mit windows.h)
Beim MinGW musst du leider damit rechnen, dass evtl die Windows Header nicht ganz so vollständig sind wie die von Microsoft.Grade runtergeladen und getestet, bekomme ich von beiden Codes den Fehler hier:
error C2664: 'FindWindowW': Konvertierung des Parameters 2 von 'const char [10]' in 'LPCWSTR' nicht möglich 1> Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.
Finde das Programm auch ziehmlich unübersichtlich und es fehlen mir einige nützliche funktionen von Code::Blocks , z.b. das alles makiert wird was gleich mit dem ist was man doppelklickt.
Edit: Habe grade eine Lösung gefunden man muss
#define _WIN32_WINNT 0x0403
zu den includes schreiben
#define _WIN32_WINNT 0x0403 #include <iostream> #include <windows.h>
Edit2: Die lösung ist für Code::Blocks
-
der Fehler kommt daher, dass in den Projektoptionen Unicode eingestellt ist.
greetz KN4CK3R
-
Ich hab jetzt alles soweit das es ohne fehler baut allerdings gehen die Keys jetzt an das fenster was im vordergrund ist anstatt direckt zum Minecraft Fenster ?!
#define _WIN32_WINNT 0x0403 #include <iostream> #include <windows.h> using namespace std; int main (int argc, char* argv[]) { HWND hwnd; DWORD dwPid; //Prozess ID des Targets HWND hwGamewindow;//Fenstername des Targets HANDLE hProcess; //ID nach dem Öffnen des Prozesses, sprich dem Recht zu Debuggen DWORD idtest; // ID von hwnd zum attachen zur 2t ID ?! DWORD idtest2; // 2te ID wir mit ID1 verbunden ?! bool attach; // Wenn WAHR verbindet es ID1 und ID2 ?! hwnd = FindWindow (0, "Minecraft"); if (!hwnd) { cout << "Das Fenster 'Minecraft' konnte nicht gefunden werden." << endl; } else { cout << "Fenster Gefunden !" << endl; cout << "WindowHandle: " << hwnd << 'n' << endl; idtest = GetCurrentThreadId(); idtest2 = GetWindowThreadProcessId(hwnd,0); attach = AttachThreadInput(idtest,idtest2, true); if(!attach) { cout<<"attach Fehler: "<<GetLastError()<<endl; } SetFocus(hwnd); } int i = 0; while(i<3) { Sleep(1000); INPUT s_input; s_input.type = INPUT_KEYBOARD; s_input.ki.wVk = VK_RETURN; s_input.ki.wScan = 28; s_input.ki.dwFlags = 0; s_input.ki.time = 0; s_input.ki.dwExtraInfo = 0; SendInput( 1, &s_input, sizeof( INPUT ) ); //Tastendruck "ENTER" simulieren. i++; } }
Edit jetzt gehts zwar aber das Fenster wird in den Foreground gesetzt
-
Warum das Rad zweimal erfinden? Guck dir mal AutoHotKey an, das hat eine eigene Scriptsprache, mit der man alle möglichen Eingaben simulieren kann.
-
An Autohotkey/AutoIt usw habe ich kein interesse, die Code ansätze hier zählen zu meinen ersten Arbeiten wie schon gesagt habe ich vor ein paar monaten mit C++ angefangen und mich da auch ihrgentwie drauf versteift.
Ich möchte ihrgentwann in der Lage sein das zu Coden was ich Coden möchte und das mit so wenig einschränkungen wie möglich ich denke da sitz ich mit C++ genau im richtigem boot.
-
Ok, das ist natürlich was Anderes. Ist als Einstieg auch nicht so verkehrt, da es als Einstiegsprojekt zu realisieren dürfte (kein zu ehrgeiziges Ziel) und später viel Spielraum für Erweiterungen lässt. Dann mal viel Erfolg.