RawInput for mouse device

Mar 23, 2013 at 10:27 PM
Edited Mar 23, 2013 at 10:29 PM
I have to do some modifications that could be part of the library. I implement this because i use advanced mouse functionality. Side buttons of my mouse.

Hieroglyph 3 support only the default mouse buttons. RawInputs over the windows message loop can support full access to all features of a device.

look for example:
http://code.google.com/p/rawinput/

here is description from microsoft:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645546%28v=vs.85%29.aspx

and here another helpfull link:
http://toymaker.info/Games/html/raw_input.html

Here is a lightwight implementation of this.
case WM_CREATE:
{
    RAWINPUTDEVICE Rid[2];

    // Keyboard
    Rid[0].usUsagePage = 1;
    Rid[0].usUsage = 6;
    Rid[0].dwFlags = 0;
    Rid[0].hwndTarget = NULL;

    // Mouse
    Rid[1].usUsagePage = 1;
    Rid[1].usUsage = 2;
    Rid[1].dwFlags = 0;
    Rid[1].hwndTarget = NULL;

    //Rid[2].usUsagePage = 0x01; 
    //Rid[2].usUsage = 0x04; 
    //Rid[2].dwFlags = 0;                 // adds joystick
    //Rid[2].hwndTarget = 0;
    
    //Rid[3].usUsagePage = 0x01; 
    //Rid[3].usUsage = 0x05; 
    //Rid[3].dwFlags = 0;                 // adds game pad
    //Rid[3].hwndTarget = 0;

    if(RegisterRawInputDevices(Rid, 2, sizeof(RAWINPUTDEVICE)) == FALSE) {
        MessageBox(NULL, L"Failed to Register Input Devices!", L"ALERT", MB_OK);
        exit(1);
    }
}
//

case WM_INPUT: 
{
    //Determine how big the buffer should be
    UINT iBuffer;

    GetRawInputData((HRAWINPUT)lparam, RID_INPUT, NULL, &iBuffer, sizeof(RAWINPUTHEADER));
    LPBYTE lpb = new BYTE[iBuffer];
    if(lpb == NULL) {
        return 0;
    } 

    UINT readSize = GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, lpb, &iBuffer, sizeof(RAWINPUTHEADER) ) ;

    if(readSize != iBuffer)
        puts( "ERROR:  GetRawInputData didn't return correct size!" ) ;
    RAWINPUT *raw = (RAWINPUT*) lpb;                

    if (raw->header.dwType== RIM_TYPEMOUSE) {
        ProcessMouseMessage(&raw->data.mouse);
    }
    if (raw->header.dwType== RIM_TYPEKEYBOARD) {
        ProcessKeyboardMessage(&raw->data.keyboard);
    }       
    if (raw->header.dwType== RIM_TYPEHID) {
        ProcessHIDMessage(&raw->data.hid);
    }
}

void Application::ProcessMouseMessage(RAWMOUSE* mouse) {
    //mouse->
}

void Application::ProcessKeyboardMessage(RAWKEYBOARD* keyboard) {
    //keyboard->
            if(!(keyboard.Flags & RI_KEY_MAKE)) { //KEY DOWN
                USHORT key = keyboard.GetData().VKey;

                EvtKeyDownPtr pEvent = EvtKeyDownPtr( new EvtKeyDown( hwnd, key, 0 ) );
                EvtManager.ProcessEvent( pEvent );
            }

            if(keyboard.Flags & RI_KEY_BREAK) { //KEY UP
                USHORT key = keyboard.GetData().VKey;
                
                EvtKeyUpPtr pEvent = EvtKeyUpPtr( new EvtKeyUp( hwnd, key, 0 ) );
                EvtManager.ProcessEvent( pEvent );
            }
}

void Application::ProcessHIDMessage(RAWHID* hid) {
    //hid->
}
Coordinator
Mar 23, 2013 at 11:54 PM
Let me read more about this, but it should be possible to add into the engine. So you still use the raw mouse and keyboard messages, but by configuring them in the WM_CREATE handler, you are allowing the extra functionality to be used, right?

If so, is this a standard configuration, or would someone else with more or fewer buttons have to configure it differently? I am more than willing to accommodate the change, I just want to ensure that it works for as many people as possible.
Mar 24, 2013 at 12:05 AM
Edited Mar 24, 2013 at 12:06 AM
" but by configuring them in the WM_CREATE handler, you are allowing the extra functionality to be used, right?"

Yes, you allowing this functionality with this ... but you can do it inside the constructor too.

