API-비트맵2(메모리DC)
- 프로그래밍/WindowsAPI
- 2011. 5. 13. 11:54
메모리 DC & 비트맵을 메모리 DC 에 선택 ( 로드 )
윈도우즈는 비트맵을 곧바로 화면 DC 로 출력하는 함수는 제공하지 않는다.
비트맵을 출력하는 함수라면 아마 다음과 같은 형태를 상상할 수 있을 것이다.
OutBitmap ( hdc , x , y , "비트맵 열기" ); (존재하지 않는 함수)
이런 함수가 있으면 매우 좋겠지만 , 안타깝게도 이런 함수는 API 가 직접 지원하지 않는다.
왜냐하면 비트맵은 크기가 큰 데이터 덩어리 이며 , 따라서 출력 속도가 형편없이 느리고 화면으로 곧바로 출력할 경우 여러가지 꼴사나운 현상이 발생할 수 있기 때문이다.
마치 파일에서 한 바이트 단위로 읽어 들이는 함수가 없는 것과 같은 이유인데, 파일을 읽고 싶으면 반드시 열기 , 읽기 , 닫기 의 과정을 거쳐야 한다.
마찬가지로 비트맵도 워낙 대용량이라 직접 출력하는 함수는 제공하지 않으며 약간의 준비를 거친 후 출력해야 한다.
이렇게 준비 동작을 취한 후 출력하면 여러번 출력할 때 이미 준비된 데이터를 전송하기만 하면 되므로
출력속도가 빠르고 예비 동작을 미리 취해 놓을 수 있다는 점에서도 유리하다.
비트맵은 화면으로 직접 출력할 수 없으며 반드시 메모리 DC 에 미리 준비해 놓고 사용해야 한다.
메모리 DC 란 DC 와 동일한 특성을 가지며 ,그 내부에 출력 표면을 가진 메모리 영역이다.
메모리에 있기는 하지만 화면 DC 에서 사용할 수 있는 모든 출력을 메모리 DC 에서도 할 수 있다.
선 , 면 , 원 등의 작도 함수는 물론 화면 DC 에서는 불가능한 것까지도 가능하다.
그래서 메모리 DC 에 먼저 그림을 그린 후 사용자 눈에 그려지는 과정은 보여주지 않고
그 결과만 화면으로 고속 복사하는 방법 ( 더블 버퍼링 ) 을 많이 사용한다.
( 메모리 DC 에 먼저 그림을 그려둔다 -> 화면에 복사한다 )
사용자 눈에 화면이 그려지는 과정을 보여주는 것은 그리 깔끔한 모습이 아니다.
여기서 우리가 하고자 하는 비트맵 출력을 위해서도 반드시 메모리 DC 를 사용해야 한다.
비트맵도 일종의 GDI 오브젝트 이지만 화면 DC 에는 선택할 수 없으며
메모리 DC 만이 비트맵을 선택할 수 있다.
그래서 메모리 DC 에 먼저 비트맵을 읽은 후 화면 DC 로 복사하는 것이다.
1.메모리DC 만들기
메모리 DC 를 만들 때는 다음 함수가 사용된다.
HDC CreateCompatibleDC( HDC hdc ); // Compatible : 호환이 되는
인수로 화면 DC 의 핸들을 주면 이 화면 DC 와 동일한 특성을 가지는 DC 를 메모리에 만들어 그 핸들을 리턴한다.
호환된다 라는 말은 사용하는 색상수 , 색상면 이 같다는 뜻이다.
호환되지 않는 DC 끼리는 정보를 공유할 수 없기 때문에 화면 DC 와 호환이 되는 메모리 DC 를 만들어야 한다.
즉 , 화면이 흑백이면 메모리 DC 도 흑백이어야 하고 , 화면이 256 색상이면 메모리 DC 도 256 색상으로 만들어져야 한다는 얘기다.
2. 비트맵 읽어들이기
메모리 DC 를 만든 후에는 비트맵을 읽어오고 이 비트맵을 메모리 DC 에 선택한다.
선택할 때는 여타의 GDI 오브젝트와 마찬가지로 SelectObject 함수를 사용하며 ( 펜 , 브러시등을 DC 에 적용하는 함수 )
비트맵을 읽어올 때는 LoadBitmap 함수를 사용한다.
HBITMAP LoadBitmap ( HINSTANCE hInstance , LPCTSTR lpBitmapName );
첫 번째 인수는 비트맵 리소스를 가진 인스턴스 핸들
두 번째 인수는 비트맵 리소스의 이름
읽어온 비트맵을 SelectObject 함수로 메모리 DC 에 선택하면 메모리 DC 의 표면에는 리소스에서 읽어온 비트맵이 그려져 있을 것이다.
3. 메모리 DC 의 그림을 화면으로 복사 ( 빗블릿 )
이제 남은 일은 메모리 DC 에 그려진 비트맵을 화면으로 복사하는 것 뿐이다.
BitBlt ( 빗블릿 ) 함수는 DC 간의 영역끼리 고속 복사를 수행한다.
메모리 DC 의 표면에 그려져 있는 비트맵을 화면 DC로 복사 함으로써 비트맵을 화면으로 출력한다.
원형은 다음과 같다.
BOOL BitBlt ( HDC hdcDest , int nXDest, int nYDest , int nWidth , int nHeight, HDC hdcSrc , int nXSrc , int nYSrc , DWORD dwRop );
첫 번째 인수는 복사 대상 DC ( 윈도우 DC ) 다음 네 개의 인수는 복사 대상 ( 윈도우 ) 의 XYWH ( 어디에 출력할 것인지 ) hdcSrc 가 메모리 DC nXSrc , nYSrc 는 메모리 DC 상 의 좌표이되 BitBlt 은 비트맵의 크기를 변경하지 않고 복사를 수행
폭과 높이는 복사 대상에서 한 번만 지정하고 복사원에서는 이 값을 그대로 사용한다.
소스를 보면 MemDC 의 0,0 위치를 복사 대상의 0,0 위치에 폭 123 , 높이 160 만큼 복사한다.
( 메모리 DC 의 그림의 50,50 위치부터 복사하고 싶다고 하면 이 값을 고치면 된다. )
그렇게 하면 다음과 같은 위치에서 부터 복사를 시작한다.
3-2)복사 옵션(빗블릿함수의 복사옵션)
BitBlt 의 마지막 인수 dwRop 는 래스터 연산 방법을 지정하며 , SRCCOPY 를 쓰면 메모리 DC 에 있는 그림을 그대로 복사한다.
dwRop 에 다른 값을 사용하면 ,기존 그림에 겹친다거나 반전 시킬 수도 있다.
앞에서 배운 그리기 모드와 개념적으로 유사하며 다음과 같은 기능이 있다.
값 | 설명 |
BLACKNESS | 대상 영역을 검정색으로 가득 채운다 |
DSTINVERT | 화면을 반전 시킨다 |
MERGECOPY | 소스 비트맵과 대상화면을 AND 연산 한다 |
MERGEPAINT | 소스 비트맵과 대상화면을 OR 연산 한다 |
SRCCOPY | 소스 영역을 대상 영역에 복사한다 |
WHITENESS | 대상 영역을 흰색으로 채운다 |
4. 메모리 DC 해제 / 비트맵 해제
비트맵 출력이 끝난 후에는 비트맵 자체와 메모리 DC 를 해제해야 한다.
비트맵은 GDI 오브젝트 이므로 , DeleteObject 함수로 지우면 되고, 메모리 DC 는 DeleteDC 라는 별도의 함수를 사용하여 지운다. 비트맵을 지우기 전에 선택 해제를 먼저 해야 하므로 OldBitmap 변수가 필요하다
이 글을 공유하기