GDI에 대해서는 앞서 간략하게 소개했었는데, 화면이나 프린터 등의 모든 출력 장치를 제어하는 윈도우즈의 핵심 모듈 중에 하나이다. 즉 출력을 위한 중앙 통제 센터 정도로 생각하면 되는데, 윈도우즈 프로그램에서의 모든 출력은 GDI를 통해서 화면과 프린터로 나가게 되어 있다.
GDI 오브젝트란 그래픽 출력에 사용되는 도구를 말하며 펜, 브러시, 비트맵, 폰트 등등이 모든 GDI 오브젝트이다. 사람이 그림을 그릴 때 연필, 붓 등의 도구를 사용하는 것과 마찬가지로 GDI가 그래픽을 출력할 때는 GDI 오브젝트를 사용한다. 즉 선을 그을 때는 펜으로 그리며 면은 브러시로 채우고 문자열을 출력할 때는 폰트를 사용한다는 말이다. GDI 오브젝트를 모아 놓은 것이 DC이며 GDI는 현재 DC에 선택되어 있는 GDI 오브젝트를 사용한다. 그래서 사용자는 그래픽을 그리기 전에 DC에 적절한 오브젝트를 선택함으로써 원하는 모양과 속성으로 그래픽을 출력할 수 있다.
예를 들어 그냥 선을 그으면 디폴터 펜인 검정색 펜으로 그려지지만 파란색 펜을 만들어서 DC에 선택한 후 그으면 GDI는 이 파란색 펜을 사용하기 때문에 파란색 선이 그려지게 되는 것이다. 마찬가지로 브러시나 폰트를 변경하면 채워지는 색상이나 문자열의 글꼴 모양을 변경할 수 있다. GDI 오브젝트는 GDI가 그래픽 출력을 위해 사용하는 도구임과 동시에 사용자가 GDI의 출력을 조정할 수 있는 도구이기도 하다. 원하는 색상과 모양의 오브젝트를 만들고 DC에 선택해 놓으면 이후부터 석택된 오브젝트의 속성대로 출력된다.
GDI 오브젝트는 내부적으로 일종의 구조체이겠지만 그 선언문이 공개되어 있지 않으므로 우리가 이 구조체를 볼 수는 없고 볼 필요도 없다. GDI 오브젝트는 모두 핸들로 관리되므로 우리는 다만 GDI 오브젝트를 생성하는 함수를 부르고 이 함수가 리턴하는 핸들을 받아서 사용하기만 하면 된다. GDI 오브젝트를 만들 때 핸들을 발급받으며 선택하거나 삭제할 때는 이 핸들만 가지고 GDI 오브젝트를 사용한다. DC가 BeginPaint나 GetDC 함수에 의해서 처음 만들어졌을 때 디폴트로 선택된 GDI 오브젝트는 다음과 같았다.
보다시피 대체로 무난한 속성으로 설정되어 있다. 그래서 DC에 별다른 지정을 하지 않더라도 그냥 출력하면 디폴트 속성이 적용되어 검정색 펜, 흰색 브러시, 시스템 글꼴로 출력되는 것이다. 이런 출력을 바꾸고 싶을 때 GDI 오브젝트를 만들고 선택하며 이 장에서 그 방법을 연구해보도록 하겠다.
스톡 오브젝트
스톡 오브젝트는 윈도우즈가 기본적으로 제공하는 GDI 오브젝트를 말한다. 아주 빈번하게 사용되므로 운영체제가 부팅할 때부터 미리 만들어 놓는다. 우리가 일부러 만들지 않더라도 언제든지 사용할 수 있으며 사용하고 난 후에 파괴할 필요도 없다. 다음 함수로 핸들을 얻어 사용하기만 하면 된다.
HGDIOBJ GetStockObject
fnObject 인수에 사용하고자 하는 스톡 오브젝트를 지정하는데 사용가능한 스톡 오브젝트는 다음과 같다. 주로 브러시와 펜이 스톡 오브젝트로 제공된다. 2장에서 처음 공부했던 WHITE_BRUSH도 알고 보면 스톡 오브젝트의 일종이다.
주로 무채색의 브러시와 펜만 제공되며 원색 브러시는 직접 만들어 써야 한다. DC_BRUSH, DC_PEN 스톡 오브젝트는 2000이상에서만 사용할 수 있는데 별도의 함수로 색상을 변경할 수 있어 편리하지만 95/98에서 지원하지 않으므로 아직 함부로 사용하기는 힘들다. 그러면 스톡 오브젝트를 사용하는 예제를 만들어 보고 GDI 오브젝트를 어떤 식으로 사용하는가를 살펴보도록 하자. GdiObject라는 프로젝트를 만들고 다음과 같이 소스를 작성한다.
지난 시간이 이야기 했지만 한 번 더 말하자만 앞으로는 WndProc의 소스만 보일 것이다. 이때까지 실습을 통해 알 수 있겠지만 WinMain은 아주 특별한 경우가 아미녀 변하지 않으므로 굳이 소스 리스트를 보일 필요가 없을 것이다. 괜히 지면만 낭비하기 때문이다. 따라서 앞으로는 꼭 필요한 경우가 아니라면 WinMain에 대한 언급은 하지 않도록 하겠다. WndProc외에는 WinMain 앞에 선언된 IpszClass 문자열값만 프로젝트의 이름으로 변경하기로 한다.
LPSTR ipszClass=TEXT("GdiObject");
이 문자열은 윈도우 클래스의 이름과 윈도우 타이틀 바에 사용되는데 당연히 바꿔야 할 부분이므로 앞으로 이 부분에 대해서도 설명을 생략하겠다. 프로젝트를 만들 때마다 이 값을 변경하는 것이 번거롭다면 굳이 바꾸지 않아도 상관없으므로 컴파일과 실행에 아무런 지장이 없다는 점만 알고 넘어가면 된다. 다만 타이틀바에 나타나는 캡션이 매번 같으면 보기에 좋지않고 프로젝트끼리 잘 구분이 되지 않기 때문에 웬만하면 각 프로젝트별로 구분을 해주는 것이 좋다.
이 소스에서 WM_PAINT 메시지ㅡㄹ 보면 BeginPaint로 DC를 얻은 후 Rectangle 함수로 사각형을 그리고 EndPaint로 그리기를 종료한다. DC를 만든 후 어떠한 GDI오브젝트도 만들거나 선택하지 않고 곧바로 사각형을 그렸으므로 이 때 사용되는 GDI 오브젝트는 모두 디폴트 GDI 오브젝트이다.