Here's my Keyboard and Mouse Classes that I use, maybe you could put them to work for you:
mouse.h
enum MouseState { BTN_RELEASED, BTN_PRESSED, BTN_ONCE };
class CMouse {
protected:
MouseState m_Buttons[6]; /* Recognizes VK_LBUTTON/VK_RBUTTON/VK_XBUTTON1/VK_XBUTTON2 */
int m_PosX; /* Current mouse position (screen coords) */
int m_PosY; /* Current mouse position (screen coords) */
int m_PosZ; /* Current mouse position (screen coords) */
int m_MoveX; /* How much X coord has moved (screen coords) */
int m_MoveY; /* How much Y coord has moved (screen coords) */
int m_MoveZ; /* How much Z coord has moved (screen coords) */
bool m_IsVisible;
public:
CMouse(void);
~CMouse(void);
void Poll(void);
void SetPosition( const int new_x, const int new_y ) {
m_PosX = new_x; m_PosY = new_y;
dbPositionMouse( new_x, new_y );
}
bool IsVisible( void ) const {
return m_IsVisible;
}
void Show( void ) {
m_IsVisible = TRUE;
dbShowMouse();
}
void Hide( void ) {
m_IsVisible = FALSE;
dbHideMouse();
}
//**********************************************************
// Since they are really just memory look-up, we want
// these functions to be in-lined (if at a possible) to
// avoid any of the method/function call overhead...
//**********************************************************
MouseState GetButtonState( const int btn ) const {
MYASSERT(btn > 0); /* VK_LMOUSE starts @ 1 */
MYASSERT(btn < 7); /* VK_XBUTTON2 ends @ 6 */
return m_Buttons[btn-1];
}
bool ButtonUp( const int btn ) const {
MYASSERT(btn > 0); /* VK_LMOUSE starts @ 1 */
MYASSERT(btn < 7); /* VK_XBUTTON2 ends @ 6 */
return (m_Buttons[btn-1] == BTN_RELEASED);
}
bool ButtonDown( const int btn ) const {
MYASSERT(btn > 0); /* VK_LMOUSE starts @ 1 */
MYASSERT(btn < 7); /* VK_XBUTTON2 ends @ 6 */
return ((m_Buttons[btn-1] == BTN_PRESSED) || (m_Buttons[btn] == BTN_ONCE));
}
bool ButtonPressed( const int btn ) const {
MYASSERT(btn > 0); /* VK_LMOUSE starts @ 1 */
MYASSERT(btn < 7); /* VK_XBUTTON2 ends @ 6 */
return (m_Buttons[btn-1] == BTN_PRESSED);
}
bool ButtonOnce( const int btn ) const {
MYASSERT(btn > 0); /* VK_LMOUSE starts @ 1 */
MYASSERT(btn < 7); /* VK_XBUTTON2 ends @ 6 */
return (m_Buttons[btn-1] == BTN_ONCE);
}
int GetMouseMoveX( void ) const {
return m_MoveX;
}
int GetMouseMoveY( void ) const {
return m_MoveY;
}
int GetMouseMoveZ( void ) const {
return m_MoveZ;
}
int GetMousePosX( void ) const {
return m_PosX;
}
int GetMousePosY( void ) const {
return m_PosY;
}
int GetMousePosZ( void ) const {
return m_PosZ;
}
};
mouse.cpp
CMouse::CMouse(void) : m_MoveX(0), m_MoveY(0), m_MoveZ(0), m_IsVisible(1) {
memset(m_Buttons, 0, sizeof(MouseState)*6); /* Set current state to RELEASED */
dbShowMouse(); /* We default to Visible, so show the mouse */
}
CMouse::~CMouse(void) {
memset(m_Buttons, 0, sizeof(MouseState)*6); /* Set current state to RELEASED */
}
void CMouse::Poll(void) {
SHORT btn;
/* We're reading button states now - up to 6-buttons recognized */
for (int x=VK_LBUTTON; x<=VK_XBUTTON2; x++) {
/*
Don't really care for this, but dbMouseClick() doesn't seem to
recognize 4-buttons after all. My mouse has 5-buttons and only
three are recognized, so we will use the GetAsyncKeyState()
function to retrieve click-states for VK_LBUTTON, VK_RBUTTON,
VK_XBUTTON1 and VK_XBUTTON2. Since these are recognized as
windows virtual-keys, we should have no problems getting them
(if present) regardless of the mouse type we are using.
*/
btn=GetAsyncKeyState(x);
if (btn & 0x8000) { /* Is the key currently pressed? */
if (m_Buttons[x-1] == BTN_RELEASED) { /* Yes. Was it released before this check? */
m_Buttons[x-1] = BTN_ONCE; /* Yes. Flag as pressed ONCE - for this frame only */
}
else {
m_Buttons[x-1] = BTN_PRESSED; /* No. Was pressed last time - Still pressed! */
}
}
else {
m_Buttons[x-1] = BTN_RELEASED; /* No. It's been released */
}
}
//**********************************************************
// TODO: 4/5/2010 - JWH - Verify that this will work
// correctly. That is, when reading dbMouseX(), dbMouseY()
// and dbMouseZ() - each of which are different functions,
// is it possible that the values can change before
// completing the update cycle? What about the MouseMove()
// functions?
//**********************************************************
/* Update the current position info */
m_PosX = dbMouseX();
m_PosY = dbMouseY();
m_PosZ = dbMouseZ(); /* NOTE: This needs to reset to Zero after a period of inactivity */
/* Update movement deltas */
m_MoveX = dbMouseMoveX();
m_MoveY = dbMouseMoveY();
m_MoveZ = dbMouseMoveZ();
}
keyboard.h
enum KeyState { KEY_RELEASED, KEY_PRESSED, KEY_ONCE };
class CKeyboard {
protected:
KeyState m_Keys[256];
public:
CKeyboard(void);
~CKeyboard(void);
void Poll(void);
//**********************************************************
// Since they are really just memory look-up, we want
// these functions to be in-lined (if at a possible) to
// avoid any of the method/function call overhead...
//**********************************************************
KeyState GetKeyState( const int key ) const {
MYASSERT(key >= 0);
MYASSERT(key < 256);
return m_Keys[key];
}
bool KeyUp( const int key ) const {
MYASSERT(key >= 0);
MYASSERT(key < 256);
return (m_Keys[key] == KEY_RELEASED);
}
bool KeyDown( const int key ) const {
MYASSERT(key >= 0);
MYASSERT(key < 256);
return ((m_Keys[key] == KEY_PRESSED) || (m_Keys[key] == KEY_ONCE));
}
bool KeyPressed( const int key ) const {
MYASSERT(key >= 0);
MYASSERT(key < 256);
return (m_Keys[key] == KEY_PRESSED);
}
bool KeyOnce( const int key ) const {
MYASSERT(key >= 0);
MYASSERT(key < 256);
return (m_Keys[key] == KEY_ONCE);
}
};
keyboard.cpp
CKeyboard::CKeyboard(void) {memset(m_Keys, 0, sizeof(KeyState)*256);} /* Set current state to RELEASED */
CKeyboard::~CKeyboard(void) {memset(m_Keys, 0, sizeof(KeyState)*256);} /* Set current state to RELEASED */
void CKeyboard::Poll(void) {
SHORT btn;
/* We're reading button states now - up to 6-buttons recognized */
for (int x=0; x<256; x++) {
/*
Don't really care for this, but GetKeyboardState() doesn't update
the key-states until after they are processed by the message-pump
(WNDPROC).
*/
btn=GetAsyncKeyState(x);
if (btn & 0x8000) { /* Is the key currently pressed? */
if (m_Keys[x] == KEY_RELEASED) { /* Yes. Was it released before this check? */
m_Keys[x] = KEY_ONCE; /* Yes. Flag as pressed ONCE - for this frame only */
}
else {
m_Keys[x] = KEY_PRESSED; /* No. Was pressed last time - Still pressed! */
}
}
else {
m_Keys[x] = KEY_RELEASED; /* No. It's been released */
}
}
}
And to use them, you do this:
CKeyboard keyboard;
CMouse mouse;
while (LoopGDK()) {
keyboard.poll();
mouse.poll();
if (keyboard.KeyOnce(VK_SPACE) {
// Do something only if the space key was just now pressed!
}
if (mouse.ButtonOnce(VK_LMOUSE) {
// Do something only if the LEFT-mouse button was just now pressed!
}
}
I love this approach. I based it on some java-code I found on the internet somewhere... works like a charm for me. Of course, I left out my specific header files, but I'm sure you'll be able to figure the appropriate #includes out for yourself.
Enjoy,
JTK