LoginSignup
5
2

More than 3 years have passed since last update.

[C#]WPFでヘッダー右クリック時のメニューを変更する

Posted at

右クリック時のメニュー(コンテキストメニュー)

image.png

こういうメニューのことをコンテキストメニューと言います。

今回は自作アプリのヘッダー部を右クリックしたときのメニューを変更する方法を記載します。

上記画面のメニューに追加するパターンと完全に自作のメニューを表示するパターンの2つを作ります。

  • パターン1
    image.png

  • パターン2
    image.png

こういう感じになります。

既存のコンテキストメニューに要素を追記する方法

Win32APIを使います。
まずはWin32API使えるようにし、使用する関数を宣言します。

        [DllImport("user32.dll")]
        private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
        [DllImport("user32.dll")]
        private static extern bool InsertMenu(IntPtr hMenu, Int32 wPosition, Int32 wFlags, Int32 wIDNewItem,
                string lpNewItem);

次に使用する定数を宣言します。

        private readonly Int32 MF_BYPOSITION = 0x400;
        private readonly Int32 MF_SEPARATOR = 0x800;
        private const Int32 ITEMONEID = 1000;
        private const Int32 ITEMTWOID = 1001;

        private readonly Int32 WM_SYSCOMMAND = 0x112;

ロード時に処理を書きます。

        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            IntPtr windowhandle = new WindowInteropHelper(this).Handle;
            HwndSource hwndSource = HwndSource.FromHwnd(windowhandle);
            IntPtr systemMenuHandle = GetSystemMenu(windowhandle, false);
            InsertMenu(systemMenuHandle,5, MF_BYPOSITION| MF_SEPARATOR, 0, string.Empty);
            InsertMenu(systemMenuHandle,6, MF_BYPOSITION, ITEMONEID, "Item 1");
            InsertMenu(systemMenuHandle,7, MF_BYPOSITION, ITEMTWOID, "Item 2");

            hwndSource.AddHook(new HwndSourceHook(WndProc));
        }

        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
        {
            if(msg == WM_SYSCOMMAND)
            {
                switch(wparam.ToInt32())
                {
                    case ITEMONEID:
                    {
                        MessageBox.Show("Item 1 was clicked");
                        handled = true;
                        break;
                    }
                    case ITEMTWOID:
                    {
                        MessageBox.Show("Item 2 was clicked");
                        handled = true;
                        break;
                    }
                }
            }

            return IntPtr.Zero;
        }

自作のコンテキストメニューを表示する方法

xaml側にリソースを定義します。
とりあえず、Item1の時だけ実装。

    <Window.Resources>
        <ContextMenu x:Key="contextMenu" >
            <MenuItem Header="Item 1" Click="MenuItem_OnClick"></MenuItem>
            <MenuItem Header="Item 2"></MenuItem>
            <MenuItem Header="Item 3"></MenuItem>
        </ContextMenu>
    </Window.Resources>

コードビハインド側

        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }
        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            IntPtr windowhandle = new WindowInteropHelper(this).Handle;
            HwndSource hwndSource = HwndSource.FromHwnd(windowhandle);

            hwndSource.AddHook(new HwndSourceHook(WndProc));
        }
        private void MenuItem_OnClick(object sender, RoutedEventArgs e)
        {
            var item = sender as MenuItem;
            MessageBox.Show(item.Header.ToString());
        }
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
        {
            if(msg == 0xa4)
            {
                ShowContextMenu();
                handled = true;
            }
            return IntPtr.Zero;
        }

        private void ShowContextMenu()
        {
            var contextMenu = Resources["contextMenu"] as ContextMenu;
            contextMenu.IsOpen = true;
        }

ソースコード

https://github.com/KoMMet/WpfContext

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2