본문 바로가기
프로그래밍/API

API-GdiObject

by 리뷰하는 (게임)프로그래머_리프TV 2010. 4. 22.



#include <windows.h>

LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
HINSTANCE g_hInst;
LPCTSTR lpszClass = TEXT("GdiObject");

int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
					 LPSTR lpszCmdParam, int nCmdShow )
{
	HWND hWnd;
	MSG Message;
	WNDCLASS WndClass;
	g_hInst = hInstance;

	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hbrBackground = (HBRUSH)GetStockObject( COLOR_WINDOW+1 );
	WndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
	WndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
	WndClass.hInstance = hInstance;
	WndClass.lpfnWndProc = WndProc;
	WndClass.lpszClassName = lpszClass;
	WndClass.lpszMenuName = NULL;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;
	RegisterClass( &WndClass );

	hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, (HMENU)NULL, hInstance, NULL );
	ShowWindow( hWnd, nCmdShow );

	while( GetMessage( &Message, NULL, 0, 0 ) )
	{
		TranslateMessage( &Message );
		DispatchMessage( &Message );
	}
	return (int)Message.wParam;
}

LRESULT CALLBACK WndProc( HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam )
{
	HDC hdc;
	PAINTSTRUCT ps;
	// 현재 브러쉬와, 이전 브러쉬를 저장하기 위한 변수
	HBRUSH Mybrush, OldBrush;
	// 현재 팬과, 이전 팬을 저장하기 위한 변수
	HPEN MyPen, OldPen;
		
	switch( iMessage )
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint( hWnd, &ps );

		// MyPen에 PS_SOLID로 5의 크기만큼 파란색으로 지정
		MyPen = CreatePen( PS_SOLID, 5, RGB(0, 0, 255) );
		// 현재 설정을 OldPen에 집어 넣고
		// 앞으로 팬의 설정을 MyPen으로 지정한다.
		OldPen = (HPEN)SelectObject( hdc, MyPen );

		// 위와 비슷 색상을 GRAY_BRUSH로 지정
		Mybrush = (HBRUSH)GetStockObject( GRAY_BRUSH );
		// 현재 팬은 MyBrush, 이전 설정은 OldBrush
		OldBrush = (HBRUSH)SelectObject( hdc, Mybrush );

		// 위 설정에 따라서 네모를 그리고
		Rectangle( hdc, 50, 50, 300, 200 );
		// OldBrush로 다시 설정해주고
		SelectObject( hdc, OldBrush );

		// OldPen으로 다시 설정
		SelectObject( hdc, OldPen );
		// 사용하고 난 GDI오브젝트는 Delete를 해주자.(Pen삭제)
		DeleteObject( MyPen );

		// 그냥 일반 네모가 찍힐 것이다.
		Rectangle( hdc, 150, 150, 300, 200 );

		// HS_BDIAGONAL(좌하향 줄무늬) 타입과 색상 지정
		Mybrush = CreateHatchBrush( HS_BDIAGONAL, RGB(255, 0, 255) );
		// 브러쉬를 설정하면서 이전 설정을 백업
		OldBrush = (HBRUSH)SelectObject( hdc, Mybrush );

		// 네모를 그리자
		Rectangle( hdc, 0, 0, 100, 200 );

		// 다시 이전 설정으로 복귀
		SelectObject( hdc, OldBrush );

		// 사용한 브러쉬 삭제
		DeleteObject( Mybrush );

		EndPaint( hWnd, &ps );
		return 0;
	}
	return( DefWindowProc( hWnd, iMessage, wParam, lParam));
}​



먼저 GDI 오브젝트와, 스톡 오브젝트에 대해서 차이를 알아야 한다.
GDI 오브젝트는 출력에 사용되는 도구인데, 펜, 브로시, 비트맵, 폰트 등등... 이라고 한다.

