C# Winform - 프로그램을 트레이에 추가하기, 트레이 아이콘 만들기 (시스템 트레이 프로그램 만들기)

반응형

개요

프로그램을 종료하지 않고 백그라운드로 실행되게 하고,

시스템 트레이를 활용하여 프로그램과 상호작용할 수 있도록 기능을 정의해보자.

<폼을 백그라운드로 실행하고, 시스템 트레이를 활용하여 폼을 불러오는 예시 화면>

 

포스팅에서 사용된 프로젝트는 깃허브에서 확인할 수 있다.

 

GitHub - luvris2/CSharp-Winforms-Example

Contribute to luvris2/CSharp-Winforms-Example development by creating an account on GitHub.

github.com


시스템 트레이 (System Tray)

시스템 트레이란? (System Tray)

컴퓨터 운영 체제에서 사용자에게 현재 실행중인 프로그램이나 서비스 상태를 아이콘으로 표시하고,

간단한 상호작용을 할 수 있도록 제공하는 영역을 의미한다.

주로 프로그램이 백그라운드에서 작업될 때 확인 및 제어하기 위해서 시스템 트레이를 이용한다.

일반적으로 작업 표시줄에 위치하며 오른쪽 끝에 (우측 하단 시계쪽) 작은 아이콘으로 나타낸다.

 

시스템 트레이는 프로그램을 대표하는 작은 아이콘들로 나열되어 구성된다.

예를 들어서 카카오톡을 'X' 버튼을 눌러 닫기를 해도 시스템 트레이에서 카카오톡을 다시 실행할 수 있다.

이 때, 카카오톡은 프로그램이 종료된 상태가 아닌 백그라운드 상태에서 실행되어 있다.

시스템 트레이에서는 카카오톡 아이콘을 눌러 카카오톡 프로그램을 다시 포그라운드로 불러올 수 있다.

<윈도우11에서의 시스템 트레이>


시스템 트레이를 사용하는 이유

  • 시스템 상태 표시를 위해
    • 백그라운드로 실행되는 프로그램의 상태를 나타내 사용자는 프로그램을 확인하지 않고로 쉽게 프로그램의 상태를 확인할 수 있다.
    • 예를 들어 와이파이 접속 상태 등을 표시한다.
  • 작업 표시줄의 깔끔한 관리를 위해
    • 현재 작업표시줄에서 사용하지 않는 프로그램을 숨기고 시스템 트레이 아이콘으로 표시한다면, 사용자는 작업 표시줄을 보다 깨끗하게 유지하면서 멀티 태스킹 시 필요한 프로그램 접근을 보다 더 빠르게 할 수 있다.
  • 간단한 상호 작용을 위해
    • 시스템 트레이 아이콘을 클릭하여 빠르고 간단하게 특정 작업을 수행할 수 있다.
    • 예를 들어 와이파이의 네트워크를 변경할 때, 시스템 트레이의 무선 네트워크를 눌러 네트워크를 변경한다.

C# 애플리케이션을 시스템 트레이에 추가하기

필요한 컨트롤 확인하기

시스템에 추가하려면 기본적으로 두 개의 컨트롤러가 필요하다.

 

1. NotifyIcon

알림 영역에 아이콘을 만드는 구성요소를 지정하는 컨트롤로,

바이러스 보호 프로그램 또는 볼륨 제어와 같이 컴퓨터 백그라운드에서 실행되는 프로세스의 바로가기이다.

즉, 시스템 트레이에 아이콘을 표시하여 프로그램의 상태나 알림을 나타낼 수 있다.

 

2. ContextMenuStrip

Windows Forms에서 사용되는 컨트롤로, 바로 가기 메뉴를 나타낸다.

일반적으로 마우스 오른쪽 단추를 클릭하면 바로 가기 메뉴가 자동으로 표시되게 해준다.

즉, 시스템 트레이에 아이콘을 우클릭하면 팝업 메뉴가 출력되며 선택한 작업을 수행할 수 있도록 해준다.


폼의 닫기 버튼을 눌러도 프로그램이 종료되지 않게 하기 (Hide)

시스템 트레이에서 백그라운드 프로그램의 상태를 알리고,

필요 시 프로그램을 포그라운드로 다시 볼 수 있게 해주어야 한다.

