/// <summary>
 ///     新しいインスタンスを作成する。
 /// </summary>
 /// ec
 /// <param name="message">マウス操作の種類を表すMouseMessage値の一つ。</param>
 /// <param name="button"></param>
 /// <param name="isDoubleClick"></param>
 /// <param name="isDesktop"></param>
 /// <param name="state">マウスの状態を表すMouseState構造体。</param>
 internal GlobalMouseHookedEventArgs(MouseMessage message, MouseButtons button, bool isDoubleClick,
     bool isDesktop, ref MouseState state)
 {
     Message = message;
     this.state = state;
     MouseButton = button;
     IsDoubleClick = isDoubleClick;
     IsDesktop = isDesktop;
 }
 /// <summary>
 ///     ダブルクリック判定
 /// </summary>
 /// <param name="button"></param>
 /// <param name="state"></param>
 /// <returns></returns>
 internal bool IsDoubleClick(MouseButtons button, MouseState state)
 {
     // perform check
     var isDblClk = ((button == _button) && (InDoubleClickTime(state.Time)) && (InDoubleClickBounds(state.Point)));
     // update history
     _button = button;
     _time = state.Time;
     _position = state.Point;
     // return result
     return isDblClk;
 }
        /// <summary>
        ///     デスクトップ判定
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        private bool IsDesktop(MouseState state)
        {
            var point = state.Point;
            var hwnd = WindowFromPoint(point.X, point.Y);

            var sb = new StringBuilder(65535);
            GetWindowText(GetForegroundWindow(), sb, 65535);
            var desktopWindowText = sb.ToString().Trim();

            return hwnd == GetDesktopWindow()
                && IsHitTestNoIcon(hwnd, point.X, point.Y)
                && (desktopWindowText == "" || desktopWindowText == "Program Manager"); // ホントにデスクトップかどうか(WindowFromPointは間違えたハンドルを返す場合があるので。semi transparent windowだと間違える?デスクトップのウインドウ名は空もしくはProgram Managerであるのでそれで判定)
        }
        private int CallNextHook(int code, MouseMessage message, ref MouseState state)
        {
            if (code >= 0)
            {
                var button = MouseButtons.None;
                switch (message)
                {
                    case MouseMessage.LDown:
                        //case MouseMessage.LUp:
                        button = MouseButtons.Left;
                        break;
                    case MouseMessage.RDown:
                        //case MouseMessage.RUp:
                        button = MouseButtons.Right;
                        break;
                    case MouseMessage.MDown:
                        //case MouseMessage.MUp:
                        button = MouseButtons.Middle;
                        break;
                    case MouseMessage.XDown:
                        //case MouseMessage.XUp:
                        if (state.XButtonData.IsXButton1) button = MouseButtons.XButton1;
                        if (state.XButtonData.IsXButton2) button = MouseButtons.XButton2;
                        break;
                    default:
                        button = MouseButtons.None;
                        break;
                }

                if ((_captureMouseButtons.Length == 0 || _captureMouseButtons.Contains(_button)) &&
                    button != MouseButtons.None)
                {
                    var e = new GlobalMouseHookedEventArgs(
                        message,
                        button,
                        IsDoubleClick(button, state),
                        IsDesktop(state),
                        ref state);
                    OnMouseHooked(e);
                    if (e.Cancel)
                        return -1;
                }
            }
            return CallNextHookEx(_hook, code, message, ref state);
        }
 private static extern int CallNextHookEx(IntPtr hook, int code, MouseMessage message, ref MouseState state);