Ejemplo n.º 1
0
        /// <summary>
        /// Displays the <see cref="TrayPopup"/> control if
        /// it was set.
        /// </summary>
        private void ShowTrayPopup(Point cursorPosition)
        {
            if (IsDisposed)
            {
                return;
            }

            //raise preview event no matter whether popup is currently set
            //or not (enables client to set it on demand)
            var args = RaisePreviewTrayPopupOpenEvent();

            if (args.Handled)
            {
                return;
            }

            if (TrayPopup != null)
            {
                //use absolute position, but place the popup centered above the icon
                TrayPopupResolved.Placement        = PlacementMode.AbsolutePoint;
                TrayPopupResolved.HorizontalOffset = cursorPosition.X;
                TrayPopupResolved.VerticalOffset   = cursorPosition.Y;

                //open popup
                TrayPopupResolved.IsOpen = true;

                var handle = IntPtr.Zero;
                if (TrayPopupResolved.Child != null)
                {
                    //try to get a handle on the popup itself (via its child)
                    var source = (HwndSource)PresentationSource.FromVisual(TrayPopupResolved.Child);
                    if (source != null)
                    {
                        handle = source.Handle;
                    }
                }

                //if we don't have a handle for the popup, fall back to the message sink
                if (handle == IntPtr.Zero)
                {
                    handle = messageSink.MessageWindowHandle;
                }

                //activate either popup or message sink to track deactivation.
                //otherwise, the popup does not close if the user clicks somewhere else
                WinApi.SetForegroundWindow(handle);

                //raise attached event - item should never be null unless developers
                //changed the CustomPopup directly...
                if (TrayPopup != null)
                {
                    RaisePopupOpenedEvent(TrayPopup);
                }

                //bubble routed event
                RaiseTrayPopupOpenEvent();
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Displays the <see cref="ContextMenu"/> if
        /// it was set.
        /// </summary>
        private void ShowContextMenu(Point cursorPosition)
        {
            if (IsDisposed)
            {
                return;
            }

            //raise preview event no matter whether context menu is currently set
            //or not (enables client to set it on demand)
            var args = RaisePreviewTrayContextMenuOpenEvent();

            if (args.Handled)
            {
                return;
            }

            if (ContextMenu != null)
            {
                //use absolute positioning. We need to set the coordinates, or a delayed opening
                //(e.g. when left-clicked) opens the context menu at the wrong place if the mouse
                //is moved!
                ContextMenu.Placement        = PlacementMode.AbsolutePoint;
                ContextMenu.HorizontalOffset = cursorPosition.X;
                ContextMenu.VerticalOffset   = cursorPosition.Y;
                ContextMenu.IsOpen           = true;

                var handle = IntPtr.Zero;

                //try to get a handle on the context itself
                var source = (HwndSource)PresentationSource.FromVisual(ContextMenu);
                if (source != null)
                {
                    handle = source.Handle;
                }

                //if we don't have a handle for the popup, fall back to the message sink
                if (handle == IntPtr.Zero)
                {
                    handle = messageSink.MessageWindowHandle;
                }

                //activate the context menu or the message window to track deactivation - otherwise, the context menu
                //does not close if the user clicks somewhere else. With the message window
                //fallback, the context menu can't receive keyboard events - should not happen though
                WinApi.SetForegroundWindow(handle);

                //bubble event
                RaiseTrayContextMenuOpenEvent();
            }
        }
Ejemplo n.º 3
0
        /// <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("me", "Missing handler for mouse event flag: " + me);
            }


            //get mouse coordinates
            var 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);

            var 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);
            }
        }