Win32 - API - Grapic

[TOC]

그래픽

GDI (Graphics Device Interface)

DC (Device Context)

DC 관련 함수

BeginPaint()
/*
HWND hWnd : 윈도우 핸들
LPPAINTSTRUCT lpPaint : 출력 영역에 대한 정보를 저장할 PAINTSTRUCT 구조체의 포인터
*/
HDC BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
PAINTSTRUCT 구조체
typedef struct tagPAINTSTRUCT {
    HDC         hdc; // 출력 영역(DC)에 대한 핸들 값
    BOOL        fErase; // 배경 삭제 여부
    RECT        rcPaint; // RECT 구조체
    BOOL        fRestore; // 시스템에서 사용
    BOOL        fIncUpdate; // 시스템에서 사용
    BYTE        rgbReserved[32]; // 시스템에서 사용
} PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT;
EndPaint()
/*
HWND hWnd : 윈도우 핸들
LPPAINTSTRUCT lpPaint : 출력 영역에 대한 정보를 저장할 PAINTSTRUCT 구조체의 포인터
*/
HDC EndPaint(HWND hWnd, const PAINTSTRUCT *lpPaint);
GetDC()
/*
HWND hWnd : 윈도우 핸들
return HDC: 윈도우 클라이언트 영역에 대한 DC(Device Context)
*/
HDC GetDC(HWND hWnd);
ReleaseDC()
/*
HWND hWnd : 윈도우 핸들
HDC hDC : GetDC()로 얻은 DC
return int : ?
*/
int ReleaseDC(HWND hWnd, HDC hDC);

GDI 오브젝트

Stock Object

GetStockObject

HGDIOBJ GetStockObject(int i);

wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

GDI 오브젝트 생성

GDI 오브젝트 사용

SelectObject()
/*
HDC hdc : DC
HGDIOBJ h : DC에 선택할 GDI 오브젝트 핸들러
return : 현재 선택되어있던 GDI 오브젝트 핸들러
*/
HGDIOBJ SelectObject(HDC hdc, HGDIOBJ h);
DeleteObject()
/*
HGDIOBJ ho : 삭제할 GDI 오브젝트 핸들러
return : 0 - 현재 선택됐거나 유효하지 않은 GDI 핸들, 0 이외 - 삭제 성공
*/
BOOL DeleteObject(HGDIOBJ ho);
todo - 현재 선택된 펜 핸들을 삭제해도 1이 리턴되는 이유는?
// Pen 생성
HPEN hPen = CreatePen(PS_DASHDOT, 1, RGB(255, 0, 0));
// DC에 펜 지정
HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);
MoveToEx(hdc, 100, 100, NULL);
LineTo(hdc, 150, 150);

//SelectObject(hdc, hOldPen);
BOOL bDeletePenResult = DeleteObject(hPen); // 1이 리턴된다.
GDI 오브젝트 사용 절차
  1. 핸들 선언
    • HPEN hPen, …
  2. GDI 오브젝트 생성
    • CreatePen(), …
  3. 생성된 GDI 오브젝트를 DC에 선택, 이때 이전 핸들을 저장
    • SelectObject()
  4. 사용
    • Rectangle(), Ellipse(), MoveToEx(), LineTo(), …
  5. 선택을 해제, 이때 저장된 이전 핸들을 선택되도록 한다.
    • SelectObject()
  6. 생성된 GDI 오브젝트를 삭제
    • DeleteObject()

GDI 오브젝트 종류

펜(Pen)
윈도우 기본 제공 펜
펜 생성
/*
int iStyle : 선의 모양 정의(PS_SOLID, PS_DASH, PS_DASHDOT...)
int nWidth : 선 굵기, 디폴트 1, 0일 경우 1로 지정됨
COLORREF color : 선 색상
*/
HPEN CreatePen(int iStyle, int nWidth, COLORREF color);
선 그리기
// DC에 펜 지정
HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);
MoveToEx(hdc, 100, 100, NULL);
LineTo(hdc, 200, 100);
사각형 그리기
Rectangle(hdc, 200, 100, 250, 150);

원 그리기

Ellipse(hdc, 250, 150, 300, 200);
브러시(Brush)
브러시 생성
HBRUSH CreateSolidBrush(COLORREF color);
// CreateHatchBrush, CreatePatternBrush, CreateBrushIndirect, CreateDIBPatternBrushPt
비트맵
이미지 종류
이미지를 다루는 두 가지 방법
  1. 비트맵을 리소스에 등록하여 사용
  2. LoadImage() 함수를 이용하여 파일로부터 읽어 사용
비트맵 사용법
// ========== Bitmap ==========
// 비트맵 헤더
BITMAP resBitmapHeader; // 리소스 비트맵 헤더
BITMAP fileBitmapHeader; // 파일 비트맵 헤더

// 리소스에 등록된 비트맵 불러오기
HBITMAP hResBitmap = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BITMAP1));

