使用WH_JOURNALRECORD并取消似乎返回WM_CANCELJOURNAL [英] Using WH_JOURNALRECORD and cancel does seem to return the WM_CANCELJOURNAL
问题描述
我正在使用C#,并且已经使程序使用SetWindowsHookEx
和WH_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.
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
消息:如果应用程序在其自己的主循环中运行,则它必须在对GetMessage
或PeekMessage
的调用与对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);
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屋!