HOWTO · Csharp

시스템 트레이에서 애플리케이션 최소화

이 문서에서는 C#을 사용하여 시스템 트레이에서 Windows Forms 애플리케이션을 최소화하는 방법을 설명합니다.

이 페이지의 내용

이 문서에서는 C#을 사용하여 Windows Forms 애플리케이션을 작업 표시줄 대신 시스템 트레이로 최소화하는 방법을 설명합니다. 이렇게 하면 앱이 백그라운드에서 계속 실행되면서 작은 트레이 아이콘을 통해 언제든 다시 접근할 수 있습니다.

Windows Forms 앱을 시스템 트레이로 최소화하는 이유

Windows Forms는 .NET에 기본 제공되는 데스크톱 GUI 프레임워크입니다. 버튼, 메뉴, 텍스트 필드, 확인란 같은 컨트롤이 System.Windows.Forms 네임스페이스에 정의되어 있으며, 가입이나 로그인 폼은 이 프레임워크로 만들 수 있는 대표적인 예입니다. Windows Forms 애플리케이션에 대한 자세한 배경 지식은 여기에서 확인할 수 있습니다.

기본적으로 Windows Forms 앱을 최소화하면 해당 버튼이 작업 표시줄에 남습니다. 자주 전환해서 사용하는 애플리케이션이라면 문제없지만, 백그라운드에서 실행되기만 하면 되는 프로그램은 작업 표시줄 공간만 차지할 뿐이며, 작업 표시줄은 금방 복잡해져 탐색하기 어려워집니다.

이러한 애플리케이션이 일반적으로 자리 잡는 곳이 시스템 트레이, 즉 작업 표시줄 오른쪽 아래 모서리의 알림 영역입니다. 각 백그라운드 앱은 작은 아이콘으로 표시되어 눈앞에서는 사라지지만 한 번의 클릭으로 다시 접근할 수 있습니다. 채팅 클라이언트와 바이러스 백신 소프트웨어가 흔히 이 방식으로 동작하며, 트레이 앱은 주의가 필요한 일이 생기면 풍선 팁으로 사용자에게 알릴 수도 있습니다.

요약하면, NotifyIcon를 사용하면 Windows Forms 앱이 계속 실행되는 동안 작업 표시줄 대신 시스템 트레이로 최소화되도록 할 수 있습니다. 이제부터 이 동작을 연결하는 방법을 살펴보겠습니다.

NotifyIcon 구성

NotifyIcon는 앱이 시스템 트레이에 표시하는 아이콘을 그리고 관리하는 System.Windows.Forms 네임스페이스의 구성 요소입니다. 화면에 보이는 컨트롤이 아니므로 폼으로 끌어 놓으면 폼 표면이 아니라 디자이너 아래쪽의 구성 요소 트레이에 배치됩니다.

Visual Studio에서 도구 상자를 열고 NotifyIcon를 더블 클릭하거나 폼으로 끌어 놓습니다:

NotifyIcon 구성 요소가 선택된 Visual Studio 도구 상자

그러면 폼에 notifyIcon1 구성 요소가 추가됩니다. 이 자습서에서 중요한 속성은 다음과 같습니다.

  • Icon: 시스템 트레이에 표시되는 아이콘으로, 가장 중요한 속성입니다. System.Drawing.Icon 값을 받으며 Visual Studio 디자이너의 파일 선택 도구는 .ico 파일을 바로 받아들입니다. 다른 이미지 형식은 코드에서 먼저 Icon으로 변환해야 하므로, 트레이에는 .ico 파일이 실용적인 선택입니다.
  • Text: 커서를 트레이 아이콘 위에 올렸을 때 표시되는 도구 설명입니다.
  • Visible: 아이콘이 트레이에 표시되는지 여부입니다. 폼이 보이는 동안에는 False로 유지해 앱이 작업 표시줄과 트레이를 동시에 차지하지 않도록 합니다.
  • BalloonTipTitle, BalloonTipText, BalloonTipIcon: ShowBalloonTip이 표시하는 풍선 알림의 제목, 본문 텍스트, 심각도 아이콘입니다.

