gpt4 book ai didi

c++ - 使用 PostMessage 模拟按键仅适用于某些应用程序?

转载 作者:太空狗 更新时间:2023-10-29 19:59:43 24 4
gpt4 key购买 nike

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

适用于:

  • 火狐

  • Visual Studio 文本编辑器
  • 不幸的是,在某些情况下没有任何反应(即使我在执行我的程序之前点击了一个文本框区域):

  • 谷歌浏览器
  • 记事本
  • 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 治疗后更新

    #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,&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;
    }

    现在,每次都发送“透明”消息。 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,&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;
    }

    ...输出 1400 千次。除此之外,没有任何改变。

    最佳答案

    当您将消息发布到错误的窗口时,这当然会发生。记事本肯定是这种情况。它不仅只有一个窗口,您可以使用 Spy++ 看到它。 GetForegroundWindow() 返回一个顶层窗口,记事本的框架窗口。在该框架窗口内,它有一个 窗口,一个 EDIT 控件。该窗口需要获取消息。

    您需要跳过几圈才能获得该窗口,GetFocus() 函数返回具有焦点的窗口,但只有当您从拥有该窗口的进程中调用它时才有效。当您在进程外执行此操作时,您必须首先调用 GetWindowThreadProcessId() 以获取拥有前台窗口的线程的 ID。然后你必须调用GetGUIThreadInfo(),它返回的GUITHREADINFO.hwndFocus就是你需要的窗口句柄。

    这仍然不是没有麻烦,你无法控制进程的键盘状态。换句话说,Shift、Ctrl 和 Alt 键以及任何死键(如某些键盘布局上的 Alt+Gr)的状态。喜欢发送 WM_CHAR 来键入键。

    关于c++ - 使用 PostMessage 模拟按键仅适用于某些应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11890972/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com