프로그램 개발/C#

[wpf] NotifyIcon/TrayIcon 사용하기

(ㅇㅅㅎ) 2021. 11. 2. 23:50
728x90
반응형

 카카오톡이나 여러 가지 프로그램을 사용하다 보면 창이 닫혀있지만 사용상태를 작업표시줄의 오른쪽에서 확인할 수 있습니다.

 이러한 작업표시줄의 오른쪽 부분을 알림 영역(NotifyIconArea)라고 하는데 이 영역에 있는 아이콘들은 NotifyIcon 혹은 TrayIcon으로 불립니다. 이 아이콘들은 백그라운드에서 실행되고 있는 프로그램에 대해서 나타내고 있습니다. 이러한 알림 영역에 해당하는 부분을 C#에서는 NotifyIcon을 이용하여 만들 수 있습니다. 하지만 WPF의 경우 지원을 하지 않기 때문에 Windows.Forms을 참조해야 합니다.

 

 


 

1. Windows.Forms 참조하기

 [솔루션 탐색기] - [참조]에서 마우스 우클릭하여 [참조 추가]를 선택합니다. 그 후 [어셈블리]에서 'forms'로 검색하여 [System.Windows.Forms]를 체크한 뒤 [확인] 버튼을 클릭합니다.

 

 

2. NotifyIcon 설정하기

using System;
using System.Windows;
using System.WIndows.Forms;

 NotifyIcon을 사용하기 위해서는 using 부분에 [System.Windows.Forms]를 추가합니다. 

 

 NotifyIcon을 생성한 뒤 아이콘 설정을 하면 아래와 같습니다.

private void SetNotification()
{
    // NotifyIcon 생성
    NotifyIcon ni = new NotifyIcon();

    // NotifyIcon에 사용할 ico 파일 경로입니다. 절대 경로로 설정해 주시면 됩니다.
    // 설정하지 않을 경우 아이콘이 보이지 않습니다.
    ni.Icon = new System.Drawing.Icon("icon.ico");
    
    // NotifyIcon이 보일 수 있도록 Visible 항목을 true로 설정합니다.
    // 기본설정이 false이기 때문에 반드시 true로 설정해주셔야합니다.
    ni.Visible = true;
    
    // NotifyIcon에 마우스를 올릴 경우 나타나는 글입니다.
    // 설정 안해주셔도됩니다.
    ni.Text = "NotifyIcon/TrayIcon";
}

 

 

 위의 설정에서는 아무 기능이 없기 때문에 창이 최소화 상태일 때 NotifyIcon을 [더블클릭]할 경우 열리도록 설정해보겠습니다.

private void SetNotification()
{
    NotifyIcon ni = new NotifyIcon();

    ni.Icon = new System.Drawing.Icon("icon.ico");
    ni.Visible = true;
    ni.Text = "NotifyIcon/TrayIcon";
    
    // NotifyIcon에 더블 클릭 이벤트 추가
    ni.DoubleClick += delegate(object sender, EventArgs eventArgs)
    {
        // 화면을 최소화 상태에서 다시 보여줍니다.
        this.Show();
        // 화면 상태를 Normal로 설정합니다.
        this.WindowState = WindowState.Normal;
    }
}

 

 

3. ContextMenu와 MenuItem 설정하기

 

 위의 기능만으로도 NotifyIcon을 사용할 수 있지만 좀 더 심화 과정으로 ContextMenu를 사용해보도록 하겠습니다. ContextMenu의 경우 NotifyIcon에서 마우스 우클릭을 하면 나타나는 메뉴를 말합니다.

 ContextMenu에 메뉴를 넣기 위해서는 MenuItem을 이용해야 됩니다. 이번 포스팅에서는 "열기"와 "닫기" 2가지 메뉴를 추가한 뒤 그에 맞는 기능을 설정해 보도록 하겠습니다.

