SetWindowsHookEx en C #

Intento conectar una aplicación de terceros para poder dibujar en su pantalla. Dibujar en la pantalla es fácil y no necesito ayuda, pero parece que tengo problemas con el uso de SetWindowsHookEx para manejar WH_GETMESSAGE. No puedo entender qué pasar para los últimos 2 parámetros.

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; } } 

SetWindowsHookEx especifica los dos últimos parámetros de esta manera:

  • hMod

[in] Manejar a la DLL que contiene el procedimiento hook indicado por el parámetro lpfn. El parámetro hMod debe establecerse en NULL si el parámetro dwThreadId especifica un subproceso creado por el proceso actual y si el procedimiento de enlace está dentro del código asociado con el proceso actual.

  • dwThreadId

[in] Especifica el identificador del subproceso con el que se asociará el procedimiento de enlace. Si este parámetro es cero, el procedimiento de enlace se asocia con todos los subprocesos existentes que se ejecutan en el mismo escritorio que el subproceso de llamada.

No estoy seguro de que pueda usar un dll de .NET de la manera requerida, pero ciertamente puede intentarlo.

hMod vía Marshal.GETHINSTANCE (typeof (Form1) .Module) y dwThreadId través de Process.Threads . Alternativamente, establezca dwThreadId en 0 si desea un dwThreadId global (es decir, un enlace para todas las llamadas de GetMessage() en el escritorio actual), pero tenga cuidado con las penalizaciones de rendimiento.

Lo siguiente sugiere que esto no funcionará:

“Los enganches globales no son compatibles con .NET Framework. Excepto por el enganche de bajo nivel WH_KEYBOARD_LL y el enganche de bajo nivel WH_MOUSE_LL, no se pueden implementar enganches globales en Microsoft .NET Framework”.

De “Cómo configurar un gancho de Windows en Visual C # .NET”

No sé, pero si usa valores de parámetros que especifiquen que desea, como dice la API, “inyecte una DLL en otro proceso”, entonces, por lo que sé, podría funcionar solo si escribe una DLL no administrada desde el cual llamarlo

Creo que necesitas P / Invocar GetModuleHandle y usar el controlador que devuelve para el tercer parámetro de SetWindowsHookEx . También creo que 0 es correcto para el cuarto parámetro, ya que no desea conectar ningún hilo específico en la aplicación de terceros.

Si esto no funciona para usted, SetWindowsHookEx en MSDN podría apuntarlo en la dirección correcta.

Sé que esta es una vieja pregunta, pero espero que todavía haya alguien que lo encuentre útil. Creo que estás mezclando int e IntPtr

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

Este trabajo para mí usa 13 …

  private static IntPtr SetHook(LowLevelKeyboardProc proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx(13, proc, GetModuleHandle(curModule.ModuleName), 0); } }