La simulation de touche avec PostMessage ne fonctionne que dans certaines applications?
Mon approche à ce problème s'est avéré être correct que dans plusieurs programmes. Pourquoi il n'est pas universel?
Fonctionne très bien sur:
Malheureusement, dans certains cas, rien ne se passe(même si je clique dans une zone de texte de la zone avant l'exécution de mon programme):
GetLastError retourne toujours 0, même en utilisant la fonction SendMessage au lieu de PostMessage.Pourriez-vous en dire mon erreur?
#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;
}
Mise à JOUR après 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;
}
Il n'y a pas de différence en effet.
Mise à JOUR après Rob Kennedy commentaire et Hans Passant la réponse de
#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;
}
Maintenant, "transparent", les messages sont envoyés à chaque fois. GetLastError() dit:
ERROR_INVALID_WINDOW_HANDLE
1400 (0x578) Invalid window handle.
GetLastError() "fixe"
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;
}
...sorties 1400
mille fois. Sauf cela, rien n'a changé.
lParam
argument. Vous n'avez pas fait cela, cependant. Votre deuxième bloc de code définit la répétez le comte. Veuillez vous référer à MSDN pour que tous les bits de lParam
veux dire.Avez-vous songé seulement à l'aide de
SendInput
à la place? Qu'est ce que c'est.PostMessage ne sera jamais en mesure de simuler l'entrée parfaitement car il y a un autre état que PostMessage ne met pas à jour (comme la touche maj unis).
Merci, je n'ai jamais entendu parler de cette fonction, et j'ai trouvé utile. Cependant, ma question est toujours ouverte.
Sonne pour moi comme une réponse, @Raymond.
OriginalL'auteur 0x6B6F77616C74 | 2012-08-09
Vous devez vous connecter pour publier un commentaire.
Cela va bien sûr se produire lorsque vous affichez le message à la mauvaise fenêtre. Ce qui est certainement le cas pour le bloc-notes. Il n'a pas qu'une seule fenêtre, quelque chose que vous pouvez voir avec Spy++. GetForegroundWindow() vous renvoie une fenêtre de niveau supérieur, le châssis de fenêtre pour le bloc-notes. À l'intérieur de la fenêtre de cadre, il a un enfant fenêtre, un contrôle d'ÉDITION. Cette fenêtre doit obtenir les messages.
Vous aurez besoin de passer par quelques étapes pour obtenir cette fenêtre, la fonction GetFocus() retourne la fenêtre qui a le focus, mais qui ne fonctionne que si vous appelez le processus propriétaire de la fenêtre. Lorsque vous effectuez ce processus, alors vous devez d'abord appeler GetWindowThreadProcessId() pour obtenir l'ID du thread qui possède la fenêtre de premier plan. Ensuite, vous devez appeler GetGUIThreadInfo(), le GUITHREADINFO.hwndFocus qu'elle renvoie est le handle de fenêtre vous avez besoin.
Ce n'est pas encore sans problème, vous ne pouvez pas contrôler l'état du clavier du processus. En d'autres termes, l'état de la Maj, Ctrl et Alt enfoncées ainsi que toutes les touches mortes (comme Alt+Gr sur certaines dispositions de clavier). Privilégiez l'envoi WM_CHAR pour la frappe des touches.
Ne pas appel GetLastError (), à moins que PostMessage renvoie la valeur FALSE.
Mis à jour à nouveau. Je ne sais pas si j'ai fait ce que vous vouliez dire.
OriginalL'auteur Hans Passant
Autre chose à garder à l'esprit est que vous ne pouvez pas toujours supposer que l'application cible est la manipulation de la saisie de l'utilisateur de la même manière. Par exemple, ils pourraient être à l'aide de quelque chose de GetAsyncKeyState() au lieu de cela, la cause de vos messages postés n'ont aucun effet du tout.
OriginalL'auteur OJ.
Vous envoyer
lParam==NULL
. Il contient le scanner de code de la clé, qui peut être demandée par les applications qui ne fonctionnent pas actuellement.Aussi, votre code ne vérifie pas la valeur de retour de GetForegroundWindow(). Il peut être NULL.
Enfin, vous omettez WM_CHAR, qui est une partie importante de clavier cycle.
OriginalL'auteur Maximus
Entre l'envoi de la KeyDown et KeyUp vous avez besoin d'une retard dans certains cas. J'ai résolu mon semblable situation en ajoutant une pause de 100ms après KeyDown
OriginalL'auteur Nasenbaer