2020년 7월 1일 수요일

WinApi - DC

1. 개요

윈도우즈에서 모든 그리기를 조율하는 데이터 구조체.

멤버가 매우 많은데, 필요할 때 마다 특정 부분만 변경해서, SelectObject 등의 함수로 적용한다.

종류는 그리는 포면에 따라, 보존 여부에 따라 구분된다

디스플레이 DC

화면 출력

프린터 DC

프린터 출력

메모리 DC

비트맵 출력 등 - 하나의 디스플레이 버퍼

정보 DC

정보 취득을 위해

Common DC

GetDC, BeginPaint 로 필요할 때마다 생성하고 지우는 것들.

그래서 속도가 느리지만 시스템에서 DC 옵션들을 캐시 해주기 때문에 매우 느린건 아니다.

Private DC

클래스 스타일에 CS_OWNDC 를 추가하는 경우 생기는 윈도우 전속 윈도우.

WM_CREATE 에서 GetDC 로 한번 초기화 하면 계속 유지된다.

주의할 점은 삭제하면 안된다는 것이다.

Class DC

Parent DC

과거의 유산. 사용이 금기시 된다.

WindowDC

GetWindowDC(hWnd) 를 통해 생성되는 DC.

작업영역을 넘어 윈도우 전체를 그릴 수 있다.

int GetDeviceCaps(HDC hdc, int nIndex);

위 함수를 통해 디바이스의 스펙을 대략 얻을 수 있다.

HORZSIZE, VERTSIZE

/ HORZRES, VERTRES

화면의 크기를 밀리미터 단위 / 픽셀 단위로 조사

LOGPIXELSX, LOGPIXELSY

인치당 픽셀 수를 계산. 프린터 DC 에서 주로 사용.

BITSPIXEL

픽셀당 비트수를 조사 = 화면의 가능한 색상 수

NUMCOLORS

색상 테이블의 수를 조사하되 256 이상의 경우 -1 리턴

CURVECAP

LINECAPS

POLYGONALCAPS

TEXTCAPS

장치의 ~~~ 능력을 조사

2. 생성, 무효화 영역

HDC hdc = GetDC(hWnd);

ReleaseDC(hWnd, hdc);

PAINTSTRUCT ps; // WM_PAINT 에서만 사용

HDC hdc = BeginPaint(hWnd, &ps);

EndPaint(hWnd, &ps);

아래 것은 무효화 영역을 유효화 해주는 기능이 추가되어 있다.

무효화 영역은 화면 전체를 다시 그리기는 낭비라서 생겼다.

Bool InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase);

Bool InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase);

위 함수로 조절한다.

lpRect 는 작업영역 기준 좌표, 전체인 경우는 NULL을 주면 되고,

bErase는 새로 쓰기를 할 것인지의 여부이다.

윈도우가 가려지던지해서 무효화 영역이 생기는 경우 WM_PAINT 메시지가 큐에 들어가는데, 여기서 BeginPaint 가 없으면 계속 메시지가 남고 무한 루프된다. 즉 BeginPaint 는 WM_PAINT를 처리한다. EndPaint 는 BeginPaint 가 생성하는 DC 를 해제한다. 이 때 처리되는 영역은 BeginPaint 가 가져오는 DC와는 관계 없이, 무효화 영역에 한정된다.

UpdateWindow(HWND hWnd);

를 사용하면 무효화 영역이 있는 경우, 큐를 무시하고 바로 WM_PAINT 를 보낸다.

BeginPaint 를 실행하면 WM_NCPAINT 와 WM_ERASEBKGND 메시지도 실행된다. 전자는 비작업영역을, 후자는 작업영역의 배경을 디폴트로 처리한다. 배경인 경우 윈도우 클래스의 배경색을 브러쉬로 해서 처리하며, 따로 DC 를 가져오지 말고 wParam 을 DC 로 바꿔서 사용해야한다. 이 DC는 클리핑 영역을 제외하고 다시 그린다.

