首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#中的SetWindowsHookEx

C#中的SetWindowsHookEx
EN

Stack Overflow用户
提问于 2009-11-28 10:47:25
回答 7查看 46K关注 0票数 10

我正在尝试挂接一个第三方应用程序,这样我就可以画到它的屏幕上了。绘制到屏幕很容易,我不需要帮助,但我似乎在使用SetWindowsHookEx处理WH_GETMESSAGE时遇到了问题。我不知道最后两个参数要传递什么。

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowDrawer
{
    public partial class Form1 : Form
    {
        private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
        static IntPtr hHook;
        IntPtr windowHandle;
        uint processHandle;

        HookProc PaintHookProcedure;     

        [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
        static extern System.IntPtr FindWindowByCaption(int ZeroOnly, string lpWindowName);

        [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
        static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        // When you don't want the ProcessId, use this overload and pass IntPtr.Zero for the second parameter
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        [System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet =System.Runtime.InteropServices.CharSet.Auto)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        { 
            PaintHookProcedure = new HookProc(PaintHookProc);
            windowHandle = FindWindowByCaption(0, "Untitled - Notepad");
            uint threadID = GetWindowThreadProcessId(windowHandle, out processHandle);
            IntPtr hMod = System.Runtime.InteropServices.Marshal.GetHINSTANCE(typeof(Form1).Module);

            // HERE IS THE PROBLEM.  WHAT THE HECK DO I PASS INTO THE LAST 2 PARAMS?  I get a null pointer
            hHook = SetWindowsHookEx(WH_GETMESSAGE, PaintHookProcedure, hMod, threadID);
        }

        public int PaintHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
           // Do some painting here.
            return CallNextHookEx(hHook, nCode, wParam, lParam); 
        }

        private const int WM_PAINT = 15;
        private const int WH_GETMESSAGE = 3;
    }
}
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-11-28 10:59:32

SetWindowsHookEx为此指定了最后两个参数:

  • hMod

包含由

参数指向的钩子过程的DLL句柄中的lpfn。如果dwThreadId参数指定由当前进程创建的线程,并且挂钩过程位于与当前进程关联的代码中,则必须将hMod参数设置为NULL。

  • dwThreadId

in指定钩子程序要与之关联的线程的标识符。如果此参数为零,则钩子过程与与调用线程运行在同一桌面上的所有现有线程相关联。

我不确定您是否能以所需的方式使用.NET动态链接库,但您可以尝试一下。

通过Marshal.GetHINSTANCE(typeof(Form1).Module)获取hMod,通过Process.Threads获取dwThreadId。或者,如果需要全局挂钩(即,.当前桌面中所有GetMessage()调用的钩子),但要注意性能损失。

票数 15
EN

Stack Overflow用户

发布于 2013-03-27 05:48:14

以下情况表明这不会起作用:

“.NET框架不支持全局挂钩。除了WH_KEYBOARD_LL低级挂钩和WH_MOUSE_LL低级挂钩之外,您不能在.NET框架中实现全局挂钩。”

来自"How to set a Windows hook in Visual C# .NET"

票数 9
EN

Stack Overflow用户

发布于 2009-11-28 10:58:11

我认为您需要P/Invoke GetModuleHandle,并使用它为SetWindowsHookEx的第三个参数返回的句柄。我还相信0对于第四个参数是正确的,因为您不希望在第三方应用程序中挂钩任何一个特定的线程。

如果这对你不起作用,MSDN上的SetWindowsHookEx可能会为你指明正确的方向。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1811383

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档