기본적으로 BeginPaint나 GetDC를 하게 되면 디폴트로 몇가지 만들어 지는데,

 GDI 오브젝트  핸들 타입   설명   디폴트 
 팬  HPEN  선을 그을 때 사용  검정색의 가는 실선
 브러시  HBRUSH  면을 채울 때 사용  흰색
 폰트  HFONT  문자 출력에 사용 되는 글꼴  시스템 글꼴
 비트맵  HBITMAP  비트맵 이미지  선택 되지 않음
 팔레트  HPALETTE  팔레트  선택 되지 않음
 리전  HRGN  화면상의 영역  선택 되지 않음


이 처럼 존재하고, 이 기본 출력을 변경하고 싶을 때에,
GDI 오브젝트를 만들고 선택한다.

그리고 스톡 오브젝트는
윈도우즈가 기본적으로 제공하는 GDI 오브젝트를 말한다.
운영체제가 부팅시 만들어 놓기 때문에, 언제든지 사용가능하고, 파괴해 주지 않아도 된다는 장점이 있다.

 fnObject  설명
 BLACK_BRUSH  검정색 브러시
 GRAY_BRUSH  회색 브러시
 NULL_BRUSH  투명 브러시
 WHITE_BRUSH  흰색 브러시
 DKGRAY_BRUSH  짙은 회색 브러시
 LTGRAY_BRUSH  옅은 회색 브러시
 DC_BRUSH  색상 브러시. SetDCBrushColor 함수로 설정
 BLACK_PEN  검정색 펜
 WHITE_PEN  흰색 펜
 NULL_PEN  투명 펜
 DC_PEN  색상 펜. SetDCPenColor 함수로 설정
 ANSI_FIXED_FONT  고정폭 폰트
 ANSI_VAR_FONT  가변폭 폰트
 DEFAULT_PALETTE  시스템 팔레트


참 많네--;

여튼, 소스를 보면,

MyPen이나 OldPen(브러시도 마찬가지)를 사용해서 SelectObject를 사용할때도 있고 그렇지 않을 때도 있다.
이 부분에 대해서 좀 애매하기도 한데,

□ 의 설정값이 있다고 치자.
■ 의 설정값으로 변경을 하게 되면

1. ■ -> □
2.         ■ -> □
라고 말 할 수 있겠다.

새로운 값이 들어 오면 이전 값을 밀어 내는데,
그 값을 OldPen, Brush에서 가지고 가는 것이다.

그리고 다시 값을 복원 하게 될때
1. □ -> ■
2.         □ -> ■
식으로 복원 하는 것이다.( 그래서 복원시에는 구지 return 값을 저장하지 않은 것이다. )

또, 스톡 오브젝트(GetStockObject)를 사용했을 경우에는 구지 delete를 해주지 않은 것도 그 이유에서 이다.
물론 나중에 다시 GdiObject를 사용 하였기 때문에 delete를 해주고 있기는 하다.
함수를 잘 보면 GetStockObject가 있고, CreatePen, CreateHatchBrush가 있는데 어떤 상황에서 DeleteObject를 해주는 지는 감이 올 것이다.

// 실행 결과


추가로 DeleteObject를 해주지 않았을 경우에 대해서 어떤 일이 벌어 질 수 있는가,
에 대한 예제가 있지만,
구지 올리기 보단,,,,
"쓰고나면 다시 상태를 돌려주자"
"쓰고나면 지우자! 무조건!!"

으로 기억하자

또한, 투명 펜이나 투명 브러시의 경우엔 외곽선을 그리지 않거나, 외곽선만을 그리고 싶을때 둘중 하나의 값을 NULL로 해주는 식으로 기억하면 될 것 같다.

'프로그래밍 > API' 카테고리의 다른 글

API-BitMap  (0) 2010.04.24
API-RopMode  (0) 2010.04.24
API-resource(3)  (0) 2010.04.21
API-resource(2)  (0) 2010.04.21
API-resource(1)  (0) 2010.04.21