이전 단계인 "6. Keyboard Input (키보드 입력)" 에서는 Keyboard 이벤트를 처리했습니다.
이번 단계에서는 Mouse 이벤트를 처리하려고 합니다.
MouseEvent.h
#pragma once
/* 마우스의 x, y좌표 */
struct MousePoint
{
int x;
int y;
};
class MouseEvent
{
public:
/* 마우스 이벤트 타입 */
enum EventType
{
LPress, // 왼쪽 버튼 누르기
LRelease, // 왼쪽 버튼 떼기
RPress, // 오른쪽 버튼 누르기
RRelease, // 오른쪽 버튼 떼기
MPress, // 휠 버튼 누르기
MRelease, // 휠 버튼 떼기
WheelUp, // 휠 올리기
WheelDown, // 휠 내리기
Move, // 마우스 움직임
RAW_MOVE, // 8번에서 할 예정
Invalid
};
private:
EventType type;
int x;
int y;
public:
MouseEvent();
MouseEvent(const EventType type, const int x, const int y);
bool IsValid() const;
EventType GetType() const;
MousePoint GetPos() const;
int GetPosX() const;
int GetPosY() const;
};
MouseEvent.cpp
#include "MouseEvent.h"
// MouseClass의 mouseBuffer에 값이 없는 경우
MouseEvent::MouseEvent()
:
type(EventType::Invalid),
x(0),
y(0)
{}
// MouseClass의 mouseBuffer에 값이 있는 경우
MouseEvent::MouseEvent(EventType type, int x, int y)
:
type(type),
x(x),
y(y)
{}
bool MouseEvent::IsValid() const
{
return this->type != EventType::Invalid;
}
// MouseEvent의 현재 타입을 가져오는 함수
MouseEvent::EventType MouseEvent::GetType() const
{
return this->type;
}
// 마우스의 현재 x, y좌표를 가져오는 함수
MousePoint MouseEvent::GetPos() const
{
return { this->x, this->y };
}
// 마우스의 현재 x좌표를 가져오는 함수
int MouseEvent::GetPosX() const
{
return this->x;
}
// 마우스의 현재 y좌표를 가져오는 함수
int MouseEvent::GetPosY() const
{
return this->y;
}
MouseClass.h
#pragma once
#include "MouseEvent.h"
#include <queue>
using namespace std;
class MouseClass
{
public:
/* 각 타입에 따라 mouseBuffer에 마우스 이벤트 타입, x, y 좌표 저장 */
void OnLeftPressed(int x, int y);
void OnLeftReleased(int x, int y);
void OnRightPressed(int x, int y);
void OnRightReleased(int x, int y);
void OnMiddlePressed(int x, int y);
void OnMiddleReleased(int x, int y);
void OnWheelUp(int x, int y);
void OnWheelDown(int x, int y);
void OnMouseMove(int x, int y);
/* 마우스 버튼이 눌렸는지 체크하는 함수 */
bool IsLeftDown();
bool IsMiddleDown();
bool IsRightDown();
/* 마우스의 좌표를 가져오는 함수 */
int GetPosX();
int GetPosY();
MousePoint GetPos();
bool MouseBufferIsEmpty(); // mouseBuffer가 비어있는지 체크하는 함수
MouseEvent ReadEvent(); // mouseBuffer의 비어있는지 여부에 따라 MouseEvent 타입을 반환
private:
queue<MouseEvent> mouseBuffer; // MouseEvent 타입을 저장하는 queue
/* 마우스 버튼이 눌렸는지 체크하는 변수 */
bool leftIsDown = false;
bool rightIsDown = false;
bool mbuttonDown = false;
/* 마우스의 x, y좌표 */
int x = 0;
int y = 0;
};
MouseClass.cpp
#include "MouseClass.h"
/* 왼쪽 버튼이 눌렸을 때 */
void MouseClass::OnLeftPressed(int x, int y)
{
this->leftIsDown = true;
this->mouseBuffer.push(MouseEvent(MouseEvent::EventType::LPress, x, y));
}
/* 왼쪽 버튼이 떼졌을 때 */
void MouseClass::OnLeftReleased(int x, int y)
{
this->leftIsDown = false;
this->mouseBuffer.push(MouseEvent(MouseEvent::EventType::LRelease, x, y));
}
/* 오른쪽 버튼이 눌렸을 때 */
void MouseClass::OnRightPressed(int x, int y)
{
this->rightIsDown = true;
this->mouseBuffer.push(MouseEvent(MouseEvent::EventType::RPress, x, y));
}
/* 오른쪽 버튼이 떼졌을 때 */
void MouseClass::OnRightReleased(int x, int y)
{
this->rightIsDown = false;
this->mouseBuffer.push(MouseEvent(MouseEvent::EventType::RRelease, x, y));
}
/* 휠 버튼이 눌렸을 때 */
void MouseClass::OnMiddlePressed(int x, int y)
{
this->mbuttonDown = true;
this->mouseBuffer.push(MouseEvent(MouseEvent::EventType::MPress, x, y));
}
/* 휠 버튼이 떼졌을 때 */
void MouseClass::OnMiddleReleased(int x, int y)
{
this->mbuttonDown = false;
this->mouseBuffer.push(MouseEvent(MouseEvent::EventType::MRelease, x, y));
}
/* 휠을 올렸을 때 */
void MouseClass::OnWheelUp(int x, int y)
{
this->mouseBuffer.push(MouseEvent(MouseEvent::EventType::WheelUp, x, y));
}
/* 휠을 내렸을 때 */
void MouseClass::OnWheelDown(int x, int y)
{
this->mouseBuffer.push(MouseEvent(MouseEvent::EventType::WheelDown, x, y));
}
/* 마우스를 움직였을 때 */
void MouseClass::OnMouseMove(int x, int y)
{
this->x = x;
this->y = y;
this->mouseBuffer.push(MouseEvent(MouseEvent::EventType::Move, x, y));
}
/* 왼쪽 버튼이 눌렸는지 체크하는 함수 */
bool MouseClass::IsLeftDown()
{
return this->leftIsDown;
}
/* 휠 버튼이 눌렸는지 체크하는 함수 */
bool MouseClass::IsMiddleDown()
{
return this->mbuttonDown;
}
/* 오른쪽 버튼이 눌렸는지 체크하는 함수 */
bool MouseClass::IsRightDown()
{
return this->rightIsDown;
}
/* 마우스의 x좌표를 가져오는 함수 */
int MouseClass::GetPosX()
{
return this->x;
}
/* 마우스의 y좌표를 가져오는 함수 */
int MouseClass::GetPosY()
{
return this->y;
}
/* 마우스의 좌표를 가져오는 함수 */
MousePoint MouseClass::GetPos()
{
return{ this->x, this->y };
}
/* mouseBuffer가 비어있는지 체크하는 함수 */
bool MouseClass::MouseBufferIsEmpty()
{
return this->mouseBuffer.empty();
}
/* mouseBuffer의 비어있는지 여부에 따라 MouseEvent 타입을 반환 */
MouseEvent MouseClass::ReadEvent()
{
if (this->mouseBuffer.empty())
{
return MouseEvent();
}
else
{
MouseEvent e = this->mouseBuffer.front(); // queue의 front에서 값을 가져옴
this->mouseBuffer.pop(); // front 값을 삭제
return e;
}
}
WindowContainer.h
#pragma once
#include "RenderWindow.h"
#include "Keyboard/KeyboardClass.h"
#include "Mouse/MouseClass.h" // 추가
class WindowContainer
{
public:
LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
protected:
RenderWindow render_window;
KeyboardClass keyboard;
MouseClass mouse; // 추가
private:
};
- MouseClass 타입의 mouse 변수 선언
WindowContainer.cpp
#include "WindowContainer.h"
LRESULT WindowContainer::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
/* -- 키보드 메시지 -- */
/* 이전과 동일 */
/* -- 마우스 메시지 -- */
/* 마우스 커서가 이동할 때 */
case WM_MOUSEMOVE:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
mouse.OnMouseMove(x, y);
return 0;
}
/* 마우스 왼쪽 버튼이 눌렸을 때 */
case WM_LBUTTONDOWN:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
mouse.OnLeftPressed(x, y);
return 0;
}
/* 마우스 오른쪽 버튼이 눌렸을 때 */
case WM_RBUTTONDOWN:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
mouse.OnRightPressed(x, y);
return 0;
}
/* 마우스 휠 버튼이 눌렸을 때 */
case WM_MBUTTONDOWN:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
mouse.OnMiddlePressed(x, y);
return 0;
}
/* 마우스 왼쪽 버튼이 떼졌을 때 */
case WM_LBUTTONUP:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
mouse.OnLeftReleased(x, y);
return 0;
}
/* 마우스 오른쪽 버튼이 떼졌을 때 */
case WM_RBUTTONUP:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
mouse.OnRightReleased(x, y);
return 0;
}
/* 마우스 휠 버튼이 떼졌을 때 */
case WM_MBUTTONUP:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
mouse.OnMiddleReleased(x, y);
return 0;
}
/* 마우스 휠을 회전할 때 */
case WM_MOUSEWHEEL:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
// 값이 0보다 크면, 휠을 올림
if (GET_WHEEL_DELTA_WPARAM(wParam) > 0)
{
mouse.OnWheelUp(x, y);
}
// 값이 0보다 작으면, 휠을 내림
else if (GET_WHEEL_DELTA_WPARAM(wParam) < 0)
{
mouse.OnWheelDown(x, y);
}
return 0;
}
default:
/* 처리되지 않은 모든 메시지의 디폴트 처리를 수행 */
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
각 마우스의 이벤트에 따라 MouseClass의 함수를 실행하고 x, y좌표를 전달합니다.
Engine.cpp
#include "Engine.h"
/* 동일 */
void Engine::Update()
{
/* 동일 */
while (!mouse.MouseBufferIsEmpty())
{
MouseEvent me = mouse.ReadEvent();
/* 마우스 x, y좌표 테스트 */
string outmsg = "X : ";
outmsg += to_string(me.GetPosX());
outmsg += ", Y : ";
outmsg += to_string(me.GetPosY());
outmsg += "\n";
OutputDebugStringA(outmsg.c_str());
/* 마우스 휠 클릭 테스트 */
if (me.GetType() == MouseEvent::EventType::MPress)
{
OutputDebugStringA("Mouse MPress\n");
}
else if (me.GetType() == MouseEvent::EventType::MRelease)
{
OutputDebugStringA("Mouse MReleased\n");
}
}
}
- 마우스 이벤트가 잘 작동하는지 확인하기 위한 테스트
- wParam
- 논리형이며 키 값이 눌러졌는지 상태 확인
- 핸들 또는 정수를 받아들일 때 주로 사용
- lParam
- 좌표의 의미를 가지며, 4byte로 이루어져 있음
- 2byte씩 잘라서 x, y값으로 사용
- 포인터 값을 전달할 때 사용
- LOWORD : X의 값
- HIWORD : Y의 값