title: Global mouse event handler
body: <p>I have the following code which I got from somewhere to capture mouse events. I modified it and made an event handler so that I can subscribe to it. The mouse events are captured correctly.  But it never fires the event-handler. Can anybody figure out whats wrong with the code?</p>
  <pre><code>public static class MouseHook
  {
      public static event EventHandler MouseAction = delegate { };
  
      public static void Start() =&gt; _hookID = SetHook(_proc);
      public static void stop() =&gt; UnhookWindowsHookEx(_hookID);
  
      private static LowLevelMouseProc _proc = HookCallback;
      private static IntPtr _hookID = IntPtr.Zero;
  
      private static IntPtr SetHook(LowLevelMouseProc proc)
      {
          using (Process curProcess = Process.GetCurrentProcess())
          using (ProcessModule curModule = curProcess.MainModule)
          {
              return SetWindowsHookEx(WH_MOUSE_LL, proc,
                GetModuleHandle(curModule.ModuleName), 0);
          }
      }
  
      private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
  
      private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
      {
          if (nCode &gt;= 0 &amp;&amp; MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
          {
             MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));  
             MouseAction(null,new EventArgs());
          }
          return CallNextHookEx(_hookID, nCode, wParam, lParam);
      }
  
      private const int WH_MOUSE_LL = 14;
  
      private enum MouseMessages
      {
          WM_LBUTTONDOWN = 0x0201,
          WM_LBUTTONUP   = 0x0202,
          WM_MOUSEMOVE   = 0x0200,
          WM_MOUSEWHEEL  = 0x020A,
          WM_RBUTTONDOWN = 0x0204,
          WM_RBUTTONUP   = 0x0205
      }
  
      [StructLayout(LayoutKind.Sequential)]
      private struct POINT
      {
          public int x;
          public int y;
      }
  
      [StructLayout(LayoutKind.Sequential)]
      private struct MSLLHOOKSTRUCT
      {
          public POINT pt;
          public uint mouseData, flags, time;
          public IntPtr dwExtraInfo;
      }
  
      [DllImport(&quot;user32.dll&quot;, CharSet = CharSet.Auto, SetLastError = true)]
      private static extern IntPtr SetWindowsHookEx(int idHook,
        LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
  
      [DllImport(&quot;user32.dll&quot;, CharSet = CharSet.Auto, SetLastError = true)]
      [return: MarshalAs(UnmanagedType.Bool)]
      private static extern bool UnhookWindowsHookEx(IntPtr hhk);
  
      [DllImport(&quot;user32.dll&quot;, CharSet = CharSet.Auto, SetLastError = true)]
      private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
        IntPtr wParam, IntPtr lParam);
  
      [DllImport(&quot;kernel32.dll&quot;, CharSet = CharSet.Auto, SetLastError = true)]
      private static extern IntPtr GetModuleHandle(string lpModuleName);
  }
  </code></pre>
  <p>I subscribe to it like this.</p>
  <pre><code>MouseHook.Start();  
  MouseHook.MouseAction += new EventHandler(Event);
  </code></pre>
  <p>Function receiving the event.</p>
  <pre><code>private void Event(object sender, EventArgs e) =&gt; Console.WriteLine(&quot;Left mouse click!&quot;); 
  </code></pre>
  <p><strong>Update:</strong>
  I put together the working code in to a <a href="https://github.com/titanium007/Windows-User-Action-Hook" rel="noreferrer">open source nuget package for user action hooks.</a></p>