속성 창에서 Icon에 .ico 파일을 할당하고 Visible은 False로 둔 채 시작합니다:

아이콘이 할당되고 Visible이 False로 설정된 NotifyIcon 속성

그런 다음 폼이 로드될 때 텍스트 관련 속성을 설정합니다. Form1_Load 처리기에서 notifyIcon1.BalloonTipTitle = "System Tray", notifyIcon1.BalloonTipText = "Some Notification", notifyIcon1.Text = "System Tray App"을 할당합니다. 다음 섹션의 실행 가능한 프로그램에서 전체 Form1_Load 메서드를 맥락과 함께 확인할 수 있습니다.

전체 멤버 목록은 NotifyIcon API 참조에 문서화되어 있습니다.

폼 숨기기 및 복원

단계별 절차는 다음과 같습니다. 세 처리기 Form1_Load, Form1_Resize, notifyIcon1_MouseDoubleClick은 Visual Studio 디자이너가 이벤트에 연결하는 Form1 partial 클래스의 멤버이며, 독립 실행형 프로그램이 아니라 Windows의 Windows Forms 프로젝트 안에서 컴파일되고 실행됩니다.

  • Visual Studio를 열고 시작 창에서 Create a new project를 선택합니다:

    Visual Studio 시작 창

  • Windows Forms App 템플릿을 선택하고 Next를 클릭합니다:

    Windows Forms App 템플릿이 표시된 새 프로젝트 만들기 대화 상자

  • 프로젝트 이름을 입력하고 Create를 클릭합니다:

    새 Windows Forms 프로젝트 이름 지정

  • 도구 상자에서 NotifyIcon를 폼으로 끌어 놓은 다음, 앞 섹션에서 설명한 대로 Icon을 할당하고 Visible을 False로 둡니다. 아이콘을 지정하지 않으면 폼이 숨겨질 때 시스템 트레이에 아무것도 나타나지 않습니다.
  • 폼의 Resize 이벤트를 연결합니다. 폼을 선택하고 속성 창에서 이벤트 목록(번개 모양 단추)을 연 다음, Resize를 더블 클릭해 Form1_Resize를 만듭니다:

    Resize가 Form1_Resize에 연결된 Form1 이벤트 목록

  • 같은 방법으로 notifyIcon1의 MouseDoubleClick 이벤트를 연결합니다. 구성 요소 트레이에서 notifyIcon1을 선택하고 이벤트 목록을 연 다음 MouseDoubleClick을 더블 클릭해 notifyIcon1_MouseDoubleClick을 만듭니다.
  • 세 처리기를 작성합니다. 아래 실행 가능한 프로그램에서 전체 맥락을 확인할 수 있으며, Visual Studio에서는 Form1_Load, Form1_Resize, notifyIcon1_MouseDoubleClick 메서드만 Form1.cs에 붙여 넣으면 됩니다.

이 처리기들은 Windows Forms 프로젝트 안에만 존재하는 System.Windows.Forms 형식에 의존하므로, 아래 프로그램은 같은 멤버 이름을 가진 작은 대체 형식(FormWindowState, MouseEventArgs, NotifyIcon)으로 감싸 독립적으로 컴파일되고 실행되도록 했습니다. Main은 사용자 역할을 합니다. 창을 최소화하고 Resize가 반응하게 한 다음 트레이 아이콘을 더블 클릭합니다. 다음 예제를 실행해 보세요:

아래 코드와 출력 블록은 원문 그대로 유지되므로, 그 안의 주석과 표시 문자열은 영어로 나타납니다.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

using System;

// Minimal stand-ins so the handler logic compiles and runs as a plain
// console program. In a real project these types come from
// System.Windows.Forms and the handlers live in the Form1 partial class.
enum FormWindowState { Normal, Minimized }

class MouseEventArgs { }

class NotifyIcon
{
    public bool Visible;
    public string Text;
    public string BalloonTipTitle;
    public string BalloonTipText;

    public void ShowBalloonTip(int timeout)
    {
        Console.WriteLine("Balloon tip: " + BalloonTipTitle + " - " + BalloonTipText);
    }
}

