使用WH_JOURNALRECORD并取消似乎返回WM_CANCELJOURNAL [英] Using WH_JOURNALRECORD and cancel does seem to return the WM_CANCELJOURNAL

查看:154
本文介绍了使用WH_JOURNALRECORD并取消似乎返回WM_CANCELJOURNAL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用C#,并且已经使程序使用SetWindowsHookExWH_JOURNALRECORD成功记录了日记消息.

I'm using C# and I've got the program successfully recording the journal messages using SetWindowsHookEx with WH_JOURNALRECORD.

我的问题是何时该停止.文档显示,如果用户按下CTRL-ESC或CTRL-ALT-DELETE,将发布WM_CANCELJOURNAL消息,我可以观察该消息以了解何时停止.我的应用程序被解除钩住了,但是我似乎再也没有得到WM_CANCELJOURNAL.

My problem comes when it's time to stop. The docs show that if the user pressed CTRL-ESC or CTRL-ALT-DELETE a WM_CANCELJOURNAL message will be posted that I can watch to know when to stop. My application gets unhooked but I never seem to get a WM_CANCELJOURNAL.

我有两个挂钩设置.一个钩子做日记记录,另一个钩子检查取消消息:

I have two hooks setup. One hook to do the Journal Record and one to check for the cancel message:

IntPtr hinstance = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);

JournalRecordProcedure = JournalRecordProc;
journalHook = SetWindowsHookEx(WH_JOURNALRECORD, JournalRecordProcedure, hinstance, 0);

GetMessageProcedure = GetMessageProc;
messageHook = SetWindowsHookEx(WH_GETMESSAGE, GetMessageProcedure, hinstance, 0); 


------

public static int JournalRecordProc(int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode < 0) return CallNextHookEx(journalHook, nCode, wParam, lParam);

    EventMsgStruct msg = (EventMsgStruct) Marshal.PtrToStructure(lParam, typeof (EventMsgStruct));

    script.Add(msg); //just a quick way to record for now

    return CallNextHookEx(journalHook, nCode, wParam, lParam);
}

public static int GetMessageProc(int code, IntPtr wParam, IntPtr lParam)
{

    //it comes here but how do I test if it's WM_CANCELJOURNAL ??
    //code always seems to be equal to zero.. I must be missing something


    return CallNextHookEx(journalHook, code, wParam, lParam);
}

推荐答案

我想您是在文档:

此角色是停止日志记录的信号,意味着不能自己记录CTRL + BREAK组合键.由于CTRL + C组合键不具有日记信号的作用,因此可以将其记录下来.还有另外两个无法记录的组合键:CTRL + ESC和CTRL + ALT + DEL.这两个组合键使系统停止所有日记记录活动(记录或回放),删除所有日记记录挂钩,并将WM_CANCELJOURNAL消息发布到日记记录应用程序.

This role as a signal to stop journal recording means that a CTRL+BREAK key combination cannot itself be recorded. Since the CTRL+C key combination has no such role as a journaling signal, it can be recorded. There are two other key combinations that cannot be recorded: CTRL+ESC and CTRL+ALT+DEL. Those two key combinations cause the system to stop all journaling activities (record or playback), remove all journaling hooks, and post a WM_CANCELJOURNAL message to the journaling application.

问题是 WM_CANCELJOURNAL消息不将a>发送至您使用SetWindowsHookEx安装的回调函数.但是,与其他WM_*消息不同,它也不打算由窗口过程(在WinForms中为WndProc)处理,因为它被发布到 thread 的消息队列中,并且与任何特定的窗口.

The problem is that the WM_CANCELJOURNAL message is not sent to the callback function you installed with SetWindowsHookEx. But unlike other WM_* messages, it is also not meant to be processed by a window procedure (WndProc in WinForms) because it is posted to the message queue of the thread and is not associated with any particular window.

相反,该文档建议人们必须在应用程序的主循环中或使用

Rather, the documentation advises that one must process it within an application's main loop or using a WH_GETMESSAGE hook:

此消息没有返回值.它应从应用程序的主循环或GetMessage挂钩过程中进行处理,而不是从窗口过程中进行处理.

This message does not return a value. It is meant to be processed from within an application's main loop or a GetMessage hook procedure, not from a window procedure.

[. . . ]

