title: SetWindowsHookEx in C#
body: <p>I'm trying to hook a 3rd party app so that I can draw to its screen. Drawing to the screen is easy, and I need no help with it, but I seem to be having issues with using <code>SetWindowsHookEx</code> to handle <code>WH_GETMESSAGE</code>. I can't figure out what to pass for the last two parameters.</p>
  
  <pre><code>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;
      }
  }
  </code></pre>