그러려면 일단 시스템 트레이로 보내기 전에 실행되고 있는 프로그램을 작업 표시줄에 없애야 한다.

프로그램 우측 상단의 'X' 버튼을 눌러도 프로그램이 종료되지 않고 백그라운드에서 실행되게 해보자.

 

폼 디자인 창에서 폼을 선택 한 후, 속성 창의 이벤트(번개 모양 아이콘)로 이동한다.

'동작' - 'FormClosing'의 우측 필드에 작동할 함수명을 정의하고 엔터를 누른다.

  • FormClosing은 폼이 종료될 때 수행하는 기능을 정의하는 이벤트 핸들러이다.

 

+ Close 관련된 이벤트 핸들러는 세 가지가 있다. 혼동해서 잘못사용하지 말자!

  • FormClosed : 폼을 닫은 후 발생되는 이벤트
  • FormClosing : 폼을 닫을 때 발생되는 이벤트
  • Close : 폼을 닫는 이벤트

<폼의 FormClosing 함수를 정의하는 화면>

 

폼이 닫힐 때의 이벤트를 정의한다.

  • 사용자가 폼을 닫을 때, 종료 기능 대신 폼을 숨기는 기능으로 변경
// 폼이 닫힐 때 발생되는 이벤트 : 백그라운드 실행
private void Form_Closing(object sender, FormClosingEventArgs e)
{
	// CloseReason.UserClosing : 사용자가 닫기 버튼을 누를 때
    if (e.CloseReason == CloseReason.UserClosing)
    {
    	// 폼 닫기 이벤트 취소
        e.Cancel = true;
        // 폼 숨기기
        this.Hide();
    }
}

 

이제 프로그램을 실행하여 우측 상단의 'X' 버튼을 눌러보자.

프로그램이 종료된 줄 알았으나, 여전히 실행중인 상태임을 확인할 수 있다.

<폼을 숨김처리하여 백그라운드에서 실행되도록한 화면>


컨트롤 추가 및 설정하기 (NotifyIcon)

C# Winform 프로젝트를 생성 한 후, 도구 상자에서 NotifyIcon을 폼에 추가한다.

<C# Winform 프로젝트의 폼에 NotifyIcon 컨트롤을 추가한 화면>

 

시스템 트레이에 표시될 아이콘이 필요하다.

포스팅을 위해 간단히 고공연의 앞글자를 따서 "고"가 표시된 아이콘을 급하게 만들었다.

이 포스팅을 따라하고 있는데 아이콘으로 사용할 파일이 없으면 아래의 파일을 다운받아 같이 진행해보자.

ko_icon.ico
0.01MB

 

폼 하단에 추가한 notifyIcon을 선택한 후 아이콘을 지정해보자. 

<notifyIcon 컨트롤에 아이콘을 추가하는 과정을 표시한 화면>

 

프로그램을 실행시켜보자.

시스템 트레이에 정상적으로 내가 설정한 아이콘이 표시된다.

단, notifyIcon은 시스템 트레이에 아이콘을 표시해주기만 하는 역할을 하므로

추가 작업(마우스 우클릭으로 메뉴 출력, 더블 클릭으로 폼 나타내기 등)은 수행할 수 없다.

<시스템 트레이에 C# 프로그램이 표시된 화면>


컨트롤 추가 및 설정하기 (ContextMenuStrip)

이제 시스템 트레이에 추가된 아이콘을 상호작용하여 특정 기능을 수행할 수 있도록 해보자.

도구 상자에서 ContextMenuStrip을 폼에 추가한다.

<C# Winform 프로젝트의 폼에 ContextMenuStrip 컨트롤을 추가한 화면>

 

그리고 생성한 notifyIcon 컨트롤과 연결을 해준다.

notifyIcon을 선택 한 후, 속성 창의 '동작' - 'ContextMenuStrip'에 연결할 ContextMenuStrip을 선택한다.

 

 

폼 하단에 추가한 ContextMenuStrip을 선택한 후 폼에 보여지는 메뉴 리스트를 완성한다.

포스팅에서는 '열기' 와 '종료' 를 지정하였다.

<contextMenuStrip에 메뉴 이름을 정의한 화면>


