2011년9월7일_winAPI_DC정보를 수정하여 그래픽출력을 달리하자.



● GDI (Graphic Device Interface)

화면, 프린터 등의 모든 출력 장치를 제어하는 윈도우즈(운영체제)의 핵심모듈.
출력을 위한 중앙 통제 센터라고 할 수 있다.


● GDI Object

그래픽출력에 사용되는 도구로 팬, 브러시, 비트맵, 폰트 등등을 말한다.

GDI 오브젝트

핸들 타입

설 명

디폴트값

정의

HPEN

선의 색

검정색 가는 실선

BLACK_PEN

브러시

HBRUSH

면의 색

흰색

WHITE_BRUSH

폰트

HFONT

문자 출력시 글꼴

시스템 글꼴

SYSTEM_FONT

비트맵

HBITMAP

비트맵이미지

선택되지 않음

팔레트

HPALETTE

팔레트

선택되지 않음

리전

HRGN

화면상의 영역

선택되지 않음

 



● DC (Device Context)

GDI Object를 모아 놓은 것 –> GDI는 현재 DC에 있는 GDI오브젝트 사용.


● 스톡오브젝트(Stock Object)

윈도우즈가 기본적으로 제공하는 GDI오브젝트.
빈번하게 사용되므로 운영체제가 부팅시 미리 만듬.
프로그래머가 일부러 만들지 않아도 언제든지 사용할 수 있으며 사용하고 난 후에 파괴할 필요도 없다.
framework개념과 비슷하구나..


▷ GetStockObject( )

HGDIOBJ GetStockObject(int fnObject);

인자로 사용하고자 하는 스톡오브젝트를 지정하는데 사용 가능한 스톡 오브젝트는 다음과 같다.

   1:  /* Stock Logical Objects */
   2:  #define WHITE_BRUSH         0                // 흰색 브러시
   3:  #define LTGRAY_BRUSH        1                // 밝은 회색 브러시
   4:  #define GRAY_BRUSH          2                // 회색 브러시
   5:  #define DKGRAY_BRUSH        3                // 어두운 회색 브러시
   6:  #define BLACK_BRUSH         4                // 검은 브러시
   7:  #define NULL_BRUSH          5                // 투명 브러시
   8:  #define HOLLOW_BRUSH        NULL_BRUSH        // 투명(?) 브러시
   9:  #define WHITE_PEN           6                // 흰색 펜
  10:  #define BLACK_PEN           7                // 검은색 펜
  11:  #define NULL_PEN            8                // 투명 펜
  12:  #define OEM_FIXED_FONT      10                // 장치 지원 폰트
  13:  #define ANSI_FIXED_FONT     11                // 고정폭 폰트
  14:  #define ANSI_VAR_FONT       12                // 가변폭 폰트
  15:  #define SYSTEM_FONT         13                // 시스템 폰트
  16:  #define DEVICE_DEFAULT_FONT 14                // 장치 기본 폰트
  17:  #define DEFAULT_PALETTE     15                // 기본 팔레트
  18:  #define SYSTEM_FIXED_FONT   16                // 시스템 고정 폰트

주로 무채색의 브러시와 펜만 제공되며 원색 브러시는 직접 만들어 써야 한다.




● 예제코드 : GdiObject

▷ main.cpp

   1: // winAPI p.154 DC정보의 수정
   2: // 2011년 9월 7일 작성 
   3: #include <windows.h>    // 모든 API함수들의 원형과 사용하는 상수들이 정의되어 있음.
   4: #include "MsgProc.h"    //add
   5: //#include "resource.h"    //자동으로 만들어지는 헤더파일.
   6:  
   7: LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);    //메시지처리함수
   8: HINSTANCE g_hlnst;    //핸들 인스턴스
   9: LPCTSTR lpszClass = TEXT("GdiObject");        //윈도우 제목으로 사용되는 const char * (문자열)
  10:  
  11: //add
  12: typedef struct MESSAGEMAP {
  13:     UINT iMessage;
  14:     LRESULT (*lpfnMsgProc)(HWND, WPARAM, LPARAM);
  15: } MESSAGEMAP;
  16:  
  17: //시작함수.
  18: int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
  19: {
  20:     HWND hWnd;
  21:     MSG Message;
  22:     WNDCLASS WndClass;
  23:     g_hlnst = hInstance;
  24:  
  25:     WndClass.cbClsExtra = 0;
  26:     WndClass.cbWndExtra = 0;
  27:     WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  28:     //WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  29:     WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  30:     WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  31:     WndClass.hInstance = hInstance;
  32:     WndClass.lpfnWndProc = WndProc;
  33:     WndClass.lpszClassName = lpszClass;
  34:     WndClass.lpszMenuName = NULL;
  35:     WndClass.style = CS_HREDRAW | CS_VREDRAW;
  36:     RegisterClass(&WndClass);
  37:  
  38:     
  39:     hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
  40:         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,        
  41:         NULL, (HMENU)NULL, hInstance, NULL);
  42:     
  43:     ShowWindow(hWnd, nCmdShow);
  44:  
  45:     while(GetMessage(&Message, NULL, 0, 0)) 
  46:     {
  47:         TranslateMessage(&Message);
  48:         DispatchMessage(&Message);
  49:     }
  50:  
  51:     return (int)Message.wParam;
  52: }
  53:  
  54: //운영체제가 호출하는 CALLBACK함수 (메시지 처리)
  55: LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
  56: {
  57:     //add
  58:     int i;
  59:  
  60:     static MESSAGEMAP MessageMaps[] = {
  61:         {WM_CREATE, OnCreate},
  62:         {WM_COMMAND, OnCommand},
  63:         {WM_LBUTTONDOWN, OnLButtonDown},
  64:         {WM_PAINT, OnPaint},
  65:         {WM_DESTROY, OnDestroy}
  66:     };
  67:  
  68:     for(i = 0 ; i < sizeof(MessageMaps) / sizeof(MessageMaps[0]) ; ++i)
  69:     {
  70:         if(MessageMaps[i].iMessage == iMessage)
  71:         {
  72:             return (*MessageMaps[i].lpfnMsgProc)(hWnd, wParam, lParam);
  73:         }
  74:     }
  75:     /////////////////////////////////
  76:  
  77:     return(DefWindowProc(hWnd, iMessage, wParam, lParam));
  78: }


