右クリック時のメニュー(コンテキストメニュー)
こういうメニューのことをコンテキストメニューと言います。
今回は自作アプリのヘッダー部を右クリックしたときのメニューを変更する方法を記載します。
上記画面のメニューに追加するパターンと完全に自作のメニューを表示するパターンの2つを作ります。
こういう感じになります。
既存のコンテキストメニューに要素を追記する方法
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;
}