mouse input without windows messages ?

Started by
22 comments, last by Norman Barrows 11 years, 1 month ago

Is it still possible to get mouse input without using the windows message queue?

I know that as of Windows Vista or so, it was still possible to use DOS interrupts.

that meant you could use AsyncGetKeyState for keyboard, INT 31h for mouse, and didn't need a windows message processor at all.

the nice thing about this was that Alt-Tab messages no longer got processed. you had full control of the PC, no lost devices. The only thing that still worked was ctrl-alt-del.

right now i'm using windows messages to get mouse input. but that's the only message i process.

if you take a careful look at the directx docs, it says the best way to do things is to load everything up into memory at program start, then go for it.

so all this reload / restore on lost device is a bad thing.

while a number of games attempt to support it (as a well behaved windows app should), few seem to succeed in all cases. many warn that it can introduce instability and recommend restarting the game (Oblivion for example).

right now, instead of attempting to recover a lost device, i simply exit with a message saying a background process took vidcard access away from the game, and recommend closing any interfering processes and restarting the game.

But it would be nice to trap out alt-tab etc.

I want full control of the pc, that way my games don't have to play well with others.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Advertisement

Eek.

You don't want to do this.

You may think that your program should have full control over everything, and that it shouldn't have to play nice with other apps, but I can assure you that a large proportion of your potential users don't share this thought. They're going to want to switch away, run other processes, etc; that's a pretty basic expectation and if you can't play nice with that expectation then they will be annoyed at you.

Taking full control of everything in the manner you describe also quite spectacularly fails the Raymond Chen "what if two programs tried to do this?" test - "When two programs duke it out like this, you can't predict which one will win, but you can predict with 100% certainty who will lose: The user."

So no, sorry to have to be blunt about it, but your program is not so awesome that the user will gladly let it take over everything in the way you want.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Yeah, maybe I'm just being lazy...

I know that OnLostDevice() _CAN_ be done correctly if one is careful about it.

I just wish the HP support software installed on my PC didn't force a full screen refresh on launch. It loads in the background and causes a lost device about 2-3 minutes after logon. Just enough time to logon, fire up a game, and then lose focus, usually resulting in a crash. Oblivion can usually handle it if it completes loading the savegame and the current level first. Other games, not so well.

It _would_ be nice to be able to switch away from the game and back again. due to the design, there's actually very little (codewise) to restore. timewise is another issue though, as everything is loaded once at program start and almost all into vidram.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Windows supports raw input http://msdn.microsoft.com/en-us/library/windows/desktop/ms645543(v=vs.85).aspx which allows you to read the mouse, keyboard, joysticks, ect... You still use the windows message queue, but you have alot more control over what/when you get data.

that meant you could use AsyncGetKeyState for keyboard, INT 31h for mouse, and didn't need a windows message processor at all.

Implementing a keyboard handler via AsyncGetKeyState rather than the windows message queue is a really bad idea. If the user presses and releases a key for a short period of time that doesn't overlap with the point in time where you poll for that key, then you won't detect that keypress. The user will have pressed a button and you game will have missed it. If you listen the the message queue, you'll correctly receive the press and release messages, no matter how frequently/infrequently you poll the queue. You also get some other useful stuff, like the ability for keys to be converted into characters according to the user's locale for text input, as well as keypress inputs...

What's wrong with using the message queue? It's there for a reason -- to separate applications from the hardware so that device drivers can correctly exist in the middle. This way, the device driver can be responsible for knowing how to handle the many different types of hardware out there and translating their inputs into a common structure. As above, it also ensures that your application doesn't miss out on any messages (unless you receive a LOT of messages and poll the queue VERY infrequently).

the nice thing about this was that Alt-Tab messages no longer got processed

You could just, listen for that message in the message queue, and return the return-code that indicates that you handled the message, so that the OS won't pass it on to the default message handler.

