0. 더미 코드를 제거한 이전 코드

더보기
#include "framework.h"
#include "GameCoding.h"

#define MAX_LOADSTRING 100

int mousePosX;
int mousePosY;


// 전역 변수:
HINSTANCE hInst;                                // 현재 인스턴스입니다.

// 이 코드 모듈에 포함된 함수의 선언을 전달합니다:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{   
    // TODO: 여기에 코드를 입력합니다.

    // 1) 윈도우 창 정보 등록
    MyRegisterClass(hInstance);

    // 2) 초기화
    if (!InitInstance (hInstance, nCmdShow))
        return FALSE;

    MSG msg;

    //3) 메인 루프 ; 
    while (::GetMessage(&msg, nullptr, 0, 0))
    {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}


//
//  함수: MyRegisterClass()
//
//  용도: 창 클래스를 등록합니다.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex{};

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GAMECODING));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = nullptr;
    wcex.lpszClassName  = L"GameCoding";
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

//
//   함수: InitInstance(HINSTANCE, int)
//
//   용도: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
//   주석:
//
//        이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
//        주 프로그램 창을 만든 다음 표시합니다.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.

   RECT windowRect = { 0, 0, 800, 600 };
   ::AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, false);

   HWND hWnd = CreateWindowW(L"GameCoding", L"Client", WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
      return FALSE;

   ::ShowWindow(hWnd, nCmdShow);
   ::UpdateWindow(hWnd);

   return TRUE;
}

//
//  함수: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  용도: 주 창의 메시지를 처리합니다.
//
//  WM_COMMAND  - 애플리케이션 메뉴를 처리합니다.
//  WM_PAINT    - 주 창을 그립니다.
//  WM_DESTROY  - 종료 메시지를 게시하고 반환합니다.
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 메뉴 선택을 구문 분석합니다:
            switch (wmId)
            {
            case IDM_EXIT:
                ::DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;

    case WM_PAINT:
        {
            PAINTSTRUCT ps;

            HDC hdc = BeginPaint(hWnd, &ps);

            EndPaint(hWnd, &ps);
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

About, 창의 이름 등등을 제거한 기본 코드.

 

0-1. Main 함수

    while (true)
    {   // 메시지가 있을 때 WndProc를 구동
        if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
        else
        {
            // 게임 로직 구동
        }
    }

메인 함수 내의 메인 루프를 수정한다.

if 문을 사용하여 메시지가 있을 때만 WndProc를 사용하도록 한다.

 

 

1. 미리 컴파일된 헤더 설정

위와 같이 설정하고 저장한다.

이후 솔루션 탐색기 - 추가 - 클래스에서 pch.h와 pch.cpp를 만든다.

그리고 pch.cpp의 미리 컴파일된 헤더 설정을 만들기로 바꾸고 저장한다.

 

1) pch.h

#pragma once

#include "Types.h"
#include "Enums.h"
#include "Defines.h"

#include <windows.h>
#include <vector>
#include <list>
#include <map>
#include <unordered_map>
#include <string>
#include <algorithm>
using namespace std;

GameCoding.cpp에 include 해준다.

 

2) Types.h

#pragma once

using int8 = __int8;
using int16 = __int16;
using int32 = __int32;
using int64 = __int64;

using uint8 = unsigned __int8;
using uint16 = unsigned __int16;
using uint32 = unsigned __int32;
using uint64 = unsigned __int64;

 

 

4. Game.h ; 게임의 베이스 코드

#pragma once
class Game
{
public:
	Game();
	~Game();

public:
	void Init();
	void Update();
	void Render();

private:
	HWND _hwnd = {};
	HDC _hdc = {};
};

앞으로도 Game 클래스는 기본적으로 Init(초기화), Update(업데이트), Render(렌더링) 세 개의 역할을 가진다.

 

5. GameCoding.cpp

1) 초기화

HWND g_hWnd;

핸들 번호를 들고있는 값이다. 전역변수로 선언한다.

그리고 아래에서 InitInstance를 찾아

g_hWnd = hWnd;

hWnd를 전역변수의 값으로 들고있게 저장한다.

 

이후에 메인 루프 위쪽에서 초기화를 한다.

    // 2) 초기화
    if (!InitInstance (hInstance, nCmdShow))
        return FALSE;

    Game game;
    game.Init(g_hWnd);

    MSG msg;

    //3) 메인 루프 ; 
    while (true)
    {   // 메시지가 있을 때 WndProc를 구동
        if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
        else
        {
            // 게임 로직 구동
            game.Update();
            game.Render();
        }
    }

메인 루프 내에서 업데이트와 렌더링을 진행한다.

 

2) X버튼을 누르면 프로그램 종료하기

while 문을 다음과 같이 수정한다.

    MSG msg = {};

    //3) 메인 루프 ; 
    while (msg.message != WM_QUIT)

 

6. Game.cpp

#include "pch.h"
#include "Game.h"

Game::Game()
{

}

Game::~Game()
{

}

void Game::Init(HWND hwnd)
{
	_hwnd = hwnd;
	_hdc = ::GetDC(hwnd);
}

void Game::Update()
{

}

void Game::Render()
{

}