RenderWindow.h
#pragma once
#include "ErrorLogger.h"
class RenderWindow
{
public:
bool Initialize(HINSTANCE hInstance, string window_title, string window_class, int width, int height);
bool ProcessMessages();
~RenderWindow();
private:
void RegisterWindowClass();
HWND handle = NULL;
HINSTANCE hInstance = NULL;
string window_title = "";
wstring window_title_wide = L"";
string window_class = "";
wstring window_class_wide = L"";
int width = 0;
int height = 0;
};
RenderWindow.cpp
생성할 창의 이름, 제목 등 특징을 설정하고 창을 띄우는 함수
만약, 핸들이 없으면 경고창을 띄움
#include "RenderWindow.h"
/* 초기화 */
bool RenderWindow::Initialize(HINSTANCE hInstance, string window_title, string window_class, int width, int height)
{
this->hInstance = hInstance;
this->width = width;
this->height = height;
this->window_title = window_title;
this->window_title_wide = StringConverter::StringToWide(this->window_title); // wstring 타입으로 변경
this->window_class = window_class;
this->window_class_wide = StringConverter::StringToWide(this->window_class); // wstring 타입으로 변경
this->RegisterWindowClass(); // 렌더링 할 윈도우 특징 설정
/* 확장 윈도우 스타일 */
this->handle = CreateWindowEx(0, // 생성 중인 윈도우의 확장 스타일
this->window_class_wide.c_str(), // 윈도우 클래스 이름
this->window_title_wide.c_str(), // 윈도우 제목
WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, // 윈도우 스타일
0, // 윈도우 수평 위치
0, // 윈도우 수직 위치
this->width, // 윈도우 너비
this->height, // 윈도우 높이
NULL, // 생성중인 윈도우의 부모에 대한 핸들
NULL, // 메뉴에 대한 핸들 or 윈도우 스타일에 따라 자식 윈도우 식별자 지정
this->hInstance, // 윈도우와 연결한 모듈의 인스턴스에 대한 핸들
nullptr); // 윈도우를 생성하기 위한 파라미터
/* 핸들이 없으면 경고창 띄움 */
if (this->handle == NULL)
{
ErrorLogger::Log(GetLastError(), "CreateWindowEX Failed for window: " + this->window_title);
return false;
}
/* 창을 띄우고 포커스를 해당 창으로 설정 */
ShowWindow(this->handle, SW_SHOW); // 지정된 창의 표시 상태 설정
SetForegroundWindow(this->handle); // 지정된 창을 만든 스레드를 포그라운드로 가져와 창을 활성화
SetFocus(this->handle); // 지정된 창에 포커스 설정
return false;
}
CreateWindowEx 함수
CreateWindowEx(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam );
- dwExStyle : 생성 중인 창의 확장 스타일 - lpClassName : 윈도우 클래스 이름 - lpWindowName : 윈도우 제목 - dwStyle : 윈도우 스타일 * WS_CAPTION : 제목 표시줄 * WS_MINIMIZEBOX : 최소화 버튼 * WS_SYSMENU : 제목 표시줄의 창 메뉴 - X, Y : 윈도우 수평/수직 위치 - nWidth, nHeight : 윈도우 너비/높이 - hWndParent : 생성중인 윈도우의 부모에 대한 핸들 - hMenu : 메뉴에 대한 핸들 or 윈도우 스타일에 따라 자식 윈도우 식별자 지정 - hInstance : 윈도우와 연결한 모듈의 인스턴스에 대한 핸들 - lpParam : 윈도우를 생성하기 위한 파라미터
CreateWindowEx 참고 링크
- CreateWindowEx 함수 : CreateWindowEx 함수 참고 링크
- dwStyle 종류 : dwStyle 종류 참고 링크
렌더링할 창의 특징을 설정하는 함수
/* 렌더링할 윈도우 특징 설정 */
void RenderWindow::RegisterWindowClass()
{
WNDCLASSEX wc; // 윈도우 클래스
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // 윈도우 클래스의 스타일
wc.lpfnWndProc = DefWindowProc; // 윈도우 프로시저의 함수명 - WndProc에서 처리하지 않은 나머지 메시지에 관한 처리를 해줌
wc.cbClsExtra = 0; // 윈도우 클래스 구조에 할당할 메모리 (사용 x)
wc.cbWndExtra = 0; // 윈도우 인스턴스에 할당할 메모리 (사용 x)
wc.hInstance = this->hInstance; // 인스턴스 핸들 전달
wc.hIcon = NULL; // 아이콘 핸들
wc.hIconSm = NULL; // 작은 아이콘 핸들
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 커서 핸들
wc.hbrBackground = NULL; // 배경 브러시 핸들
wc.lpszMenuName = NULL; // 메뉴 리소스 - 메뉴에 대해 NULL로 종료된 문자열에 대한 포인터
wc.lpszClassName = this->window_class_wide.c_str(); // 윈도우 클래스 이름에 대해 NULL로 종료된 문자열에 대한 포인터
wc.cbSize = sizeof(WNDCLASSEX); // 윈도우 클래스 구조체의 크기
RegisterClassEx(&wc); // 윈도우 클래스 등록
}
WNDCLASSED 구조체
- cbSize : 윈도우 클래스 구조체의 크기 - style : 윈도우 클래스 스타일 - lpfnWndProc : 창 프로시저에 대한 포인터 - WndProc에서 처리하지 않은 나머지 메시지에 관한 처리를 해줌 - cbClsExtra : 윈도우 클래스 구조에 할당할 메모리 (사용 x) - cbWndExtra : 윈도우 인스턴스에 할당할 메모리 (사용 x) - hInstance : 인스턴스 핸들 전달 - hIcon : 아이콘 핸들 - hCursor : 커서 핸들 - hbrBackground : 배경 브러시 핸들 - lpszMenuName : 메뉴 리소스 - 메뉴에 대해 NULL로 종료된 문자열에 대한 포인터 - lpszClassName : 윈도우 클래스 이름에 대해 NULL로 종료된 문자열에 대한 포인터 - hIconSm : 작은 아이콘 핸들
WNDCLASSEX 참고 링크
메시지를 처리해주는 함수
bool RenderWindow::ProcessMessages()
{
/* 윈도우 메시지 핸들 */
MSG msg;
ZeroMemory(&msg, sizeof(MSG)); // 메모리 구조 초기화
if (PeekMessage(&msg, // 메시지 정보를 수신하는 MSG 구조에 대한 포인터
this->handle, // 메시지를 검색할 창에 대한 핸들
0, // 검사할 메시지 범위의 첫 번째 메시지 값
0, // 검사할 메시지 범위의 마지막 메시지 값
PM_REMOVE)) // 메시지 처리 방법
{
TranslateMessage(&msg); // 가상 키 메시지를 문자 메시지로 변환
DispatchMessage(&msg); // 창 프로시저에 메시지를 전달
}
/* 창이 닫혔는지 체크 */
if (msg.message == WM_NULL)
{
if (!IsWindow(this->handle)) // 창이 닫힌 경우
{
this->handle = NULL;
UnregisterClass(this->window_class_wide.c_str(), this->hInstance); // 창 클래스의 등록을 취소
return false;
}
}
return true;
}
RenderWindow 함수의 소멸자
/* 소멸자 */
RenderWindow::~RenderWindow()
{
if (this->handle != NULL)
{
UnregisterClass(this->window_class_wide.c_str(), this->hInstance);
DestroyWindow(handle);
}
}
#include "RenderWindow.h" // 헤더 파일 변경
// 아까 추가한 라이브러리를 가져옴
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "DirectXTK.lib")
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, // 인스턴스에 대한 핸들
_In_opt_ HINSTANCE hPrevInstance, // 사용 X
_In_ LPWSTR lpCmdLine, // 커맨드 라인을 유니코드 문자열로 포함
_In_ int cCmdShow) // 기본 응용 프로그램 창이 최소화, 최대화 또는 정상적으로 표시되는지 여부를 나타내는 플래그
{
/* 에러 창 띄우기
HRESULT hr = E_INVALIDARG; // 올바르지 않은 매개 변수
ErrorLogger::Log(hr, "FAILURE");
*/
RenderWindow rw;
rw.Initialize(hInstance, "Title", "MyWindowClass", 800, 600); // 창 크기를 800, 600으로 설정
/* 창을 닫을 때까지 열어둠 */
while (rw.ProcessMessages() == true) {} // 창을 끄는 경우 ProcessMessages에서 false가 반환되어 종료됨
return 0;
}