Sign in to follow this  

DirectInput and Windows messages

This topic is 3626 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi! I'm new at this great forum, so this is my first post. Hi everyone!! :D I'm quite familiar with DirectInput setting up (creating DirectInput interface, creating devices, ...) but I really don't know what to do about Windows message queue. If I use DirectInput for managing user input, does it mean that I have to completely forget about managing Windows messages? Should I not call TranslateMessage and DispatchMessage?? An example: while (1) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); ProcessKBInput(); Render(); } else { } } Here I manage keyboard input with ProcessKBInput() function and manage Direct3D stuff with Render() function. My other question is: are ProcessKBInput() and Render() calls well where they are? Should I move them to the "else" part of the loop? Where should I call this functions? I hope was clear. Thank you very much for your help! Keep up this good work!! ;)

Share this post


Link to post
Share on other sites
You are only handling input and rendering when a message has been recieved, but you probably want to do this every frame, like so:


while (1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}
ProcessKBInput();
Render();
}



Quote:
If I use DirectInput for managing user input, does it mean that I have to completely forget about managing Windows messages? Should I not call TranslateMessage and DispatchMessage??


I'm pretty sure the answer is no (after all, not all messages are input messages), but what you should do is completely forget about DirectInput for handling keyboard and mouse input (you can still use it for joysticks). Here's why.

Share this post


Link to post
Share on other sites
First of all, thanks for replying, you are so kind (and so fast!) :)

I understand this code snippet you pasted and it makes sense, thank you. I suppose then that Windows message handling will depend on my DirectInput keyboard type (if it is exclusive or non-exclusive and all of that)...

Regarding to not using DirectInput for keyboard and mouse, I have to say that I read everywhere that Windows keyboard message handling is too slow for game programming. That's a bit of a contradiction by Microsoft... That's why I decided to learn DirectInput. And not that I don't believe what you said, but I would like to continue using it. I think the link you posted refers more than anything to user TEXT input, that obviously is tedious under DirectInput.

Thank you very much for replying Gage64! ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by PezMutanT
Regarding to not using DirectInput for keyboard and mouse, I have to say that I read everywhere that Windows keyboard message handling is too slow for game programming. That's a bit of a contradiction by Microsoft... That's why I decided to learn DirectInput. And not that I don't believe what you said, but I would like to continue using it. I think the link you posted refers more than anything to user TEXT input, that obviously is tedious under DirectInput.
No, DirectInput is slower than using window messages. Window messages are being sent to your window anyway, you're just not using them (Although when you use DirectInput for mouse input, you no longer get WM_MOUSEMOVE messages). DirectInput just spawns another thread to read those messages, meaning you have the additional overhead of thread context switching.

