Simuliert drücken einer Taste mit PostMessage funktioniert nur in bestimmten Anwendungen?
Mein Ansatz für dieses problem stellte sich heraus, um korrekt zu sein, nur in mehreren Programmen. Warum es nicht universal?
Funktioniert gut auf:
Leider in einigen Fällen passiert nichts(auch wenn ich Sie in ein Textfeld Bereich vor der Ausführung von meinem Programm):
GetLastError gibt immer 0, auch mit SendMessage statt PostMessage.Könnten Sie mein Fehler?
#include <Windows.h>
#include <iostream>
int main()
{
HWND hCurrentWindow;
Sleep(5000);
hCurrentWindow = GetForegroundWindow();
std::cout<<"GO!!!\n";
for(int i=0; i<500; i++) //simulate 500 keystrokes of 'E'.
{
PostMessage(hCurrentWindow,WM_KEYDOWN,0x45,NULL);
PostMessage(hCurrentWindow,WM_KEYUP,0x45,NULL);
}
std::cout<<GetLastError()<<std::endl;
system("Pause");
return 0;
}
UPDATE nach Maximus sugestion
#include <Windows.h>
#include <iostream>
int main()
{
HWND hCurrentWindow;
Sleep(5000);
hCurrentWindow = GetForegroundWindow();
if(!hCurrentWindow)
std::cout<<"Failed get set the window handle\n";
std::cout<<"GO!!!\n";
for(int i=0; i<500; i++)
{
PostMessage(hCurrentWindow,WM_KEYDOWN,0x45,0x45);
PostMessage(hCurrentWindow,WM_KEYUP,0x45,0x45);
}
std::cout<<GetLastError()<<std::endl;
system("Pause");
return 0;
}
Gibt es keinen Unterschied in der Wirkung.
UPDATE nach Rob Kennedy ' s Kommentar und Hans Passant die Antwort
#include <Windows.h>
#include <iostream>
int main()
{
HWND hCurrentWindow;
DWORD procID;
GUITHREADINFO currentWindowGuiThreadInfo;
Sleep(5000);
hCurrentWindow = GetForegroundWindow();
if(!hCurrentWindow)
std::cout<<"Failed get main the window handle\n";
GetWindowThreadProcessId(hCurrentWindow,&procID);
GetGUIThreadInfo(procID,¤tWindowGuiThreadInfo);
hCurrentWindow = currentWindowGuiThreadInfo.hwndFocus;
if(!hCurrentWindow)
std::cout<<"Failed get the child window handle\n";
std::cout<<"GO!!!\n";
for(int i=0; i<500; i++)
{
PostMessage(hCurrentWindow,WM_KEYDOWN,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
PostMessage(hCurrentWindow,WM_KEYUP,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
}
std::cout<<GetLastError()<<std::endl;
system("Pause");
return 0;
}
Nun, "transparent" - Nachrichten gesendet werden, jedes mal. GetLastError() sagt:
ERROR_INVALID_WINDOW_HANDLE
1400 (0x578) Invalid window handle.
GetLastError() "behoben"
int main()
{
HWND hCurrentWindow;
DWORD procID;
GUITHREADINFO currentWindowGuiThreadInfo;
Sleep(5000);
hCurrentWindow = GetForegroundWindow();
if(!hCurrentWindow)
std::cout<<"Failed get main the window handle\n";
GetWindowThreadProcessId(hCurrentWindow,&procID);
GetGUIThreadInfo(procID,¤tWindowGuiThreadInfo);
hCurrentWindow = currentWindowGuiThreadInfo.hwndFocus;
if(!hCurrentWindow)
std::cout<<"Failed get the child window handle\n";
std::cout<<"GO!!!\n";
for(int i=0; i<500; i++)
{
if(!PostMessage(hCurrentWindow,WM_KEYDOWN,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC))) std::cout<<GetLastError()<<std::endl;
if(!PostMessage(hCurrentWindow,WM_KEYUP,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC))) std::cout<<GetLastError()<<std::endl;
}
system("Pause");
return 0;
}
...Ausgänge 1400
tausend mal. Außer diesem, hat sich nichts geändert.
lParam
argument. Sie haben das nicht getan, obwohl. Ihre zweite code-block legt die Wiederholungen. Bitte finden Sie im MSDN nach, was alle bits des lParam
bedeuten.Haben Sie in Betracht gezogen, nur mit
SendInput
statt? Das ist, was es ist.PostMessage wird nie in der Lage sein zu simulieren input perfekt, denn es gibt andere Staat, der PostMessage nicht aktualisiert (wie Umschalttaste Staaten).
Danke, ich habe noch nie gehört, über diese Funktion vor und ich fand es nützlich. Aber meine Frage ist noch offen.
Klingt für mich wie eine Antwort, @Raymond.
InformationsquelleAutor 0x6B6F77616C74 | 2012-08-09
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies wird natürlich geschehen, wenn Sie post die Nachricht an das falsche Fenster. Das ist sicherlich der Fall für den Editor. Es muss nicht nur ein Fenster, etwas, das Sie sehen können mit Spy++. GetForegroundWindow() gibt Ihnen eine top-level-Fenster, Rahmen-Fenster für den Editor. Innerhalb des frame-Fenster, es hat eine Kind Fenster, einem EDIT-Steuerelement. Das Fenster muss erhalten die Nachrichten.
Müssen Sie Sprung durch ein paar Reifen zu bekommen, die Fenster, die GetFocus () - Funktion gibt das Fenster mit dem Fokus, aber das funktioniert nur, wenn Sie es aufrufen, den Prozess, der das Fenster besitzt. Wenn Sie diese out-of-process-dann müssen Sie Sie zuerst in GetWindowThreadProcessId() die ID des Threads, der besitzt das Vordergrund-Fenster. Dann rufen Sie GetGUIThreadInfo(), die GUITHREADINFO.hwndFocus es gibt das Fenster-handle, die Sie benötigen.
Ist dies immer noch nicht ohne Probleme, Sie können nicht Steuern, die Tastatur-Zustand des Prozesses. In anderen Worten, den Zustand der Umschalt -, Strg-und Alt-Tasten so gut wie keine Toten Tasten (wie Alt+Gr auf bestimmte Tastatur-layouts). Zugunsten senden WM_CHAR für die Schlüssel eingeben.
Jedoch nicht rufen Sie GetLastError (), es sei denn, PostMessage-Methode FALSE zurück.
Erneut aktualisiert. Ich weiß nicht, ob ich getan habe, was du meintest.
InformationsquelleAutor Hans Passant
Etwas anderes zu Bedenken ist, dass man nicht immer davon ausgehen, dass die Ziel-Anwendung ist die Verarbeitung von Benutzereingaben in der gleichen Weise. Zum Beispiel könnten Sie mit etwas GetAsyncKeyState() statt, wodurch Ihre Nachrichten haben keine Wirkung.
InformationsquelleAutor OJ.
Senden Sie
lParam==NULL
. Es enthält den scan-code der Taste, die möglicherweise benötigt werden, die Anwendungen, die nicht berufstätig sind aktuell.Auch, dein code funktioniert nicht überprüfen Sie den Rückgabewert von GetForegroundWindow(). Es kann sein, NULL.
Schließlich, Sie weglassen WM_CHAR, die ein wichtiger Teil der Tastatur-Zyklus.
InformationsquelleAutor Maximus
Zwischen dem senden der KeyDown-und KeyUp-Sie brauchen keine Verzögerung in einigen Fällen. Ich löste meine ähnliche situation durch hinzufügen einer pause von 100ms nach dem KeyDown -
InformationsquelleAutor Nasenbaer