i post some code ...mom
Mar 24, 2013 at 12:14 AM
Edited Mar 24, 2013 at 12:19 AM
you can use the code above ...its the lightwight version you can use.

I use http://code.google.com/p/rawinput/ API because i get a nice Mouse Object and a nice Keyboard Event. The code is only a warper around the RawInput.

(I uses this only for the mouse buttons at the moment, keyboard runs over the normal WM_KEYDOWN and WM_KEYUP, WM_MOUSEMOVE, etc)

But it is possible to implement it full by the rawInput message (keyboard, mouse, (perhaps gamepad or joystick))

application.cpp:
....
#include "EvtErrorMessage.h"

#include "..\RawInput\RawInputAPI.h"
#include "..\RawInput\RawInput.h"

//--------------------------------------------------------------------------------
using namespace Glyph3;
//--------------------------------------------------------------------------------
// Initialize the application pointer to NULL
Application* Application::ms_pApplication = NULL;

typedef RawInput::Input<RawInput::Unbuffered> InputSys;
std::unique_ptr<InputSys> input;

//--------------------------------------------------------------------------------
Application::Application() :
...
application.cpp (method for init):
//RawInput
void Application::InitInput(HWND hwnd) {
    input = std::unique_ptr<InputSys>(new InputSys(hwnd, RIDEV_DEVNOTIFY, RIDEV_INPUTSINK/*, HID_FLAGS*/));

    (*input)
        .connect(RawInput::RawMouse::Event([&](const RawInput::RawMouse & mouse) {
            if(mouse.Button(RI_MOUSE_BUTTON_1_DOWN|RI_MOUSE_BUTTON_2_DOWN|RI_MOUSE_BUTTON_3_DOWN|RI_MOUSE_BUTTON_4_DOWN|RI_MOUSE_BUTTON_5_DOWN)) {
                //get the mouse position
                int x = _mouseX;
                int y = _mouseY;

                //coding the mouse position into a long.
                long lparam = y << 16 | x;
                unsigned int wparam = mouse.GetData().usButtonFlags;

                //throw the event.
                EvtMouseDownPtr pEvent = EvtMouseDownPtr( new EvtMouseDown( hwnd, wparam, lparam)); //mouse.GetData().usButtonFlags, mouse.GetData().usFlags ) );
                EvtManager.ProcessEvent( pEvent );
            }

            if(mouse.Button(RI_MOUSE_BUTTON_1_UP|RI_MOUSE_BUTTON_2_UP|RI_MOUSE_BUTTON_3_UP|RI_MOUSE_BUTTON_4_UP|RI_MOUSE_BUTTON_5_UP)) {
                //get the mouse position
                int x = _mouseX;
                int y = _mouseY;
                //mouse.GetWindowPos(x, y);
                
                //coding the mouse position into a long.
                long lparam = y << 16 | x;
                unsigned int wparam = mouse.GetData().usButtonFlags;

                //throw the event.
                EvtMouseUpPtr pEvent = EvtMouseUpPtr( new EvtMouseUp( hwnd, wparam, lparam)); //( hwnd, mouse.GetData().usButtonFlags, mouse.GetData().usFlags ) );
                EvtManager.ProcessEvent( pEvent );
            }
        }));
}
LRESULT Application::WindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) {
...
case WM_INPUT_DEVICE_CHANGE: //WIP - Only for Windows Vista or greater.
            {
                //RAW INPUT
                input->Change(wparam, lparam); // WIP - Only for Windows Vista or greater.
            } break;
        case WM_INPUT:
            {
                //RAW INPUT
                input->Update(hwnd, msg, wparam, lparam);

            } break;
...
}
Keyboard can make with inside the InitInput()-Method as well:
              .connect(RawInput::RawKeyboard::Event([&](const RawInput::RawKeyboard & keyboard) {
            if(!(keyboard.GetData().Flags & RI_KEY_MAKE)) { //KEY DOWN
                USHORT key = keyboard.GetData().VKey;

                EvtKeyDownPtr pEvent = EvtKeyDownPtr( new EvtKeyDown( hwnd, key, 0 ) );
                EvtManager.ProcessEvent( pEvent );
            }

            if(keyboard.GetData().Flags & RI_KEY_BREAK) { //KEY UP
                USHORT key = keyboard.GetData().VKey;
                
                EvtKeyUpPtr pEvent = EvtKeyUpPtr( new EvtKeyUp( hwnd, key, 0 ) );
                EvtManager.ProcessEvent( pEvent );
            }