Home > other >  How to disappear ContextMenu when user click outside ContextMenu for Tray Icon in WPF .net
How to disappear ContextMenu when user click outside ContextMenu for Tray Icon in WPF .net

Time:01-25

I am working on a .NET WPF project using Visual Studio 2022 and I added tray icon functionality to my app. Everything works fine except when tray icon is right clicked context menu opened but when user clicks outside ContextMenu it does not disappear. I tried to add "StaysOpen" property to false but it did not work. What should I do to solve this? here is my code:

public partial class MainWindow : Window
{
        public NotifyIcon m_notifyIcon;

        public MainWindow()
        {
            InitializeComponent();
            m_notifyIcon = new System.Windows.Forms.NotifyIcon();
            m_notifyIcon.BalloonTipText = "The app has been minimised. Click the tray icon to show.";
            m_notifyIcon.BalloonTipTitle = "The App";
            m_notifyIcon.Text = "The App";
            m_notifyIcon.Icon = new System.Drawing.Icon("48x48_active.ico");
            m_notifyIcon.DoubleClick  = new EventHandler(m_notifyIcon_Click);
            m_notifyIcon.MouseDown  = new MouseEventHandler(notifier_MouseDown);

            Hide();
            if (m_notifyIcon != null)
                m_notifyIcon.ShowBalloonTip(2000);

            CheckTrayIcon();
        }
        void OnClose(object sender, CancelEventArgs args)
        {
            m_notifyIcon.Dispose();
            m_notifyIcon = null;
        }

        private WindowState m_storedWindowState = WindowState.Normal;

        void OnStateChanged(object sender, EventArgs args)
        {
            if (WindowState == WindowState.Minimized)
            {
                Hide();
                if (m_notifyIcon != null)
                    m_notifyIcon.ShowBalloonTip(2000);
            }
            else
                m_storedWindowState = WindowState;
        }

        void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs args)
        {
            CheckTrayIcon();
        }

        void m_notifyIcon_Click(object sender, EventArgs e)
        {
            Show();
            WindowState = m_storedWindowState;
        }

        void CheckTrayIcon()
        {
            ShowTrayIcon(true);
        }

        void ShowTrayIcon(bool show)
        {
            if (m_notifyIcon != null)
                m_notifyIcon.Visible = show;
        }

        void notifier_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)

            {
                ContextMenu menu = (ContextMenu)this.FindResource("NotifierContextMenu");

                menu.IsOpen = true;
            }
        }

        private void Menu_Open(object sender, RoutedEventArgs e)
        {
            Show();
            WindowState = m_storedWindowState;
        }

        private void Menu_Close(object sender, RoutedEventArgs e)
        {
            System.Windows.Application.Current.Shutdown();
        }
    }

<Window x:Class="TrayApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TrayApp"
        mc:Ignorable="d"
        StateChanged="OnStateChanged" IsVisibleChanged="OnIsVisibleChanged"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>

        <ContextMenu Focusable="{Binding FocusMenu}" x:Key="NotifierContextMenu"

                StaysOpen="False"    Placement="MousePoint" >

            <MenuItem  Header="Open" Click="Menu_Open"/>

            <MenuItem  Header="Close" Click="Menu_Close"/>
        </ContextMenu>

    </Window.Resources>
    <Grid>
    </Grid>
</Window>

CodePudding user response:

What should I do to solve this?

Activate the ContextMenu using the Win32 SetForegroundWindow API:

[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

void notifier_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        ContextMenu menu = (ContextMenu)this.FindResource("NotifierContextMenu");
        menu.IsOpen = true;

        IntPtr handle = ((HwndSource)PresentationSource.FromVisual(menu)).Handle;
        SetForegroundWindow(handle);
    }
}
  • Related