Tutorial 25: Simple Bitmap
이 번장에서는, 비트맵을 어떻게 사용하는지를 설명한다. 정확히 말하면, 윈도우의 작업영역에 어떻게 비트맵을 표시하는지를 설명한다.
소스 | 리소스 스크립트 | 비트 맵 | 실행 결과 |
|
비트맵은 컴퓨터에 저장되어 있는 그림이라고 생각할 수 있다. 그림 관련 포맷은 여러가지가 있지만, Windows의 표준형식은 Windows Bitmap Graphics 파일(. bmp)이다. 이번에 설명하는 「비트맵」은, 이 Windows bitmap graphics이다. 가장 간단히 사용하려면 , 리소스로 사용하면 되지만, 여기에는 2가지 방법이 있다. 하나는 다음과 같이 리소스 정의 파일(. rc)에 비트맵을 저장하는 방식이다.
#define IDB_MYBITMAP 100 IDB_MYBITMAP BITMAP "c:\project\example.bmp"이 방법은 비트맵이란 것을 나타내는 정수를 사용한다. IDB_MYBITMAP라는 이름이 100 이라는 것을 정의하고 있다. 프로그램에서는, 이 이름을 비트맵을 참조할 때에 사용하게 된다. 다음으론 비트맵의 리소스를 정의하고 있다. 리소스 컴파일러에게 비트맵 파일이 실제로 어디에 있는지를 지정해 주고있다.
다른 한가지 방법은 비트맵을 다음과 같이 이름으로 정의하는 것이다.
MyBitMap BITMAP "c:\project\example.bmp"이 방법은, 이전 방법에서 정수로 구별하는 것을, 「MyBitMap」라는 문자열로서 구별하게 된다.
양쪽 방법 모두 정상적로 작동하지만, 예제에서는 전자의 방법(resource file에)으로 비트맵을 저장하는 방법을 사용한다.
LoadBitmap 함수를 호출해서 비트맵의 핸들을 얻는다.
LoadBitmap proto hInstance:HINSTANCE, lpBitmapName:LPSTR성공적으로 수행되면 비트맵 핸들을 반환한다. hInstance는 프로그램의 인스턴스 핸들이다. lpBitmapName는 비트맵 파일명이다(방법 2에서는).
만약 IDB_MYBITMAP 와 같이 정수형태로 비트맵을 참조할 경우에는,해당 정수를 적어준다(예를들어 100 ). 간단한 코드는 다음과 같다.●첫번째 방법
.386 .model flat, stdcall ................ . const IDB_MYBITMAP equ 100 ............... .data? hInstance dd ? .............. .code ............. invoke GetModuleHandle, NULL mov hInstance, eax ............ invoke LoadBitmap, hInstance, IDB_MYBITMAP ...........●두번째 방법
.386 .model flat, stdcall ................ .data BitmapName db "MyBitMap", 0 ............... .data? hInstance dd ? .............. .code ............. invoke GetModuleHandle, NULL mov hInstance, eax ............ invoke LoadBitmap, hInstance, addr BitmapName ...........- DC핸들을 얻는다. 얻는방법은 WM_PAINT 메세지에서 BeginPaint 함수를 호출하든지,또는 다른 메세지에서 GetDC 함수를 호출하는 것이다
- 이전 단계에서 얻어진 DC핸들과 동일한 속성을 가진 메모리DC를 생성한다.메모리DC는, 비트맵을 그릴수 있는 기능을 가진 논리화면 영역이다.
이런 처리가 끝나면, 어떤 함수를 호출해서, 메모리DC 표면에 출력한 내용을, 실제의 DC에 복사한다. 이것은, 더블 버퍼링으로 불리는 기술로, 그림을 고속으로 출력시키는 방법이다. 메모리DC는 , CreateCompatibleDC 함수를 호출해서 생성할 수 있다.
CreateCompatibleDC proto hdc:HDC이 함수가 성공적으로 수행되면, eax 레지스터에 메모리DC의 핸들이 저장된다. hdc는 실제DC이며, 이 DC와 동일한 특성을 가진 메모리DC를 생성한다.
이상태에서, 메모리DC에 출력이 끝났다.
이번에는,비트맵을 출력할려는 표면을 가진 DC를 선택해주어야 한다. 이것은, SelectObject 함수를 호출해서 할 수 있다. 이 함수는, 첫번째 인수로 메모리DC의 핸들을, 두번째 인수는 표시할려는 비트맵을 지정한다. SelectObject 함수는 다음과 같은 프로토타입으로 되어있다.
SelectObject proto hdc:HDC, hGdiObject:DWORD- 메모리DC에 출력이 완료됬을 것이다.
이제 해야할 것은 실제DC에 메모리DC의 내용을 복사해야하지만, 이는 BitBlt 함수를 호출하는 방법, 또는 StretchBlt 함수를 호출하는 방법 등 몇가지가 있다. BitBlt 함수는 단순히 DC간의 복사작업만 하는 것에 비해, StretchBlt 함수는 크기를 다르게 할 수 있다.하지만 BitBlt 함수보다는 조금더 시간이 더 걸린다. 예제에서는 간단한 BitBlt 함수를 사용한다.
BitBlt proto hdcDest:DWORD, nxDest:DWORD, nyDest:DWORD, nWidth:DWORD, nHeight:DWORD, hdcSrc:DWORD, nxSrc:DWORD, nySrc:DWORD, dwROP:DWORD
- hdcDest
비트맵 대상의 DC핸들- nxDest, nyDest
출력 영역의 좌상단의 좌표값- nWidth, nHeight
출력영역의 길이와 폭- hdcSrc
비트맵 원본의 DC핸들- nxSrc, nySrc
원본 비트맵의 좌상단의 좌표값- dwROP
래스터 오퍼레이션 코드(ROP)를 지정한다. 그림데이터를 복사할 때, 원본과 대상의 색상데이터를 어떻게 결합하는지를 지정할 수 있다.
대부분의 경우, 새로운 데이터로 덮어쓰기하는 것이다.- 비트맵에 대한 처리가 끝나면, DeleteObject 함수를 호출해서 삭제한다.
이를 요약하면 다음과 같다.
- 리소스 스크립트에 비트맵을 기술한다
- LoadBitmap 함수를 호출해서, 리소스로부터 비트맵을 로드한다
- 비트맵 핸들을 얻는다
- 비트맵을 출력하고 싶은 DC의 핸들을 얻는다
- 그 DC와 동일한 형태의 메모리DC를 생성한다
- 그 메모리DC에 비트맵을 출력한다
- 메모리DC로부터 실제DC로 복사한다
|
|
|
#define IDB_MAIN 1 IDB_MAIN BITMAP "tweety78.bmp"IDB_MAIN 이라는 정수를 정의하고, 그 값을 1 로 설정한다. 이후 리소스 식별자로 사용한다. 리소스에 포함되어 있는 비트 맵 파일은, "tweety78.bmp" 라는 파일명으로서, 리소스 스크립트와 같은 폴더에 있다.
.if uMsg==WM_CREATE invoke LoadBitmap, hInstance, IDB_MAIN mov hBitmap, eaxWM_CREATE 메세지에 대한 처리로서 리소스로부터 비트맵 파일을 로드하기위해, 두번째 인수에 비트맵의 리소스ID를 설정해서 LoadBitmap 함수를 호출한다. 성공적으로 수행되면, 비트맵 핸들이 반환된다.
비트맵이 로드 되면, 메인 윈도우의 작업영역에 출력한다.
.elseif uMsg==WM_PAINT invoke BeginPaint, hWnd, addr ps mov hdc, eax invoke CreateCompatibleDC, hdc mov hMemDC, eax invoke SelectObject, hMemDC, hBitmap invoke GetClientRect, hWnd, addr rect invoke BitBlt, hdc, 0,0, rect.right, rect.bottom, hMemDC, 0,0, SRCCOPY invoke DeleteDC, hMemDC invoke EndPaint, hWnd, addr ps이번에는, WM_PAINT 메세지에 대한 처리로서, 비트맵을 출력할 경우사용한다. 먼저, BeginPaint 함수를 호출해서 DC핸들을 얻는다. 그리고, CreateCompatibleDC 함수를 호출하여 DC와 호환되는 메모리DC를 생성한다. SelectObject 함수로, 메모리DC의 오브젝트에 비트맵을 선택해 준다. GetClientRect 함수를 호출하여,작업영역의 출력크기를 결정하고, 메모리DC로부터 실제 DC로 비트맵을 전송하는 BitBlt 함수를 호출함으로써, 작업영역에 실제 비트맵 출력된다. 출력이 완료되면, 메모리DC는 필요없기 때문에, DeleteDC 함수로 삭제한다. 마지막으로, EndPaint 함수로서 출력세션을 종료한다.
.elseif uMsg==WM_DESTROY invoke DeleteObject, hBitmap invoke PostQuitMessage, NULL비트맵이 필요없다면, DeleteObject 함수로 삭제한다.