C++ 用PostMessage模拟按键只在某些应用程序中有效?

C++ 用PostMessage模拟按键只在某些应用程序中有效?,c++,winapi,keypress,C++,Winapi,Keypress,我解决这个问题的方法只有在几个项目中才被证明是正确的。为什么它不是通用的 适用于: Firefox VisualStudio文本编辑器 不幸的是,在某些情况下什么也不会发生(即使我在执行程序之前点击文本框区域): 谷歌浏览器 记事本 GetLastError始终返回0,即使使用SendMessage而不是PostMessage。您能指出我的错误吗 #include <Windows.h> #include <iostream> int main() { H

我解决这个问题的方法只有在几个项目中才被证明是正确的。为什么它不是通用的

适用于:
  • Firefox

  • VisualStudio文本编辑器
  • 不幸的是,在某些情况下什么也不会发生(即使我在执行程序之前点击文本框区域):
  • 谷歌浏览器
  • 记事本
  • 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;
    }
    
    GetLastError()“已修复”

    intmain()
    {
    HWND Hcurrent窗口;
    德沃德·普罗西德;
    GUITHREADINFO当前窗口GUITHREADINFO;
    睡眠(5000);
    hCurrentWindow=GetForegroundWindow();
    如果(!hCurrentWindow)
    
    std::cout您发送
    lParam==NULL
    。它包含当前不工作的应用程序可能需要的密钥扫描代码

    此外,您的代码没有检查getForeGroundIndow()的返回值。它可能是NULL


    最后,您省略了WM_CHAR,这是键盘周期的一个重要部分。

    当您将消息发布到错误的窗口时,当然会发生这种情况。记事本就是这样。它不仅仅只有一个窗口,您可以通过Spy++.GetForegroundWindow()看到这一点返回一个顶级窗口,即记事本的框架窗口。框架窗口内有一个子窗口,一个编辑控件。该窗口需要获取消息

    要获得该窗口,您需要跳转几圈,GetFocus()函数返回具有焦点的窗口,但只有从拥有该窗口的进程调用它时,该函数才有效。在进程外执行此操作时,必须首先调用GetWindowThreadProcessId()若要获取拥有前台窗口的线程的ID,则必须调用GetGuitThreadInfo(),它返回的GuitThreadInfo.hwndFocus就是所需的窗口句柄


    这仍然不是没有问题的,您无法控制进程的键盘状态。换句话说,Shift、Ctrl和Alt键以及任何无效键(如某些键盘布局上的Alt+Gr)的状态。支持发送WM_CHAR用于键入键。

    另外需要记住的是,您不能总是假设目标应用程序以相同的方式处理用户输入。例如,他们可能使用了某些东西,导致您发布的消息完全无效。

    在发送向下键和向上键之间,您需要这样做我解决了类似的问题,在按下键后增加了100毫秒的暂停

        {
            PostMessage(hCurrentWindow,WM_KEYDOWN,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
            Sleep(100);
            PostMessage(hCurrentWindow,WM_KEYUP,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
        }
    

    Maximus建议您在
    lParam
    参数中包含扫描代码。但您还没有这样做。您的第二个代码块设置了重复计数。请参阅MSDN了解
    lParam
    的所有位的含义。您是否考虑过只使用
    SendInput
    来代替?这就是它的用途。PostMessage将永远无法实现完美模拟输入,因为PostMessage不会更新其他状态(如shift键状态)。@RobKennedy谢谢,我以前从未听说过此函数,我发现它很有用。但是,我的问题仍然悬而未决。听起来像是一个答案,@Raymond.don call GetLastError()除非PostMessage返回FALSE。再次更新。我不知道我是否按照你的意思做了。不确定这是否正确,扫描代码必须是lParam的第16-23位。WM_CHAR由TranslateMessage注入,不应该由代码发送,除非它是你发送的唯一消息。
    #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,&currentWindowGuiThreadInfo);               
        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;
    }
    
    1400 (0x578)
    
    Invalid window handle.
    
    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,&currentWindowGuiThreadInfo);               
        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;
    }
    
        {
            PostMessage(hCurrentWindow,WM_KEYDOWN,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
            Sleep(100);
            PostMessage(hCurrentWindow,WM_KEYUP,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
        }