private ContextMenu SetContextMenu(NotifyIcon ni)
{
    // ContextMenu 생성합니다.
    ContextMenu menu = new ContextMenu();

    // 첫번째 메뉴 "열기" MenuItem을 생성합니다.
    MenuItem item1 = new MenuItem();
    
    // 메뉴의 Text는 "열기"로 지정합니다.
    item1.Text = "열기";
    
    // "열기" 메뉴의 클릭이벤트를 설정합니다.
    item1.Click += delegate (object click, EventArgs eventArgs)
    {
        this.Show();
        this.WindowState = WindowState.Normal;
    };
    
    // "열기" 메뉴를 ContextMenu에 추가합니다.
    menu.MenuItems.Add(item1);

    // 두번째 메뉴 "닫기" MenuItem을 생성합니다.
    MenuItem item2 = new MenuItem();
    
    // 메뉴의 Text는 "닫기"로 지정합니다.
    item2.Text = "닫기";
    
    // "닫기" 메뉴의 클릭이벤트를 설정합니다.
    item2.Click += delegate (object click, EventArgs eventArgs)
    {
        // 프로그램을 강제로 종료하는 부분입니다.
        System.Windows.Application.Current.Shutdown();
        
        // 프로그램 종료 후 NotifyIcoy 리소스를 해제합니다.
        // 해제하지 않을 경우 프로그램이 완전히 종료되지 않는 경우도 발생합니다.
        ni.Dispose();
    };
    
    // "닫기" 메뉴를 ContextMenu에 추가합니다.
    menu.MenuItems.Add(item2);
    
    return menu;
}

 

이렇게 추가한 ContextMenu는 NotifyIcon의 ContextMenu 항목에 설정해줍니다.

private void SetNotification()
{
    NotifyIcon ni = new NotifyIcon();
    ni.Icon = new System.Drawing.Icon("icon.ico");
    ni.Visible = true;
    ni.Text = "NotifyIcon/TrayIcon";
    ni.DoubleClick += delegate(object sender, EventArgs eventArgs)
    {
        this.Show();
        this.WindowState = WindowState.Normal;
    }
    
    // NotifyIcon에 ContextMenu 추가합니다.
    ni.ContextMenu = SetContextMenu(ni);
    
    // 혹은 이 부분에서 SetContextMenu 내용을 작성한 뒤
    // ni.ContextMenu = menu;
    // 이와 같이 설정하셔도 됩니다.
}

 

 

4. 닫기 버튼에서 종료 기능 없애기

 NotifyIcon에 직접적인 관련이 있는 기능은 아니지만 보편적으로 NotifyIcon을 사용할 때 닫기 버튼에서 종료 기능을 없애고 창만 닫도록 설정합니다.

 

 xaml에서 Closing 이벤트를 추가합니다.

<Window
        ...
        mc:Ignorable="d" 
        Closing="Window_Closing"
        Title="MainWindow" Height="200" Width="200">
    <Grid />
</Window>

 

전체 코드는 더보기를 클릭해서 봐주시길 바랍니다.

더보기

XAML

<Window x:Class="TrayIcon.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:TrayIcon"
        mc:Ignorable="d" Closing="Window_Closing"
        Title="MainWindow" Height="200" Width="200">
    <Grid />
</Window>

 

C#

using System;
using System.Windows;
using System.Windows.Forms;

namespace TrayIcon
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            SetNotification();
        }

        private void SetNotification()
        {
            NotifyIcon ni = new NotifyIcon();
            ni.Icon = new System.Drawing.Icon("icon.ico");
            ni.Visible = true;
            ni.DoubleClick += delegate (object sender, EventArgs eventArgs)
            {
                this.Show();
                this.WindowState = WindowState.Normal;
            };
            ni.ContextMenu = SetContextMenu(ni);
            ni.Text = "NotifyIcon/TrayIcon";
        }
        
        private ContextMenu SetContextMenu(NotifyIcon ni)
        {
            ContextMenu menu = new ContextMenu();

            MenuItem item1 = new MenuItem();
            item1.Text = "열기";
            item1.Click += delegate (object click, EventArgs eventArgs)
            {
                this.Show();
                this.WindowState = WindowState.Normal;
            };
            menu.MenuItems.Add(item1);

            MenuItem item2 = new MenuItem();
            item2.Text = "닫기";
            item2.Click += delegate (object click, EventArgs eventArgs)
            {
                System.Windows.Application.Current.Shutdown();
                ni.Dispose();
            };
            menu.MenuItems.Add(item2);

            return menu;
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            this.Hide();
            e.Cancel = true;
        }
    }
}
반응형