Input Module |
封装与输入相关的属性,函数。
input.h |
struct CInputEventList { GEInputEvent event; CInputEventList* next; }; class Input { public: Input(); void GetMousePos(float* x, float* y); void SetMousePos(float x, float y); int GetMouseWheel(); bool IsMouseOver(); bool KeyDown(int key); bool KeyUp(int key); bool GetKeyState(int key); char* GetKeyName(int key); int GetKey(); int GetChar(); bool GetEvent(GEInputEvent* event); void UpdateMouse(); void Init(); void ClearQueue(); void BuildEvent(int type, int key, int scan, int flags, int x, int y); public: int VKey; int Char; int Zpos; float Xpos; float Ypos; bool bMouseOver; bool bCaptured; char keyz[256]; CInputEventList* queue; }; class Input |
input.cpp |
//************* 输入系统内部接口 ***************** Input::Input() { queue = 0; Char = VKey = Zpos = 0; Xpos = Ypos = 0; bMouseOver = false; bCaptured = false; // keyz保存着现在键盘的信息,在同一帧可以实现多按键 memset(&keyz, 0, sizeof(keyz)); } void Input::Init() { POINT pt; GetCursorPos(&pt); ScreenToClient(pge->win->hwnd, &pt); Xpos = (float)pt.x; Ypos = (float)pt.y; } // 创建输入事件 void Input::BuildEvent(int type, int key, int scan, int flags, int x, int y) { CInputEventList *last, *eptr = new CInputEventList; unsigned char kbstate[256]; POINT pt; eptr->event.type = type; eptr->event.chr = 0; pt.x = x; pt.y = y; GetKeyboardState(kbstate); if (type == INPUT_KEYDOWN) { if ((flags&GEINP_REPEAT) == 0) keyz[key] |= 1; ToAscii(key, scan, kbstate, (unsigned short*)&eptr->event.chr, 0); } if (type == INPUT_KEYUP) { keyz[key] |= 2; ToAscii(key, scan, kbstate, (unsigned short*)&eptr->event.chr, 0); } if (type == INPUT_MOUSEWHEEL) { eptr->event.key = 0; eptr->event.wheel = key; ScreenToClient(pge->win->hwnd, &pt); // 这里把位置设为(0,0),其实可以不用 } else { eptr->event.key = key; eptr->event.wheel = 0; } if (type == INPUT_MBUTTONDOWN) // 鼠标按键按下,要设置成焦点 { keyz[key] |= 1; SetCapture(pge->win->hwnd); bCaptured = true; } if (type == INPUT_MBUTTONUP) // 鼠标弹起,释放焦点 { keyz[key] |= 2; ReleaseCapture(); SetMousePos(Xpos, Ypos); pt.x = (int)Xpos; pt.y = (int)Ypos; bCaptured = false; } // 检测功能键 if (kbstate[VK_SHIFT] & 0x80) flags |= GEINP_SHIFT; if (kbstate[VK_CONTROL] & 0x80) flags |= GEINP_CTRL; if (kbstate[VK_MENU] & 0x80) flags |= GEINP_ALT; if (kbstate[VK_CAPITAL] & 0x1) flags |= GEINP_CAPSLOCK; if (kbstate[VK_SCROLL] & 0x1) flags |= GEINP_SCROLLLOCK; if (kbstate[VK_NUMLOCK] & 0x1) flags |= GEINP_NUMLOCK; // 设置输入时间标志 eptr->event.flags = flags; if (pt.x == -1) // 这里表示非鼠标事件 { eptr->event.x = Xpos; eptr->event.y = Ypos; } else // 鼠标是否出界判定 { if (pt.x < 0) pt.x = 0; if (pt.y < 0) pt.y = 0; if (pt.x >= pge->win->nScreenWidth) pt.x = pge->win->nScreenWidth - 1; if (pt.y >= pge->win->nScreenHeight) pt.y = pge->win->nScreenHeight - 1; eptr->event.x = (float)pt.x; eptr->event.y = (float)pt.y; } eptr->next = 0; // 加入输入事件的队列 if (!queue) queue = eptr; else { last = queue; while (last->next) last = last->next; last->next = eptr; } if (eptr->event.type == INPUT_KEYDOWN || eptr->event.type == INPUT_MBUTTONDOWN) { VKey = eptr->event.key; Char = eptr->event.chr; } else if (eptr->event.type == INPUT_MOUSEMOVE) { Xpos = eptr->event.x; Ypos = eptr->event.y; } else if (eptr->event.type == INPUT_MOUSEWHEEL) { Zpos += eptr->event.wheel; } } // 获得事件,事件队列的第一件事情 bool Input::GetEvent(GEInputEvent* event) { CInputEventList* eptr; if (queue) { eptr = queue; memcpy(event, &eptr->event, sizeof(GEInputEvent)); queue = eptr->next; delete eptr; return true; } return false; } void Input::ClearQueue() { CInputEventList *nexteptr, *eptr = queue; memset(&keyz, 0, sizeof(keyz)); while (eptr) { nexteptr = eptr->next; delete eptr; eptr = nexteptr; } queue = 0; VKey = 0; Char = 0; Zpos = 0; } //********* 鼠标 ************** void Input::UpdateMouse() { POINT pt; RECT rc; GetCursorPos(&pt); GetClientRect(pge->win->hwnd, &rc); MapWindowPoints(pge->win->hwnd, NULL, (LPPOINT)&rc, 2); if (bCaptured || (PtInRect(&rc, pt) && WindowFromPoint(pt) == pge->win->hwnd)) bMouseOver = true; else bMouseOver = false; } void Input::GetMousePos(float* x, float *y) { *x = Xpos; *y = Ypos; } void Input::SetMousePos(float x, float y) { POINT pt; pt.x = (long)x; pt.y = (long)y; ClientToScreen(pge->win->hwnd, &pt); SetCursorPos(pt.x, pt.y); } int Input::GetMouseWheel() { return Zpos; } bool Input::IsMouseOver() { return bMouseOver; } //************* 键盘 ****************** bool Input::KeyDown(int key) { return (keyz[key] & 1) != 0; } bool Input::KeyUp(int key) { return (keyz[key] & 2) != 0; } bool Input::GetKeyState(int key) { return ((::GetKeyState(key) & 0x8000) != 0); // ::GetKeyState(key) 调用window中的 } char* Input::GetKeyName(int key) { return KeyNames[key]; } int Input::GetKey() { return VKey; } int Input::GetChar() { return Char; } input.cpp |
在主循环中测试输入,如图:
时间: 2024-10-16 11:52:05