C# - 제목 표시줄 커스터마이징하기 (타이틀바 UI 만들기)

반응형

개요

C# Winform 으로 제작한 윈도우 프로그램의 기본 제목 표시줄을 제거하고,

사용자가 제목 표시줄(타이틀바)를 직접 커스터마이징해서 사용할 수 있도록 해보자.

포스팅에서는 제목 표시줄을 만들고 창 이동, 최소화, 최대화, 닫기 기능을 재현하였다.

(최대화 여부를 보여주려고 해상도를 일부러 낮췄다. 옛날엔 이 낮은 해상도에서 어떻게 작업을 했었는지 의문)

<커스텀 타이틀바 구현 예시 화면>

 

포스팅에서 설명하는 내용은 깃허브에서 확인할 수 있다.

 

GitHub - luvris2/CSharp-Winforms-Example

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

github.com


제목 표시줄 없애기

우선 제목 표시줄을 커스터마이징하려면, 제목 표시줄을 없애야 한다.

  1. 디자인 창에서 폼 선택
  2. 속성 창에서 '모양' - 'FormBorderStyle' 선택
  3. 값 변경 : Sizable > None

[ FormBorderStyle 값 정보 ]

  • Fixed3D : 고정된 3차원 테두리
  • FixedDialog : 고정된 대화 상자 스타일의 굵은 테두리
  • FixedSingle : 고정된 단일 선 테두리
  • FixedToolWindow : 크기를 조정할 수 없는 도구 창 테두리
  • None : 테두리 없음
  • Sizable : 크기를 조정할 수 있는 테두리
  • SizableToolWindow : 크기를 조정할 수 있는 도구 창 테두리

<폼의 제목 표시줄을 제거하기 위한 FromBorderStyle 값 변경 화면>

 

<FormBorderStyle의 값을 None으로 변경하여 제목 표시줄을 제거한 폼 화면>


제목 표시줄 커스터마이징하기

UI : 제목 표시줄 역할을 하는 패널 만들기

포스팅에서 설명하기 위한 예시일뿐, 제목 표시줄 역할을 하는 UI는 선호에 맞게 구성하면 됩니다.

 

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

 

작업 표시줄처럼 보이게 하기 위해 TableLayoutPanel의 속성을 변경해준다.

  • Dock : Top
  • BackColor : LightSkyBlue
  • Size : x값은 그대로, y값 25 (본인이 보기 편하게 조절)
  • RowCount : 1
  • ColumnCount : 4
  • Columns (혹은 행 및 열 편집)
    • Column1 : Percent : 100.00%
    • Column2 : Absolute : 25
    • Column3 : Absolute : 25
    • Column4 : Absolute : 25

<Columns 속성 편집 예시 화면>

 

  • 폼 디자인 화면

<폼 디자인 예시 화면>

 

TableLayoutPanel 컬럼에 컨트롤을 추가하고, 각 컨트롤의 속성을 정의해준다.

  • Column1 : Label > 제목 표시줄의 프로그램 제목 표시와 프로그램 창의 위치 이동을 위함
    • Label
      • name : lbl_title
      • Dock : Fill
      • Text : 테스트
      • TextAlign : MiddleCenter
  • Column2 : Button > 최소화 버튼의 기능 정의를 위함
    • Button
      • name : btn_min
      • Size : 19, 19
      • Text : - (하이픈)
  • Column3 : Button > 최대화 버튼의 기능 정의를 위함
    • Button
      • name : btn_max
      • Size : 19, 19
      • Text : ㅁ (한글 ㅁ)
  • Column4 : Button > 닫기 버튼의 기능 정의를 위함
    • Button
      • name : btn_close
      • Size : 19, 19
      • Text : X (영어 대문자 엑스)

<컬럼에 컨트롤을 추가한 폼 디자인 예시 화면>


코딩 : 기능 정의하기

1. 제목 표시줄 폼 이동 기능 (Column1 > lbl_title)

제목 표시줄을 마우스로 드래그하면 폼이 이동되는 기능을 정의해보자.

마우스를 누르고(MouseDown)드래그하여 폼을 이동(MouseMove)한 뒤,

드래그를 마치면(MouseUp) 해당 위치로 폼이 이동되어야 한다.

로직은 다음과 같다.

  1. 변수 정의
    • 드래그 상태를 확인하기 위한 bool 타입 변수 정의 : 드래그 변수가 true일 경우, 드래그로 인식
    • 위치를 확인하기 위한 Point 타입 변수 정의 : 현재 위치와 이동될 위치를 업데이트하기 위함
  2. 마우스 클릭 시
    • 드래그 변수의 값을 true 변경
    • 위치 변수의 값을 현재 마우스 이벤트의 e값으로 저장 (MouseEventArgs e)
  3. 마우스 클릭 완료 시
    • 드래그 변수의 값을 false로 변경
