SetWindowsHookEx en C #

J’essaie de connecter une application tierce afin de pouvoir afficher son écran. Dessiner à l’écran est facile et je n’ai besoin d’aucune aide, mais j’ai apparemment des problèmes avec l’utilisation de SetWindowsHookEx pour gérer WH_GETMESSAGE. Je ne peux pas comprendre quoi passer pour les 2 derniers parameters.

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, ssortingng 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(ssortingng 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 spécifie ainsi les deux derniers parameters:

  • hMod

[in] Handle de la DLL contenant la procédure de raccordement pointée par le paramètre lpfn. Le paramètre hMod doit être défini sur NULL si le paramètre dwThreadId spécifie un thread créé par le processus en cours et si la procédure de raccordement se trouve dans le code associé au processus en cours.

  • dwThreadId

[in] Spécifie l’identificateur du thread auquel la procédure de raccordement doit être associée. Si ce paramètre est égal à zéro, la procédure de raccordement est associée à tous les threads existants s’exécutant sur le même bureau que le thread appelant.

Je ne suis pas sûr que vous puissiez utiliser une DLL .NET de la manière requirejse, mais vous pouvez certainement essayer.

hMod via Marshal.GetHINSTANCE (typeof (Form1) .Module) et dwThreadId via Process.Threads . Sinon, définissez dwThreadId sur 0 si vous souhaitez un raccordement global (c’est-à-dire un raccordement pour tous les GetMessage() du bureau actuel), mais prenez garde aux pénalités de performances.

Ce qui suit suggère que cela ne fonctionnera pas:

“Les hooks globaux ne sont pas pris en charge dans le .NET Framework. Sauf pour le hook de bas niveau WH_KEYBOARD_LL et le hook de bas niveau WH_MOUSE_LL, vous ne pouvez pas implémenter de hooks globaux dans Microsoft .NET Framework.”

De “Comment définir un hook Windows dans Visual C # .NET”

Je ne sais pas, mais si vous utilisez des valeurs de paramètre qui spécifient que vous souhaitez, comme le dit l’API, “injecter une DLL dans un autre processus”, alors, je sais que cela ne fonctionnera que si vous écrivez une DLL non gérée. à partir de laquelle l’appeler.

Je crois que vous devez utiliser P / Invoke GetModuleHandle et utiliser le GetModuleHandle qu’il renvoie pour le troisième paramètre de SetWindowsHookEx . Je crois aussi que 0 est correct pour le quasortingème paramètre, car vous ne voulez pas accrocher un fil particulier dans l’application tierce.

Si cela ne fonctionne pas pour vous, SetWindowsHookEx sur MSDN peut vous orienter dans la bonne direction.

Je sais que c’est une vieille question mais j’espère qu’il y aura encore quelqu’un qui trouvera cela utile. Je pense que vous IntPtr int et IntPtr

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

Ce travail pour moi utilise 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); } }