There's only a few reasons to use DirectInput:
  • You need high DPI mouse input and you need to target pre-XP machines (Bear in mind that Win2k is 8 years old now)
  • You need Force Feedback

    To answer the original question; your message loop should remain unchanged. The cost of calling TranslateMessage() is almost nill, and you still need to process other messages.

    Share this post


    Link to post
    Share on other sites
    Thanks Evil Steve.

    You mean that I should leave the loop like I first posted it?

    About DirectInput, I really can't say surely because I'm such a beginner, but in my opinion DirectInput tries to improve keyboard management and this improvement has a cost, that is the new thread you say.

    Anyway, I don't know exactly what are you refering to when you use the term SLOWER than Windows messages. Either you want to say that DirectInput makes your computer "slower" because of the extra work that the new thread involve, or you really mean that keyboard managing (keydown and keyup) are slowerly notified to an application that uses DirectInput than one that uses Windows messaging system.

    I think first case is irrelevant considering state-of-the-art computers. In case it's the second one, I don't understand why Microsoft would develop DirectInput if it doesn't improve Windows messages in some kind of way.

    Like I said before, it's not that I don't "believe" what you say, but I don't find any other explanation for having read many manuals that recommend using DirectInput for game development instead of Windows message queue.

    Thank you! ;)

    Share this post


    Link to post
    Share on other sites
    Quote:

    Anyway, I don't know exactly what are you refering to when you use the term SLOWER than Windows messages. Either you want to say that DirectInput makes your computer "slower" because of the extra work that the new thread involve, or you really mean that keyboard managing (keydown and keyup) are slowerly notified to an application that uses DirectInput than one that uses Windows messaging system.

    It's certainly no faster, and Windows messages are more direct.

    Quote:

    I don't understand why Microsoft would develop DirectInput if it doesn't improve Windows messages in some kind of way.

    It lets you work with joysticks and gamepads much easier. It happens to support keyboard/mouse stuff as well, but it's keyboard/mouse stuff isn't as good. Use it for joysticks or gamepads, not for keyboard/mouse stuff.

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by PezMutanT
    Thanks Evil Steve.

    You mean that I should leave the loop like I first posted it?
    Yup.

    Quote:
    Original post by PezMutanT
    About DirectInput, I really can't say surely because I'm such a beginner, but in my opinion DirectInput tries to improve keyboard management and this improvement has a cost, that is the new thread you say.
    Improve it how? You get action mapping, but that's really it for keyboard input.

    Quote:
    Original post by PezMutanT
    Anyway, I don't know exactly what are you refering to when you use the term SLOWER than Windows messages. Either you want to say that DirectInput makes your computer "slower" because of the extra work that the new thread involve, or you really mean that keyboard managing (keydown and keyup) are slowerly notified to an application that uses DirectInput than one that uses Windows messaging system.

    I think first case is irrelevant considering state-of-the-art computers. In case it's the second one, I don't understand why Microsoft would develop DirectInput if it doesn't improve Windows messages in some kind of way.
    It's slower because DirectInput does (more or less) exactly the same as your app is doing alrady, just in another thread. That means that there's more going on in your app. It's not a massive speed difference, the other issues that DirectInput has are of greater concern.
    DirectInput had its uses on pre-XP versions of Windows for Mouse or Joystick input, but never had any advantage for keyboard input. I'd guess that the reason they added keyboard support was for consistancy.

    Quote:
    Original post by PezMutanT
    Like I said before, it's not that I don't "believe" what you say, but I don't find any other explanation for having read many manuals that recommend using DirectInput for game development instead of Windows message queue.)
    They were most likely written a few years ago, where supporting pre-XP was more important.

    DirectInput can in some cases be more responsive, but for games, that's not important at all. Because DirectInput reads keyboard messages in a thread, it can read keypresses that happen during a frame. Your code just checks once a frame (Pumps window messages once, checks for keyboard input once), so you won't benifit from this. If you were writing an app that needs to check keyboard input more frequently, DirectInput would seem to be more responsive that window messages; but you could just pump window messages more than once per frame to get the same effect.

    As I meantioned, speed is just a minor point, the other points are more important - the only reason I mention it is because people often say that DirectInput is lower level and must be faster to use. If you look at my journal entry (Gage64 linked to it), there's more important reasons - if you're using DirectInput, you'll have difficulty supporting languages like Chinese, and even languages with different keyboard layouts.
    If you use DI for mouse input, you loose pointer balistics that Windows provides for free, which makes the mouse feel weird if you ever have a cursor onscreen (Not for E.g. a 3D camera, but for GUI style apps), because it doesn't behave the same as the cursor normally does in Windows.

    Share this post


    Link to post
    Share on other sites
    Wow, this is definitely a great forum, so many responses in such a short time... thank you very much! ;)

    I agree that it's silly doing something that is already done (in this case, keyboard management with Windows messages), but I think DirectInput gives you a level of abstraction so you can treat your keyboard as a joystick or a gamepad, forgetting about keycodes and stuff and thinking of keys as if they were buttons. I think this may be good for game development, as well as the more responsiveness you mentioned.

    It makes sense what you said about when the manuals I've read were written, I suppose they became a little obsolete.

    To sum up, we could say it's a matter of taste using Windows messages or DirectInput, or you STRONGLY recommend using Windows messages?

    Also, I didn't understand very well what you meant in your last paragraph about using DirectInput for mouse input.

    Thank you! ;)

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by PezMutanT
    To sum up, we could say it's a matter of taste using Windows messages or DirectInput, or you STRONGLY recommend using Windows messages?
    It depends how much code you have so far. If it's not going to be too much work to change to window messages, I'd go with that.

    Quote:
    Original post by PezMutanT
    Also, I didn't understand very well what you meant in your last paragraph about using DirectInput for mouse input.
    In Windows, move the mouse 10cm on your desk slowly, and notice how far the cursor moves. Now move it 10cm quickly, and notice that the cursor moves further. That's pointer ballistics - adding acceleration to the pointer, basically. There's quite a lot of work gone into making it feel natural, and duplicating it can be difficult.

    If you use DirectInput, it doesn't apply pointer ballistics to the cursor, so it'll move the same distance no matter how fast you move the mouse. That can make GUIs feel weird compared to Windows. Unreal Tournament 2004 has this for instance, and so do many other games that are mostly 3D.

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by Evil Steve
    Quote:
    Original post by PezMutanT
    Thanks Evil Steve.

    You mean that I should leave the loop like I first posted it?

    Yup.


    What about the change I made to it? isn't the original code only reading input/rendering when a message is received? Wouldn't you want to perform rendering each frame?

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by Gage64

    What about the change I made to it? isn't the original code only reading input/rendering when a message is received? Wouldn't you want to perform rendering each frame?


    You're right, but the way you posted probably isn't the best way to go about it either. In your version, you only receive one message per frame. This can be very bad, depending on what your framerate is. Instead, you should process all messages that are waiting in the queue and then do everything else


    while( msg.message != WM_QUIT )
    {
    if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
    {
    TranslateMessage( &msg );
    DispatchMessage( &msg );
    }
    else
    {
    // Input
    // Render
    }
    }


    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by Gage64
    What about the change I made to it? isn't the original code only reading input/rendering when a message is received? Wouldn't you want to perform rendering each frame?
    Whoops, that's a good point - sorry.

    Technically you should process all pending window messages, then render though. Otherwise the process or rendering might cause more messages to be sent to the message, resulting in your message queue getting "rather large" [smile]

    Share this post


    Link to post
    Share on other sites
    Excellent, great answers here so far...

    However, what if you want/need to process input messages NOT synchronized to frame rate?

    For example, I want my rendering to be done in a separate thread so that I can choose to disable the rendering thread without effecting the game logic. I want to process input
    messages in a different thread at a different frequency.

    After looking over Steve's journal, I am convinced that the WM_KEYDOWN method is the best for processing input. However, this must be done in the WindowProcedure which is part of the window thread. It is possible to use PeekMessage elsewhere, but then I wouldn't have access to the necessary lParam and wParam.

    Thus, in order to decouple the processing of input from rendering, it seems I would have to create the window in the main thread and then just have the rendering thread paint into the window. This introduces some synchronization issues, such as when the window is closed in the middle of a render loop...

    Is there a way to process the input WITHOUT being linked to a window?

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by MJP
    You're right, but the way you posted probably isn't the best way to go about it either. In your version, you only receive one message per frame. This can be very bad, depending on what your framerate is. Instead, you should process all messages that are waiting in the queue and then do everything else
    Quote:
    Original post by Evil Steve
    Technically you should process all pending window messages, then render though. Otherwise the process or rendering might cause more messages to be sent to the message, resulting in your message queue getting "rather large" [smile]


    That makes sense. I've seen it written with and without the 'else' clause many times and never knew if it makes a difference. Now I finally know. [smile]

    Thank you both.

    Share this post


    Link to post
    Share on other sites
    I've always had trouble understanding that too. Now I'm starting to, but I'm not sure. MJP says to manage input and rendering inside the 'else' clause and I understand it is because, while messages are still on queue you have to process them until there's nothing left on queue, and after that managing input and rendering, is this right?

    Also, I don't understand what MJP says about Gage64 version "you only receive one message per frame". Can anybody explain it, please?

    yahastu, I'm sorry but I can't help you :(

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by PezMutanT
    Also, I don't understand what MJP says about Gage64 version "you only receive one message per frame". Can anybody explain it, please?


    while (1)
    {
    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
    if(msg.message == WM_QUIT)
    break;

    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    ProcessKBInput();
    Render();
    }



    What happens there is the following:
    1- check to see if there are messages. if there are, process the first one in the queue.
    2- Update stuff and render stuff.
    3- Repeat.
    This means that for each frame of processing and rendering, only 1 message is being taken off the front of the queue. If your game processing is quite complex, there might be multiple messages sent to the queue (either by code or by the user) while the processing is being done. The queue can get long, and messages that should be processed nearly instantly can take a while to reach the front of the queue.

    By changing it to this,

    while( msg.message != WM_QUIT )
    {
    if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
    {
    TranslateMessage( &msg );
    DispatchMessage( &msg );
    }
    else //<- important!
    {
    // Input
    // Render
    }
    //here
    }



    the following happens:
    1- check to see if there are messages. If there are, process the first one, then the thread will jump to where i've commented "here" in the code. So we reach the end of the loop and return to the start of the loop- checking for another message.
    2- This repeats until there are no messages left, and then, and only then, do we reach our processing and rendering.
    This basically means that window messages take priority over game code, which is the way it should be, because they can be processed a lot quicker, and will often affect what will then happen in the game code.
    Does that answer your question?

    metal

    Share this post


    Link to post
    Share on other sites
    Yes, metalmidget, it absolutely does, thank you!

    It looked weird to me that Windows messages took priority over input and rendering. This means that there are iterations on this loop (when a message exists on queue) where no frame is rendered, hence nothing "changes" on screen. Does this involve low responsiveness in my game input and rendering? Or is this delay insignificant to the game playability?

    Again, thank you! ;)

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by PezMutanT
    It looked weird to me that Windows messages took priority over input and rendering. This means that there are iterations on this loop (when a message exists on queue) where no frame is rendered, hence nothing "changes" on screen. Does this involve low responsiveness in my game input and rendering? Or is this delay insignificant to the game playability?
    It's insignificant. All the *Message() functions are pretty quick - the slowest is probably DispatchMessage, because it calls your window procedure, but even then, it'll be extremely quick.

    Because you're not rendering or anything for that one tick, that tick is extremely quick (Probably something like half a millisecond or less), and doesn't count as a frame (Because there's no Present() call made). So it's almost identical to pumping all window messages then rendering.

    Share this post


    Link to post
    Share on other sites

    This topic is 3626 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

    If you intended to correct an error in the post then please contact us.

    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