//************* 输入系统内部接口 *****************
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;
}