C++ Windows日志播放挂钩(WH_JOURNALPLAYBACK)忽略EVENTMSG HWND参数

C++ Windows日志播放挂钩(WH_JOURNALPLAYBACK)忽略EVENTMSG HWND参数,c++,winapi,C++,Winapi,我正在编写一个程序,以编程方式模拟键盘和鼠标的点击。它需要将单击发送到目标窗口句柄(例如:记事本编辑控件)。我正在获取记事本窗口的句柄,并为该窗口生成WM_KEYDOWN、WM_SYSKEYDOWN、WM_keydup、WM_syskeydup消息。事件存储在队列中,然后使用WH_JOURNALPLAYBACK钩子播放 对于下面的代码段,虽然回放过程中的目标hwnd设置正确,但消息永远不会到达目标句柄。如果我把记事本放在前台,它会收到信息 我不知道为什么WH_JOURNALPLAYBACK会忽略

我正在编写一个程序,以编程方式模拟键盘和鼠标的点击。它需要将单击发送到目标窗口句柄(例如:记事本编辑控件)。我正在获取记事本窗口的句柄,并为该窗口生成WM_KEYDOWN、WM_SYSKEYDOWN、WM_keydup、WM_syskeydup消息。事件存储在队列中,然后使用WH_JOURNALPLAYBACK钩子播放

对于下面的代码段,虽然回放过程中的目标hwnd设置正确,但消息永远不会到达目标句柄。如果我把记事本放在前台,它会收到信息

我不知道为什么WH_JOURNALPLAYBACK会忽略handle参数。我希望为各种句柄生成一系列自动化消息,并将其回放,这样即使不聚焦窗口,我们也可以发送键盘和鼠标事件

请让我知道

  • 如果可以使用日志向各种目标句柄发送消息 回放挂钩
  • 为什么在hwnd下面的代码中被忽略

#包括
#包括
#包括
使用std::cout;
使用std::endl;
使用std::error;
结构事件
{
味精;
UINT-wparam;
UINT-lparam;
HWND-HWND;
事件(单元m、单元wp、单元lp、硬件和硬件)
:msg(m),
wparam(wp),
LPRAM(lp),
hwnd(h)
{}
};
HHOOK jhook=NULL;
std::队列事件;
bool gotoNextMsg=false;
LRESULT回调JournalPlaybackProc(int代码、WPARAM WPARAM、LPARAM LPARAM)
{
开关(代码)
{
案例HC_跳过:

cout日志挂钩将事件注入系统消息队列。对于键盘和鼠标消息,系统将它们分派到当前聚焦窗口,就像用户手动输入一样。事件中指定的HWND不使用,在分派过程中会被替换

并且如果您认为一个已记录的日志可以多次播放,并且它的数据可以跨应用程序实例甚至重启,并且HWNDS可以随着时间的推移而重复使用,那么即使系统消息队列不参与,日志回放也不能利用事件的HWND,这应该是有意义的。 因此,您不能使用

WH_JOURNALPLAYBACK
以不在前台的特定窗口为目标。您必须自己发送录制的消息。但请注意Raymond Chen在博客中提到的一些注意事项:

#include <queue> 
#include <iostream> 
#include <windows.h> 
using std::cout; 
using std::endl; 
using std::error; 

struct Event
{
    UINT msg; 
    UINT wparam; 
    UINT lparam; 
    HWND hwnd;

    Event(UINT m, UINT wp, UINT lp, HWND h)
        :msg(m), 
        wparam(wp), 
        lparam(lp), 
        hwnd(h) 
    {}
};

HHOOK jhook= NULL; 
std::queue<Event> events; 

bool gotoNextMsg = false; 
LRESULT CALLBACK JournalPlaybackProc(int code, WPARAM wParam, LPARAM lParam)
{
    switch( code )
    {

    case HC_SKIP:
        cout<<"skip: "<<endl; 
        if(!events.empty())
        {
            events.pop(); 
        }
        break; 

    case HC_GETNEXT:
        {
            cout<<"next: "<<events.size()<<endl; 
            gotoNextMsg = true; 
            EVENTMSG * evm = (EVENTMSG*) lParam; 
            Event e = events.front(); 
            switch(e.msg)
            {
            case WM_KEYDOWN:
                cout<<"WM_KEYDOWN"<<endl; 
                break; 
            case WM_KEYUP:
                cout<<"WM_KEYUP"<<endl; 
                break; 
            case WM_SYSKEYDOWN:
                cout<<"WM_SYSKEYDOWN"<<endl; 
                break; 
            case WM_SYSKEYUP:
                cout<<"WM_SYSKEYUP"<<endl; 
                break; 
            }
            cout<<"handle: "<<e.hwnd<<endl; 
            cout<<"handle1:"<<evm->hwnd<<endl; 
            evm->message = e.msg;
            evm->paramL = e.wparam; 
            evm->paramH = e.lparam; 
            evm->hwnd = e.hwnd; 
            evm->time = ::GetTickCount(); 
        }
        break;

    default:
        if( code < 0 )
            ::CallNextHookEx(jhook, code, wParam, lParam); 
        break;
    }

    if(events.empty())
    {
        cout<<"uinstalled"<<endl; 
        ::UnhookWindowsHookEx(jhook);
        ::PostMessage(NULL, WM_USER+100, 0, 0); 
    }

    return 0; 
}