C#/WPF

WPF System Menu 불러오기

기공이 2018. 4. 26. 11:30

윈도우의 상단 Title Bar를 우클릭 하면 아래와 같은 시스템 메뉴가 나오게 됩니다.



시스템 메뉴를 굳이 위 상단 Title Bar 클릭이 아닌 다른 이유로 불러야 할 때가 있습니다. (Custom Title Bar 등...)


WPF 특정 Control을 우클릭 했을 떄 시스템 메뉴를 여는 법에 대해 써보겠습니다.



우선 MouseDown Event Handler가 필요합니다. 저는 Label을 눌렀을 때 뜨도록 하겠습니다.


1
<Label PreviewMouseDown="System_MouseDown">
cs


PreviewMouseDown 과 MouseDown의 차이는 없습니다.



그리고 DLL파일을 Import하야 하기 때문에 using을 씁니다.


using System.Runtime.InteropServices;


다음 내용이 필요합니다. 


1
2
3
4
5
6
7
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
[DllImport("user32.dll")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
static extern int TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y, 
                                int nReserved, IntPtr hWnd, IntPtr prcRect);
cs



다음은 Event Handler 입니다.


1
2
3
4
5
6
7
8
9
10
11
private void System_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.ChangedButton == MouseButton.Right)
    {
        var pos = PointToScreen(e.GetPosition(this));
        IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
        IntPtr hMenu = GetSystemMenu(hWnd, false);
        int cmd = TrackPopupMenu(hMenu, 0x100, (int)pos.X, (int)pos.Y, 0, hWnd, IntPtr.Zero);
        if (cmd > 0) SendMessage(hWnd, 0x112, (IntPtr)cmd, IntPtr.Zero);
    }
}
cs


3 : 우클릭을 했을 때

5 : Argument e를 통해 현재 마우스의 위치를 찾아내고

8 : 그 곳에 시스템 메뉴가 뜨게 합니다.

9 : 결과를 Window에 Message로 보냅니다.


시스템 메뉴를 불러오는 과정은 Win API를 사용하는 과정이여서 자세한 내용은 생략하겠습니다.


(참고)