c#中的窗口挂钩

Posted

技术标签:

【中文标题】c#中的窗口挂钩【英文标题】:Window hooks in c# 【发布时间】:2011-02-11 21:29:22 【问题描述】:

我正在尝试从 csharp 连接到其他窗口。我正在使用SetWindowsHookEx,但将其从 c++ t c# 转换为运气不佳。 我找到了这个线程here 但它没有解决。问题是 SetWindowsHookEx 返回 0。 它包括我发现的最佳代码示例:

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;
    

有什么帮助、建议吗?

【问题讨论】:

【参考方案1】:

WH_GETMESSAGE 挂钩是一个全局挂钩。它需要一个可以注入另一个进程的 DLL。 hMod 参数。有一个问题,你不能用托管语言编写这样的 DLL。目标进程不会初始化 CLR。​​

有一个code project 提供了这样一个DLL,也许你可以让它工作。需要黑带。

【讨论】:

【参考方案2】:

您看过EasyHook 项目吗?这似乎是一个非常活跃的项目。 Microsoft 在其网站上也有 an example。

【讨论】:

他们正在挂钩到自己的窗口,所以第三个参数是 0。我需要挂钩到其他进程。 但是您的第一个链接很有趣。我会阅读有关此项目的信息。

以上是关于c#中的窗口挂钩的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法为 Windows 窗体中的特定按钮挂钩鼠标事件

C# 挂钩以获取原始鼠标/键事件

Windows (C++) 中的 WH_JOURNALRECORD 挂钩 - 从未调用过回调。

如何挂钩应用程序?

本地键盘挂钩终止目标进程

在 C# 中的窗口窗体应用程序中关闭窗口时发出警报 [重复]