title: Every other window freezes after replacing mouse action - c#
body: <p>I'm writing an application that binds custom actions to my mouse buttons. For example, I connected the volume up to one of the thumb buttons. Everything works fine as long as I stay in one window because every other windows and the taskbar seems to freeze and it will take some time before the windows are activated again or if I kill my application or the window I am working in. </p>
  
  <p>In the code below I capture the mouse events and check with the settings in the application if the button action is still default or if it has changed. If the action has changed, then the application should for example turn the volume up with two.</p>
  
  <pre><code>    [DllImport("kernel32.dll")]
      public static extern IntPtr GetModuleHandle(string name);
  
      public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
  
      public static bool usingKeyboard = false;
      public static bool leftButtonDown = false;
  
      static int hMHook;
  
      public const int WH_MOUSE_LL = 14;
  
      //Declare MouseHookProcedure as a HookProc type.
      static HookProc MouseHookProcedure;
  
      private enum MouseMessages
      {
          WM_LBUTTONDOWN = 0x0201,
          WM_LBUTTONUP = 0x0202,
          WM_MOUSEMOVE = 0x0200,
          WM_MOUSEWHEEL = 0x020A,
          WM_RBUTTONDOWN = 0x0204,
          WM_RBUTTONUP = 0x0205,
          WM_XBUTTONDOWN = 0x020B,
          WM_XBUTTONUP = 0x020C,
          WM_MBUTTONUP = 0x0208,
          WM_MBUTTONDOWN = 0x0207
      }
  
      [StructLayout(LayoutKind.Sequential)]
      public class POINT
      {
          public int x;
          public int y;
      }
  
      [StructLayout(LayoutKind.Sequential)]
      public class MouseHookStruct
      {
          public POINT pt;
          public int hwnd;
          public int wHitTestCode;
          public int dwExtraInfo;
      }
  
      [DllImport("kernel32.dll")]
      static extern uint GetLastError();
  
      [DllImport("user32.dll", CharSet = CharSet.Auto,
       CallingConvention = CallingConvention.StdCall)]
      public static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
      IntPtr hInstance, int threadId);
  
      [DllImport("user32.dll", CharSet = CharSet.Auto,
       CallingConvention = CallingConvention.StdCall)]
      public static extern bool UnhookWindowsHookEx(int idHook);
  
      [DllImport("user32.dll", CharSet = CharSet.Auto,
       CallingConvention = CallingConvention.StdCall)]
      public static extern int CallNextHookEx(int idHook, int nCode,
      IntPtr wParam, IntPtr lParam);
  
      private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
      {
          MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
  
          MouseUsageMessage message = new MouseUsageMessage(1);
          MouseUsageManager.mouseUsageMessageQueue.Add(message);
          if (nCode &gt;= 0)
          {
              if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
              {
                  leftButtonDown = true;
              } else if (MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam)
              {
                  leftButtonDown = false;                   
              } else if (MouseMessages.WM_RBUTTONDOWN == (MouseMessages)wParam)
              {
  
              } else if (MouseMessages.WM_RBUTTONUP == (MouseMessages) wParam) {
  
              } else if (MouseMessages.WM_XBUTTONUP == (MouseMessages)wParam)
              {
                  switch (MyMouseHookStruct.hwnd)
                  {
                      case 65536:
                          if (Settings.Default.thumbClick1User != Settings.Default.thumbClick1Default)
                          {
                              ExecuteAction(Settings.Default.thumbClick1User);
                              return 1;
                          }
                          break;
                      case 131072:
                          if (Settings.Default.thumbClick2User != Settings.Default.thumbClick2Default)
                          {
                              ExecuteAction(Settings.Default.thumbClick2User);
                              return 1;
                          }
                          break;
                  }
              } else if (MouseMessages.WM_MBUTTONDOWN == (MouseMessages)wParam)
              {
  
              }
          }
          return CallNextHookEx(hMHook, nCode, wParam, lParam);
      }
  </code></pre>
  
  <p>Why are the other windows freezing or why can't I use my mouse on the other windows after I've clicked the thumb buttons?</p>
  
  <p>EDIT: Additional code</p>
  
  <pre><code>private void ExecuteAction(string setting)
      {
          VolumeControl vc = new VolumeControl();
          Keybindings kb = new Keybindings();
          switch (setting)
          {
              case "volUp":
                  vc.VolUp();
                  break;
              case "volDown":
                  vc.VolDown();
                  break;
              case "cut":
                  kb.Cut();
                  break;
              case "selectAll":
                  kb.SelectAll();
                  break;
              case "copy":
                  kb.Copy();
                  break;
              default:
                  break;
          }
      }
  </code></pre>
  
  <p>The setting string that is sended to the ExecuteAction function is just a string with the action to be performed, i.e. copy, volume up, volume down etc.</p>
  
  <p>VolumeControl class:</p>
  
  <pre><code>public class VolumeControl
  {
      private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
      private const int APPCOMMAND_VOLUME_UP = 0xA0000;
      private const int APPCOMMAND_VOLUME_DOWN = 0x90000;
      private const int WM_APPCOMMAND = 0x319;
  
      IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
  
      [DllImport("user32.dll")]
      public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg,
          IntPtr wParam, IntPtr lParam);
  
  
      public void VolDown()
      {
          SendMessageW(handle, WM_APPCOMMAND, handle,
              (IntPtr)APPCOMMAND_VOLUME_DOWN);
      }
  
      public void VolUp()
      {
          SendMessageW(handle, WM_APPCOMMAND, handle,
              (IntPtr)APPCOMMAND_VOLUME_UP);
      }
  }
  </code></pre>
  
  <p>Create Hook function, the function that is called when the class is initialized:</p>
  
  <pre><code>    private void createHook()
      {
          while (hMHook == 0) //|| hKHook == 0)
          {
  
              //if (hMHook == 0)
              //{
                  //hMHook = SetWindowsHookEx(WH_MOUSE_LL,
                              //MouseHookProcedure,
                              //GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName),
                              //(IntPtr)0,
                              //0);
              //}
  
              if (hMHook == 0)
              {
                  hMHook = SetWindowsHookEx(WH_MOUSE_LL,
                          MouseHookProcedure,
                          GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName),
                          0);
              }
  
              if (hMHook == 0) //|| hKHook == 0)
              {
                  Console.WriteLine("SetWindowsHookEx Failed");
                  return;
              }
              Console.WriteLine("Hooked");
          }
      }
  </code></pre>