hge source explor 0x6 input module

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

  在主循环中测试输入,如图:

原文地址:https://www.cnblogs.com/yoru/p/5510125.html