- KeyManager 설계.
// CKeyMgr.h
...
enum class KEY_STATE
{
NONE, // 아무것도 안 눌렀을 때
TAP, // 막 눌렀을 때
HOLD, // 누르고 있을 때
RELEASE, // 놓았을 때
};
enum class KEY
{
LEFT,
RIGHT,
UP,
DOWN,
Q, W, E, R, T, Y, U, I, O, P,
A, S, D, F, G, H, J, K, L,
Z, X, C, V, B, N, M,
ALT,
CTRL,
LSHIFT,
SPACE,
ENTER,
ESC,
END
};
...
먼저 enum 값으로 사용할 키 값과 키 상태 4가지를 정의해줌.
// CKeyMgr.h
...
struct tKeyInfo
{
KEY_STATE eState;
bool bPrevPress; // 이전 프레임에서 눌렸는지 여부
};
class CKeyMgr
{
SINGLETON(CKeyMgr)
private:
vector<tKeyInfo> m_vecKey;
public:
void init();
void update();
public:
KEY_STATE GetKeyState(KEY _eKey) const { return m_vecKey[(int)_eKey].eState; }
};
그리고 이를 구조체 형태로 해서 → tKeyInfo
vector 로 만든 것을 멤버 변수로 선언해줌.
매 프레임마다 이 수십 개의 키 정보들을 update() 함수에서 갱신해주면 됨.
int g_arrVK[(int)KEY::END] =
{
VK_LEFT,
VK_RIGHT,
VK_UP,
VK_DOWN,
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P',
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L',
'Z', 'X', 'C', 'V', 'B', 'N', 'M',
VK_MENU, // ALT
VK_CONTROL, // CTRL
VK_LSHIFT, // LSHIFT
VK_SPACE, // SPACE
VK_RETURN, // ENTER
VK_ESCAPE, // ESC
};
이건 사용자가 설정한 enum class KEY 를 윈도우에서 제공하는 키로 바꿔주기 위한 배열. 귀찮지만 입력을 추가하고 싶을 때마다 여길 바꿔줘야 할 듯.
void CKeyMgr::update()
{
for (int i = 0; i < (int)KEY::END; ++i)
{
// 이전 프레임에서 눌렸는지 여부와 현재 프레임에서 눌렸는지 여부를 비교.
// 4가지 상태로 구분. - NONE, TAP, HOLD, RELEASE.
bool bCurPress = (GetAsyncKeyState(g_arrVK[i]) & 0x8000);
if (bCurPress)
{
if (m_vecKey[i].bPrevPress)
{
m_vecKey[i].eState = KEY_STATE::HOLD;
}
else
{
m_vecKey[i].eState = KEY_STATE::TAP;
}
}
else
{
if (m_vecKey[i].bPrevPress)
{
m_vecKey[i].eState = KEY_STATE::RELEASE;
}
else
{
m_vecKey[i].eState = KEY_STATE::NONE;
}
}
m_vecKey[i].bPrevPress = bCurPress;
}
}
모든 KeyInfo 마다 bPrevPress 에서 이전 프레임에 눌렸는지를 저장함.
현재 프레임에서 눌렸는지를 나타내는 bCurPress 값과 비교하면 4 가지 상태를 알 수 있음.
이를 그냥 if-else if-else 해서 갱신해주는 코드.
// 키 눌렸을 때 한번만 이동.
if (CKeyMgr::GetInstance()->GetKeyState(KEY::LEFT) == KEY_STATE::TAP)
{
pos.x -= 100.f;
}
이제 키 입력 상태에 따라 다양한 계산이 가능.
- 윈도우 포커스 유무에 따른 키 입력 처리
void CKeyMgr::update()
{
// GetFocus: 현재 포커싱된 윈도우 핸들 반환.
HWND hWnd = GetFocus();
// 포커싱이 되어 있으면 키 상태 갱신.
if(hWnd != nullptr)
{
...
}
// 포커싱이 안되어 있으면 모든 키 상태 NONE으로 초기화.
else
{
for (int i = 0; i < (int)KEY::END; ++i)
{
m_vecKey[i].bPrevPress = false;
if(m_vecKey[i].eState == KEY_STATE::TAP ||
m_vecKey[i].eState == KEY_STATE::HOLD)
{
m_vecKey[i].eState = KEY_STATE::RELEASE;
continue;
}
m_vecKey[i].eState = KEY_STATE::NONE;
}
}
}
GetFocus 함수를 통해 현재 윈도우에 포커스가 있는지 확인 후, 있으면 기존의 키 입력 처리를 해줌.
없다면 전체 키에 대해 bPrevPress 값은 false 로,
eState 값은 RELEASE 나 NONE 으로 변경해준다.
'Win32 api' 카테고리의 다른 글
| Win32 api 강의 17 - 18화. (0) | 2025.09.15 |
|---|---|
| Win32 api 15 - 16화. (0) | 2025.09.14 |
| Win32 api 강의 12화. (0) | 2025.09.13 |
| Win32 api 강의 11화. (0) | 2025.09.13 |
| Win32 api 강의 10화. (0) | 2025.09.12 |