▷ MsgProc.h

   1: //MsgProc.h
   2: #ifndef __MSGPROC_H_
   3: #define    __MSGPROC_H_
   4:  
   5: #include <windows.h>
   6:  
   7: LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
   8: LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
   9: LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam);
  10: LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam);
  11: LRESULT OnDestroy(HWND hWnd, WPARAM wParam, LPARAM lParam);
  12:  
  13: extern HINSTANCE g_hlnst;
  14:  
  15: #endif


▷ MsgProc.cpp

   1: //MsgProc.cpp
   2:  
   3: #include "MsgProc.h"
   4: //#include "resource.h"
   5:  
   6:  
   7: LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
   8: {
   9:     return 0;
  10: }
  11:  
  12: LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
  13: {
  14:  
  15:     return 0;
  16: }
  17:  
  18: LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
  19: {
  20:  
  21:     return 0;
  22: }
  23:  
  24: LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
  25: {
  26:     HDC hdc;
  27:     PAINTSTRUCT ps;
  28:     HBRUSH MyBrush, OldBrush;
  29:     HPEN MyPen, OldPen;
  30:  
  31:     hdc = BeginPaint(hWnd, &ps);
  32:  
  33:     //MyBrush = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
  34:     //OldBrush = (HBRUSH)SelectObject(hdc, MyBrush);
  35:     Rectangle(hdc, 50, 50, 300, 200);
  36:     //SelectObject(hdc, OldBrush);
  37:  
  38:     //사각형의 테두리를 회색으로. -> 사각형을 내부를 투명으로 
  39:     //MyPen = (HPEN)GetStockObject(WHITE_PEN);
  40:     //OldPen = (HPEN)SelectObject(hdc, MyPen);
  41:     MyBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
  42:     OldBrush = (HBRUSH)SelectObject(hdc, MyBrush);
  43:  
  44:     Rectangle(hdc, 150, 100, 450, 300);
  45:  
  46:     SelectObject(hdc, OldBrush);
  47:     //SelectObject(hdc, OldPen);
  48:  
  49:     EndPaint(hWnd, &ps);
  50:  
  51:     return 0;
  52: }
  53:  
  54: LRESULT OnDestroy(HWND hWnd, WPARAM wParam, LPARAM lParam)
  55: {
  56:     PostQuitMessage(0);
  57:     return 0;
  58: }
  59:  


<실행결과>

image 

투명브러시를 사용하여 사각형을 겹쳤다.

다음과 같이 MsgProc.cpp파일을 조금 수정하여 브러시 색깔을 바꾸면,

   1: LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
   2: {
   3:     HDC hdc;
   4:     PAINTSTRUCT ps;
   5:     HBRUSH MyBrush, OldBrush;
   6:     HPEN MyPen, OldPen;
   7:  
   8:     hdc = BeginPaint(hWnd, &ps);
   9:  
  10:     MyBrush = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
  11:     OldBrush = (HBRUSH)SelectObject(hdc, MyBrush);
  12:     Rectangle(hdc, 50, 50, 300, 200);
  13:     SelectObject(hdc, OldBrush);
  14:  
  15:     //사각형의 테두리를 회색으로. -> 사각형을 내부를 투명으로 
  16:     MyPen = (HPEN)GetStockObject(WHITE_PEN);
  17:     OldPen = (HPEN)SelectObject(hdc, MyPen);
  18:     MyBrush = (HBRUSH)GetStockObject(GRAY_BRUSH);
  19:     OldBrush = (HBRUSH)SelectObject(hdc, MyBrush);
  20:  
  21:     Rectangle(hdc, 150, 100, 450, 300);
  22:  
  23:     SelectObject(hdc, OldBrush);
  24:     SelectObject(hdc, OldPen);
  25:  
  26:     EndPaint(hWnd, &ps);
  27:  
  28:     return 0;
  29: }



image 

사격형 내부의 색깔과 두 번재 사격형의 테두리색이 바뀌었다.

 

   5:     HBRUSH MyBrush, OldBrush;
  10:     MyBrush = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
  11:     OldBrush = (HBRUSH)SelectObject(hdc, MyBrush);

예전 DC설정과 현재 바꿀 브러시설정을 저장할 변수를 선언하여,
GetStockObject()를 호출하면 아래와 같이,

image 

DC핸들이 가리키는 곳의 GDI오브젝트(브러시)에 MyBrush의 값이 들어가게 되고,
OldBrush의 값은 과거의 DC설정이 저장된다.