WM_CANCELJOURNAL消息具有NULL窗口句柄,因此无法将其分派到窗口过程.应用程序可以通过两种方式查看WM_CANCELJOURNAL消息:如果应用程序在其自己的主循环中运行,则它必须在对GetMessagePeekMessage的调用与对DispatchMessage的调用之间捕获该消息.如果应用程序不在自己的主循环中运行,则它必须设置监视消息的GetMsgProc挂钩过程(通过调用SetWindowsHookEx指定WH_GETMESSAGE挂钩类型).

The WM_CANCELJOURNAL message has a NULL window handle, therefore it cannot be dispatched to a window procedure. There are two ways for an application to see a WM_CANCELJOURNAL message: If the application is running in its own main loop, it must catch the message between its call to GetMessage or PeekMessage and its call to DispatchMessage. If the application is not running in its own main loop, it must set a GetMsgProc hook procedure (through a call to SetWindowsHookEx specifying the WH_GETMESSAGE hook type) that watches for the message.

在托管WinForms代码中,您显然无权访问或控制应用程序的主循环.我不确定添加邮件过滤器添加到您的应用程序中将使您能够处理以下消息:我还没有尝试过.如果可以,那可能就是您要采取的方法,考虑替代方法,即安装一个 second 钩子WH_GETMESSAGE,然后在该钩子过程中侦听WM_CANCELJOURNAL消息

In managed WinForms code, you obviously don't have any access to or control over the application's main loop. I'm not sure if adding a message filter to your application will let you handle this message or not: I haven't tried it. If it will, that's probably the route you want to take, considering the alternative, which is to install a second hook, WH_GETMESSAGE, and then in that hook procedure, listen for the WM_CANCELJOURNAL message.

更新:

GetMessageProc回调函数中,code参数只是告诉您挂钩过程是否应该处理该消息.实际上,几乎所有时间都为0,这与符号常量HC_ACTION等效.如果code参数小于0,则挂接过程应仅调用CallNextHookEx函数,而不执行任何进一步的处理.基本上,这与您对JournalRecordProc回调函数所做的完全相同.

In the GetMessageProc callback function, the code parameter just tells you whether the hook procedure should process the message. Virtually all of the time, it's going to be 0, which is equivalent to the symbolic constant HC_ACTION. If the code parameter is less than 0, the hook procedure should simply call the CallNextHookEx function without performing any further processing. That's basically the exact same thing you did for the JournalRecordProc callback function.

将在 MSG结构,作为lParam参数传递给回调函数的指针.但这就是Win32的东西.不要弄乱.NET中的原始指针,让P/Invoke封送处理程序为您处理所有这些肮脏的东西.本机MSG结构等效于托管 c30>结构(与WndProc方法所用的东西相同),因此,如果这样声明GetMessageProc回调函数,则事情会简单得多:

The window message is going to be found in a MSG structure, a pointer to which is passed to the callback function as the lParam parameter. But that's Win32 stuff. Don't mess with raw pointers in .NET, let the P/Invoke marshaler handle all of that dirty stuff for you. The native MSG structure is equivalent to the managed System.Windows.Forms.Message structure (the same thing used by the WndProc method), so if you declare your GetMessageProc callback function like this, things will be much simpler:

public delegate int GetMessageProc(int code, IntPtr wParam, ref Message lParam);

然后,将Windows消息作为

Then, the windows message is found as the Msg member of the Message structure. That's the value you want to compare against WM_CANCELJOURNAL:

public static int GetMessageProc(int code, IntPtr wParam, ref Message lParam)
{
    if (code >= 0)
    {
        if (lParam.Msg == WM_CANCELJOURNAL)
        {
            // do something
        }
    }

    return CallNextHookEx(messageHook, code, wParam, ref lParam);
}

请注意,为了使对CallNextHookEx的上述调用正常工作,您还必须提供与GetMessageProc回调函数签名匹配的CallNextHookEx函数的重载定义:

Note that in order for the above call to CallNextHookEx to work, you'll also have to provide an overloaded definition of the CallNextHookEx function that matches the signature of your GetMessageProc callback function:

[DllImport("user32.dll")]
public static extern int CallNextHookEx(IntPtr hHook, int nCode,
                                        IntPtr wParam, ref Message lParam);

这篇关于使用WH_JOURNALRECORD并取消似乎返回WM_CANCELJOURNAL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