반응형

이번에는 MFC 프로그래밍에서 bitmap에 대한 것을 알아보도록 하겠습니다.

.

.

.

bitmap은 이미지 파일로

MFC 프로그래밍에서 출력하는 방법으로는 아래와 같습니다.

.

.

.

.

.

MFC로 만들기

1. [리소스 추가] -> Bitmap -> [새로 만들기]

2. 빈 화면 -> 그리기

.

.

.

bitmap 속성

비트맵 편집기 속성

Width, Height : 비트맵 크기, 수정 가능

Colors : 사용하는 컬러 수로 32비트까지 지원 가능

.

.

비트맵 노드 속성

 ID : 비트맵에 대한 식별자, 수정 가능

File name : 비트맵 파일을 저장할 파일 이름

.

.

Bitmap 파일 불러오기

[리소스 추가] -> [Bitmap] -> [가져오기]

내 컴퓨터에 있는 이미지를 가져올 수 있습니다.

.

.

.

BItBlt 함수 속성

BOOL BitBlt(
	HDC	hdc,
    int	nXD, int nYD,
    int	nW,	 int nH,
    HDC memdc,
    int nXS, int nYS,
    DWORD	dwRop
);

.

.

.

StretchBlt 함수 속성

BOOL StretchBlt(
	HDC	hdc,
    int	nXD, int nYD, int nW, int nH,
    HDC memdc,
    int nXS, int nYS, int nWS, int nHS,
    DWORD	dwRop
);

.

.

.

윈도 화면에 꽉 찬 Bitmap 출력 (StretchBlt 이용)

