Anfängerfrage zu getforegroundwindow() und Fokus setzen
-
Falls jemand diesen Post schon in einem anderen Bereich gelesen hat, dann tut es mir Leid, mir ist aufgefallen das ich in den falschen Bereich geschrieben habe und ich kann die Leider nicht rückgängig machen..
Hallo c++ Community,
Ich bin derzeit dabei ein Programm zu schreiben, das als erstes feststellt ob ICQ geöffnet ist, und falls ja oben in das Fenster eine Nachricht schreibt. Den ersten Teil habe ich schon selbst hinbekommen, nun wurde mir vorgeschlagen das ganze mit PostMessage zu machen. Aber dazu brauche ich angeblich die Funktion SetforegroundWindow(), und ich muss einen Fokus setzen um anzugeben, wo im ICQ Fenster die Nachricht hingeschickt werden soll.Leider habe ich keine Ahnung. Unter SetforegroundWindow() könnte ich mir sowas :SetForegroundWindow(hWnd);
vorstellen, aber bitte korrigiert mich wenn das falsch ist
Zum Thema Fokus setzen habe ich leider keine Ahnung deswegen hoffe ich ihr könnt mir weiter helfen.. Viele Grüße
PS: Das Programm sieht bis jetzt(ohne SetForegroundWindow) so aus:#include <windows.h> #include <stdio.h> #include <iostream> using namespace std; int main() { getchar(); HWND hWnd = FindWindow( NULL, "ICQ" ); if( hWnd != NULL ) { cout << "ICQ gefunden" << endl; PostMessage(hWnd,WM_CHAR,'A',0); getchar(); } else { cout << "Bitte öffnen sie ICQ!" << endl; } return 0; }
-
Du hast wirklich kein Talent für passende Forenwahl...
-
Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (auch C++0x) 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.
-
Hallo,
und wie weit funktioniert das Programm?
(Kann es leider selbst nicht ausprobieren)Um eine Nachricht an ein Fenster zu senden, muss es nicht im Vordergrund sein, also weiß ich nicht warum du SetForegroundWindow() brauchst.
Ich würde auch WM_KEYDOWN nehmen anstatt WM_CHAR.
Gruß
Fabian
-
SetForegroundWindow() stimmt so zwar, aber du brauchst imho weder SetForegroundWindow() noch SetFocus().
Sende einfach ein WM_CHAR an an das hwnd der TExtbox des Nachrichtenfensters, also nicht an das vom icq-fenster.
Das mit SetForegroundWindow() und SetFocus() bräuchtest du nur dann, wenn du mit keybd_event() arbeiten willst, aber die Methode mit PostMessage() ist da deutlich besser. So musst du dem User z.B. nicht den Fokus klauen, was auf Dauer ziemlich nervig wäre...
Eine Liste aller Childs könntest du dir z.B. mit EnumChildWindows() holen oder wenn du Fenstertitel oder -klasse weist direkt mit FindWindowEx();
lg,
andi01.
-
danke andi für die ausführliche antwort. Nur leider kommt eine Fehlermeldung wenn ich es mit
FindWindowEx(hWnd);
versuche... was mache ich falsch??
PS: Die Fehlermeldung ist : too few arguments to function `HWND__* FindWindowExA(HWND__, HWND__, const CHAR*, const CHAR*)'
-
"too few arguments" sagt doch alles: du übergibst zu wenige Argumente: du übergibst einen Parameter, FIndWindowEx() erwartet aber mehrere... auch hier würde ein Blick in die msdn helfen:
http://msdn.microsoft.com/en-us/library/ms633500(v=vs.85).aspx
FindWindowEx() geht z.B. so:
FindWindowEx(hwnd_parent, hwnd_child_after, LPCTSTR Klassenname, LPCTSTR Fenstername);
hwnd_parent ist hier das hwnd vom icq-fenster;
hwnd_childs_after kannst du erstmal auf NULL setzen, das ist dazu da wenn du die childs der Reihe nach durchgehst erst ab einem bestimmten Child zu suchen.
Klassenname ist der Name der Fensterklasse, zu der das Child gehört. Wenn er dir nicht bekannt ist kannst du ihn NULL setzen, musst dafür aber im nächsten Parameter den Titel angeben.
Fenstername ist der Titel des Childwindows. Wenn dir der bekannt ist kannst du den hier einsetzen, wenn du diesen Parameter NULL setzt und z.B. hwnd_child:after NULL ist wird kaum das gewünschte HWND rauskommen^^
in dem Fall solltest du dir eine Liste aller CHilds besorgen (s.o.).
lg,
andi01.
-
Danke, jetzt bin ich schonmal einen Schritt weiter
Nur wie bekomme ich den Namen von dem Childwindow??
-
das ist gar nicht so leicht^^ deshalb mache ich das normalerweise auch anders;
so bekommt man z.B. eine Liste aller Childs:
#include<vector> vector<HWND> childs; BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lparam) { if(IsWindow(hwnd)) { childs.push_back(hwnd); } return true; } void childliste() { HWND parent=FindWindowA(0, "ICQ"); EnumChildWindows(parent, EnumProc, 0); }
jetzt musst du nur noch das richtige Child finden, du kannst es ja probehalber mal an alle childs schicken und schaun, bei welchem Child das 'A' im Eingabefeld landet.
allerdings bin ich mir unsicher, ob das Nachrichtenfenster nicht ein eigenes Fenster ist... dann musst du das als Parent angeben statt dem icq-fenster;
lg,
andi01.
-
Vielen Dank!
Ich denke das wird jetzt die letzte Frag sein und zwar:
Bis jetzt sieht mein Programm so aus:#include <vector> #include <windows.h> #include <stdio.h> #include <iostream> using namespace std; int main() { HWND hWnd = FindWindow( NULL, "ICQ" ); HWND hwnd_parent = hWnd; HWND hwnd_child_after; vector<HWND> childs; BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lparam) { if(IsWindow(hwnd)) { childs.push_back(hwnd); } return true; } void childliste() { HWND parent=FindWindowA(0, "ICQ"); EnumChildWindows(parent, EnumProc, 0); } if( hWnd != NULL ) { cout << "ICQ gefunden" << endl; } PostMessage(hWnd,WM_CHAR,'A',0); getchar(); } else { cout << "Bitte öffnen sie ICQ!" << endl; } return 0; }
und jetzt kommen ein haufen Fehlermeldungen.. Was ist an dem Code falsch? mfg
-
lol seit wann darf man Funktionen innerhalb von main() definieren??
du musst nur die Position deiner Funktionen ändern: alle außerhalb von main(), auch globale Variablen außerhalb, z.B. so:
#include <vector> #include <windows.h> #include <stdio.h> #include <iostream> using namespace std; HWND hWnd; HWND hwnd_parent; HWND hwnd_child_after; vector<HWND> childs; BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lparam) { if(IsWindow(hwnd)) { childs.push_back(hwnd); } return true; } void childliste() { HWND parent=FindWindowA(0, "ICQ"); EnumChildWindows(parent, EnumProc, 0); } void childliste() { HWND parent=FindWindowA(0, "ICQ"); EnumChildWindows(parent, EnumProc, 0); } int main() { hWnd = FindWindow( NULL, "ICQ" ); hWnd_parent = hWnd; if( hWnd != NULL ) { cout << "ICQ gefunden" << endl; } PostMessage(hWnd,WM_CHAR,'A',0); getchar(); } else { cout << "Bitte öffnen sie ICQ!" << endl; } return 0; }
aber nicht zu früh freuen
ich habe gerade heraugefunden dass es nochmal um einiges schwerer wird:
-ein Nachrichtenfenster ist ein eigenständiges Parent, kein Child vom icq-fenster
- angenommen du chattest mit der Person Max Mustermanndann trägt auch das Nachrichtenfenster den Titel "Max Mustermann", der Titel aller Nachrichtenfenster unterscheidet sich also...
-die textbox ist child des jeweiligen NachrichtenfensrersFensterklasse aller Nachrichtenfenster: "__oxFrame.class__" ohne die ""
Fensterklasse aller Nachrichteneingabeboxen: "Internet Explorer_Server" ohne die ""ich bin gerade auch am Grübeln wie man am einfachsten an alle Nachriochtenfenster kommt, aber ich habe da schon eine Idee: die Fensterklasse ist überall gleich und ich habe bereits herausgefunden wie sie heist...
das macht es viel einfacher... ich teste mal eben ob das so geht woe ich denke...lg,
andi01.
-
so, ich habe es jetzt geschafft die Auswahl bis auf 4 Childs einzuschränken, und es funktioniert
im Zielfenster steht 'A'
war doch etwas schwerer als ich gedacht hatte^^
#include<windows.h> #include<conio.h> #include<iostream> #include<string> #include<vector> using namespace std; vector<HWND> icq_fenster; vector<HWND> nachrichtenfenster; vector<HWND> childs; vector<string> alte_titel; BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lparam) { if(IsWindow(hwnd)) { char buf[1000]; GetClassNameA(hwnd, buf, 1000); string temp; temp+=buf; if(strcmp(temp.c_str(), "__oxFrame.class__")==0) { icq_fenster.push_back(hwnd); } } return true; } BOOL CALLBACK EnumProc2(HWND hwnd, LPARAM lparam) { char buf[1000]; GetClassNameA(hwnd, buf, 1000); char buf2[1000]; GetWindowTextA(hwnd, buf2, 1000); if(strcmp(buf, "Internet Explorer_Server")==0&&strcmp(buf2, "")==0)//nachrichteneingabe gehört zu der Klasse und hat keinen Fenstertitel { childs.push_back(hwnd); } return true; } int main() { //hole alle icq-fenster EnumWindows(EnumProc, 0); //filtere Fenster "ICQ" heraus for(int a=0;a<icq_fenster.size();a++) { char buf[1000]; GetWindowTextA(icq_fenster[a], buf, 1000); if(strcmp(buf, "ICQ")!=0&&strcmp(buf, "")!=0) { nachrichtenfenster.push_back(icq_fenster[a]); } } //hole alle gefilterten childs dieser parents: for(int a=0;a<icq_fenster.size();a++) { EnumChildWindows(icq_fenster[a], EnumProc2, 0); } //alte titel sichern: for(int a=0;a<childs.size();a++) { char buf[1000]; GetWindowTextA(childs[a], buf, 1000); string temp; temp+=buf; temp.clear(); alte_titel.push_back(temp); } //jetzt solltest du dein bis auf ganz wenige haben! nun kannst du dein A reinschreiben: for(int a=0;a<childs.size();a++) { PostMessage(childs[a], WM_CHAR, 'A', 0); } getch(); }
btw: so findet man z.B. die Fensterklassen heraus:
void fensterklassen_finden() { for(;;) { cout<<"\n\ntaste drücken\n"; getch(); POINT p; GetCursorPos(&p); HWND fenster=WindowFromPoint(p); cout<<"HWND: "<<fenster<<endl; char buf[1000]; GetWindowTextA(fenster, buf, 1000); string temp; temp+=buf; cout<<"Fenstertitel: "<<temp<<endl; char classname[1000]; GetClassNameA(fenster, classname, 1000); cout<<"Klassenname: "<<classname<<endl; } getch(); }
und zu deinem Fehler von oben: Funktionen werden NIE in main() definiert!!!
lg,
andi01.
-
Wow.. Vielen Dank, es funktioniert wunderbar.. Nur würde ich auch gerne wissen wie es mit SetForegroundWindow() + Focus geht.. Bis jetzt sieht es so aus:
#include <windows.h> #include <stdio.h> #include <iostream> using namespace std; int main() { HWND hWnd = FindWindow( NULL, "Camtasia Studio 7.0.1 Setup" ); // Handle von dem Camtasia Fenster ermitteln und unter hWnd speichern. if( hWnd != NULL ) // Falls Camtasia Setup offen ist... { cout << "Camtasia Studio Setup 7.0.1 gefunden" << endl; SetForegroundWindow(hWnd); Sleep(3000); PostMessage(hWnd,WM_CHAR,'A',0); // Nachricht ans Fenster senden, hier "A". getchar(); } else // Falls das Fenster nicht gefunden wird... { cout << "Bitte öffnen sie das Camtasia Studio Setup!" << endl; getchar(); } return 0; }
Ja, ich habe jetzt mal das Camtasia Studio Setup genommen da ich es zufällig zwischendurch installiert habe und mir aufgefallen ist, das man es daran perfekt probieren könnte..
Das ganze sieht so aus:
Das Fensterhandle wird unter hWnd gespeichert, das funktioniert auch alles perfekt.. Nur leider wir dann mit PostMessage kein A dorthingeschrieben.. Jetzt muss man doch den Focus setzen, oder? Und wenn ja, wie? ^^ Das A soll dann in das Feld Name. MFG!
-
Hi,
da ich das Setup selbst nicht habe kann ich dir diesmal leider nur eine theoretische Anleitung geben wie du das hinbekommst(klappt aber für ALLE Programme ):Erstmal: Egal bei welchem Prgramm, um mit PostMessage() Zeichen in eine Textbox zu schreiben brauchst du NIE SetForegroundWindow() oder SetFocus().
Also entweder nimmst du die deutlich bessere MEthode mit PostMessage() und ohne SetForegroundWindow() oder SetFocus() oder du nimmst zu Übungszwecken die schlechtere Variante mit SetForegroundWindow(), SetFocus() und keybd_event(); Beides mischen ist definitiv falsch bzw. unnötig.
zur Variante mit PostMessage():
Schritt 1: Besorge dir das Parent-hwnd [FindWindow()]
Schritt 2: Besorge dir den Namen der Fensterklasse des Feldes Name; dazu empfehle ich folgenden Codeschnipsel:
void fensterklassen_finden() { for(;;) { cout<<"\n\nMaus IN Zielfenster stellen (bzw. auf Titelleiste), taste drücken\n"; getch(); POINT p; GetCursorPos(&p); HWND fenster=WindowFromPoint(p); cout<<"HWND: "<<fenster<<endl; char buf[1000]; GetWindowTextA(fenster, buf, 1000); cout<<"Fenstertitel: "<<buf<<endl; char classname[1000]; GetClassNameA(fenster, classname, 1000); cout<<"Klassenname: "<<classname<<endl; } getch(); }
damit kannst du die Fensterklassennamen herausfinden.
Schritt 3: Besorge dir mit EnumChildsWindows() und einer entsprechenden Callback-Funktion eine Liste aller Childs vom Parent und schreibe diese in einen globalen Vektor. (--> bsp. icq)
Schritt 4: Entweder du legst nun einen neuen globalen Vektor an und kopierst da die HWND aller Childs, die zur Klasse der Textbox gehören rein, oder du entfernst aus dem alten Vektor [vektor.erase(...)] alle Childs die nicht zur Fensterklasse der Textbox gehören.
Schritt 5: An alle Childs die jetzt noch übrig sind (normalerweise sind das nur noch äußerst wenige
) schickst du mit PostMessage dein 'A'
Zur Variante 2:
Diese Variante ist nicht empfehlenswert:
Schritt 1: Finde das HWND des PArents heraus [FindWindow()]
Schritt 2: SetForegroundWindow(hwnd_parent);
Schritt 3: Finde wie oben beschrieben das HWND der Textbox raus; aber ACHTUNG: diesmal darf nur noch 1 HWND eines Childs übrig sein! sollten mehr übrig sein und du hast bereits alle Möglichkeiten von oben durchprobiert, lass den User die Maus auf die Textbox stellen und hol dir mit GetCursorPos() und WindowFromPoint() wie in Variante 1 Schritt 2 das HWND der Textbox;
Schritt4: SetFocus(hwnd_textbox);
Schritt 5: benutze keybd_event() zum Schreiben von 'A' [Erklärung siehe msdn]
http://msdn.microsoft.com/en-us/library/ms646304(v=vs.85).aspx
ansonsten einfach mal googeln, da gibts genug beispiele
ganz allgemein hilft auch immer ein Blick in die msdn, wenn man nicht genau über eine Funktion bescheid weiß. Du musst nur aufpassen dass du nicht die MFC-variante oder so erwischst
Einfach mal den Begriff zusammen mit "msdn" ohne die "" googeln, da wo Windows dabeisteht, das ist meist der richtige Link.
lg,
andi01.P.S.: Ein paar EInrückungen in deinem Code wären generell nicht schlecht, im Code von deinem letzten Post hat man mühe zu erkennen, welche Befehle wohin gehören. Das macht es nicht nur für uns leichter deinen Code zu lesen und zu korrigieren, sondern du behälstst auch selbst beim Coden viel leichter den Überblick
Auch geeignete Variablennamen wären eine gute Idee, z.B. statt HWND hwnd lieber HWND child;
EDIT:
und noch etwas ganz allgemeines zu deinem Code oben: Wenn du ein Parent mit einer Textbox als Child hast, in die du reinschreiben willst, sendet man die Nachricht NIE an das Parent sondern IMMER an das Childs, nämlich die Textbox!
-
LoL, der Kleine will ein butefrorce Attacke auf den Registrierungsdialog ausführen. Ach wie niedlich der Zwerg.
Lern lieber mal mit Ollydbg und IDA Pro umzugehen. Im Bushhacker Forum solltest du auch mal vorbeischauen.
-
...... schrieb:
LoL, der Kleine will ein butefrorce Attacke auf den Registrierungsdialog ausführen.
Na dann mal viel Spaß
Bei der Länge des Schlüssels und unter Berücksichtigung aller möglichen Zeichen dauert das ewig. Mal ganz abgesehen von der Zeit die das Programm braucht um die Eingabe zu checken... Wenn das jedesmal nur ein paar hundert Millisekunden dauert sitzt er bei einem etwa 15-20 stelligen Schlüssel ewig
diese Methode ist nicht wirklich erfolgsversprechend^^
falls er es doch für andere Zwecke braucht weiß er ja jetzt wie's geht, deshalb kann er das ruhig wissen
lg,
andi01.
-
ne mit ollydbg bin ich schon lange durch, hab auch nen keygen gemacht