1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "resource.h"
 
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    HDC hdc, MemDC;
    PAINTSTRUCT ps;
    HBITMAP MyBitMap, OldBitMap;
 
    switch(iMessage) {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        MemDC = CreateCompatibleDC(hdc);
        MyBitMap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));
        OldBitMap = (HBITMAP)SelectObject(MemDC, MyBitMap);
        BitBlt(hdc, 00153126, MemDC, 00, SRCCOPY);
        SelectObject(MemDC, OldBitMap);
        DeleteObject(MyBitMap);
        DeleteDC(MemDC);
        EndPaint(hWnd, &ps);
        return 0;
    }
 
    return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
cs

 

상기 코드는 BitMap File을 화면에 출력하는 코드입니다.

 

< 메모리 DC >

 

윈도우즈는 비트맵을 곧바로 화면 DC로 출력하는 함수를 제공하지 않는다.

비트맵은 대용량이므로 메모리 DC에 미리 그림을 그려놓고 화면에 출력하는 방식을 사용함으로써 출력 속도를 빠르게 한다.

메모리 DC란 화면 DC와 동일한 특성을 가지며 그 내부에 출력 표면을 가진 메모리 영역이다.

 

1
HDC CreateCompatibleDC(HDC hdc);
cs

 

상기 함수를 통해 메모리 DC를 생성할 수 있으며 인자로 화면 DC의 핸들을 넘겨주어 화면 DC와 동일한 특성을 가지는 DC를

메모리에 만든 후 그 핸들을 리턴한다.

 

1
HBITMAP LoadBitmap(HINSTANCE hInstance, LPCTSTR lpBitmapName);
cs

 

또한, 비트맵을 읽어올 때는 상기의 LoadBitmap 함수를 사용한다.

첫 번째 인자는 비트맵 리소스를 가진 인스턴스의 핸들이며, 두 번째 인자는 비트맵 리소스의 이름이다.

읽어온 비트맵을 SelectObject 함수로 메모리 DC에 선택하면 메모리 DC의 표면에는 리소스에서 읽어온 비트맵이 그려져 있을

것이다.

 

1
BOOL BitBlt(HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, int y1, DWORD rop);
cs

 

BitBlt 함수는 DC간의 영역끼리 고속 복사를 수행한다. 메모리 DC의 표면에 그려져 있는 비트맵을 화면 DC로 복사함으로써

비트맵을 화면으로 출력한다.

첫 번째 인자는 복사 대상 화면 DC이고, 다음 네 개의 인자(x, y, cx, cy)는 화면에 표시할 x, y 좌표와 width, height 값이다.

그 다음 여섯 번째 인자는 비트맵이 그려져 있는 메모리 DC이며 그 다음 2개 인자(x1, y1)은 메모리 DC에 그려져 있는

비트맵 이미지 중 복사할 시작 좌표를 의미한다.

즉, x1 = 0, y1 = 0이면 전체 이미지를 복사해오는 것이고 x1 = 30, y1 = 30이면 비트맵 이미지의 30,30 좌표부터 복사를 한다는

의미이다. width, height는 앞에서 지정한 것과 동일한 값을 가지므로 별도로 width, heigth 값을 지정하진 않는다.

마지막 인자인 rop은 래스터 연산 방법을 지정하며 SRCCOPY를 쓰면 이미지를 그대로 복사한다.

이 외에도 BLACKNESS / DSTINVERT / MERGECOPY / MERGEPAINT / WHITENESS가 있다.

 

비트맵 출력이 끝난 후에는 비트맵 자체와 메모리 DC를 해제해야 한다.

비트맵도 GDI 오브젝트이므로 펜, 브러쉬와 동일한 방법으로 OldBitMap을 메모리 DC에 Select 해준 후에 DeleteObject를 호출한다.

또한, 메모리 DC는 DeleteDC라는 별도의 함수를 통해 메모리 DC를 해제하면 된다.

 

< ScretchBlt >

 

DC 간에 비트맵을 전송하는데 확대 및 축소가 가능한 함수이다.

 

1
2
BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest,
                HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, DWORD rop);
cs

 

상기 코드에서 BitBlt 부분만 해당 함수로 변경하면 된다.

BitBlt와 인자가 조금 다른데 StrechBit의 네 번째, 다섯 번째 인자(wDest, hDest)에는 화면에 출력하고자 하는 이미지의

Width, Heigth 값을 넣어준다. 원본 이미지보다 크다면 확대될 것이고 작다면 축소되서 화면에 표시된다.

또한, 아홉 번째, 열 번째 인자에는 원본 이미지의 Width, Height 값을 입력하면 된다.

 

그러나 상기와 같이 작성된 코드는 매우 비효율적인 코드이다.

WM_PAINT 메시지는 그리기를 할 때마다 호출되는데 이때마다 비트맵을 읽어 와서 출력하고 해제하는 것을 반복한다면 그리기

속도가 매우 느릴것이다.

 

원칙적으로 비트맵은 WM_CREATE에서 미리 읽어 두고 WM_PAINT에서는 출력만 해야 한다.

그리고 비트맵을 출력하기가 너무 번거로운 문제가 있기 때문에 비트맵을 간단하게 출력할 수 있는 래퍼 함수를 만들어서 사용하는

것이 좋다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void DrawBitmap(HDC hdc, int x, int y, HBITMAP hBitmap)
{
    HDC MemDC;
    HBITMAP OldBitMap;
    int bx, by;
    BITMAP bitmap;
 
    MemDC = CreateCompatibleDC(hdc);
    OldBitMap = (HBITMAP)SelectObject(MemDC, hBitmap);
 
    GetObject(hBitmap, sizeof(BITMAP), &bitmap);
    bx = bitmap.bmWidth;
    by = bitmap.bmHeight;
 
    BitBlt(hdc, x, y, bx, by, MemDC, 00, SRCCOPY);
 
    SelectObject(MemDC, OldBitMap);
    DeleteDC(MemDC);
}
 
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    static HBITMAP MyBitMap;
 
    switch(iMessage) {
    case WM_CREATE:
        MyBitMap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));
        return 0;
    case WM_DESTROY:
        DeleteObject(MyBitMap);
        PostQuitMessage(0);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        DrawBitmap(hdc, 1010, MyBitMap);
        EndPaint(hWnd, &ps);
        return 0;
    }
 
    return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
cs

 

GetObject 함수를 통해 전달된 비트맵의 크기를 자동으로 조사해서 비트맵 전체를 출력한다.

GetObject는 핸들로부터 펜, 브러시, 비트맵 등의 GDI 오브젝트 정보를 조사하는 함수인데 BITMAP 구조체의

bmWidth, bmHeigth 멤버를 읽으면 멤버를 읽으면 비트맵 크기를 구할 수 있다.

 

우선 WM_CREATE에서 비트맵을 미리 읽어 두었으며 WM_PAINT에서는 비트맵을 출력만 하고 해제는 WM_DESTROY

에서 한다.

+ Recent posts