Sign in to follow this  
adt7

[SlimDX] How to use RawInput properly?

Recommended Posts

I've looked at the samples, but the RawInput sample is, well... lacking. I've currently got DirectInput working and doing what I want, but I keep reading in various places that it shouldn't be used anymore, which is why I'm looking to make the switch. I know how to register the devices, and hook the events, but I can't figure out how use this like I would with DirectInput. I want to be able to setup some simple methods, like IsKeyDown(key), MouseX(), MouseY()... etc, like I have for my DirectInput. Is this even possible with RawInput, is it even the right way to do about this?

Share this post


Link to post
Share on other sites
If you want such methods you have to write a class yourself. It could contain a bool array for the different buttons which you write to depending on the events you get. You could than query that array via your method IsKeyDown() for instance.

Share this post


Link to post
Share on other sites
I know I'll have to write my own class.

I should have been clearer. With DirectInput I could get a KeyboardState object each frame and then query, with RawInput I don't seem to have that option, so what is the equivalent?

I'm not great with handling Events and it's kind of thrown me off.

Share this post


Link to post
Share on other sites
I use something along those lines for the mouse:

//handling the window messages

case WM_INPUT:
{
UINT dwSize = 40;
static BYTE lpb[40];

GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));

RAWINPUT *raw = (RAWINPUT*)lpb;

if (raw->header.dwType == RIM_TYPEMOUSE)
{

setMouseX(raw->data.mouse.lLastX);
setMouseY(raw->data.mouse.lLastY);

if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
setMouseWheel(short(raw->data.mouse.usButtonData));


if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) setMouseKey(1, true);
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP) setMouseKey(1, false);

//[...]

}

return 0;
}


Does that help you out?

Share this post


Link to post
Share on other sites
Unfortunately not, as I'm working in C# with SlimDX and I'm trying to find out the proper usage of the methods etc. in the SlimDX.RawInput namespace.

I've read the documentation, but actually fitting it together into something that resembles DirectInput is stumping me.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mike.Popoloski
It's pretty simple. Register your device using Device::RegisterDevice, and then hook up the events you want to listen to, such as Device::KeyboardInput.


To quote myself:
Quote:
Original post by adt7
I know how to register the devices, and hook the events, but I can't figure out how use this like I would with DirectInput.


The problem is, I don't know where to go from there. With DirectInput I could get a KeyboardState object, and then query that using it's isKeyDown methods (which I then called from outside using my own public method) meaning I had a generic input class I could use with anything.

Is it possible to use Raw Input in that way? Would I have to create my own KeyboardState object to get it to work like this?

Maybe I should just stick with DirectInput, it just annoys me though because it's not the "right way" to do things anymore, but at least I understand it.

Share this post


Link to post
Share on other sites
Modern input handling on Windows doesn't want you polling the device for the current state, it wants you to wait for events and act upon them accordingly. This system has the benefit of easily being able to emulate the other, since you can keep your own custom state object around and update that whenever a new event comes in if you wish.

Share this post


Link to post
Share on other sites
I've managed to get the functionality I need for the Keyboard using an int, bool Dictionary. Mouse movement is sorted too.

I am however having difficulty with storing the MouseButtonFlags in a meaning structure that I can poll as required.

EDIT:

Sorry, that wasn't clear at all. With the keyboard I'm doing:
bool isKeyDown = (e.State == KeyState.Pressed || e.State == KeyState.SystemKeyPressed);
keysPressed[(int)e.Key] = isKeyDown;



However, with the mouse I've got a large if-statement using MouseButtonFlags, ie:
if ((e.ButtonFlags & MouseButtonFlags.LeftDown) == MouseButtonFlags.LeftDown)
{
buttonPressed[1] = true;
}
else
{
if ((e.ButtonFlags & MouseButtonFlags.LeftUp) == MouseButtonFlags.LeftUp)
{
buttonPressed[1] = false;
}
}



Is there a more elegant way of writing this for the mouse?

[Edited by - adt7 on August 14, 2009 4:42:12 PM]

Share this post


Link to post
Share on other sites
Well, I've been trying to do this same thing for a while now. I have a RawInput class that handles raw input data (surprise!).

There is an extern object (g_input) that update()s on WndProc's WM_INPUT case, then you can query like this in your game:

if (g_input.KeyboardEvent(VK_RIGHT)) { /*do stuff*/ }

Actually, it doesn't work flawlessly, i'm still hacking at it. It work perfect, except for two things, can't press more than one key at a time (current state gets overridden) and pressed keys stay pressed (buffer isn't cleaned up).

Oh, and buffered reads doesn't seem to work, that's it I promise :/

Maybe we could joint efforts and get a decent implementation, wadya say?

Share this post


Link to post
Share on other sites
Sounds good. This is my current implementation.

To be honest, the only bit I'm unhappy with is the series of if-elses in the Device_MouseInput method. I can't help but feel it could be cleaner.

