[winAPI 03] Core class & Singleton
μ½μ΄(Core)λ λ§κ·Έλλ‘ μ€μ¬μ΄λΌλ μλ―Έλ‘ μ£Όμν κΈ°λ₯μ μ 곡νκ³ μ λ°μ μΈ νλ‘κ·Έλ¨ κ΅¬μ‘°λ₯Ό μ μνλ©° μ±κΈν€(singleton)μ ν΄λμ€μ μΈμ€ν΄μ€κ° λ¨ νλλ§ μμ±λλλ‘ λ³΄μ₯νλ μννΈμ¨μ΄ ν¨ν΄μ΄λ€. μ°λ¦¬κ° νλ‘κ·Έλ¨μ λ§λ€ λ μ½μ΄ ν΄λμ€μ κ°μ²΄κ° μ€μ¬μ΄ λ κ²μ΄κΈ°μ μ΄ κ°μ²΄λ μ¬λ¬ κ°μΌ μκ° μμ΄ μ±κΈν€ ν¨ν΄μΌλ‘ ꡬννκ³ μ νλ€.
- Core class ( λμ ν λΉ Heap μμ μ¬μ© )
// Core.h
class Core {
private:
static Core* pInst;
Core();
~Core();
public:
static Core* Instance()
{
if (pInst == nullptr) {
return new Core;
}
return pInst;
}
static void Release()
{
if (pInst != nullptr) {
delete pInst;
pInst = nullptr;
}
}
};
// Core.cpp
#include "Core.h"
Core* Core::pInst = nullptr;
// main.cpp - wWinMain
Core* pCore = Core::Instance();
μ°μ κ°μ²΄μ μμ±μ νλλ‘ μ ννλ €λ©΄ μ΄λ»κ² ν΄μΌ νλκ°?
→ μμ±μμ μλ©Έμλ privateμΌλ‘ μ μΈν΄μ£Όλ©΄ λλ€. μ€λ‘μ§ λ©€λ² ν¨μλ‘λ§ λ§λ€κ³ μ§μ°κ³ μμ±λ μ μκ² νλ€.
μ΄λμλ μ½κ² μ κ·Όνλ €λ©΄?
→ μκΈ° μμ μ ν¬μΈν°λ₯Ό λ°ννλ ν¨μλ‘ λ§λ€λ©΄ λλ€. λ€λ§, μμ±μμ μλ©Έμκ° privateμΌλ‘ μ μΈλ κ²½μ° μΈλΆμμ κ°μ²΄λ₯Ό λ§λ€ μ μκ² λλ€(νλΌμ΄λΉμ΄λΌ μμ±μλ‘ μ κ·Όμ΄ λΆκ°λ₯ν¨). κ°μ²΄κ° μλλ° λ©€λ² ν¨μμ λ©€λ² λ³μμ μ κ·Όμ΄ κ°λ₯νκ°?
→ No. λκ° ν¨μλ₯Ό νΈμΆνλμ§ μ μ μμ΄(thisκ° μμ) μ κ·Όμ΄ λΆκ°λ₯νλ€.
→ λ©€λ² μμ΄ νΈμΆνλ €λ©΄ static(μ μ )μΌλ‘ μ μΈν νμκ° μλ€
→ μ μ λ©€λ² ν¨μλ λ΄λΆ μ μ λ©€λ²λ‘λ§ μ κ·Όν μ μλ€.
μ μ (static) λ³μ μ μΈμ λνμ¬
1. ν¨μ μμ μ μΈ → data μμ (ν¨μκ° μ’
λ£λλλΌλ ν λΉλ 곡κ°μ λ¨μμμ -> ν΄λΉ ν¨μμμλ§ μ κ·Ό κ°λ₯)
2. νμΌ μμ μ μΈ → dataμμ, νμΌ μμμλ§ μ κ·Όμ΄ κ°λ₯
3. ν΄λμ€ μμ μ μΈ → dataμμ / ν΄λμ€μ μ¬μ΄μ¦(ν¬κΈ°)μλ μκ΄ μκ² , ν΄λμ€ λ΄λΆμμλ§ μ κ·Ό κ°λ₯
→ μ΄λμλ λ§λ€λλΌλ λ°μ΄ν° μμμ μλ κ²
* μ μ λ©€λ²λ 무쑰건 ν΄λμ€ μΈλΆμμ μ΄κΈ°ν ν΄μ€μΌν¨ → μνλ©΄ λ§ν¬ μ€λ₯
Core ν΄λμ€μ λ©€λ² ν¨μλ‘ λ κ°μ§λ₯Ό λ§λ€μ
1. μΈμ€ν΄μ€λ₯Ό μ»λ ν¨μ ( static Core* Instance() )
μκΈ° μμ μ ν¬μΈν°νμ λ°ννλ Instanceν¨μλ₯Ό λ§λ λ€
→ μ΅μ΄ νΈμΆλλ κ²½μ° (pInstκ° nullptrμΈ κ²½μ°) : λμ μΌλ‘ Core κ°μ²΄ νλλ₯Ό λ§λ€μ΄ κ·Έ μ£Όμλ₯Ό λ°ννλ€.
→ 2λ² μ΄μ νΈμΆμΈ κ²½μ° μ무 κ²λ νμ§ μλλ€.
2. ν΄μ νλ ν¨μ ( static void Release() )
λμ μΌλ‘ μ¬μ©ν κ°μ²΄λ ν΄μ κ° νμνλ€. pInstκ° nullptrμ΄ μλλΌλ©΄(κ°μ²΄κ° μλ€λ©΄) λ©λͺ¨λ¦¬λ₯Ό ν΄μ νκ³ κ·Έ 곡κ°μ nullptrλ‘ λ°κΎΌλ€.
pInstλ Core.cppμμ 무쑰건 μ΄κΈ°ννλ€.
- Core class ( Dataμμ μ¬μ© )
class Core {
private:
Core();
~Core();
public:
static Core* Instance() {
static Core core;
return &core;
}
};
κ°λ¨νλ€. Coreμ μ£Όμλ₯Ό μ»μ΄μ μ κ·Όνλ©΄ λλλ° ν΄μ ν νμκ° μκ³ κ°λ¨νλ€λ μ₯μ μ΄ μμ§λ§, λ¨μ μΌλ‘λ νλ‘κ·Έλ¨ μ€κ°μ μ§μΈ μ μλ€λ μ¬μ€μ΄λ€. λ³΄ν΅ Managerμμ μ°μ΄λ©° κ΅³μ΄ μ§μΈ νμ μμ λ λ§μ΄ μ¬μ©λλ€.
μμ£Ό μ¬μ©νλ κ²λ€μ λ§€ν¬λ‘λ‘ μ ν΄λλ©΄ μ’λ€μ°μ κ·Έ μ μ 미리 λ§λ€κ³ λ€μ μ΄ν΄λ³Ό κ²½μ°κ° μλ κ²λ€μ λͺ¨μ pch.hλ‘ λ§λ€κ³ , 미리 μ»΄νμΌ λ ν€λλ‘ λ§λ€μ΄ λμ.미리 μ»΄νμΌ λ ν€λλ λͺ¨λ cppνμΌμ μ‘΄μ¬ν΄μΌ νλ©° μ΄λ₯Ό μ¬μ©νλ©΄ μ»΄νμΌ μλλ₯Ό μ¬λ¦΄ μ μλ€.
// pch.h
#pragma once
#include <windows.h>
#include "define.h"
* νλ‘μ νΈμ μμ± → C/C++ → 미리 μ»΄νμΌλ ν€λ → 맨 μμ μ€μ λ§λ€κΈ° + λ λ²μ§Έ ν€λ νμΌ μ΄λ¦ μ€μ
define.h λ΄λΆμ Core ν΄λμ€μ instanceλΆλΆμ λ§€ν¬λ‘λ‘ μ§μ νλ€.
#include "pch.h"
# define SINGLE(type) public:\
static Core* Instance()\
{\
static Core mgr;\
return &mgr;\
}
μ¬κΈ°μ λ°±μ¬λμ¬(\)λ λ§€ν¬λ‘ λ΄μμ ν μ€ λμ°λ κ²μ μλ―Ένλ€. publicλ μμ§λ§μ.λͺ¨λ cpp νμΌ λ΄μ pch.hλ₯Ό μΆκ°νλ€λ©΄,μμ Core ν΄λμ€ νμΌμ μλμ κ°μ΄ μΈ μ μλ€.
#pragma once
class Core {
SINGLE(Core);
private:
Core();
~Core();
public:
};
- Core classλ₯Ό μ΄μ©ν΄μ ν΄μλ μ€μ κ³Ό μ¬κ°ν 그리기
본격μ μΌλ‘ Core classλ₯Ό μ΄μ©ν΄ λ§λ€μ΄λ³΄μ.
// Core.class
class Core {
SINGLE(Core);
private:
HWND handle;
POINT ptResolution;
HDC hDC;
Core();
~Core();
public:
int Init(HWND _hWnd, POINT _ptResolution);
void Progress();
};
Core ν΄λμ€ λ΄λΆμ μ°½ νΈλ€μ λ°μ λ³μ(handle)μ, ν΄μλλ₯Ό λ°μ λ³μ(ptResolution)μ λ§λ λ€, hDCλ 그리기 μν λ³μλ‘ μ‘°κΈ μ΄λ°κ° λ°μμ μ€λͺ νκ² λ€.
μ΄ λ³μλ€μ λͺ¨λ privateμΌλ‘ μ΄ κ°λ€μ κ°μ§κ³ μ€μ νκΈ° μν ν¨μλ€μ publicμΌλ‘ μ€μ νλ€.
#include "pch.h"
#include "Core.h"
Core::Core()
:handle(0)
, ptResolution{}
, hDC(0)
{
}
Core::~Core()
{
ReleaseDC(handle, hDC);
}
int Core::Init(HWND _handle, POINT _ptResolution)
{
handle = _handle;
ptResolution = _ptResolution;
RECT rt = {0, 0 , ptResolution.x, ptResolution.y };
AdjustWindowRect(&rt, WS_OVERLAPPEDWINDOW, true);
SetWindowPos(handle, nullptr, 100, 100, rt.right - rt.left, rt.bottom - rt.top, 0);
return S_OK;
}
void Core::Progress()
{
}
Core.cppμ μ΄ν΄λ³΄κ² λ€. μ°μ μμ±μμμ κ° λ³μμ λν μ΄κΈ°νλ₯Ό, μλ©Έμμμ μΆνμ μΈ hDCλ₯Ό ν΄μ νλ λΆλΆμ μ¨μ€λ€.
Init()ν¨μλ class κ°μ²΄κ° μμν λ μ΄κΈ°νν΄μΌ νλ λΆλΆμ λ£μ ν¨μλ€. νΈλ€ κ°(_handle)κ³Ό μ€μ ν ν΄μλ κ°(_ptResolution)μ λ§€κ°λ³μλ‘ λ°λλ€.
κ° λ§€κ°λ³μ κ°μ λ©€λ² λ³μ handleμ ptResolutionμ λ£λλ€.
AdjustWindowRect() ν¨μλ μλμ°κ° μ€μ λ‘ κ·Έλ¦΄ μ μλ μμμ κ³μ°νλλ°, λ©λ΄λ°λ μλμ° μ°½ μ£Όλ³μΌλ‘ μ겨μλ ν λ리 μμ(8pixel μ λ)λ₯Ό μ μΈν μμμ μλ―Ένλ€. κ° λ§€κ°λ³μμ μλ―Έλ λ€μκ³Ό κ°λ€.
IpRect : μλμ°μ ν¬κΈ°μ μμΉλ₯Ό μ§μ νλ RECT ꡬ쑰체μ λν ν¬μΈν°
dwStyle : μλμ°μ μ€νμΌ (λͺ¨μκ³Ό λμ - ν λ리, μ λͺ© νμμ€, ν¬κΈ° μ‘°μ μ΄ κ°λ₯νμ§ λ±)
bMenu : λ©λ΄λ°
νμ¬ RECT ꡬ쑰체λ₯Ό μ΄μ©ν΄μ μλμ° ν¬κΈ°λ₯Ό μ‘°μ νλ©° SetWindowPos() ν¨μλ₯Ό μ¬μ©ν΄ μλμ°μ μμΉμ ν¬κΈ°λ₯Ό μ€μ νλ€.
rt-right - rt.left μ rt.bottom - rt.topμ κ°κ° μλμ°μ λλΉμ λμ΄λ₯Ό μλ―Ένλ€.
hWnd: μλμ° νΈλ€
hWndInsertAfter: μλ‘μ΄ Z μμλ₯Ό μ€μ
X: μλμ°μ x μ’ν
Y: μλμ°μ y μ’ν
cx: μλμ°μ λλΉ
cy: μλμ°μ λμ΄
uFlags: μλμ° μμΉμ ν¬κΈ°λ₯Ό μ€μ νλ λ° μ¬μ©λλ νλκ·Έ
λ€μμ mainμ μμ ν΄ λ°μν΄μ£Όμ΄μΌ νλ€.
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_WINDOWSPROJECT, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
if (FAILED(Core::Instance()->Init(hWnd, POINT{ 1280, 768 }))) {
MessageBox(nullptr, L"Core κ°μ²΄ μ΄κΈ°ν μ€ν¨", L"ERROR", MB_OK);
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT));
MSG msg;
while (true){
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
if (WM_QUIT == msg.message)
break;
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else{
Core::Instance()->Progress();
}
}
return (int) msg.wParam;
}
μμ λ€λ£¨μλ―μ΄ Core κ°μ²΄λ Instance()λ₯Ό μ΄μ©ν΄ μμ±ν΄μ μ κ·Όν΄μΌ νλ€.
μ΄λ₯Ό μ΄μ©ν΄ μ΄κΈ°ν μμ μ μ€ννμ.
νμ¬ μ°λ¦¬κ° λ€λ£¨κ³ μλ μ°½μ handle κ°κ³Ό 1280, 768μ ν΄μλ κ°μΌλ‘ μ λ¬νκ² λ€.
λ§μ½ μ΄ μμ μ μ€ν¨νλ©΄ FALED κ°μ΄ trueκ° λμ΄ λ©μΈμ§ λ°μ€λ₯Ό μμ±νκ³ μ’ λ£νλλ‘ νμ.
μ΄μ μ¬κ°νμ κ·Έλ €λ³΄μ.
μ΄μ λ Core class λ΄λΆμ Progress() ν¨μ λ΄λΆμ κ³μ μ€νλλ λΆλΆμ μ¬κΈ°μ μ½λ©ν κ²μ΄λ€.
그리기 μμ λν μ¬κΈ°μ μ§νν μ μλλ° λ©μΈμ§μμ μ²λ¦¬νλ κ²κ³Ό λκ°μ΄ DCκ° νμνλ€. λ°λΌμ ν΄λμ€ λ΄λΆμ HDC λ©€λ² λ³μλ₯Ό νλ λ§λ€μ΄ μ€ κ².
μ΄λ₯Ό μ΄μ©ν΄μ ν΄λμ€ λ΄λΆ ν¨μμμ μ΄λ»κ² 그릴 κ²μΈκ°?
Object ν΄λμ€λ₯Ό νλ λ§λ€κ² λ€
// Object.h
#pragma once
class Object {
public:
POINT ptPos;
POINT ptScale;
public:
Object();
~Object();
};
// Object.cpp
#include "pch.h"
#include "Object.h"
Object::Object()
: ptPos{}
, ptScale{}
{
}
Object::~Object()
{
}
μμΌλ‘ μ΄ Object classλ₯Ό μ΄μ©ν΄ κ²μμ μ‘΄μ¬νλ 물체λ₯Ό λ§λ€ κ²μ΄λ€. λ³΄ν΅ νμ¬ λ©€λ² λ³μλ€μ privateμ μ΄μ©ν΄ λ§λλ κ²μ΄ μ³μ§λ§, publicμΌλ‘ μΌλ¨ μ€μ νκ² λ€.
// Core.cpp
#include "Object.h"
Object obj;
// ...
int Core::Init(HWND _handle, POINT _ptResolution)
{
// ...
hDC = GetDC(handle);
obj.ptPos = POINT{ ptResolution.x, ptResolution.y };
obj.ptScale = POINT{ 100,100 };
return S_OK;
}
void Core::Progress()
{
Rectangle(hDC, 10, 10, 110, 110);
}
hDC λ³μμ handle κ°μ μ΄μ©ν΄ DCλ₯Ό κ°μ Έμ€κ³ , μ¬κ°νμ 그릴 λ νμν κ°λ€μ ꡬ쑰체μ μ λ¬ν΄μ£Όλλ‘ νλ€.
μ΄ν Progress() ν¨μ λ΄μμ μ¬κ°νμ κ·Έλ €μ£Όλ©΄ λλ€.
λ©μΈμ§ λ°©μμ΄ μλλΌ κ³μν΄μ κ°±μ νλ λ°©λ²μΌλ‘ μ¬κ°νμ κ·Έλ¦° κ²μ΄λ€.
(μ€μ κ²μμ κ° μ₯λ©΄μ λ€μ κ·Έλ¦°λ€. μ΄λ₯Ό λ λλ§μ΄λΌ νκ³ 1μ΄ 60λ² ν΄μΌ μμ°μ€λ½κ² 보μ )
λ€μμ ν€ μ λ ₯μ λ°μμ μ¬κ°νμ μ΄λμμΌλ³΄μ
- ν€ μ λ ₯ν΄μ μ¬κ°ν μ΄λνκΈ° (Updateν©μμ Renderν¨μ)
// Core.h
class Core {
SINGLE(Core);
private:
HWND handle;
POINT ptResolution;
HDC hDC;
Core();
~Core();
private:
void Update(); // μΆκ°
void Render(); // μΆκ°
public:
int Init(HWND _hWnd, POINT _ptResolution);
void Progress();
};
// Core.cpp
// Init ν¨μ
obj.ptPos = POINT{ ptResolution.x / 2, ptResolution.y / 2 }; // μμ
oid Core::Progress()
{
Update();
Render();
}
void Core::Update()
{
// ν€μ
λ ₯..
if (GetAsyncKeyState(VK_LEFT) & 0x8000) {
obj.ptPos.x -= 1;
}
if (GetAsyncKeyState(VK_RIGHT) & 0x8000) {
obj.ptPos.x += 1;
}
}
void Core::Render()
{
Rectangle(hDC,
obj.ptPos.x - obj.ptScale.x / 2,
obj.ptPos.y - obj.ptScale.y / 2,
obj.ptPos.x + obj.ptScale.x / 2,
obj.ptPos.y + obj.ptScale.y / 2);
}
Update() ν¨μλ 물체μ λ³κ²½λ μ’νλ₯Ό μΆμ νκ³ μ λ°μ΄νΈνλ ν¨μλ©°, Render()μ μ΄ μ 보λ₯Ό ν λλ‘ κ·Έλ¦¬λ κΈ°λ₯μ μννλ ν¨μλ€.
GetAsyncKeyState() ν¨μλ₯Ό μ΄μ©νλ©΄ λΉνΈλ₯Ό ν΅ν΄ μ¬λ¬ μ 보λ₯Ό κ°μ Έμ¬ μ μλλ° 0x8000κ³Ό λΉνΈμ°μ° ν΄μ£Όλ©΄ ν€κ° λλ Έλμ§λ₯Ό νμΈν μ μλ€. ν€κ° λλ Έμ λ ν΄λΉ μ’νλ₯Ό λλ¦¬κ³ μ€μ΄λ μ½λλ€.
κ²°κ³Όλ₯Ό λ΄λ³΄μ
ν€λ³΄λ μ€λ₯Έμͺ½ λ°©ν₯ν€λ₯Ό λλ₯΄λ©΄ μ΄λ κ² λλ€
μλͺ»λκ² μλλΌ νμ¬ μ½λμμ Progress()ν¨μκ° 1μ΄μ 4λ§λ² μ λκ° λμκ°μ(λ무 λΉ¨λΌμ) μκΈ°λ λ¬Έμ λ€
μ΄λ₯Ό ν΄κ²°νκΈ° μν λ°©μμ λ€μ μκ°μ..