我对此问题的处理方法仅在几个程序中才是正确的。为什么它不普遍?
正常工作:
不幸的是,在某些情况下没有任何反应(即使我在执行程序之前点击文本框区域):
GetLastError总是返回0,即使使用SendMessage而不是PostMessage。你能否指出我的错误?
#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;
}
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;
}
效果没有区别。
Rob Kennedy的评论和Hans Passant的回答后更新
#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;
}
现在,每次都会发送“透明”消息。 GetLastError()说:
ERROR_INVALID_WINDOW_HANDLE
1400 (0x578) Invalid window handle.
GetLastError()“已修复”
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;
}
...输出1400
千次。除此之外,没有任何改变。
答案 0 :(得分:5)
当您将消息发布到错误的窗口时,这当然会发生。对于记事本来说肯定是这样的。它没有一个窗口,你可以用Spy ++看到它。 GetForegroundWindow()返回一个顶级窗口,即记事本的框架窗口。在该框架窗口内部,它有一个子窗口,一个EDIT控件。该窗口需要获取消息。
你需要跳过几个环来获得那个窗口,GetFocus()函数返回带焦点的窗口,但只有从你拥有窗口的进程中调用它才有效。当您在进程外执行此操作时,必须首先调用GetWindowThreadProcessId()以获取拥有前台窗口的线程的ID。然后你必须调用GetGUIThreadInfo(),它返回的GUITHREADINFO.hwndFocus是你需要的窗口句柄。
这仍然不是没有问题,你无法控制进程的键盘状态。换句话说,Shift,Ctrl和Alt键的状态以及任何死键(如某些键盘布局上的Alt + Gr)。喜欢发送WM_CHAR来键入密钥。
答案 1 :(得分:2)
要记住的其他事情是,您不能总是假设目标应用程序以相同的方式处理用户输入。例如,他们可能正在使用GetAsyncKeyState()来代替,导致您发布的消息完全没有效果。
答案 2 :(得分:1)
您发送lParam==NULL
。它包含当前不工作的应用程序可能需要的密钥的扫描代码。
此外,您的代码不会检查 GetForegroundWindow()的返回值。它可能是 NULL 。
最后,省略 WM_CHAR ,这是键盘循环的重要部分。
答案 3 :(得分:1)
在发送KeyDown和KeyUp之间,在某些情况下需要delay。我通过在KeyDown
之后添加100ms的暂停来解决我的类似情况 {
PostMessage(hCurrentWindow,WM_KEYDOWN,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
Sleep(100);
PostMessage(hCurrentWindow,WM_KEYUP,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
}