public class KeyboardStatus
{
private Dictionary<int, bool> keysPressed = new Dictionary<int, bool>();

public void KeyPressed(Keys key, bool isKeyDown)
{
keysPressed[(int)key] = isKeyDown;
}

public bool IsKeyDown(Keys key)
{
bool isKeyDown;
if (keysPressed.TryGetValue((int)key, out isKeyDown))
return isKeyDown;
return false;
}
}

public class MouseStatus
{
public float X, Y;
private Dictionary<int, bool> buttonsPressed = new Dictionary<int, bool>();

public void ButtonPressed(int button)
{
buttonsPressed[button] = true;
}

public void ButtonReleased(int button)
{
buttonsPressed[button] = false;
}

public bool IsButtonDown(int button)
{
bool isButtonDown;
if (buttonsPressed.TryGetValue(button, out isButtonDown))
return isButtonDown;
return false;
}
}

public class Input
{
private Vector2 mousePos;
private KeyboardStatus keyboardStatus;
private MouseStatus mouseStatus;

public Input()
{
Device.RegisterDevice(UsagePage.Generic, UsageId.Keyboard, DeviceFlags.None);
Device.RegisterDevice(UsagePage.Generic, UsageId.Mouse, DeviceFlags.None);

Device.KeyboardInput += Device_KeyboardInput;
Device.MouseInput += Device_MouseInput;

keyboardStatus = new KeyboardStatus();
mouseStatus = new MouseStatus();
}

private void Device_KeyboardInput(object sender, KeyboardInputEventArgs e)
{
bool isKeyDown = (e.State == KeyState.Pressed || e.State == KeyState.SystemKeyPressed);
keyboardStatus.KeyPressed(e.Key, isKeyDown);
}

private void Device_MouseInput(object sender, MouseInputEventArgs e)
{
if ((e.ButtonFlags & MouseButtonFlags.LeftDown) == MouseButtonFlags.LeftDown)
mouseStatus.ButtonPressed(0);
else if ((e.ButtonFlags & MouseButtonFlags.LeftUp) == MouseButtonFlags.LeftUp)
mouseStatus.ButtonReleased(0);

if ((e.ButtonFlags & MouseButtonFlags.RightDown) == MouseButtonFlags.RightDown)
mouseStatus.ButtonPressed(1);
else if ((e.ButtonFlags & MouseButtonFlags.RightUp) == MouseButtonFlags.RightUp)
mouseStatus.ButtonReleased(1);

if ((e.ButtonFlags & MouseButtonFlags.MiddleDown) == MouseButtonFlags.MiddleDown)
mouseStatus.ButtonPressed(2);
else if ((e.ButtonFlags & MouseButtonFlags.MiddleUp) == MouseButtonFlags.MiddleUp)
mouseStatus.ButtonReleased(2);

if ((e.ButtonFlags & MouseButtonFlags.Button4Down) == MouseButtonFlags.Button4Down)
mouseStatus.ButtonPressed(3);
else if ((e.ButtonFlags & MouseButtonFlags.Button4Up) == MouseButtonFlags.Button4Up)
mouseStatus.ButtonReleased(3);

if ((e.ButtonFlags & MouseButtonFlags.Button5Down) == MouseButtonFlags.Button5Down)
mouseStatus.ButtonPressed(4);
else if ((e.ButtonFlags & MouseButtonFlags.Button5Up) == MouseButtonFlags.Button5Up)
mouseStatus.ButtonReleased(4);

mousePos.X += e.X;
mousePos.Y += e.Y;
}

public void Update()
{
mouseStatus.X = mousePos.X;
mouseStatus.Y = mousePos.Y;

mousePos = Vector2.Zero;
}

public bool IsKeyDown(Keys key)
{
return keyboardStatus.IsKeyDown(key);
}

public bool IsMouseButtonDown(int button)
{
return mouseStatus.IsButtonDown(button);
}

public float MouseDX()
{
return mouseStatus.X;
}

public float MouseDY()
{
return mouseStatus.Y;
}

public void Dispose()
{
Device.KeyboardInput -= Device_KeyboardInput;
Device.MouseInput -= Device_MouseInput;
}

Share this post


Link to post
Share on other sites
Oh man I got confused, I thought you were using C++ for this :)

Anyways, looking at the way you query for mouse buttons I can't help to feel the same way you do.

Maybe you could do something like this?

Quote:

bool Input::MouseEvent(const unsigned short & button)
{
return ri_mouse.usButtonFlags == button;
}


Then call it like this:

Quote:

if (g_input.MouseEvent(BUTTON1_DOWN)) {
/*...*/
}

if (g_input.MouseEvent(BUTTON1_UP)) {
/*...*/
}

//etc...


It doesn't get much simpler than that, although I don't know how *exactly* you are querying.

Also, looking through SlimDX's source (http://code.google.com/p/slimdx/) I found this, maybe it could help you:

http://code.google.com/p/slimdx/source/browse/#svn/trunk/samples/RawInput/MouseRI%3Fstate%3Dclosed

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this