// 창 이동 관련 전역 변수
bool mouseDown;
Point lastLocation;

// 마우스 좌클릭 시
private void lbl_title_MouseDown(object sender, MouseEventArgs e)
{
    // 마우스 클릭 여부, 폼의 마지막 위치 저장
    if (e.Button == MouseButtons.Left)
    {
        mouseDown = true;
        lastLocation = e.Location;
    }
}

// 마우스 클릭을 마친 경우 클릭 이벤트
private void lbl_title_MouseUp(object sender, MouseEventArgs e)
{
    // 마우스 클릭 여부 저장
    mouseDown = false;
}

// 마우스로 폼 이동 시
private void lbl_title_MouseMove(object sender, MouseEventArgs e)
{
    // 마우스 클릭 상태 시 폼이 이동된 위치로 이동
    if (mouseDown)
    {
        this.Location = new Point(
            (this.Location.X - lastLocation.X) + e.X,
            (this.Location.Y - lastLocation.Y) + e.Y);

        this.Update();
    }
}

 

2. 폼 최소화 (Column2 > btn_min)

// 최소화
private void btn_min_Click(object sender, MouseEventArgs e)
{
    this.WindowState = FormWindowState.Minimized;
}

 

 

3. 폼 최대화 (Column3 > btn_max)

폼 최대화 기능을 일반적으로 두 가지의 조건을 따른다.

  • 창이 최대화가 아닐 때, 창을 최대화 하는 기능
  • 창이 최대화 상태일 때, 기존의 크기로 되돌아가는 기능
// 최대화 / 원상태로
private void btn_max_Click(object sender, MouseEventArgs e)
{
    // 최대화 상태가 아닐 때 최대화
    if (this.WindowState == FormWindowState.Normal)
    {
        this.WindowState = FormWindowState.Maximized;
    }
    // 최대화 상태일 때 원상태로
    else
    {
        this.WindowState = FormWindowState.Normal;
    }
}

 

4. 닫기 (Column4 > btn_close)

// 닫기
private void btn_close_Click(object sender, MouseEventArgs e)
{
    this.Close();
}

 

5. 각 컨트롤별 기능 정의 함수 연결

각 컨트롤을 선택하여 속성 창의 이벤트(번개 모양 아이콘)를 눌러 이벤트에 맞게 정의한 함수를 연결해준다.

  • 제목 표시줄 (lbl_title)

<제목 표시줄 이벤트 함수 정의 예시>

 

  • 최소화 버튼 (btn_min)

<최소화 버튼 이벤트 함수 정의 예시>

 

  • 최대화 버튼 (btn_max)

<최대화 버튼 이벤트 함수 정의 예시>

 

  • 닫기 버튼 (btn_close)

<닫기 버튼 이벤트 함수 정의 예시>

 

전체 소스 코드

더보기
namespace C__Winform_Custom_Title_Bar
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // 창 이동 관련 전역 변수
        bool mouseDown;
        Point lastLocation;

        // 마우스 좌클릭 시
        private void lbl_title_MouseDown(object sender, MouseEventArgs e)
        {
            // 마우스 클릭 여부, 폼의 마지막 위치 저장
            if (e.Button == MouseButtons.Left)
            {
                mouseDown = true;
                lastLocation = e.Location;
            }
        }

        // 마우스 클릭을 마친 경우 클릭 이벤트
        private void lbl_title_MouseUp(object sender, MouseEventArgs e)
        {
            // 마우스 클릭 여부 저장
            mouseDown = false;
        }

        // 마우스로 폼 이동 시
        private void lbl_title_MouseMove(object sender, MouseEventArgs e)
        {
            // 마우스 클릭 상태 시 폼이 이동된 위치로 이동
            if (mouseDown)
            {
                this.Location = new Point(
                    (this.Location.X - lastLocation.X) + e.X,
                    (this.Location.Y - lastLocation.Y) + e.Y);

                this.Update();
            }
        }

        // 최소화
        private void btn_min_Click(object sender, MouseEventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
        }

        // 최대화 / 원상태로
        private void btn_max_Click(object sender, MouseEventArgs e)
        {
            // 최대화 상태가 아닐 때 최대화
            if (this.WindowState == FormWindowState.Normal)
            {
                this.WindowState = FormWindowState.Maximized;
            }
            // 최대화 상태일 때 원상태로
            else
            {
                this.WindowState = FormWindowState.Normal;
            }
        }

        // 닫기
        private void btn_close_Click(object sender, MouseEventArgs e)
        {
            this.Close();
        }
    }
}

 

반응형