private User32.MOUSEEVENTF MakeGestureBtnEvent(GestureTriggerButton btn, bool isUp, out uint data) { data = 0; switch (btn) { case GestureTriggerButton.Right: var isMouseSwapped = Native.IsMouseButtonSwapped(); if (!isMouseSwapped) { return(isUp ? User32.MOUSEEVENTF.MOUSEEVENTF_RIGHTUP : User32.MOUSEEVENTF.MOUSEEVENTF_RIGHTDOWN); } else { return(isUp ? User32.MOUSEEVENTF.MOUSEEVENTF_LEFTUP : User32.MOUSEEVENTF.MOUSEEVENTF_LEFTDOWN); } case GestureTriggerButton.Middle: return(isUp ? User32.MOUSEEVENTF.MOUSEEVENTF_MIDDLEUP : User32.MOUSEEVENTF.MOUSEEVENTF_MIDDLEDOWN); case GestureTriggerButton.X1: data = 1; return(isUp ? User32.MOUSEEVENTF.MOUSEEVENTF_XUP : User32.MOUSEEVENTF.MOUSEEVENTF_XDOWN); case GestureTriggerButton.X2: data = 2; return(isUp ? User32.MOUSEEVENTF.MOUSEEVENTF_XUP : User32.MOUSEEVENTF.MOUSEEVENTF_XDOWN); default: Debug.Assert(false, "WTF"); return(User32.MOUSEEVENTF.MOUSEEVENTF_ABSOLUTE); } }
public static string ToMnemonic(this GestureTriggerButton gestureBtn) { switch (gestureBtn) { case GestureTriggerButton.Middle: return("●"); case GestureTriggerButton.Right: return("◑"); case GestureTriggerButton.X1: return("X1"); case GestureTriggerButton.X2: return("X2"); default: return(string.Empty); } }
//NOTE: hook procs run in a separate thread. private void MouseHookProc(MouseKeyboardHook.MouseHookEventArgs e) { //处理 左键 + 中键 用于 暂停继续的情形 if (HandleSpecialButtonCombination(e)) { return; } if (_isPaused) { return; } var mouseData = (Native.MSLLHOOKSTRUCT)Marshal.PtrToStructure(e.lParam, typeof(Native.MSLLHOOKSTRUCT)); //fixme: 判断是否在模拟事件, 为什么不一定可靠? if (_simulatingInput || mouseData.dwExtraInfo.ToInt64() == SIMULATED_EVENT_TAG) { Debug.WriteLine("Simulated:" + e.Msg); if (InitialStayTimeout && _isInitialTimeout) { Debug.WriteLine("_captured=false"); _captured = false; } return; } var prevPos = _curPos; _curPos = new Point(e.X, e.Y); var m = e.Msg; switch (m) { //必须在这里立即决定是否应该捕获 case MouseMsg.WM_RBUTTONDOWN: case MouseMsg.WM_MBUTTONDOWN: case MouseMsg.WM_XBUTTONDOWN: if (!_captured) { if (m == MouseMsg.WM_MBUTTONDOWN && (TriggerButton & GestureTriggerButton.Middle) == 0 || m == MouseMsg.WM_RBUTTONDOWN && (TriggerButton & GestureTriggerButton.Right) == 0 || m == MouseMsg.WM_XBUTTONDOWN && (TriggerButton & GestureTriggerButton.X) == 0) { return; } try { //notice: 这个方法在钩子线程中运行,因此必须足够快,而且不能失败 _captured = OnBeforePathStart(); } catch (Exception ex) { #if DEBUG throw; #endif //如果出错,则不捕获手势 _captured = false; } if (_captured) { //_gestureBtn = (m == MouseMsg.WM_RBUTTONDOWN ? GestureButtons.RightButton : GestureButtons.MiddleButton); switch (m) //TODO: extract function { case MouseMsg.WM_RBUTTONDOWN: _gestureBtn = GestureTriggerButton.Right; break; case MouseMsg.WM_MBUTTONDOWN: _gestureBtn = GestureTriggerButton.Middle; break; case MouseMsg.WM_XBUTTONDOWN: var x = (XButtonNumber)(mouseData.mouseData >> 16); //which X Button _gestureBtn = x == XButtonNumber.One ? GestureTriggerButton.X1 : GestureTriggerButton.X2; break; default: Debug.Assert(false, "WTF! shouldn't happen"); break; } _modifierEventHappendPrevTime = new DateTime(0); e.Handled = true; Post(WM.GESTBTN_DOWN); } } else //另一个键作为手势键的时候,作为修饰键 { GestureModifier gestMod; // = m == MouseMsg.WM_RBUTTONDOWN ? GestureModifier.RightButtonDown : GestureModifier.MiddleButtonDown; switch (m) //TODO: extract function { case MouseMsg.WM_RBUTTONDOWN: gestMod = GestureModifier.RightButtonDown; break; case MouseMsg.WM_MBUTTONDOWN: gestMod = GestureModifier.MiddleButtonDown; break; case MouseMsg.WM_XBUTTONDOWN: var x = (XButtonNumber)(mouseData.mouseData >> 16); //which X Button gestMod = x == XButtonNumber.One ? GestureModifier.X1 : GestureModifier.X2; break; default: gestMod = GestureModifier.LeftButtonDown; break; } e.Handled = HandleModifier(gestMod); } break; case MouseMsg.WM_MOUSEMOVE: if (_captured) { //永远不拦截move消息,所以不设置e.Handled = true Post(WM.GESTBTN_MOVE); } else { if (_isVirtualGesturing) { //忽略禁用列表 OnBeforePathStart(); _captured = true; _gestureBtn = GestureTriggerButton.Right; Post(WM.GESTBTN_DOWN, 1); } //未捕获的情况下才允许hotcorner HotCornerHitTest(); } break; case MouseMsg.WM_MOUSEWHEEL: if (_captured) { //获得滚动方向 int delta = (short)(mouseData.mouseData >> 16); var gestMod = delta > 0 ? GestureModifier.WheelForward : GestureModifier.WheelBackward; e.Handled = HandleModifier(gestMod); } else if (DateTime.UtcNow - _modifierEventHappendPrevTime < TimeSpan.FromMilliseconds(300)) //延迟一下,因为 中键手势 + 滚动,可能导致快捷键还没结束,而滚轮事件发送到了目标窗口,可鞥解释成其他功能(比如ctrl + 滚轮 = 缩放) { e.Handled = true; } break; case MouseMsg.WM_LBUTTONDOWN: if (_captured) { e.Handled = HandleModifier(GestureModifier.LeftButtonDown); } break; case MouseMsg.WM_RBUTTONUP: case MouseMsg.WM_MBUTTONUP: case MouseMsg.WM_XBUTTONUP: if (_captured) { var gestBtn_as_MouseMsg = (MouseMsg)(-1); switch (_gestureBtn) { case GestureTriggerButton.Middle: gestBtn_as_MouseMsg = MouseMsg.WM_MBUTTONUP; break; case GestureTriggerButton.Right: gestBtn_as_MouseMsg = MouseMsg.WM_RBUTTONUP; break; case GestureTriggerButton.X1: case GestureTriggerButton.X2: gestBtn_as_MouseMsg = MouseMsg.WM_XBUTTONUP; break; } //是手势键up if (m == gestBtn_as_MouseMsg) { _captured = false; Post(WM.GESTBTN_UP); } e.Handled = true; } break; default: //其他消息不处理 break; } }
public Gesture(GestureTriggerButton gestureBtn = GestureTriggerButton.Right, int defaultCapacity = 16) { GestureButton = gestureBtn; Dirs = new List <GestureDir>(defaultCapacity); Modifier = GestureModifier.None; }