GDI 기초: 도형과 텍스트 그리기

GDI 기초 / 그리기 확장: 선, 사각형, 원 그려보기

GDI 기초 과정을 통해 직접 그리는 구조를 이해해야 합니다. 입력으로 좌표를 받고, 그 좌표를 기준으로 WM_PAINT에서 다시 그리는 방식이 핵심입니다.
이전 단계에서 입력 처리까지 구현했다면, 이제 단순 텍스트를 넘어 도형을 직접 그려보는 단계로 넘어가게 됩니다. 이 과정에서 “출력”이 아니라 “렌더링”이라는 개념이 자연스럽게 연결됩니다.

Hello World와 입력 처리 다음에 GDI 를 배우는 이유

WinAPI의 흐름은 다음처럼 확장됩니다.

  • Hello World → 화면 출력
  • 입력 처리 → 사용자 반응
  • GDI → 화면 구성

이 단계부터는 프로그램이 단순히 결과를 보여주는 것이 아니라, 화면 자체를 직접 만들어가는 구조로 바뀝니다.

STEP 1 – GDI 와 HDC 개념 이해하기

GDI의 핵심은 HDC입니다. 이는 화면에 그리기 위한 디바이스 컨텍스트 핸들로, 모든 그리기 작업의 기준이 됩니다.

PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);

// 그리기 작업 수행

EndPaint(hwnd, &ps);

BeginPaint와 EndPaint 사이에서만 안정적으로 그리기가 이루어집니다. 이 구조를 벗어나면 화면이 정상적으로 갱신되지 않을 수 있습니다.

STEP 2 – 선 그리기: MoveToEx와 LineTo 사용하기

선은 가장 기본적인 도형이며, 시작점과 끝점을 이용해 그립니다.

  1. 시작 위치 설정 (MoveToEx)
  2. 끝 위치까지 선 그리기 (LineTo)
MoveToEx(hdc, 50, 50, NULL);
LineTo(hdc, 200, 200);

MoveToEx로 시작 위치를 지정하지 않으면 예상과 다른 위치에서 선이 그려질 수 있습니다.

STEP 3 – 사각형과 원 그리기

사각형과 원은 경계 좌표를 이용해 간단하게 그릴 수 있습니다.

Rectangle(hdc, 50, 50, 200, 150);
Ellipse(hdc, 220, 50, 350, 150);

이 함수들은 왼쪽 위와 오른쪽 아래 좌표를 기준으로 도형을 생성합니다. 기본 색상이 적용되는 이유는 GDI의 기본 펜과 브러시가 사용되기 때문입니다.

STEP 4 – 입력 처리와 그리기 연결하기

GDI를 실제 프로그램처럼 사용하려면 입력 처리와 반드시 연결해야 합니다.

기본 흐름은 다음과 같습니다.

  • 입력 발생
  • 좌표 저장
  • InvalidateRect 호출
  • WM_PAINT에서 도형 그리기
case WM_LBUTTONDOWN:
{
    g_x = LOWORD(lParam);
    g_y = HIWORD(lParam);

    InvalidateRect(hwnd, NULL, TRUE);
}
return 0;
case WM_PAINT:
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);

    Ellipse(hdc, g_x - 20, g_y - 20, g_x + 20, g_y + 20);

    EndPaint(hwnd, &ps);
}
return 0;

이 구조를 통해 클릭 위치에 원을 그릴 수 있습니다.
여기서 중요한 점은 WM_PAINT가 화면을 매번 새로 그린다는 것입니다. 그래서 이전 도형이 사라지는 현상이 발생할 수 있습니다. 여러 개의 도형을 유지하려면 좌표를 하나가 아니라 리스트 형태로 저장해야 합니다.
이 개념까지 이해하면 WinAPI에서 단순 출력이 아닌, 실제 그래픽 프로그램의 기초를 갖추게 됩니다.