WPF/개발

WPF Title Bar Custom ContextMenu 생성하는 방법

푸코잇 2024. 9. 2. 14:58

WPF Title Bar(타이틀바)에서 마우스 우클릭하면 기본 ContextMenu(컨텍스트 메뉴)가 표시된다.

기본이 아닌 Custom ContextMenu를 생성하는 방법에 대해 배워보자.

 

Behavior 생성

1. Microsoft.Xaml.Behaviors.Wpf Nuget 패키지 설치

Nuget-Behaviors

 

2. Window Behavior 생성하기

public class ContextMenuBehavior : Behavior<Window>
    {
        private const uint WM_NCRBUTTONDOWN = 0xa4;
        private const uint HTCAPTION = 0x02;
        private Window window;

        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.Loaded += OnLoaded;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.Loaded -= OnLoaded;
        }
        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            // WPF 윈도우에 Win32 메시지 훅 설정
            window = sender as Window;
            IntPtr windowhandle = new WindowInteropHelper(window).Handle;
            HwndSource hwndSource = HwndSource.FromHwnd(windowhandle);
            hwndSource.AddHook(new HwndSourceHook(WndProc));
        }

        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            // 비클라이언트 영역에서 마우스 우클릭하고
            // 마우스 포인터가 TitleBar에 위치하고 있다면
            if ((msg == WM_NCRBUTTONDOWN) && (wParam.ToInt32() == HTCAPTION))
            {
                ShowContextMenu();

                // 기본 컨텍스트 메뉴 표시하지 않도록 설정
                handled = true;
            }

            return IntPtr.Zero;
        }

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

 

Window가 로드될때 메시지 훅을 설정하여 윈도우 타이틀바에서 마우스 우클릭했을 때 Custom ContextMenu가 표시되도록 설정한 것이다.

 

Custom ContextMenu 생성

1. MainWindow.xaml

<Window x:Class="TitleBarContextMenu.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TitleBarContextMenu"
        mc:Ignorable="d"
        Title="TitleBar ContextMenu" Height="180" Width="280">

    <!--Behavior 설정-->
    <b:Interaction.Behaviors>
        <local:ContextMenuBehavior/>
    </b:Interaction.Behaviors>

    <Window.Resources>
        <!--Custom ContextMenu-->
        <ContextMenu x:Key="contextMenu">
            <MenuItem Header="Item1"/>
            <MenuItem Header="Item2"/>
            <MenuItem Header="Item3"/>
        </ContextMenu>
    </Window.Resources>

    <Grid>
        <TextBlock Text="클라이언트영역"
                   FontSize="30"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"/>
    </Grid>
</Window>

ContextMenu를 리소스로 생성한다.

이때 Key값이 일치해야하므로 주의하자.

 

WPF-TitleBar-ContextMenu

 

Window TitleBar에서 마우스 우클릭하면 Custom ContextMenu가 표시된다.