我正在尝试挂接一个第三方应用程序,这样我就可以画到它的屏幕上了。绘制到屏幕很容易,我不需要帮助,但我似乎在使用SetWindowsHookEx处理WH_GETMESSAGE时遇到了问题。我不知道最后两个参数要传递什么。
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;
}
}发布于 2009-11-28 10:59:32
SetWindowsHookEx为此指定了最后两个参数:
hMod包含由
参数指向的钩子过程的DLL句柄中的lpfn。如果dwThreadId参数指定由当前进程创建的线程,并且挂钩过程位于与当前进程关联的代码中,则必须将hMod参数设置为NULL。
dwThreadIdin指定钩子程序要与之关联的线程的标识符。如果此参数为零,则钩子过程与与调用线程运行在同一桌面上的所有现有线程相关联。
我不确定您是否能以所需的方式使用.NET动态链接库,但您可以尝试一下。
通过Marshal.GetHINSTANCE(typeof(Form1).Module)获取hMod,通过Process.Threads获取dwThreadId。或者,如果需要全局挂钩(即,.当前桌面中所有GetMessage()调用的钩子),但要注意性能损失。
发布于 2013-03-27 05:48:14
以下情况表明这不会起作用:
“.NET框架不支持全局挂钩。除了WH_KEYBOARD_LL低级挂钩和WH_MOUSE_LL低级挂钩之外,您不能在.NET框架中实现全局挂钩。”
来自"How to set a Windows hook in Visual C# .NET"
发布于 2009-11-28 10:58:11
我认为您需要P/Invoke GetModuleHandle,并使用它为SetWindowsHookEx的第三个参数返回的句柄。我还相信0对于第四个参数是正确的,因为您不希望在第三方应用程序中挂钩任何一个特定的线程。
如果这对你不起作用,MSDN上的SetWindowsHookEx可能会为你指明正确的方向。
https://stackoverflow.com/questions/1811383
复制相似问题