MFC GDI 기본 사용법, 선부터 텍스트까지 CDC로 쉽게 출력하는 방법
🖼️ GDI 입문자를 위한 기초부터 실습까지 한 번에 정리!
윈도우 데스크탑 애플리케이션을 개발하면서 그래픽 출력이 필요한 경우, 가장 기본이 되는 기술이 바로 GDI입니다.
MFC를 처음 접하는 분들에게 GDI는 다소 생소하게 느껴질 수 있지만, 실제로는 굉장히 직관적이고 유용한 도구입니다.
특히 CDC 클래스를 통해 선을 그리고 사각형을 만들며 텍스트를 출력하는 방식은 다양한 응용으로 이어질 수 있어 기초부터 확실히 다져두는 것이 중요하죠.
오늘은 MFC에서 GDI를 활용하는 기본 사용법을 처음부터 하나씩 알려드리려 합니다.
이 글에서는 MFC의 GDI(Graphics Device Interface)를 활용해 다양한 도형과 텍스트를 출력하는 방법을 소개합니다.
CDC 객체의 개념부터 사용법, 그리고 실제 그리기 코드까지 예시를 통해 쉽게 이해할 수 있도록 구성했어요.
처음 MFC를 접하셨거나, GDI에 대해 다시 정리하고 싶은 분이라면 꼭 끝까지 읽어보세요.
📋 목차
🖍️ GDI란 무엇인가요?
GDI(Graphics Device Interface)는 마이크로소프트 윈도우에서 그래픽을 출력하기 위한 핵심 API입니다.
화면, 프린터, 메모리 등 다양한 디바이스에 그래픽 요소를 그릴 수 있도록 도와주며, 선, 도형, 텍스트, 비트맵 등의 출력을 처리하는 데 사용됩니다.
GDI는 내부적으로 디바이스 독립적인(DI) 방식으로 작동하기 때문에, 어떤 출력 장치에서도 동일한 방식으로 결과물을 그릴 수 있다는 장점이 있습니다.
이러한 특성은 다양한 화면 해상도나 프린터 출력에서도 일관된 품질을 유지하는 데 유리하죠.
MFC에서는 이러한 GDI 기능을 CDC 클래스를 통해 캡슐화하여 보다 간편하게 사용할 수 있도록 제공합니다.
즉, 복잡한 WinAPI 호출 없이도 객체 지향 방식으로 그래픽을 출력할 수 있다는 뜻입니다.
💡 TIP: GDI는 DirectX처럼 고성능 그래픽을 위한 기술은 아니지만, 대부분의 데스크탑 애플리케이션에서 충분한 퍼포먼스를 발휘하며 코드도 간단한 편입니다.
🧩 GDI의 기본 구성 요소
GDI는 주로 다음과 같은 구성 요소를 기반으로 작동합니다.
이들을 적절히 조합하면 원하는 출력 결과를 만들 수 있습니다.
- ✏️Pen: 선을 그릴 때 사용하는 GDI 객체
- 🟫Brush: 도형 내부를 채우는 데 사용
- 🔠Font: 텍스트의 서체를 설정
- 🖼️Bitmap: 이미지 처리에 사용되는 객체
이러한 객체들을 SelectObject()를 통해 DC에 설정하고, 그에 맞는 출력 함수를 호출하는 방식이 GDI의 기본 동작 흐름입니다.
📐 MFC에서 CDC 객체의 역할
MFC에서는 GDI 기능을 객체 지향적으로 사용할 수 있도록 CDC 클래스를 제공합니다.
CDC는 ‘Device Context’를 캡슐화한 클래스이며, 윈도우나 프린터 같은 출력 장치에 그리기 작업을 수행할 수 있게 해줍니다.
개발자가 직접 HDC를 처리하지 않고도 CDC 객체를 통해 다양한 그래픽 출력 작업을 손쉽게 수행할 수 있다는 것이 큰 장점입니다.
CDC 클래스는 내부적으로 HDC 핸들을 소유하고 있으며, 각종 GDI 함수들을 멤버 함수 형태로 제공합니다.
🧱 CDC 객체를 얻는 방법
MFC에서 CDC 객체는 상황에 따라 다양한 방식으로 획득할 수 있습니다.
대표적인 방법은 다음과 같습니다.
- 🖌️OnDraw() 또는 OnPaint(): CView 또는 CWnd에서 재정의하여 사용하는 대표적인 그리기 함수
- 📥GetDC(): 임시로 현재 윈도우의 DC를 얻을 때 사용
- 📤CClientDC, CWindowDC: 클라이언트 영역 또는 전체 윈도우 영역에 접근할 때 사용
CDC 객체를 사용할 때는 반드시 자원을 반납하는 것도 중요합니다.
예를 들어 GetDC()를 사용한 경우 ReleaseDC()로 반환해줘야 하며, 이는 GDI 리소스 누수를 방지하기 위한 필수 절차입니다.
⚠️ 주의: OnPaint() 함수 안에서는 반드시 CPaintDC 객체를 사용해야 하며, GetDC()를 사용하는 것은 올바르지 않은 방식입니다.
// OnPaint 예시 코드
void CMyView::OnPaint()
{
CPaintDC dc(this); // 클라이언트 영역에 대한 DC 객체 생성
dc.MoveTo(10, 10);
dc.LineTo(200, 200);
}
✏️ 선, 사각형, 타원 등 기본 도형 그리기
MFC에서 GDI를 통해 도형을 그리는 과정은 매우 직관적입니다.
CDC 객체를 사용하면 선, 사각형, 타원 등 다양한 도형을 쉽게 출력할 수 있습니다.
도형을 그리기 전에 Pen과 Brush를 설정하면 더욱 세밀한 스타일 조정도 가능합니다.
📏 기본 도형 출력 함수
MFC에서 사용되는 대표적인 도형 출력 함수는 다음과 같습니다.
- ➖MoveTo(x, y): 시작 지점을 지정합니다
- ➡️LineTo(x, y): 선을 그립니다 (MoveTo와 함께 사용)
- ⬛Rectangle(x1, y1, x2, y2): 사각형을 그립니다
- 🟢Ellipse(x1, y1, x2, y2): 타원을 그립니다
// 기본 도형 그리기 예시
void CMyView::OnDraw(CDC* pDC)
{
pDC->MoveTo(50, 50);
pDC->LineTo(200, 50);
pDC->Rectangle(50, 70, 200, 120);
pDC->Ellipse(50, 130, 200, 200);
}
🎨 Pen과 Brush로 스타일 지정
더 세밀한 제어를 위해 CPen과 CBrush 객체를 생성한 뒤, SelectObject()로 DC에 설정할 수 있습니다.
이렇게 하면 선의 굵기, 색상, 도형의 채우기 색 등을 자유롭게 변경할 수 있습니다.
💎 핵심 포인트:
모든 Pen과 Brush 객체는 사용 후 반드시 삭제(delete)해야 GDI 리소스 누수를 방지할 수 있습니다.
🔤 문자열 출력과 폰트 설정 방법
MFC에서 문자열을 화면에 출력하는 방법은 CDC::TextOut() 또는 CDC::DrawText() 함수를 사용하는 것입니다.
기본적인 텍스트 출력은 매우 간단하며, 원하는 위치에 문자열을 배치할 수 있습니다.
출력하고자 하는 문자열에 특별한 서체나 크기, 스타일을 적용하고 싶다면 CFont 클래스를 사용하여 폰트를 설정한 뒤, 해당 폰트를 DC에 선택하면 됩니다.
✍️ 기본 텍스트 출력
void CMyView::OnDraw(CDC* pDC)
{
pDC->TextOut(50, 50, _T("Hello, MFC GDI!"));
}
TextOut은 단순히 문자열을 특정 위치에 출력할 때 적합하고, DrawText는 영역에 따라 자동 줄바꿈, 정렬 등 좀 더 유연한 컨트롤이 가능합니다.
🧶 사용자 지정 폰트 설정
폰트를 변경하고 싶다면 CFont 객체를 생성 후 LOGFONT 구조체를 통해 속성을 정의하고, 이를 SelectObject로 적용합니다.
void CMyView::OnDraw(CDC* pDC)
{
CFont font;
font.CreateFont(
24, 0, 0, 0, FW_BOLD, FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS,
_T("Arial")
);
CFont* pOldFont = pDC->SelectObject(&font);
pDC->TextOut(50, 50, _T("굵은 Arial 폰트 출력"));
pDC->SelectObject(pOldFont);
}
💡 TIP: TextOut은 빠르지만 단순한 텍스트 출력에 적합하며, 정렬이나 줄바꿈이 필요할 경우 DrawText를 사용하는 것이 좋습니다.
🎨 GDI 객체 관리의 핵심 팁
GDI 객체는 시스템 리소스를 사용하는 자원이기 때문에, 사용 후 반드시 적절하게 해제해야 합니다.
MFC에서는 CPen, CBrush, CFont 등 다양한 GDI 객체 클래스를 제공하며, 이를 활용하여 다양한 스타일을 설정할 수 있습니다.
하지만 이들 객체를 무분별하게 생성하거나 해제하지 않으면 GDI 리소스 누수가 발생할 수 있어 주의가 필요합니다.
🧼 SelectObject 이후 원래 객체 복원
GDI 객체를 DC에 적용할 때는 SelectObject() 함수를 사용하는데, 이때 반환되는 기존 객체를 따로 저장해 두었다가 작업이 끝난 후 반드시 복원해주는 것이 올바른 사용법입니다.
CPen pen(PS_SOLID, 2, RGB(255,0,0));
CPen* pOldPen = pDC->SelectObject(&pen);
// 선 그리기
pDC->MoveTo(10, 10);
pDC->LineTo(200, 10);
// 원래 펜으로 복원
pDC->SelectObject(pOldPen);
⚠️ 주의: GDI 객체를 new 연산자로 동적으로 생성한 경우 delete를 통해 수동 해제가 필요합니다. 그렇지 않으면 리소스 누수가 발생할 수 있습니다.
📋 GDI 객체 관리 체크리스트
- ✅SelectObject() 사용 시 기존 객체 보관
- ✅사용이 끝나면 반드시 SelectObject()로 원래 객체 복원
- ✅delete 연산자로 동적 생성 객체 해제
- ✅RAII 방식을 도입하면 자동 해제에 유리
GDI는 기본적인 그래픽 출력 기능을 손쉽게 구현할 수 있는 강력한 도구입니다.
하지만 성능 이슈나 리소스 관리를 등한시하면 오히려 시스템에 부담을 줄 수 있기 때문에, 철저한 객체 관리가 무엇보다 중요합니다.
❓ 자주 묻는 질문 (FAQ)
MFC에서 GDI는 꼭 필요한가요?
고급 그래픽이 필요하지 않다면 GDI만으로도 충분합니다.
CDC와 HDC의 차이는 무엇인가요?
CDC를 사용하면 다양한 GDI 함수를 멤버 함수로 쉽게 사용할 수 있습니다.
GDI와 GDI+는 어떻게 다른가요?
GDI+는 안티앨리어싱, 알파 블렌딩 등 고급 기능을 지원합니다.
CPaintDC와 CClientDC의 차이는?
상황에 따라 적절한 객체를 선택하는 것이 중요합니다.
출력된 GDI 객체가 화면에 보이지 않는 경우는?
그 외 영역에서 출력하면 다시 그려질 때 사라질 수 있습니다.
폰트를 여러 개 사용할 경우 주의할 점은?
리소스 누수를 방지하는 가장 좋은 방법은?
MFC에서 GDI 대신 사용할 수 있는 다른 그래픽 기술은?
그러나 이들은 설정과 구현 난이도가 더 높기 때문에 상황에 맞게 선택해야 합니다.
🧾 MFC에서 GDI를 활용해 그래픽 출력하는 가장 쉬운 방법
MFC에서 GDI를 활용해 선, 사각형, 텍스트 등을 출력하는 작업은 생각보다 어렵지 않습니다.
핵심은 CDC 객체를 올바르게 사용하고, 필요한 GDI 객체(Pen, Brush, Font 등)를 적절히 생성 및 관리하는 것입니다.
GDI는 DirectX나 OpenGL처럼 고성능 그래픽에는 적합하지 않을 수 있지만, 일반적인 애플리케이션에서는 충분한 성능과 간편한 코드 구조로 사랑받고 있습니다.
본 글에서는 GDI의 기본 개념부터 시작해 MFC에서 CDC를 통해 도형 및 텍스트를 출력하는 방법, 그리고 GDI 객체 관리 팁까지 자세히 다뤄봤습니다.
이제 여러분도 MFC 애플리케이션에 멋진 UI 요소를 직접 구현할 수 있을 것입니다.
꾸준한 연습과 실습으로 GDI의 다양한 기능을 익혀보세요!
🏷️ 관련 태그:MFC, GDI, CDC, 윈도우프로그래밍, 그래픽출력, C++, VisualStudio, GDI객체관리, 텍스트출력, 도형그리기