/// <summary> /// Checks if a given <see cref="PopupActivationMode"/> is a match for /// an effectively pressed mouse button. /// </summary> public static bool IsMatch(this MouseEvent me, PopupActivationMode activationMode) { switch (activationMode) { case PopupActivationMode.LeftClick: return(me == MouseEvent.IconLeftMouseUp); case PopupActivationMode.RightClick: return(me == MouseEvent.IconRightMouseUp); case PopupActivationMode.LeftOrRightClick: return(me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconRightMouseUp)); case PopupActivationMode.LeftOrDoubleClick: return(me.Is(MouseEvent.IconLeftMouseUp, MouseEvent.IconDoubleClick)); case PopupActivationMode.DoubleClick: return(me.Is(MouseEvent.IconDoubleClick)); case PopupActivationMode.MiddleClick: return(me == MouseEvent.IconMiddleMouseUp); case PopupActivationMode.All: //return true for everything except mouse movements return(me != MouseEvent.MouseMove); default: throw new ArgumentOutOfRangeException("activationMode"); } }
/// <summary> /// Processes mouse events, which are bubbled /// through the class' routed events, trigger /// certain actions (e.g. show a popup), or /// both. /// </summary> /// <param name="me">Event flag.</param> private void OnMouseEvent(MouseEvent me) { if (IsDisposed) { return; } switch (me) { case MouseEvent.MouseMove: RaiseTrayMouseMoveEvent(); // immediately return - there's nothing left to evaluate return; case MouseEvent.IconRightMouseDown: RaiseTrayRightMouseDownEvent(); break; case MouseEvent.IconLeftMouseDown: RaiseTrayLeftMouseDownEvent(); break; case MouseEvent.IconRightMouseUp: RaiseTrayRightMouseUpEvent(); break; case MouseEvent.IconLeftMouseUp: RaiseTrayLeftMouseUpEvent(); break; case MouseEvent.IconMiddleMouseDown: RaiseTrayMiddleMouseDownEvent(); break; case MouseEvent.IconMiddleMouseUp: RaiseTrayMiddleMouseUpEvent(); break; case MouseEvent.IconDoubleClick: // cancel single click timer singleClickTimer.Change(Timeout.Infinite, Timeout.Infinite); // bubble event RaiseTrayMouseDoubleClickEvent(); break; case MouseEvent.BalloonToolTipClicked: RaiseTrayBalloonTipClickedEvent(); break; default: throw new ArgumentOutOfRangeException(nameof(me), "Missing handler for mouse event flag: " + me); } // get mouse coordinates Point cursorPosition = new Point(); if (messageSink.Version == NotifyIconVersion.Vista) { // physical cursor position is supported for Vista and above WinApi.GetPhysicalCursorPos(ref cursorPosition); } else { WinApi.GetCursorPos(ref cursorPosition); } cursorPosition = TrayInfo.GetDeviceCoordinates(cursorPosition); bool isLeftClickCommandInvoked = false; // show popup, if requested if (me.IsMatch(PopupActivation)) { if (me == MouseEvent.IconLeftMouseUp) { // show popup once we are sure it's not a double click singleClickTimerAction = () => { LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); ShowTrayPopup(cursorPosition); }; singleClickTimer.Change(DoubleClickWaitTime, Timeout.Infinite); isLeftClickCommandInvoked = true; } else { // show popup immediately ShowTrayPopup(cursorPosition); } } // show context menu, if requested if (me.IsMatch(MenuActivation)) { if (me == MouseEvent.IconLeftMouseUp) { // show context menu once we are sure it's not a double click singleClickTimerAction = () => { LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); ShowContextMenu(cursorPosition); }; singleClickTimer.Change(DoubleClickWaitTime, Timeout.Infinite); isLeftClickCommandInvoked = true; } else { // show context menu immediately ShowContextMenu(cursorPosition); } } // make sure the left click command is invoked on mouse clicks if (me == MouseEvent.IconLeftMouseUp && !isLeftClickCommandInvoked) { // show context menu once we are sure it's not a double click singleClickTimerAction = () => { LeftClickCommand.ExecuteIfEnabled(LeftClickCommandParameter, LeftClickCommandTarget ?? this); }; singleClickTimer.Change(DoubleClickWaitTime, Timeout.Infinite); } }