#include <windows.h>
#include <TCHAR.H>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
	WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpszCmdLine, int nCmdShow)
	// UNICODE 사용시 wWinMain() 형태 	
	// hPrevInstance 이전 인스턴스 항상 0값
	// lpszCmdLine > 외부에서 (내부로) 입력받는 변수
	// nCmdShow 윈도우 출력 형태에 관련한 값
{
	HWND     hwnd;
	MSG		 msg;
	WNDCLASS WndClass;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;	//height, vertical redraw
	WndClass.lpfnWndProc = WndProc;		// Proc 설정
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hInstance = hInstance;
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);	// 형변환
	WndClass.lpszMenuName = NULL;
	WndClass.lpszClassName = _T("Window Class Name");
	RegisterClass(&WndClass);		// WndClass 등록
	hwnd = CreateWindow(_T("Window Class Name"),
		_T("Jung-Stroy"),		// 
		WS_OVERLAPPEDWINDOW,		// 윈도우 스타일
		600, 400,					// 창출력좌표 x, y 
		600, 400,					// 창크기 x, y축
		NULL,						// 부모 윈도우
		NULL,						// 메뉴바 핸들
		hInstance,					// 인스턴스
		NULL						// 여분, NULL
		);
	ShowWindow(hwnd, nCmdShow);		// 윈도우 출력, WM_PAINT 출력내용 가져옴
	UpdateWindow(hwnd);				// WM_PAINT 출력내용 발생해서 출력하도록
									// hwnd 핸들을 통해 보여주고 갱신

	//ShowWindow(hwnd, SW_SHOW);	// 위와 같음
	//UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))	// 메시지 큐의 메시지를 가져옴
	{
		TranslateMessage(&msg);		// 키입력에 반응하는 메시지 변환, WM_KEYDOWN (키가 눌릴때) WM_CHAR 메시지 발생
		DispatchMessage(&msg);		// WndProc() 함수 호출과 WndProc()으로 메세지 전달
	}								// 종료는 WM_QUIT 발생할때 FALSE 리턴하면서 종료
	return (int)msg.wParam;			// wParam, lParam 윈도우 크기가 어떻게 변했는지, 변경된 클라이언트, 키보드, 마우스 값

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
	WPARAM wParam, LPARAM lParam)
	//	WinDef.h 에서 정의
	//	wPram > unsigned ptr, lParam > long ptr 
{
	HDC hdc, memdc;
	PAINTSTRUCT ps;
	static HBITMAP hBitmap;
	BITMAP bm;
	RECT rect;
	static int nx, ny;

	switch (iMsg)
	{
	case WM_CREATE:
		hBitmap = (HBITMAP)LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance, MAKEINTRESOURCE(IDB_BITMAP5_2));
		break;

	case WM_PAINT:
		GetClientRect(hwnd, &rect);	// 윈도우 크기를 받아온다.
		GetObject(hBitmap, sizeof(bm), &bm);
		
		hdc = BeginPaint(hwnd, &ps);
		memdc = CreateCompatibleDC(hdc);
		SelectObject(memdc, hBitmap);
		StretchBlt(hdc, 0, 0, rect.right, rect.bottom, memdc, 0, 0,bm.bmWidth , bm.bmHeight, SRCCOPY);
		DeleteDC(memdc);
		EndPaint(hwnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

.

.

.

크기를 자유자재로 움직일 수 있음.

.

.

.

이번에는 비트맵 파일이 윈도 화면에 연속해서 나타나게 함으로 바둑판 모양으로 윈도 배경에 나타나도록 하는 코드를 알아보도록 하겠습니다.

.

.

.

코드 (BitBlt 함수 이용)

#include <windows.h>
#include <TCHAR.H>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
	WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpszCmdLine, int nCmdShow)
	// UNICODE 사용시 wWinMain() 형태 	
	// hPrevInstance 이전 인스턴스 항상 0값
	// lpszCmdLine > 외부에서 (내부로) 입력받는 변수
	// nCmdShow 윈도우 출력 형태에 관련한 값
{
	HWND     hwnd;
	MSG		 msg;
	WNDCLASS WndClass;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;	//height, vertical redraw
	WndClass.lpfnWndProc = WndProc;		// Proc 설정
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hInstance = hInstance;
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);	// 형변환
	WndClass.lpszMenuName = NULL;
	WndClass.lpszClassName = _T("Window Class Name");
	RegisterClass(&WndClass);		// WndClass 등록
	hwnd = CreateWindow(_T("Window Class Name"),
		_T("Jung-Story"),		//
		WS_OVERLAPPEDWINDOW,		// 윈도우 스타일
		600, 400,					// 창출력좌표 x, y 
		600, 400,					// 창크기 x, y축
		NULL,						// 부모 윈도우
		NULL,						// 메뉴바 핸들
		hInstance,					// 인스턴스
		NULL						// 여분, NULL
		);
	ShowWindow(hwnd, nCmdShow);		// 윈도우 출력, WM_PAINT 출력내용 가져옴
	UpdateWindow(hwnd);				// WM_PAINT 출력내용 발생해서 출력하도록
									// hwnd 핸들을 통해 보여주고 갱신

	//ShowWindow(hwnd, SW_SHOW);	// 위와 같음
	//UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))	// 메시지 큐의 메시지를 가져옴
	{
		TranslateMessage(&msg);		// 키입력에 반응하는 메시지 변환, WM_KEYDOWN (키가 눌릴때) WM_CHAR 메시지 발생
		DispatchMessage(&msg);		// WndProc() 함수 호출과 WndProc()으로 메세지 전달
	}								// 종료는 WM_QUIT 발생할때 FALSE 리턴하면서 종료
	return (int)msg.wParam;			// wParam, lParam 윈도우 크기가 어떻게 변했는지, 변경된 클라이언트, 키보드, 마우스 값

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
	WPARAM wParam, LPARAM lParam)
	//	WinDef.h 에서 정의
	//	wPram > unsigned ptr, lParam > long ptr 
{
	HDC hdc, memdc;
	PAINTSTRUCT ps;
	static HBITMAP hBitmap;
	RECT rect;
	int i, j;

	switch (iMsg)
	{
	case WM_CREATE:
		hBitmap = (HBITMAP)LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance, MAKEINTRESOURCE(IDB_BITMAP5_2));
		break;

	case WM_PAINT:
		GetClientRect(hwnd, &rect);	// 윈도우 크기를 받아온다.
		hdc = BeginPaint(hwnd, &ps);
		memdc = CreateCompatibleDC(hdc);
		SelectObject(memdc, hBitmap);
		for (i = 0; i <= rect.right / 100; i++) {
			for (j = 0; j <= rect.bottom / 100; j++) {
				BitBlt(hdc, i * 100, j * 100, 100, 100,memdc,0,0,SRCCOPY);
			}
		}
		DeleteDC(memdc);
		EndPaint(hwnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

.

.

.

실행 화면

.

.

.

이번에는 아무버튼이나 클릭 시 윈도 화면에서 이미지가 움직이면서 바운드되는 것을 알아보도록 하겠습니다.

코드

#include <windows.h>
#include <TCHAR.H>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
	WPARAM wParam, LPARAM lParam);
HINSTANCE hInst;	// 그림을 그리기 위한 inst.

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpszCmdLine, int nCmdShow)
	// UNICODE 사용시 wWinMain() 형태 	
	// hPrevInstance 이전 인스턴스 항상 0값
	// lpszCmdLine > 외부에서 (내부로) 입력받는 변수
	// nCmdShow 윈도우 출력 형태에 관련한 값
{
	HWND     hwnd;
	MSG		 msg;
	WNDCLASS WndClass;
	hInst = hInstance;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;	//height, vertical redraw
	WndClass.lpfnWndProc = WndProc;		// Proc 설정
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hInstance = hInstance;
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);	// 형변환
	WndClass.lpszMenuName = NULL;
	WndClass.lpszClassName = _T("Window Class Name");
	RegisterClass(&WndClass);		// WndClass 등록
	hwnd = CreateWindow(_T("Window Class Name"),
		_T("Jung-Stroy"),		// 
		WS_OVERLAPPEDWINDOW,		// 윈도우 스타일
		600, 400,					// 창출력좌표 x, y 
		600, 400,					// 창크기 x, y축
		NULL,						// 부모 윈도우
		NULL,						// 메뉴바 핸들
		hInstance,					// 인스턴스
		NULL						// 여분, NULL
		);
	ShowWindow(hwnd, nCmdShow);		// 윈도우 출력, WM_PAINT 출력내용 가져옴
	UpdateWindow(hwnd);				// WM_PAINT 출력내용 발생해서 출력하도록
									// hwnd 핸들을 통해 보여주고 갱신

	//ShowWindow(hwnd, SW_SHOW);	// 위와 같음
	//UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))	// 메시지 큐의 메시지를 가져옴
	{
		TranslateMessage(&msg);		// 키입력에 반응하는 메시지 변환, WM_KEYDOWN (키가 눌릴때) WM_CHAR 메시지 발생
		DispatchMessage(&msg);		// WndProc() 함수 호출과 WndProc()으로 메세지 전달
	}								// 종료는 WM_QUIT 발생할때 FALSE 리턴하면서 종료
	return (int)msg.wParam;			// wParam, lParam 윈도우 크기가 어떻게 변했는지, 변경된 클라이언트, 키보드, 마우스 값

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
	WPARAM wParam, LPARAM lParam)
	//	WinDef.h 에서 정의
	//	wPram > unsigned ptr, lParam > long ptr 
{
	HDC hdc, memdc;
	PAINTSTRUCT ps;
	static HBITMAP hBitmap;
	static int x, y, sX, sY;
	RECT rect;

	switch (iMsg)
	{
	case WM_CREATE:
		hBitmap = (HBITMAP)LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP5_2));
		x = 0;
		y = 0;
		sX = 20;
		sY = 20;
		InvalidateRgn(hwnd,NULL,true);
		break;

	case WM_KEYDOWN:
		if (wParam) {
			SetTimer(hwnd, 0, 100, NULL);
		}

	case WM_TIMER:
		GetClientRect(hwnd, &rect);	// 윈도우 크기 받아오기
		x = x + sX;
		y = y + sY;
		if (x + 100 > rect.right || x < 0) {
			sX = -1 * sX;
			x = x + sX;
		}
		if (y + 100 > rect.bottom || y < 0) {
			sY = -1 * sY;
			y = y + sY;
		}
		hdc = GetDC(hwnd);
		memdc = CreateCompatibleDC(hdc);
		SelectObject(memdc, hBitmap);
		BitBlt(hdc, x, y, 100, 100, memdc, 60, 60, SRCCOPY);
		DeleteDC(memdc);
		ReleaseDC(hwnd, hdc);
		break;
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
		hdc = GetDC(hwnd);
		memdc = CreateCompatibleDC(hdc);
		SelectObject(memdc, hBitmap);
		BitBlt(hdc, x, y, 100, 100, memdc, 60, 60, SRCCOPY);
		DeleteDC(memdc);
		ReleaseDC(hwnd, hdc);
		EndPaint(hwnd, &ps);
		break;

	case WM_DESTROY:
		KillTimer(hwnd, 0);
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

.

.

.

실행 화면

.

.

.

.

더블 버퍼링

위에서 사용한 비트맵 이미지를 여러 개 이용하여 동영상을 나타낼 때 사용이 됩니다.

.

.

.

이미지를 순서대로 화면 디바이스 컨택스트에 출력합니다.

예를 들어 풍경 위에 날아가는 비행기를 표현한다면 

풍경 이미지를 먼저 출력

그다음에 비행기 이미지를 출력

날아가는 모습을 나타내고자 한다면 풍경 이미지 출력과 새 이미지 출력을 번갈아가며 계속 수행하면 됩니다.

.

.

.

이러한 더블 더퍼링은 이미지를 계속 출력해 주어야 하기 때문에 화면이 자주 깜빡거리는 문제점이 있습니다.

.

.

.

이런 문제점을 해결해 주기 위해서는

메모리 디바이스 콘텍스트를 하나 더 사용하면 됩니다.

추가된 메모리 디바이스 콘텍스트에 그리기를 원하는 그림들을 모두 출력한 다음 화면 디바이스 콘텍스트로 한꺼번에 옮기는 방법을 이용합니다.

.

.

이러한 절차로 이루어지기 때문에 추가된 메모리 디바이스 콘텍스트가 추가된 버퍼 역할을 하기 때문에 이 방법을 더블 버퍼링이라고 부릅니다!

.

.

더블 버퍼링 로드맵

.

.

.

.

.

.

.

위의 이미지를 이용한 더블 버퍼링 (애니메이션) 예제

#include <windows.h>
#include <TCHAR.H>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
	WPARAM wParam, LPARAM lParam);
HINSTANCE hInst;	// 그림을 그리기 위한 inst.

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpszCmdLine, int nCmdShow)
	// UNICODE 사용시 wWinMain() 형태 	
	// hPrevInstance 이전 인스턴스 항상 0값
	// lpszCmdLine > 외부에서 (내부로) 입력받는 변수
	// nCmdShow 윈도우 출력 형태에 관련한 값
{
	HWND     hwnd;
	MSG		 msg;
	WNDCLASS WndClass;
	hInst = hInstance;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;	//height, vertical redraw
	WndClass.lpfnWndProc = WndProc;		// Proc 설정
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hInstance = hInstance;
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);	// 형변환
	WndClass.lpszMenuName = NULL;
	WndClass.lpszClassName = _T("Window Class Name");
	RegisterClass(&WndClass);		// WndClass 등록
	hwnd = CreateWindow(_T("Window Class Name"),
		_T("Jung-Story"),		
		WS_OVERLAPPEDWINDOW,		// 윈도우 스타일
		600, 400,					// 창출력좌표 x, y 
		600, 400,					// 창크기 x, y축
		NULL,						// 부모 윈도우
		NULL,						// 메뉴바 핸들
		hInstance,					// 인스턴스
		NULL						// 여분, NULL
		);
	ShowWindow(hwnd, nCmdShow);		// 윈도우 출력, WM_PAINT 출력내용 가져옴
	UpdateWindow(hwnd);				// WM_PAINT 출력내용 발생해서 출력하도록
									// hwnd 핸들을 통해 보여주고 갱신

	//ShowWindow(hwnd, SW_SHOW);	// 위와 같음
	//UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))	// 메시지 큐의 메시지를 가져옴
	{
		TranslateMessage(&msg);		// 키입력에 반응하는 메시지 변환, WM_KEYDOWN (키가 눌릴때) WM_CHAR 메시지 발생
		DispatchMessage(&msg);		// WndProc() 함수 호출과 WndProc()으로 메세지 전달
	}								// 종료는 WM_QUIT 발생할때 FALSE 리턴하면서 종료
	return (int)msg.wParam;			// wParam, lParam 윈도우 크기가 어떻게 변했는지, 변경된 클라이언트, 키보드, 마우스 값

}

void Animation(int xPos, int yPos, HDC hdc) {
	HDC memdc;
	HBITMAP RunBit[10], hBit, oldBit;
	static int count;
	int i;
	count++;
	count = count % 10;
	RunBit[0] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R1));
	RunBit[1] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R2));
	RunBit[2] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[3] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[4] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[5] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[6] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[7] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[8] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R9));
	RunBit[9] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R10));
	memdc = CreateCompatibleDC(hdc);
	hBit = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP5_20));
	oldBit = (HBITMAP)SelectObject(memdc, hBit);
	BitBlt(hdc, 0, 0, 819, 614, memdc, 0, 0, SRCCOPY);
	SelectObject(memdc, RunBit[count]);
	BitBlt(hdc, xPos, yPos, 180, 240, memdc, 0, 0, SRCCOPY);
	SelectObject(memdc, oldBit);
	for (i = 0; i < 10; i++)
		DeleteObject(RunBit[i]);
	DeleteDC(memdc);
	DeleteObject(hBit);
}



LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
	WPARAM wParam, LPARAM lParam)
	//	WinDef.h 에서 정의
	//	wPram > unsigned ptr, lParam > long ptr 
{
	HDC hdc;
	PAINTSTRUCT ps;
	static int xPos;
	

	switch (iMsg)
	{
	case WM_CREATE:
		xPos = -100;
		SetTimer(hwnd, 1, 100, NULL);
		break;

	case WM_TIMER:
		xPos += 10;
		if (xPos > 819) xPos = -100;
		InvalidateRgn(hwnd, NULL, true);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
		Animation(xPos, 300, hdc);
		EndPaint(hwnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

.

.

.

실행화면

 

.

.

.

위의 예제 문제점

캐릭터와 함께 사각형 모양이 나오는 걸 볼 수 있습니다.

해결을 하기 위해 마스크 이미지를 이용합니다.

마스크는 캐릭터와 같은 모양의 그림자 이미지입니다.

.

.

.

마스크 이용 애니메이션 예제

#include <windows.h>
#include <TCHAR.H>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
	WPARAM wParam, LPARAM lParam);
HINSTANCE hInst;	// 그림을 그리기 위한 inst.

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpszCmdLine, int nCmdShow)
	// UNICODE 사용시 wWinMain() 형태 	
	// hPrevInstance 이전 인스턴스 항상 0값
	// lpszCmdLine > 외부에서 (내부로) 입력받는 변수
	// nCmdShow 윈도우 출력 형태에 관련한 값
{
	HWND     hwnd;
	MSG		 msg;
	WNDCLASS WndClass;
	hInst = hInstance;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;	//height, vertical redraw
	WndClass.lpfnWndProc = WndProc;		// Proc 설정
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hInstance = hInstance;
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);	// 형변환
	WndClass.lpszMenuName = NULL;
	WndClass.lpszClassName = _T("Window Class Name");
	RegisterClass(&WndClass);		// WndClass 등록
	hwnd = CreateWindow(_T("Window Class Name"),
		_T("Jung-Story"),		//
		WS_OVERLAPPEDWINDOW,		// 윈도우 스타일
		600, 400,					// 창출력좌표 x, y 
		600, 400,					// 창크기 x, y축
		NULL,						// 부모 윈도우
		NULL,						// 메뉴바 핸들
		hInstance,					// 인스턴스
		NULL						// 여분, NULL
		);
	ShowWindow(hwnd, nCmdShow);		// 윈도우 출력, WM_PAINT 출력내용 가져옴
	UpdateWindow(hwnd);				// WM_PAINT 출력내용 발생해서 출력하도록
									// hwnd 핸들을 통해 보여주고 갱신

	//ShowWindow(hwnd, SW_SHOW);	// 위와 같음
	//UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))	// 메시지 큐의 메시지를 가져옴
	{
		TranslateMessage(&msg);		// 키입력에 반응하는 메시지 변환, WM_KEYDOWN (키가 눌릴때) WM_CHAR 메시지 발생
		DispatchMessage(&msg);		// WndProc() 함수 호출과 WndProc()으로 메세지 전달
	}								// 종료는 WM_QUIT 발생할때 FALSE 리턴하면서 종료
	return (int)msg.wParam;			// wParam, lParam 윈도우 크기가 어떻게 변했는지, 변경된 클라이언트, 키보드, 마우스 값

}

void Animation(int xPos, int yPos, HDC hdc) {
	HDC memdc;
	HBITMAP RunBit[10], hBit, oldBit,Mask[10];
	static int count;
	int i;
	count++;
	count = count % 10;
	RunBit[0] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R1));
	RunBit[1] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R2));
	RunBit[2] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[3] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[4] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[5] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[6] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[7] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R3));
	RunBit[8] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R9));
	RunBit[9] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_R10));
	Mask[0] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_M1));
	Mask[1] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_M2));
	Mask[2] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_M3));
	Mask[3] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_M4));
	Mask[4] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_M5));
	Mask[5] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_M6));
	Mask[6] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_M7));
	Mask[7] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_M8));
	Mask[8] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_M9));
	Mask[9] = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP_M10));

	memdc = CreateCompatibleDC(hdc);
	hBit = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP5_20));
	oldBit = (HBITMAP)SelectObject(memdc, hBit);
	BitBlt(hdc, 0, 0, 819, 614, memdc, 0, 0, SRCCOPY);
	SelectObject(memdc, Mask[count]);
	BitBlt(hdc, xPos, yPos, 180, 240, memdc, 0, 0, SRCAND);
	SelectObject(memdc, RunBit[count]);
	BitBlt(hdc, xPos, yPos, 180, 240, memdc, 0, 0, SRCPAINT);
	SelectObject(memdc, oldBit);
	for (i = 0; i < 10; i++) {
		DeleteObject(RunBit[i]);
		DeleteObject(Mask[i]);
	}
	DeleteDC(memdc);
	DeleteObject(hBit);
}



LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
	WPARAM wParam, LPARAM lParam)
	//	WinDef.h 에서 정의
	//	wPram > unsigned ptr, lParam > long ptr 
{
	HDC hdc;
	PAINTSTRUCT ps;
	static int xPos;
	

	switch (iMsg)
	{
	case WM_CREATE:
		xPos = -100;
		SetTimer(hwnd, 1, 100, NULL);
		break;

	case WM_TIMER:
		xPos += 10;
		if (xPos > 819) xPos = -100;
		InvalidateRgn(hwnd, NULL, true);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
		Animation(xPos, 300, hdc);
		EndPaint(hwnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

.

.

.

실행화면

.

.

.

이렇게 오늘은 MFC의 더블 버퍼링과 마스크 bitmap에 대해서 알아보았습니다.

 

반응형

+ Recent posts