3. GDI(Graphic Device Interface) Obj

대표적으로 아래 여섯이 있는 GDIOBJ를 모아 주관하는 것이 DC(Device Context) 이다.

HPEN

선 그을 때만 사용

HBRUSH

면을 채울 때 사용

HFONT

폰트

HBITMAP

비트맵 이미지

HPALETTE

팔렛

HRGN

화면상 영역

HGDIOBJ GetStockObject(int option);

으로 기본적 GDI 오브젝트를 만들 수 있다.

(HBRUSH)GetStockObject(GRAY_BRUSH);

으로 캐스팅해서 사용한다.

하지만 나는 CreateSolidBrush(RGB(0, 0, 0))을 차라리 쓰겠다.

이러한 GDI obj를

SelectObject(HDC, HGDIOBJ);

을 통해 적용할 수 있는데 이때 리턴값은 이전의 HGDIOBJ이다.

그리고 삭제를 해야한다.

DeleteObject(HGDIOBJ);

이 때 지금 어떤 HDC에 적용된 GDIOBJ는 삭제되지 않는다.

그래서 SelectObject의 리턴값을 보존해서 그걸로 교체한 후 삭제해야한다.

4. 그리기 모드, 저장

int SetROP2(HDC, int);

는 그리기 모드를 설정하는 것이다.

int GetROP2(HDC);

는 어떤 그리기 모드인지 리턴한다.

옵션은 반전, 덮어 쓰기, nor의 결과값 등 많다.

int SaveDC(HDC hdc);

는 현재 dc 의 옵션들을 스택에 저장하고 int 값으로 꼬리표를 리턴한다.

BOOL RestoreDC(HDC hdc, int nSavedDC);

위 함수로 dc 의 옵션을 재적용한다.

5. 비트맵

HDC CreateCompatibleDC(HDC);

로 비트맵을 저장할 DC를 만든다.

DC와 거의 같은 기능을 하는, 내부에 출력 표면을 가진 메모리 영역이다.

DC와는 거의 똑같지만 비트맵 이미지 같은 용량이 큰 것들은 여기에 먼저 그려야한다.

다 그린후 DC끼리 고속복사를 해서 적용시키는 것이 주된 사용방법.

HBITMAP CreateCompatibleBitmap (HDC hdc, int nWidth, int nHeight);

로 DC 의 색깔 정보와 호환되는 빈 비트맵을 만든다.

백 버퍼 등에 사용된다.

1

2

3

4

5

6

bmp1 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BMPEX));

bmp2 = (HBITMAP)SelectObject(memDC, bmp1);

BitBlt(hdc, 0, 0, 300, 300, memDC, 0, 0, SRCCOPY);

SelectObject(memDC, bmp2);

DeleteObject(bmp1);

DeleteDC(memDC);

BitBlt(hdc, 0, 0, 300, 300, memDC, 0, 0, SRCCOPY);

StretchBlt(hdc, x1, y1, x2, y2, memDC, x3, y3, x4, y4, SRCCOPY);

BOOL TransparentBlt ( HDC hDestDC, x1, y1, x2, y2, memDC, x3, y3, x4, y4, UINT clrTransparent);

앞 좌표 네개는 붙여 넣을 좌표이다.

뒷 좌표는 불러올 비트맵의 좌표인데 BitBlt 는 시작좌표만 설정하면 된다.

SRCCOPY 가 있는 인수는 복사할 옵션의 플래그이고 clrTransparent 는 투명화할 색깔이다.

StretchBlt 를 쓰면 반전도 가능하다.

축소 시 어떤 픽셀을 제거할 것인가에 대해선 dc 의 속성이 결정하며 SetStretchBltMode 라는 함수로 수정한다.

TransparentBlt 는 msimg32.lib 를 링크 해야 하므로 주의.

간단히 아래 코드를 추가하는 것으로 링크를 하게 할 수 있다.

#pragma comment(lib, "msimg32.lib")

댓글 없음:

댓글 쓰기

List