However, if you're going to do this, you should really make it an option that the user can enable in your menu, because it's a standard convention when doing anything on Windows that the alt+tab combo will work at any time. Breaking conventions like that is really unfriendly to your users; giving them the option to disable alt+tab if they choose to is much nicer. You can also give them the option to disable the windows key if you like.

right now, instead of attempting to recover a lost device, i simply exit with a message saying a background process took vidcard access away from the game, and recommend closing any interfering processes and restarting the game.

That's really bad. It's my PC. If I need to quickly alt+tab to reply to an email or order a pizza, and your game quits as a result, then your game is at fault. It would have to be pretty amazing for me to keep playing tongue.png If I want to be restricted to only running one program at once, I would still be running DOS instead of Windows.

It's not hard to manage a lost device -- whenever you create any of the resources that need to be recreated, store a pointer to them in some kind of "manager". When you handle the lost device, you've then got a list of resources to recreate in the one spot.

If you want to reduce the chances of a lost device occurring in the first place, you can use a "fullscreen window" instead of actual fullscreen mode. You can run your game in windowed mode, but create a window that fill the entire screen, has no border or title bar, and is on top of everything else. This makes it as stable as regular windowed apps (which means it plays nicely with alt+tabbing) but looks like a fullscreen app.

The way I deal with lost devices is by having each module register up to 4 "handlers" - OnCreate, OnRelease, OnLost, OnReset - which then get called in the appropriate places.

By the way, and this is a very important point, lost device handling is not only for Alt-Tabbing. See http://msdn.microsoft.com/en-us/library/windows/desktop/bb174714%28v=vs.85%29.aspx

By design, the full set of scenarios that can cause a device to become lost is not specified

If you were handling lost devices from WM_ACTIVATE messages then you were doing it wrong; you need to be checking for D3DERR_DEVICELOST from your Present calls instead.


if you take a careful look at the directx docs, it says the best way to do things is to load everything up into memory at program start, then go for it. so all this reload / restore on lost device is a bad thing.

That's a misinterpretation of the docs; the intention is to warn against a common beginners mistake (which may be seen when porting from e.g. OpenGL's immediate mode) which is to create and destroy e.g. a vertex buffer each frame during normal operation.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Windows supports raw input

If i decide to "take over the PC", looks like that's the way to get my mouse input. But i'm having second thoughts on not supporting recovery of lost devices.

Implementing a keyboard handler via AsyncGetKeyState rather than the windows message queue is a really bad idea. If the user presses and releases a key for a short period of time that doesn't overlap with the point in time where you poll for that key, then you won't detect that keypress.

i poll at a rate of 15 times per second. never had any issues. been using this method since XP, when BIOS interrupt driven keyboard support went away. I've been building games for a long time. Since before DirectX, even since before Windows itself. When windows came along, you saw what still worked, what they (microsoft) broke, and what would have to be done differently. You used windows where you had to and then got back to the real business of building games once you got the operating system out of the way again. I used to capture the entire keyboard state 15 times a second, and then test the results as needed. now I simply do GetAsyncKeyState on individual keys as needed (at a poll rate 15 times per second).

You could just, listen for that message in the message queue, and return the return-code that indicates that you handled the message, so that the OS won't pass it on to the default message handler.

This sounds like a nice elegant way to handle things.

But i'm already pretty much convinced i should "play well" with others and implement on_lost_device().

You can also give them the option to disable the windows key if you like.

Haven't tried that one, but yes, that's another focus buster there: "Focus, focus, lost my focus, where's that confounded device?"

If you want to reduce the chances of a lost device occurring in the first place, you can use a "fullscreen window" instead of actual fullscreen mode. You can run your game in windowed mode, but create a window that fill the entire screen, has no border or title bar, and is on top of everything else. This makes it as stable as regular windowed apps (which means it plays nicely with alt+tabbing) but looks like a fullscreen app.

No lost devices? Any other changes required other than going windowed vs fullscreen at startup? What window style is used in CreateWindowEx? I currently use WS_POPUP, with CS_HREDRAW | CS_VREDRAW for the window class.

The way I deal with lost devices is by having each module register up to 4 "handlers" - OnCreate, OnRelease, OnLost, OnReset - which then get called in the appropriate places.

Yes, this seems to be the architecture used in the Directx demos. Its probably as straight-forward an implementation as is possible.

If you were handling lost devices from WM_ACTIVATE messages then you were doing it wrong; you need to be checking for D3DERR_DEVICELOST from your Present calls instead.

Thats what I do. I added a check for 3d3_ok and d3d_device_lost after I present() a frame. but then i just display a lamo error message and exit - I know, LAZY!

That's a misinterpretation of the docs; the intention is to warn against a common beginners mistake (which may be seen when porting from e.g. OpenGL's immediate mode) which is to create and destroy e.g. a vertex buffer each frame during normal operation.

so its performance related, and not about memory fragmentation? I can't remember off hand where i saw it, maybe a Chuck Walburn (sp?) post on MSDN? It was definitely from Microsoft. They seemed to be advising against dynamic loading during gameplay, due to fragmentation issues and the hazards of getting your reference counts screwed up and therefore memory leaks.However i do understand that paging of level data (meshes, textures, etc) is done everyday in games like FPS's.

Now what about the load times? Right now i load everything at program start. everything goes into D3DPOOL_DEFAULT, plus there are 20 D3DXMESH_DYNAMIC meshes (probably in managed pool). load times are about 10 seconds. pretty much everything would have to be reloaded into vidram on lost device. So 10 seconds load time every time i task switch back to the game, right? Yuk!

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

That's why D3DPOOL_MANAGED exists; so that you don't need to worry about this. The driver will handle it for you, and believe me, the driver knows more about what's best for it's own internal architecture than you do. As a general rule - unless the docs explicitly say that you need to use D3DPOOL_DEFAULT (e.g. depending on your D3DUSAGE) you should be using D3DPOOL_MANAGED. Task switching is not a 10-second job with this; it goes down to well under a second (and any video mode changes required if using a fullscreen mode will likely take longer than resource recreation) - don't assume before you have actual facts and measurements to back things up.

You're falling into a few traps here. First off you're worrying about memory fragmentation before you've even determined that memory fragmentation is even a problem for you. There's a name for that - pre-emptive optimization. Secondly, you're basing your performance assumptions only on factors you can directly measure in your own code, whereas in reality there are a whole heap of factors outside of your code and that you can't directly measure that also come into play.

You're also still equating dynamic creation and destruction of resources during gameplay with the destruction and creation required during lost device recovery, and that's a huge mistake because they're not the same kind of thing. Lost device recovery is a response to an abnormal operational state, not something you do on a regular basis. When a lost device happens everything that was in video RAM gets chucked out; you're starting from a clean slate again and fragmentation is not a concern. Let me re-emphasise - this is not a normal operational state, this is not something that you do every frame. The warning against dynamic creation/destruction applies if you're doing it every frame, lost devices are a special case.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

As a general rule - unless the docs explicitly say that you need to use D3DPOOL_DEFAULT (e.g. depending on your D3DUSAGE) you should be using D3DPOOL_MANAGED.

I could have sworn that default was the recommended usage, and managed was for special cases (maybe like stuff you reload on lost device? <g>). guess i'd better look it up again. as i recall, with managed, the driver handled restoring vidram as needed, but it ran slower (perhaps because of a need to confirm sync between the two copies?). there was some downside i recall. I'll look it up again. maybe i misinterpreted it.

First off you're worrying about memory fragmentation before you've even determined that memory fragmentation is even a problem for you.

to tell you the truth, i'm not really worried about that, i've always been very good at making sure my mallocs and frees (so to speak) match up.

my only concern is load time. i can see how having the assets in managed would be faster than reloading to default from disk.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

I found it interesting to note that Oblivion doesn't support Alt-Tab.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

This topic is closed to new replies.

Advertisement