...

View Full Version : C++/win32: GetAsyncKeyState with timer



Dunna
02-13-2005, 12:56 AM
Hello, I am writing a win32 game in which the player enters their name at the keyboard. I am using a timer at 1 millisecond intervals which constantly checks through a bunch of:

if ( GetAsyncKeyState( 0x41 ) )
return 'a';
and so on...
The problem is that if the user enters, say the letter 'a', it get's copied into the buffer (with sprintf) about 10 times because the timer is so fast. Is there a way to 'lock' the key after it is pressed by the user so that my game does not detect it about 10 times? I can't slow the timer down without risking that I miss a keypress which would annoy the player, and I can't use a check to see if the same key is entered twice in a row because the player may have done this purposefully. (I hope you understand what I mean, if not I will clarify it as best I can).
Another solution might just be a different way to detect the keypresses. I would use DirectX which simplifies everything, but the program has mostly been written already and I don't want to switch it over.
Thanks in advance,
dunna.

Dr. Evil
02-13-2005, 08:23 AM
Can't you just catch the WM_KEYDOWN or WM_CHAR messages?

Mhtml
02-13-2005, 01:45 PM
I agree. You are going about this the wrong way entirely. Catching the WM_KEYDOWN or WM_CHAR messages will be more efficient.

In my engine, because I have taken an Object Oriented approach, I have a key state object which records the last 256 key states into a buffer. I find this is a good way to go about it. It's fast, the info is always there and you aren't continually polling, it's more event driven. Perhaps you should think about taking the same approach.

Dunna
02-13-2005, 09:47 PM
Yes, but for the WM_KEYDOWN and the WM_CHAR events don't you need a window? Sometimes I don't have a window running at all while something is loading, and other times I switch between windows but I want all the data in the same buffer. (I haven't tried the WM_CHAR, but I assume it will fail because the WM_KEYDOWN never gets read. I have been doing the message check in the WinMain function because I have multiple WinProc's.)

It looks something like this (only relevant information shown):




// this is in winmain
while( GetMessage(Msg.message, 0, 0, NULL) > 0 )
{
TranslateMessage(&Msg);
if (Msg.message = WM_TIMER)
{
CheckKeys();
// Other stuff for the timer here, but not relevant
}
}
//Code orginally by Dr. Evil


For some reason WM_KEYDOWN fails to be detected. I suppose this is because this code is not contained within a WinProc function.

Mhtml
02-14-2005, 12:54 AM
Do you realise you are doing an assignment in that Msg.message if condition, instead of a comparison?

You could create a window hook to catch keys.

[edit:]
Ok a few ideas.

1) If there isn't a window, there shouldn't be a need to catch keys anyway right?

2) If there isn't a window, create a transparent one and set focus to it.

Dunna
02-14-2005, 02:47 AM
OK, the code above may have some error in it because it was from memory. As for the transparent window / setting focus to it, I'll give it a try. There IS a window, just not one. Keys are constantly being read by different ones, so I just one one handler function to read them in and store them (CheckKeys()).

Mhtml
02-14-2005, 02:52 AM
Ok, well right now I'm thinking perhaps you should try going OO. It might be a bit more work, but it's definitely better in the long run.

Dunna
02-14-2005, 02:57 AM
OO? What is that? :confused:

Mhtml
02-14-2005, 03:00 AM
Object Oriented, ie; C++ classes.

Dunna
02-14-2005, 03:08 AM
So how is that going to solve my problem? (sorry if I'm a lttle slow...)

Mhtml
02-14-2005, 03:20 AM
Well it's a different way of managing all of your data, it's sort of hard for me to explain... But if you know OOP (object oriented programming) then you'd see what I'm getting at.

You'd have your engine object, and your input object, your engine would manage all of your windows and direct all input to the input object instance. It's more modular, easier to manage.

There are lots of tutorials on classes out there. It isn't completely necessary, but I find working with classes to be much easier for something like this.

Dr. Evil
02-14-2005, 09:20 AM
Yes, but for the WM_KEYDOWN and the WM_CHAR events don't you need a window? Sometimes I don't have a window running at all while something is loading, and other times I switch between windows but I want all the data in the same buffer. (I haven't tried the WM_CHAR, but I assume it will fail because the WM_KEYDOWN never gets read. I have been doing the message check in the WinMain function because I have multiple WinProc's.)

It looks something like this (only relevant information shown):




// this is in winmain
while( GetMessage(Msg.message, 0, 0, NULL) > 0 )
{
TranslateMessage(&Msg);
if (Msg.message = WM_TIMER)
{
CheckKeys();
// Other stuff for the timer here, but not relevant
}
}
//Code orginally by Dr. Evil


For some reason WM_KEYDOWN fails to be detected. I suppose this is because this code is not contained within a WinProc function.

If you have a window you shouldn't check the message in the message loop, just put DispatchMessage(&Msg), and it will give it to the windows, that may be why they didn't recieve the WM_CHAR message in the first place. If you want to keep the timer, just catch the WM_TIMER message.

Mhtml
02-14-2005, 09:33 AM
I didn't even realise you weren't dispatching the message. But regardless, the WM_TIMER idea is not a good one.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum