반응형
개요
C# Winform 으로 제작한 윈도우 프로그램의 기본 제목 표시줄을 제거하고,
사용자가 제목 표시줄(타이틀바)를 직접 커스터마이징해서 사용할 수 있도록 해보자.
포스팅에서는 제목 표시줄을 만들고 창 이동, 최소화, 최대화, 닫기 기능을 재현하였다.
(최대화 여부를 보여주려고 해상도를 일부러 낮췄다. 옛날엔 이 낮은 해상도에서 어떻게 작업을 했었는지 의문)
포스팅에서 설명하는 내용은 깃허브에서 확인할 수 있다.
제목 표시줄 없애기
우선 제목 표시줄을 커스터마이징하려면, 제목 표시줄을 없애야 한다.
- 디자인 창에서 폼 선택
- 속성 창에서 '모양' - 'FormBorderStyle' 선택
- 값 변경 : Sizable > None
[ FormBorderStyle 값 정보 ]
- Fixed3D : 고정된 3차원 테두리
- FixedDialog : 고정된 대화 상자 스타일의 굵은 테두리
- FixedSingle : 고정된 단일 선 테두리
- FixedToolWindow : 크기를 조정할 수 없는 도구 창 테두리
- None : 테두리 없음
- Sizable : 크기를 조정할 수 있는 테두리
- SizableToolWindow : 크기를 조정할 수 있는 도구 창 테두리
제목 표시줄 커스터마이징하기
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
- 폼 디자인 화면
TableLayoutPanel 컬럼에 컨트롤을 추가하고, 각 컨트롤의 속성을 정의해준다.
- Column1 : Label > 제목 표시줄의 프로그램 제목 표시와 프로그램 창의 위치 이동을 위함
- Label
- name : lbl_title
- Dock : Fill
- Text : 테스트
- TextAlign : MiddleCenter
- Label
- Column2 : Button > 최소화 버튼의 기능 정의를 위함
- Button
- name : btn_min
- Size : 19, 19
- Text : - (하이픈)
- Button
- Column3 : Button > 최대화 버튼의 기능 정의를 위함
- Button
- name : btn_max
- Size : 19, 19
- Text : ㅁ (한글 ㅁ)
- Button
- Column4 : Button > 닫기 버튼의 기능 정의를 위함
- Button
- name : btn_close
- Size : 19, 19
- Text : X (영어 대문자 엑스)
- Button
코딩 : 기능 정의하기
1. 제목 표시줄 폼 이동 기능 (Column1 > lbl_title)
제목 표시줄을 마우스로 드래그하면 폼이 이동되는 기능을 정의해보자.
마우스를 누르고(MouseDown)드래그하여 폼을 이동(MouseMove)한 뒤,
드래그를 마치면(MouseUp) 해당 위치로 폼이 이동되어야 한다.
로직은 다음과 같다.
- 변수 정의
- 드래그 상태를 확인하기 위한 bool 타입 변수 정의 : 드래그 변수가 true일 경우, 드래그로 인식
- 위치를 확인하기 위한 Point 타입 변수 정의 : 현재 위치와 이동될 위치를 업데이트하기 위함
- 마우스 클릭 시
- 드래그 변수의 값을 true 변경
- 위치 변수의 값을 현재 마우스 이벤트의 e값으로 저장 (MouseEventArgs e)
- 마우스 클릭 완료 시
- 드래그 변수의 값을 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();
}
}
}
반응형