티스토리 뷰
웹 인터페이스를 보면 대부분의 요소에서 직각은 거의 찾아볼 수 없고 버튼도 검색창도 대부분 라운드 박스 형태를 가진다. 그렇지만, C# Winform 형태의 프로그램 개발 환경에서 라운드 사각형으로 뭔가를 만든다는 것은 쉽지 않은 일이다. 기본 컨트롤에서는 그러한 필요를 채울 수 없기 때문이다. 이번 포스팅에서는 Label 컨트롤을 상속받아 라운드 박스 형태로 출력하는 레이블 컨트롤을 만들어 보고자 한다.
public class MYRoundBox : Label
{
[Browsable(false)]
public new Image Image { get { return base.Image; } set { base.Image = value; } }
[Browsable(false)]
public new ContentAlignment ImageAlign { get { return base.ImageAlign; } set { base.ImageAlign = value; } }
[Browsable(false)]
public override ContentAlignment TextAlign { get { return base.TextAlign; } set { base.TextAlign = value; } }
[Browsable(false)]
public new BorderStyle BorderStyle { get { return base.BorderStyle; } set { base.BorderStyle = value; } }
[Browsable(false)]
public override Color BackColor { get { return base.BackColor; } set { base.BackColor = value; } }
[Category("모양")]
public Color 내부배경색
{
get => _backColor;
set
{
_backColor = value;
Invalidate();
}
}
[Category("모양")]
public int 모서리크기
{
get => _cornerSize;
set
{
_cornerSize = value;
Invalidate();
}
}
[Category("모양")]
public int 테두리굵기
{
get => _borderSize;
set
{
_borderSize = value;
Invalidate();
}
}
[Category("모양")]
public Color 테두리색
{
get => _borderColor;
set
{
_borderColor = value;
Invalidate();
}
}
private int _cornerSize = 15;
private Color _borderColor = Color.DarkGray;
private int _borderSize = 1;
private Color _backColor = Color.LightGray;
public MYRoundBox()
{
base.BackColor = Color.Transparent;
}
protected override void OnPaint(PaintEventArgs e)
{
using (var graphicsPath = getRoundPath(this.ClientRectangle))
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
var brush = new SolidBrush(_backColor);
var pen = new Pen(_borderColor, _borderSize);
e.Graphics.FillPath(brush, graphicsPath);
if (_borderSize > 0) e.Graphics.DrawPath(pen, graphicsPath);
TextRenderer.DrawText(e.Graphics, Text, this.Font, this.ClientRectangle, this.ForeColor);
}
}
private GraphicsPath getRoundPath(Rectangle rectangle)
{
GraphicsPath path = new GraphicsPath();
int bd2 = _borderSize / 2;
path.AddArc(rectangle.X + bd2, rectangle.Y + bd2, _cornerSize, _cornerSize, 180, 90);
path.AddArc(rectangle.X + rectangle.Width - _cornerSize - _borderSize, rectangle.Y + bd2, _cornerSize, _cornerSize, 270, 90);
path.AddArc(rectangle.X + rectangle.Width - _cornerSize - _borderSize, rectangle.Y + rectangle.Height - _cornerSize - _borderSize, _cornerSize, _cornerSize, 0, 90);
path.AddArc(rectangle.X + bd2, rectangle.Y + rectangle.Height - _cornerSize - _borderSize, _cornerSize, _cornerSize, 90, 90);
path.CloseAllFigures();
return path;
}
}
우선 클래스 선두에 [Browsable(false)]로 속성창에서 속성이 나타나지 않도록 막은 것은 레이블 컨트롤의 이미지와 테두리, 텍스트 배치 및 컨트롤 자체의 배경색 등으로 컨트롤 자체의 배경색은 클래스 생성자에서 투명색으로 설정했다. 라운드 박스의 내부 배경색, 테두리 색과 크기, 모서리 크기를 클래스 속성으로 조정할 수 있도록 했다. 결과적은 새롭게 추가하는 라운드박스 컨트롤은 기존 Label 컨트롤과 달리 이미지를 표시하지 않고, 텍스트도 위치를 조정하지 못하고 중앙에 고정으로 배치한다. 컨트롤 영역을 따라 표시하는 테두리는 적용하지 않는다.
OnPaint 이벤트에 따라 지정한 속성 값에 맞는 라운드 박스를 그리는 방식으로, 라운드 박스 형태의 정보를 갖는 경로(Path)를 getRoundPath 함수를 통해 생성하는데 이때 주의할 점은 선의 두께가 1을 초과하는 두꺼운 선을 그리는 경우, 선 그리기 작업은 선의 두께를 기준 경로 양쪽에 고르게 배분한다는 점이다. 예를 들어 동일한 위치에 두께 5인 초록색 선을 그린 다음에 두께 1인 검은색 선을 그리면 검은색 선은 초록색 선 중앙에 위치하게 된다. getRoundPath 함수에서는 선의 두께를 감안하여 기준 경로를 그리고 있다. AddArc로 네 꼭짓점의 라운드 호를 그린 다음에 CloseAllFigures()를 사용하여 하나의 경로로 연결하는 방식이다.

위의 그림은 위의 컨트롤을 추가하고 속성창에서 해당 컨트롤을 확인한 것이다.
'프로그래밍' 카테고리의 다른 글
| C# 배열 확장 및 항목 삭제하기 (0) | 2025.08.29 |
|---|---|
| 윈도우 10에서 프로그램 비정상 종료시 덤프를 남기도록 설정하는 방법 (0) | 2025.08.18 |
| PHP에서 동적으로 압축 파일을 생성해서 다운로드시키기 (0) | 2025.08.01 |
| C# PictureBox에서 이미지가 자동으로 돌아가는 문제 해결, Exif (0) | 2025.07.08 |
| C# 난독화시 악성코드로 오탐지되는 문제 해결 방법 (0) | 2025.07.08 |