팝업 메뉴 기능 정의하기 (ContextMenuStrip)

ContextMenuStrip 메뉴 이벤트 함수 추가

메뉴에 대한 기능을 정의하는 방법은 다음과 같다.

  1. 정의한 ContextMenuStrip 메뉴 리스트 중 하나를 선택한다.
  2. 우측 하단의 속성 창에서 이벤트(번개 모양 아이콘)로 이동한다.
  3. 작업될 분류를 정하고 (포스팅에서는 Click) 함수의 이름을 지정한 후 엔터를 누른다.
  4. cs 코드창에서 생성된 메서드에 대한 기능 정의 코드를 작성한다.

<ContextMenuStrip 메뉴 기능 수행 함수를 만드는 방법 예시 화면>

 

<메뉴의 기능 함수 정의 후 자동으로 코드가 생성된 화면>

 

'열기' 기능 (클릭 이벤트, Show)

  • 폼이 백그라운드로 실행 될 때, 시스템 트레이의 메뉴를 활용하여 폼을 보여준다.
// 열기 기능
private void ContextMenuStrip_Open(object sender, EventArgs e)
{
    this.Show();
}

 

'종료' 기능 (클릭 이벤트, Exit)

  • 시스템 트레이의 메뉴를 활용하여 프로그램을 종료한다.
// 종료 기능
private void ContextMenuStrip_Exit(object sender, EventArgs e)
{
    Application.Exit();
}

전체 소스 코드

  • Form1.cs
더보기
namespace C__Tray_Example
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // 폼이 닫힐 때 발생되는 이벤트 : 백그라운드 실행
        private void Form_Closing(object sender, FormClosingEventArgs e)
        {
            // CloseReason.UserClosing : 사용자가 닫기 버튼을 누를 때
            if (e.CloseReason == CloseReason.UserClosing)
            {
                // 폼 닫기 이벤트 취소
                e.Cancel = true;
                // 폼 숨기기
                this.Hide();
            }
        }

        // 열기 기능
        private void ContextMenuStrip_Open(object sender, EventArgs e)
        {
            this.Show();
            //this.Visible = true;
        }

        // 종료 기능
        private void ContextMenuStrip_Exit(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
}

번외 : 백그라운드 실행 방법 (폼 숨기기 방법, Hide VS Visible)

폼을 보여주고 숨길 때에 두가지의 방식이 있다.

  1. Hide() 메서드를 사용하여 폼을 숨긴 경우
    • Show() 메서드를 이용하여 폼을 다시 보이게 할 수 있다.
  2. Visible 속성을 사용하여 폼을 숨긴 경우
    • true, false 값으로 폼을 숨기거나 다시 보이게 할 수 있다.

폼을 숨기는 것은 Hide 메서드나 Visible 속성의 기능은 둘 다 같이 작동한다.

차이점에 대한 공식적인 내용을 찾기가 너무 어려워서,

스택오버플로우에서 Hide()와 Visible 의 차이점에 대한 글에 내용을 간단히 발췌했다.

  • Q : Hide()와 Visible의 차이점이 무엇인가요?
  • A : 동일한 방식으로 작동한다. 선호도에 따라 사용하면 된다.

출처 : https://stackoverflow.com/questions/3600354/control-difference-between-hide-and-visible


실행 및 테스트

  • 프로그램 실행 시
    • 작업 표시줄과 프로그램이 정상적으로 화면에 출력된다.

<프로그램 실행 화면>

 

  • 프로그램 닫기 버튼 클릭 시
    • 프로그램이 작업표시줄에서 사라졌으나 종료되지 않고 백그라운드에서 실행되고 있다.
      (시스템 트레이에서 프로그램이 실행중임을 아이콘으로 확인 가능)

<백그라운드에서 실행되고 있고 시스템 트레이에서 작동중임을 나타내는 기능>

 

  • 시스템 트레이의 아이콘을 '우클릭' - '열기' 했을 경우
    • 백그라운드에서 실행되던 폼이 화면에 출력된다.

<시스템 트레이 메뉴의 '열기' 기능>

 

  • 시스템 트레이의 아이콘을 '우클릭' - '종료' 했을 경우
    • 프로그램이 종료된다.

참고

 

 

반응형