κΈ°νλ νλμ μλ μΌμ΄λΌκ³€ μλ μι³₯μ κ°μ κ². βC.M.
ο»Ώ
1 μμνκΈ°μ μ #
μ΄ κ°μμμ½μ μ΄ν΄νκΈ° μ μ λ€μκ³Ό κ°μ μ¬νμ λν μ§μμ΄ νμν©λλ€.
- ν΄λμ€ κΈ°μ΄ - struct ν€μλμ λμ νμ©μ΄λ©΄ λ©λλ€. λ§΄λ²λ³μμ λ©μλ κ°λ μ λ.
- C++ static ν€μλμ μ©λ²
- ν¨μν¬μΈν° - ν¨μν¬μΈν°λ₯Ό μ°Έμ‘°νμΈμ.
2 STATE_MANAGER ? #
win32api/μ΄μνΌνκΈ°3 μμ λ₯Ό 보면 νμ΄ννλ©΄κ³Ό κ²μνλ©΄μ μ μ ν¨μν¬μΈν°λ‘ κ΅μ²΄νλ―μ΄ λ§λ€μλ κ²μ μ μ μμ΅λλ€. μ΄λ λ§€λ² μ μν¨μν¬μΈν°λ³μλ₯Ό μ μΈν΄μΌνκ³ μ½λμμ λ²κ·Έκ° μΌμ΄λ νλ₯ λ λμΌλ―λ‘ κ°λ¨ν ν΄λμ€λ‘ μ 리ν΄λ³΄μ... ν΄μ λ§λ€μ΄μ§ κ²μ΄ STATE_MANAGERμ
λλ€.
State_Manager ν΄λμ€λ λ€μκ³Ό κ°μ νΉμ§μ κ°μ ΈμΌλ§(?) ν©λλ€.
- μ±κΈν€μΌ κ² - ν€λνμΌλ§ includeλλ©΄ λ§μΉ μ΄λμλ μΈμ€ν΄μ€λ₯Ό μ μΈνμ§ μκ³ λΆλ¬μΈ μ μμ΄μΌν©λλ€.
- ν¨μν¬μΈν°μ μν μ΄κ±°νλ³μλ₯Ό μ°κ΄μν¬ κ² - κ·Έλμ μνλ₯Ό λ³κ²½ν λμλ μ΄κ±°ν κ°λ§ κ΅μ²΄νλ©΄ λλλ‘ κ΅¬νν©λλ€.
state_manager.hppμ νλ¨μ 보면 STATEMANAGERλΌλ λ§€ν¬λ‘λ₯Ό μ μΈν΄λμλλ°, μ΄λ μμ€μ½λκ° κΈΈμ΄μ§λ κ²μ λ°©μ§νκΈ° μν΄μ μ
λλ€.
3.1 state_manager.hpp #
#ifndef __STATE_MANAGER_HPP__
#define __STATE_MANAGER_HPP__
#include <windows.h>
#define MAX_STATE_NUM 255
#define WM_ENTERSTATE (0x7FFF - 1)
#define WM_LEAVESTATE (0x7FFF - 2)
enum StateType { stTitle, stGame, stHighScore, stGameOver };
struct State {
StateType type;
WNDPROC winproc;
};
struct State_Manager {
State m_state[MAX_STATE_NUM];
int m_statenum;
StateType m_current_type;
WNDPROC m_current_proc;
// μλ‘μ΄ μνλ₯Ό μ€μ
bool SetState(StateType type_, WNDPROC ptrWinProc);
// νμ¬ μνλ₯Ό λ³κ²½
bool SwitchState(StateType type_, HWND hwnd_);
// νμ¬ μνμ λμνλ μλμ° νλ‘μμ Έλ₯Ό μ€ν
LRESULT ExecuteWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
// μ μ λ©μλ. State_Manager μ μ μ±κΈν€ κ°μ²΄ ν¬μΈν°λ₯Ό λ°ν
static State_Manager *instance();
};
#define STATEMANAGER (State_Manager::instance())
#endif
3.2 state_manager.cpp #
#include "State_Manager.hpp"
static State_Manager *g_instance = NULL;
State_Manager *State_Manager::instance() {
// νμ¬ State_Managerλ₯Ό μ²μ νΈμΆν κ²μ΄λΌλ©΄ μλ‘ μΈμ€ν΄μ€λ₯Ό μμ±
if (!g_instance) {
g_instance = new State_Manager();
g_instance->m_statenum = 0;
g_instance->m_current_proc = NULL;
}
return g_instance;
}
bool State_Manager::SetState(StateType type_, const WNDPROC ptrWinProc) {
State *pState = NULL;
for (int i = 0; i < this->m_statenum; i++) {
if (this->m_state[i].type == type_) {
pState = &(this->m_state[i]);
break;
}
}
if (!pState) {
this->m_state[this->m_statenum].type = this->m_current_type = type_;
this->m_state[this->m_statenum].winproc = this->m_current_proc = ptrWinProc;
this->m_statenum++;
return true;
}
else {
this->m_current_type = type_;
pState->winproc = this->m_current_proc = ptrWinProc;
return false;
}
}
bool State_Manager::SwitchState(StateType type_, HWND hwnd_) {
State *pState = NULL;
for (int i = 0; i < this->m_statenum; i++) {
if (this->m_state[i].type == type_) {
pState = &(this->m_state[i]);
break;
}
}
if (!pState) return false;
else {
SendMessage(hwnd_, WM_LEAVESTATE, (WPARAM) this->m_current_type, (LPARAM) NULL);
this->m_current_type = pState->type;
this->m_current_proc = pState->winproc;
SendMessage(hwnd_, WM_ENTERSTATE, (WPARAM) this->m_current_type, (LPARAM) NULL);
return true;
}
}
LRESULT State_Manager::ExecuteWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
if (this->m_current_proc != NULL) {
WNDPROC tmpProc = this->m_current_proc;
return tmpProc(hwnd, message, wParam, lParam);
}
else return DefWindowProc(hwnd, message, wParam, lParam);
}
3.3 ν μ€νΈμ© main.cpp #
κ°λ¨ν νμ¬ μνλ₯Ό λ³κ²½ν΄λ³΄μμ΅λλ€. κ° state μ§μ
κ³Ό ν΄μ μμ λ©μΈμ§λ°μ€λ₯Ό λμμΌλ‘μ νλ¦μ μ μ μκ² νμ΅λλ€.
#include <windows.h>
#include "state_manager.hpp"
LRESULT CALLBACK CoreWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
return STATEMANAGER->ExecuteWinProc(hwnd, message, wParam, lParam);
}
LRESULT CALLBACK TitleWinProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK GameWinProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
/* μλμ° ν΄λμ€λͺ
μ μ ν©λλ€ */
char szClassName[ ] = "State λ³νλ°λͺ¨";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
HWND hwnd; /* μλμ° νΈλ€ */
MSG messages; /* μλμ° λ©μΈμ§λ₯Ό μμμ μΌλ‘ λ΄μλ λ³μ. λ©μΈμ§ 루νμμ μ¬μ©. */
WNDCLASSEX wincl; /* μλμ°ν΄λμ€ λ°μ΄ν ꡬ쑰체 */
/* μλμ° ν΄λμ€ λ°μ΄ν ꡬ쑰체μ κ°μ μ±μ΄λ€ */
wincl.hInstance = hThisInstance; /* νμ¬ μΈμ€ν΄μ€ νΈλ€κ° μ§μ */
wincl.lpszClassName = szClassName; /* ν΄λμ€ μ΄λ¦. λ³΄ν΅ μ΄ν리μΌμ΄μ
μ΄λ¦μ μ§μ . */
wincl.lpfnWndProc = CoreWinProc; /* μλμ° νλ‘μμ Έ ν¨μ ν¬μΈν° */
wincl.style = CS_DBLCLKS; /* λλΈν΄λ¦ μ΄λ²€νΈλ₯Ό λ°μλ€μ
λλ€ */
wincl.cbSize = sizeof (WNDCLASSEX); /* μ΄ κ΅¬μ‘°μ²΄ ν¬κΈ° μ€μ . (λ°λμ ν΄μΌν¨) */
/* λ§μ°μ€ 컀μ μ΄λ―Έμ§λ‘μ κΈ°λ³Έ μμ€ν
컀μλ₯Ό μ€μ ν©λλ€ */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* λ©λ΄μ€μ μν¨ */
wincl.cbClsExtra = 0; /* μλμ° ν΄λμ€μ 첨λΆλ λ°μ΄ν μμ. λλΆλΆμ κ²½μ° 0 */
wincl.cbWndExtra = 0; /* λΆκ°μ μΈ μλμ° μΈμ€ν΄μ€ λλ ꡬ쑰체 μμ. λλΆλΆμ κ²½μ° 0 */
/* μλμ° κΈ°λ³Έ λ°°κ²½μμμ μ§μ . κΈ°λ³Έ ν
λ§ μμμΌλ‘ μ μ©ν©λλ€. */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* μλμ° ν΄λμ€λ₯Ό λ±λ‘νκ³ μ€ν¨ν κ²½μ°μλ νλ‘κ·Έλ¨μ μ’
λ£ν©λλ€ */
if (!RegisterClassEx (&wincl))
return 0;
/* ν΄λμ€κ° λ±λ‘λμμΌλ©΄ μ΄μ μλμ°λ₯Ό μμ±ν©λλ€! */
hwnd = CreateWindowEx (
0, /* μλμ° νμ₯ μ΅μ
*/
szClassName, /* ν΄λμ€μ΄λ¦ */
"ν
μ€νΈμ΄ν리μΌμ΄μ
", /* μλμ° νμ΄ν λ°μ μ ν λ¬Έμμ΄ */
WS_OVERLAPPEDWINDOW, /* κΈ°λ³Έ μλμ° νν */
CW_USEDEFAULT, /* μλμ° μμΉ x μ’ν */
CW_USEDEFAULT, /* μλμ° μμΉ y μ’ν */
544, /* μλμ° ν */
375, /* μλμ° λμ΄ */
HWND_DESKTOP, /* μλμ°λ λ°μ€ν¬νμ λν΄ μμμλμ°λ‘μ μμ± */
NULL, /* λ©λ΄μμ */
hThisInstance, /* νλ‘κ·Έλ¨ μΈμ€ν΄μ€ νΈλ€ */
NULL /* μλμ° μμ±μ μ¬μ©ν μΆκ° λ°μ΄ν μμ */
);
/* νλ©΄μ μλμ°κ° 보μ΄λλ‘ νλ€. nCmdShowλ WinMain()μμ 4λ²μ§Έ λ§€κ°λ³μμ. */
ShowWindow (hwnd, nCmdShow);
/* κ° stateμ λμνλ μλμ°νλ‘μμ Έ ν¬μΈν°λ₯Ό μ€μ */
STATEMANAGER->SetState(stGame, GameWinProc);
STATEMANAGER->SetState(stTitle, TitleWinProc); // μ΄ stateκ° μ²μ stateκ° λλ€
/* λ©μΈμ§λ£¨ν μ€ν. GetMessage()κ° 0μ λ°νν λκΉμ§ κ³μ 루νλ₯Ό λ°λ³΅ν©λλ€. */
while (GetMessage (&messages, NULL, 0, 0))
{
/* κ°μ ν€ λ©μΈμ§(WM_KEYDOWN)μ λ¬Έμ λ©μΈμ (WM_CHAR)λ‘ λ²μν©λλ€ */
TranslateMessage(&messages);
/* μλμ° νλ‘μμ Έλ‘ λ©μΈμ§λ₯Ό 보λ
λλ€ */
DispatchMessage(&messages);
}
/* νλ‘κ·Έλ¨ λ°νκ°μ 0μ
λλ€. μ΄λ PostQuitMessage() ν¨μμμ λ§€κ°λ³μλ‘ λκ²Όλ κ°μ΄ λμ΄μ€κ² λ©λλ€. (μλ μ°Έμ‘°) */
return messages.wParam;
}
LRESULT CALLBACK GameWinProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_ENTERSTATE:
MessageBox(hwnd, "GameStateμ§μ
","Game",MB_OK);
break;
case WM_LEAVESTATE:
MessageBox(hwnd, "GameStateμ’
λ£","Game",MB_OK);
break;
case WM_LBUTTONDOWN:
STATEMANAGER->SwitchState(stTitle, hwnd);
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_PAINT :
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 10, 10, "Game!", 5);
EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK TitleWinProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_ENTERSTATE:
MessageBox(hwnd, "TitleStateμ§μ
","Title",MB_OK);
break;
case WM_LEAVESTATE:
MessageBox(hwnd, "TitleStateμ’
λ£","Title",MB_OK);
break;
case WM_LBUTTONDOWN:
STATEMANAGER->SwitchState(stGame, hwnd);
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_PAINT :
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 10, 10, "νμ΄ν!", 7);
EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}









![[http]](/wiki/imgs/http.png)
