목표
Win32 API를 활용해 윈도우에 도형, 비트맵 등을 출력하고 ROP2 모드를 설정하기 위한 GDI, DC의 개념과 스톡 오브젝트(Stock Object)의 개념에 대해서 알아보도록 하겠습니다.
목차 클릭하면 해당 목차로 이동합니다.
개요
GDI(Graphic Devcie Interface)와 DC(Device Context)는 이전 포스팅에서 꾸준히 다뤄온 친구들입니다. 다시 한 번 복습하고 구체적인 내용을 알아보도록 하겠습니다.
[Windows API] Device Context란?, Win32 API를 활용해 문자열 출력하기
1. GDI, GDI 오브젝트, DC의 개념
GDI는 화면, 프린터와 같은 모든 출력 장치를 제어하는 인터페이스입니다. 그래픽을 출력하기 위해 사용되는 도구를 GDI 오브젝트(Object)라고 합니다. 펜, 브러시, 비트맵, 폰트 등이 GDI 오브젝트에 해당합니다. 이러한 GDI 오브젝트는 DC(Device Context)에 담겨져 있습니다. 우리는 DC에서 원하는 내용을 변경하여 출력합니다. 그래서 여태까지 GetDC, BeginPaint와 같은 함수를 사용해 DC를 생성해 핸들을 얻어서 사용했던 것입니다.
글로 설명하면 복잡하게 느껴질 수 있기 때문에 그림을 보도록 하겠습니다.
GDI 오브젝트는 DC에 담겨져 있고 GDI를 통해 출력 장치에 출력을 하게 됩니다. 개발자는 GetDC, BeginPaint와 같은 함수를 통해 DC를 생성하게 됩니다.
GDI 오브젝트의 내부는 공개되어 있지 않기 때문에, 핸들을 이용해서 사용합니다. 핸들에 대한 내용은 다음 링크를 참고해주세요.
[Windows API] Win32 API에서 제공하는 자료형(데이터 타입) 모음과 핸들(HANDLE)
기본적으로 DC가 만들어졌을 때 디폴트로 선택된 GDI 오브젝트는 다음과 같습니다.
GDI 오브젝트 | 핸들 타입 | 설명 | 디폴트 |
펜(Pen) | HPEN | 선을 그을 때 사용된다. | 검정색의 가는 선 |
브러시(Brush) | HBRUSH | 면을 채울 때 사용된다. | 흰색 |
폰트(Font) | HFONT | 문자 출력에 사용되는 글꼴 | 시스템 글꼴 |
비트맵(HBITMAP) | HBITMAP | 비트맵 이미지 | 선택되지 않음 |
팔레트(HPALETTE) | HPALETTE | 팔레트 | 선택되지 않음 |
영역(RGN) | HRGN | 영역 | 선택되지 않음 |
기본적으로 핸들을 불러와 사용하게 되면 디폴트값이 선택되어 사용됩니다. 그래서 앞서 진행했던 프로젝트에서 선을 긋게 되면 검은색의 가는 선이 출력되는 것입니다.
1-1 스톡 오브젝트(Stock Object)
윈도우에서 기본적으로 제공하는 GDI 오브젝트를 스톡 오브젝트라고 합니다. 스톡 오브젝트는 언제든 사용할 수 있고, 사용 후에 해지않아도 된다는 특징이 있습니다. 핸들을 얻어 사용하면 되므로 편리하다는 장점이 있습니다. 반면, 사용자가 직접 만들어 사용하는 오브젝트는 꼭 해지해야 합니다.
스톡 오브젝트를 사용하기 위한 함수는 다음과 같습니다.
HGDIOBJ GetStockObject(int fnObject);
GetStockObject 함수를 사용해 스톡 오브젝트를 사용할 수 있습니다. 인수인 fnObject는 얻고자 하는 오브젝트입니다. 윈도우에서 제공하는 스톡 오브젝트는 다음과 같습니다.
fnObject | 설명 |
BLACK_BRUSH | 검정색 브러쉬 |
GRAY_BRUSH | 회색 브러쉬 |
NULL_BRUSH | 투명 브러쉬 |
WHITE_BRUSH | 흰색 브러쉬(디폴트) |
DKGRAY_BRUSH | 진한 회색 브러쉬 |
LTGRAY_BRUSH | 연한 회색 브러쉬 |
BLACK_PEN | 검정색 펜(디폴트) |
WHITE_PEN | 흰색 펜 |
NULL_PEN | 투명 펜 |
ANSI_FIXED_FONT | 고정폭 폰트 |
ANSI_VAR_FONT | 가변폭 폰트 |
DEFAULT_PALETTE | 시스템 팔레트 |
보시는 것처럼 디폴트 값이 정해져 있기 때문에, 브러쉬나 펜 등 오브젝트의 정보를 선택하지 않아도 디폴트 값이 적용됩니다.
2. 스톡 오브젝트 활용과 색상
GdiObject 프로젝트
여태까지 진행했던 프로젝트에서 GDI 오브젝트 중 디폴트 값을 사용해서 선, 그림 등을 윈도우에 출력했습니다. 이번 프로젝트에서 스톡 오브젝트 중 브러쉬를 변경하여 사각형을 출력하는 프로젝트를 실습해보도록 하겠습니다.
설명에 앞서 코드부터 확인해보도록 하겠습니다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage,
WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH MyBrush, OldBrush;
switch (iMessage) {
case WM_CREATE:
hWndMain = hWnd;
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
MyBrush = (HBRUSH)GetStockObject(GRAY_BRUSH);
OldBrush = (HBRUSH)SelectObject(hdc, MyBrush);
Rectangle(hdc, 30, 30, 200, 100);
SelectObject(hdc, OldBrush);
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
먼저, 브러쉬의 핸들을 얻습니다. 평소와 다르게 MyBrush, OldBrush 2개를 얻는 것을 확인할 수 있습니다. 이는 하나의 값은 무조건 갖고 있어야 하기 때문에, 기존의 정보를 저장해두기 위함입니다. 자세한 내용은 다음 포스팅에서 확인하겠습니다.
WM_PAINT 메세지 처리 부분을 보면, BeginPaint 함수를 통해 DC를 생성해 핸들값을 hdc에 저장합니다. GetStockObject 함수를 통해 스톡 오브젝트를 사용합니다. 위에서 확인했듯이, 반환형이 int형입니다. 핸들값을 사용하기 위해 BRUSH의 핸들인 HBRUSH로 명시적 형변환을 합니다. 이후, SelectObject 함수를 통해서 기존 브러쉬 정보를 저장합니다. 이를 사용후, 저장하고 있던 브러쉬 정보를 선택하고 마무리합니다.
평소와 다르게 리소스를 반환하는(메모리를 삭제하는) 코드가 없습니다. 이는, 윈도우에서 기본적으로 제공하는 스톡 오브젝트는 따로 리소스를 반환하지 않아도 되기 때문입니다. (자동으로 되기 때문에)
색상
이제, 선이나 도형을 그릴 때 색상을 변경할 수 있습니다. Win32 API에서 색상은 COLORREF라는 DWORD형 구조체를 사용합니다. RGB로 표현하며 각 빨강(RED), 초록(GREEN), 파랑(BLUE)의 색상 정보를 나타냅니다. 자세한 정보는 Microsoft의 문서를 확인해주세요.
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-rgb
정리
펜, 브러쉬 등 우리가 윈도우를 생성할 때 무심코 사용했던 그래픽 요소들을 사용하기 위한 GDI, DC의 개념에 대해서 알아보았습니다. 기본적으로 스톡 오브젝트를 사용해서 윈도우를 생성하고 있던 것입니다. 다음 포스팅에서 그래픽에 대한 자세한 내용들을 확인해보도록 하겠습니다.
'개발 > Win32 API Programming' 카테고리의 다른 글
[Windows API] Win32 API의 그리기 모드와 ROP2 모드, 선 그리기 (0) | 2022.02.15 |
---|---|
[Windows API] Win32 API의 펜과 브러쉬, Old의 의미 (0) | 2022.02.08 |
[Windows API] Win32 API를 활용해 작업 영역 얻기 (0) | 2022.01.27 |
[Windows API] Win32 API의 백그라운드 작업과 콜백 함수 (0) | 2022.01.20 |
[Windows API] Win32 API를 활용해 시계, 일회용 타이머 만들기 - (2) (0) | 2022.01.18 |