捕捉窗口消息,然后触发代码

本文关键字:代码 然后 窗口 消息 | 更新日期: 2023-09-27 18:04:16

我有一个窗口代码,在其中,我有一个函数订阅接收系统消息:

... IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)

在这个函数中,当我看到等待的消息时,我触发我的类

... IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    ...some code checking the type of the mesage, etc....
    new MyClass(); //Trigger my class
}

如果我这样做,那么我得到这个错误" rpc_e_cantcallout_ininputsyncall "。经过一些研究,如果我正确理解这一点,它将不允许我运行MyClass或类似的代码,因为我试图在系统尚未完成传递所有消息时执行它,或一些类似的问题。

所以为了绕过这个问题,我把消息转发给自己,像这样:

[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam);      
private static  IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    ...some code checking the type of the mesage, etc....
   if (msg != 0xD903) //If msg is not 55555 this message is not a repost and therefore repost it
   {
       var devType = Marshal.ReadInt32(lParam, 4); 
       Debug.WriteLine(devType); //This correctly prints out "2"  which i get from lParam
       PostMessage(hwnd, 55555, wParam, lParam);     //repost message
   }
   else //If the msg is 55555 this message is my repost and I can execute MyClass with no problems
   {
       var devType = Marshal.ReadInt32(lParam, 4); 
       Debug.WriteLine(devType); //This should also print out "2", since I am merely reposting the lParam, without changing it in any way, but instead it prints "0"
      new MyClass(); //Trigger my class
   }
}

要解决我的问题,我需要知道:

为什么我转发消息时devType是0 ?

是否有一些(简单的)方法,当我收到系统消息时,我可以直接触发MyClass,而不必重新发布消息给我自己?

捕捉窗口消息,然后触发代码

关于你的LParam为0…您将IntPtr视为大小为4,如果您的目标AnyCpu并且您在64位操作系统上,则不是这种情况。因此,如果它的大小实际上是8,并且它存储在内存中的Little Endian中(它在windows中),那么读取4将获得前4个字节,如果值小于4个字节的最大值,则该值将为0。在Little Endian中,值是从右到左(从最大地址到最小地址)存储的。因此,很可能前4个字节中没有任何内容,并且您没有读取后4个字节,因为您假设IntPtr为4字节。

尝试使用

元帅。ReadInt32(lParam, lParam. size)

IntPtr。Size在32位运行时将返回4,在64位运行时将返回8(为您管理该困境)。

至于其余的,

也要记住,如果你想做一个全局钩子,

你可以在。net中对MSG处理程序做的唯一全局钩子,例如SetWindowsHookEx,是"WH_KEYBOARD_LL低级钩子和WH_MOUSE_LL"。

现在你可以钩住你自己的进程,但是你不能在。net中全局地钩住其他进程。

如果你是钩子自己的进程,你为什么不重写WndProc在表单类,然后你不需要DllImport任何东西,它将在正确的顺序(例如,你不会得到它早或晚)。

相关文章: