본문 바로가기

デベロップメント/ゲームプログラミング

2.2.6 WinProc 함수

2.2.6 WinProc 함수


마지막으로 중요한 WinProc 함수를 설명합니다.
이것은 메세지를 처리하기 위해 사용되는 함수입니다.
「WinProc」는 이 함수에 붙여진 일반적인 이름입니다.
이 함수의 이름은 전술(前述)의 윈도우 클래스를 작성하는 함수로 WNDCLASSEX 구조체에 지정된 이름과 일치할 필요가 있습니다.

프로그램에는 다양한 종류의 메세지가 송신되고 있습니다.
프로그램이 응답할 메세지에 대해서는  WinProc에 필요한 코드를 기술합니다.
프로그램이 무시한 메세지는 전부 Windows에 대해서 처리됩니다.

#코드 2.9가 응답하고 있는 메세지는, WM_DESTROY 밖에 없습니다.

WM_DESTROY는 윈도우가 화면에서 삭제되어, 그 후 파기될 때에 Windows에서 송신됩니다.

WM_DESTROY 메세지를 수신했다면, PostQuitMessage(0)를 호출해, 어플리케이션이 종료를 요구하고 있는 것을 Windows에 전합니다.

이 호출에 대해, 이번에는 WM_QUIT가 메세지 큐에 추가됩니다.

WM_QUIT 메세지로, WinMain내의 메인의 메세지 루프가 종료됩니다.


#코드 2.9 윈도우 이벤트 콜 백 함수

// ========================================================================
// 윈도우 이벤트 콜 백 함수
// ========================================================================
LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
	switch(msg){
		case WM_DESTROY:
			// Windows에 이 프로그램을 종료하도록 전달함
			PostQuitMessage(0);
			return 0;
		}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}


이걸로 완성입니다.

단순히 「Hello World」라고 표시하도록 하기 위해 실로 많은 코드가 필요했습니다.

하지만, 이와 같이 많은 코드를 기술하는 것으로, 어플리케이션의 윈도우의 외견이나 처리방법을 자유로이 컨트롤 하는 것이 가능하게 되었습니다.

질 높은 게임을 제작하기 위해서는, 이러한 세밀한 콘트롤이 필요합니다.

코드 2.10에 「Hello World」 샘플의 완전한 코드를 보여드리겠습니다.


#코드 2.10 Hello World 샘플

// Programming 2D Games
// Copyright (c) 2011 by:
// Charles Kelly
// 제 2장 Windows 스타일의 「Hello World」 v1.0
// winmain.cpp
#define WIN32_LEAN_AND_MEAN
#include "windows.h"

// 함수 프로토타입
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
bool CreateMainWindow(HINSTANCE, int);
LRESULT WINAPI WinProc(HWND, UINT, WPARAM, LPARAM);

// 전역 변수
HINSTANCE hinst;
HDC hdc;
TCHAR ch = ' ';
RECT rect;
PAINTSTRUCT ps;

// 정수
const char CLASS_NAME[] = "WinMain";
const char APP_TITLE[] = "Hello World";
const int WINDOW_WIDTH = 400;
const int WINDOW_HEIGHT = 400;

// ===================================================================================================
// Windows 어플리케이션의 시작점
// 파라메터
// 	hInstance : 어플리케이션의 현재의 인스턴스에 대한 핸들
// 	hPrevInstance : 항상 NULL (폐지된 파라메터)
// 	lpCmd : 커맨드라인 인수의 NULL 종단문자열에 대한 포인터
// 	nCmdShow : 윈도우를 어떤 방식으로 표시할지를 지정
// ===================================================================================================

int WINAPI WinMain(HINSTANCE hInstance,
					HINSTANCE hPrevInstance,
					LPSTR lpCmdLine,
					int nCmdShow) {
	MSG msg;

	// 윈도우를 작성
	if (!CreateMainWindow(hInstance, nCmdShow)) return false;

	// 메인의 메세지 루프
	int done = 0;
	while (!done) {

		// PeekMessage는 Windows 메세지가 있는가를 테스트 하는 비블록 메소드
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {

			// 종료 메세지를 감지
			if (msg.message == WM_QUIT) done = 1;

			// 메세지를 디코드해서 WinProc에 전함
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	return msg.wParam;
}

// ===================================================================================================
// 윈도우 이벤트 콜 백 함수
// ===================================================================================================
LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch (msg) {
		case WM_DESTROY:

			// 윈도우에 이 프로그램을 종료하도록 전달
			PostQuitMessage(0);
			return 0;
	}

	return DefWindowProc(hwnd, msg, wParam, lParam);
}

// ===================================================================================================
// 윈도우를 작성
// 반환 값 : 에러의 경우에 false
// ===================================================================================================
bool CreateMainWindow(HINSTANCE hInstance, int nCmdShow) {
	WNDCLASSEX wcx;
	HWND hwnd;

	// 윈도우 클래스의 구조체를 메인 윈도우를 기술할 파라메터로 설정합니다.
	wcx.cbSize = sizeof(wcx);					// 구조체의 사이즈
	wcx.style = CS_HREDRAW | CS_VREDRAW;				// 윈도우 사이즈 변경시에 다시 화면을 그림
	wcx.lpfnWndProc = WinProc;					// 윈도우 프로시져를 가리킴
	wcx.cbClsExtra = 0;						// 확장 클래스 메모리 없음
	wcx.cbWndExtra = 0;						// 확장 윈도우 메모리 없음
	wcx.hInstance = hInstance;					// 인스턴스에 대한 핸들
	wcx.hIcon = NULL;
	wcx.hCursor = LoadCursor(NULL, IDC_ARROW);			// 사전 정의된 화살표 커서
	wcx.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);	// 배경 브러쉬
	wcx.lpszMenuName = NULL;					// 메뉴 리소스의 이름
	wcx.lpszClassName = CLASS_NAME;					// 윈도우 클래스의 이름
	wcx.hIconSm = NULL;						// 작은 아이콘
	
	// 윈도우 클래스를 등록
	// 에러 시, RegisterClassEx는 0으로 되돌림
	if (RegisterClassEx(&wcx) == 0) return false;			// 에러시에
	
	// 윈도우를 작성
	hwnd = CreateWindow(CLASS_NAME,					// 윈도우 클래스의 이름
						APP_TITLE,		// 타이틀 바의 텍스트
						WS_OVERLAPPEDWINDOW,	// 윈도우의 스타일
						CW_USEDEFAULT,		// 윈도우의 수평 위치의 디폴트
						CW_USEDEFAULT,		// 윈도우의 수직 위치의 디폴트
						WINDOW_WIDTH,		// 윈도우의 너비
						WINDOW_HEIGHT,		// 윈도우의 높이
						(HWND)NULL,		// 부모 윈도우 없음
						(HMENU)NULL,		// 메뉴 없음
						hInstance,		// 어플리케이션 인스턴스에 대한 핸들
						(LPVOID)NULL);		// 윈도우 파라메터 없음
	
	// 윈도우의 작성에 에러가 발생했을 경우
	if (!hwnd) return false;

	// 윈도우를 표시
	ShowWindow(hwnd, nCmdShow);

	// 윈도우 프로시져에 WM_PAINT 메세지를 보냄
	UpdateWindow(hwnd);
	return true;
}



서장으로