class Form1
{
    FormWindowState WindowState = FormWindowState.Normal;
    NotifyIcon notifyIcon1 = new NotifyIcon();

    void Hide() { Console.WriteLine("Form hidden"); }
    void Show() { Console.WriteLine("Form shown"); }

    private void Form1_Load(object sender, EventArgs e)
    {
        notifyIcon1.BalloonTipTitle = "System Tray";
        notifyIcon1.BalloonTipText = "Some Notification";
        notifyIcon1.Text = "System Tray App";
    }

    private void Form1_Resize(object sender, EventArgs e)
    {
        if (WindowState == FormWindowState.Minimized)
        {
            this.Hide();
            notifyIcon1.Visible = true;
            notifyIcon1.ShowBalloonTip(1000);
        }
        else if (FormWindowState.Normal == this.WindowState)
        {
            notifyIcon1.Visible = false;
        }
    }

    private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
    {
        this.Show();
        notifyIcon1.Visible = false;
        WindowState = FormWindowState.Normal;
    }

    static void Main()
    {
        Form1 form = new Form1();
        form.Form1_Load(null, new EventArgs());
        form.WindowState = FormWindowState.Minimized;
        form.Form1_Resize(null, new EventArgs());
        form.notifyIcon1_MouseDoubleClick(null, null);
        form.Form1_Resize(null, new EventArgs());
    }
}
Form hidden
Balloon tip: System Tray - Some Notification
Form shown

Resize는 WindowState가 바뀔 때마다 발생하므로 최소화에 반응하기에 알맞은 위치입니다. this.Hide()는 폼의 작업 표시줄 버튼을 완전히 제거합니다. 단순한 최소화는 버튼을 작게 줄여 그곳에 둘 뿐입니다. 아이콘을 Visible로 만들고 ShowBalloonTip을 호출하면 이동 사실을 알리며, 1000 인수는 풍선의 표시 시간을 밀리초 단위로 지정합니다. else if 분기는 창이 Normal로 돌아올 때마다 아이콘을 다시 숨기므로, 트레이 아이콘을 거치지 않는 복원도 함께 처리합니다.

복원 처리기에서 this.Show()는 숨겨진 폼을 다시 표시하고, WindowState = FormWindowState.Normal은 최소화를 해제하며, 폼이 작업 표시줄 버튼을 되찾았으므로 아이콘도 다시 숨깁니다.

트레이 동작 테스트

애플리케이션을 실행합니다(F5). 빈 Form1 창이 나타납니다:

실행 중인 Form1 창

이 시점에서 앱은 작업 표시줄을 차지하고 있으며 시스템 트레이에는 아직 아무것도 추가되지 않았습니다:

최소화 전 앱 버튼이 표시된 작업 표시줄

폼의 최소화 버튼을 클릭합니다:

최소화 버튼이 강조 표시된 Form1

Form1_Resize 처리기가 실행됩니다. 폼과 작업 표시줄 버튼이 사라지고 아이콘이 시스템 트레이에 나타나며, 구성한 제목과 텍스트로 풍선 팁이 표시됩니다. 위의 실행 가능한 프로그램이 세 출력 줄로 인쇄하는 것과 같은 순서입니다:

최소화 후 앱 아이콘이 표시된 시스템 트레이

트레이 아이콘을 더블 클릭해 복원 경로를 확인합니다. 폼이 정상 상태로 다시 나타나고 작업 표시줄 버튼이 돌아오며 트레이 아이콘은 사라집니다. 애플리케이션은 전체 과정 내내 계속 실행됩니다. 트레이로의 최소화는 실행 여부가 아니라 표시되는 위치만 바꿀 뿐입니다.

최소화 후에도 아이콘이 나타나지 않으면 디자이너나 코드에서 Icon이 할당되었는지 확인하세요. 아이콘이 없으면 NotifyIcon는 아무것도 렌더링하지 않고(ShowBalloonTip도 아무것도 표시하지 않습니다), 숨겨진 앱은 복원할 수 있는 가시적인 수단 없이 실행 상태로 남게 됩니다.