// 파일의 비트맵 불러오기, 파일은 프로젝트 폴더가 기준이다.(프로젝트 폴더 밖의 Debug 폴더에 넣지 않는다)
// 마지막 파라미터를 LR_LOADFROMFILE로 지정해야한다.
HBITMAP hFileBitmap = (HBITMAP)LoadImage(NULL, TEXT("zzal.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

// 비트맵 헤더를 읽어들임
GetObject(hResBitmap, sizeof(BITMAP), &resBitmapHeader);
GetObject(hFileBitmap, sizeof(BITMAP), &fileBitmapHeader);

// Memory DC 생성
HDC hResMemDC = CreateCompatibleDC(hdc);
HDC hFileMemDC = CreateCompatibleDC(hdc);

// Memory DC에 비트맵 선택
SelectObject(hResMemDC, hResBitmap);
SelectObject(hFileMemDC, hFileBitmap);

// Memory DC를 화면 DC에 복사
BitBlt(hdc, 300, 300, resBitmapHeader.bmWidth, resBitmapHeader.bmHeight, hResMemDC, 0, 0, SRCCOPY);
BitBlt(hdc, 300 + resBitmapHeader.bmWidth, 300, fileBitmapHeader.bmWidth, fileBitmapHeader.bmHeight, hFileMemDC, 0, 0, SRCCOPY);

// 생성했던 비트맵과 Memory DC를 제거
DeleteObject(hResBitmap);
DeleteObject(hFileBitmap);
DeleteDC(hResMemDC);
DeleteDC(hFileMemDC);
// ========== Bitmap ========== end
LoadBitmap()
/*
HINSTANCE hInstance : 인스턴스 핸들
LPCSTR lpBitmapName : 리소스 비트맵 이름(MAKEINTRESOURCE를 이용한다)
*/
HBITMAP LoadBitmap(HINSTANCE hInstance, LPCSTR lpBitmapName);
LoadImage()
/*
HINSTANCE hIns : 인스턴스 핸들
LPCSTR name : 파일 이름(경로)
UINT type : 이미지 타입 - IMAGE_BITMAP, IMAGE_CURSOR, IMAGE_ICON
int cx : 아래에서 설명
int cy : 상동
UINT fuLoad : 이미지를 읽어올 방법
*/
HANDLE LoadImage(HINSTANCE hIns, LPCSTR name, UINT type, int cx, int cy, UINT fuLoad);

HBITMAP hFileBitmap = (HBITMAP)LoadImage(NULL, TEXT("zzal.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
DDB & DIB
DIB Section
GetObject()
/*
HANDLE h : GDI 오브젝트의 핸들
int c : pv로 전달될 데이터 타입의 크기
LPVOID pv : 읽은 데이터를 기록할 버퍼
*/
int GetObject(HANDLE h, int c, LPVOID pv)
메모리 DC
/*
HDC hdc : 복사 원본이 될 DC
return : 복사된 DC
*/
HDC CreateCompatibleDC(HDC hdc)
BitBlt()
/*
HDC hdc : 비트맵이 복사될 DC
int x : 비트맵이 복사될 좌표
int y : 비트맵이 복사될 좌표
int cx : 비트맵이 복사될 넓이
int cy : 비트맵이 복사될 높이
HDC hdcSrc : 복사될 비트맵을 가지고 있는 DC
int x1 : 복사될 비트맵의 좌측 좌표
int y1 : 복사될 비트맵의 상단 좌표
DWORD rop : raster-operation code. 브러쉬와 복사원, 복사처의 비트맵 색상이 논리 연산될 방법을 지정
*/
BOOL BitBlt(HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, int y1, DWORD rop);
DeleteDC()
/*
HDC hdc : 삭제할 DC
return : 삭제 성공 여부
*/
BOOL DeleteDC(HDC hdc);
StretchBlt()
TransparentBlt()
TransparentBlt(hdc, 300 + resBitmapHeader.bmWidth, 300, fileBitmapHeader.bmWidth, fileBitmapHeader.bmHeight, hFileMemDC, 0, 0, fileBitmapHeader.bmWidth, fileBitmapHeader.bmHeight, RGB(231, 223, 220));
SetROP2
SetROP2(hdc, R2_MASKPEN); // 외곽은 검은색, 내부는 비어있는 사각형

색상 매크로 함수

RGB()

COLORREF RGB(BYTE r, BYTE g, BYTE b);
COLORREF 구조체
// COLORREF를 만드는 매크로 함수 
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))

GetRValue(), GetGValue(), GetBValue()

BYTE GetRValue(DWORD rgb);

BYTE r = GetRValue(color);

SetPixel

COLORREF SetPixel(HDC hdc, int x, int y, COLORREF color);

SetPixel(hdc, 150, 150, RGB(255, 0, 0));

GetPixel

COLORREF GetPixel(HDC hdc, int x, int y);

COLORREF color1 = GetPixel(hdc, 150, 150);

SetTextColor

COLORREF SetTextColor(HDC hdc, COLORREF color);

SetTextColor(hdc, RGB(255, 0, 0));

SetBkColor

COLORREF SetBkColor(HDC hdc, COLORREF color);

SetBkColor(hdc, RGB(0, 255, 255));

InvalidateRect()

/*
HWND hWnd : 무효화 대상이 되는 윈도우, NULL일 경우 전체 윈도우
RECT *lpRect : 무효화 영역, NULL(0)일 경우 전체 영역
BOOL bErase : TRUE : 지우고 다시 그림, FALSE : 지우지 않고 겹쳐그림
*/
BOOL InvalidateRect(HWND hWnd, RECT *lpRect, BOOL bErase);

무효영역