Advanced DirectInput keyboard input?
How could I write an DirectInput keyboard interface wich allows US-Style keyboards and EU-Style keyboards without the key-positions getting changed?
I also want to be able to get the input as an string, because I want to write an console window using DirectInput.
Could anybody point me to the ultimate DirectInput tutorial/code/whatever wich covers all I need?
I noticed that directInput doesen''t allow you to specify the type of keyboard, but I didn''t know the mapping is different!
Do you have a list of the key codes as they appear on the actual keys?
www.cppnow.com
Do you have a list of the key codes as they appear on the actual keys?
www.cppnow.com
No, I don''t have such an list I think...
Then... how could I do an keyboard input for US keyboards only??
Then... how could I do an keyboard input for US keyboards only??
to get strings with directinput, you have to store the character equivalents of each key and buffer them when you need a string. its really a pain in the arse...at least thats the way i did it...if there''s an easier way let me know. also, you have to handle things like the repeat rate for keys being held down, since directinput doesn''t do that for you, and for each press you will probably get multiple letters, like getting "hhhhhhhhheeeeeeeeellllllllllllllllloooooooo" when pressing the keys H E L L O...to get the repeat rates through the windows api i did this:
// determine keyboard repeat rate for text entry mode
int winKeyDelay;
SystemParametersInfo(
SPI_GETKEYBOARDDELAY,
0,
&winKeyDelay,
0
);
// windows stores the key delay as an int with the range
// 0 - 3; 0 being ~250ms, and 3 being ~1000ms so we have to
// convert it into a millisecond ammount
s_keyRepeatDelay = (winKeyDelay + 1) * 250;
DWORD winKeySpeed;
SystemParametersInfo(
SPI_GETKEYBOARDSPEED,
0,
&winKeySpeed,
0
);
// windows stores the key repeat speed as a DWORD ranging
// from 0 to 31; 0 being ~2.5 repeats per second, and 31
// being ~30 repeats per second; this means that for each
// 1 that the windows value goes up, the number of
// milliseconds between repeats goes down by ~11.5, starting
// at 400 for a windows value of 0
s_keyRepeatRate = 400 - (WORD)(((float)(winKeySpeed)) * 11.5f);
to store the keys with their character equivalents i used an array of these structs:
struct IKey {
bool isPrintable;
char printUpper;
char printLower;
bool isPressed;
bool justPressed;
DWORD timePressed;
DWORD lastRepeat;
bool wasPressed;
};
to populate the struct i had this function:
/***********************************************************
** IInitializeKeystate()
************************************************************/
void IInitializeKeystate () {
// this is gonna be nice and long...
// give appropriate printing characters to the
// keys that require them
for (WORD x = 0; x < NUM_KEYS; x++) {
s_lastKeystate[x].isPrintable = true;
s_lastKeystate[x].isPressed = false;
s_lastKeystate[x].timePressed = 0;
s_lastKeystate[x].lastRepeat = 0;
s_lastKeystate[x].wasPressed = false;
if (x == KEY_1) {
s_lastKeystate[x].printLower = ''1'';
s_lastKeystate[x].printUpper = ''!'';
}
else if (x == KEY_2) {
s_lastKeystate[x].printLower = ''2'';
s_lastKeystate[x].printUpper = ''@'';
}
else if (x == KEY_3) {
s_lastKeystate[x].printLower = ''3'';
s_lastKeystate[x].printUpper = ''#'';
}
else if (x == KEY_4) {
s_lastKeystate[x].printLower = ''4'';
s_lastKeystate[x].printUpper = ''$'';
}
...
note i redefined the DIK_ key names, since this particular implementation is intended to be somewhat portable...
anyway, i don''t know if any of that helps, but thats what i got...
// determine keyboard repeat rate for text entry mode
int winKeyDelay;
SystemParametersInfo(
SPI_GETKEYBOARDDELAY,
0,
&winKeyDelay,
0
);
// windows stores the key delay as an int with the range
// 0 - 3; 0 being ~250ms, and 3 being ~1000ms so we have to
// convert it into a millisecond ammount
s_keyRepeatDelay = (winKeyDelay + 1) * 250;
DWORD winKeySpeed;
SystemParametersInfo(
SPI_GETKEYBOARDSPEED,
0,
&winKeySpeed,
0
);
// windows stores the key repeat speed as a DWORD ranging
// from 0 to 31; 0 being ~2.5 repeats per second, and 31
// being ~30 repeats per second; this means that for each
// 1 that the windows value goes up, the number of
// milliseconds between repeats goes down by ~11.5, starting
// at 400 for a windows value of 0
s_keyRepeatRate = 400 - (WORD)(((float)(winKeySpeed)) * 11.5f);
to store the keys with their character equivalents i used an array of these structs:
struct IKey {
bool isPrintable;
char printUpper;
char printLower;
bool isPressed;
bool justPressed;
DWORD timePressed;
DWORD lastRepeat;
bool wasPressed;
};
to populate the struct i had this function:
/***********************************************************
** IInitializeKeystate()
************************************************************/
void IInitializeKeystate () {
// this is gonna be nice and long...
// give appropriate printing characters to the
// keys that require them
for (WORD x = 0; x < NUM_KEYS; x++) {
s_lastKeystate[x].isPrintable = true;
s_lastKeystate[x].isPressed = false;
s_lastKeystate[x].timePressed = 0;
s_lastKeystate[x].lastRepeat = 0;
s_lastKeystate[x].wasPressed = false;
if (x == KEY_1) {
s_lastKeystate[x].printLower = ''1'';
s_lastKeystate[x].printUpper = ''!'';
}
else if (x == KEY_2) {
s_lastKeystate[x].printLower = ''2'';
s_lastKeystate[x].printUpper = ''@'';
}
else if (x == KEY_3) {
s_lastKeystate[x].printLower = ''3'';
s_lastKeystate[x].printUpper = ''#'';
}
else if (x == KEY_4) {
s_lastKeystate[x].printLower = ''4'';
s_lastKeystate[x].printUpper = ''$'';
}
...
note i redefined the DIK_ key names, since this particular implementation is intended to be somewhat portable...
anyway, i don''t know if any of that helps, but thats what i got...
also, in that previous post, s_keyRepeatDelay is the time in milliseconds before a key starts repeating, and s_keyRepeatRate is the time in milliseconds between repeasts.
and to test if a key should be repeated, my code looks like this:
// go through the keystates and send text messages as
// needed
for (WORD x = 0; x < NUM_KEYS; x++) {
IKey * key = &s_lastKeystate[x];
// deterime if key should be sent or repeated at all
if (!key->isPressed)
continue;
if (!key->wasPressed) {
// first press; send it
}
else {
if (key->lastRepeat == 0) {
// no repeats yet, see if we should
if (!((TimeGetTicks() - key->timePressed) > s_keyRepeatDelay))
continue; // no repeat yet
else
key->lastRepeat = TimeGetTicks(); // repeat
}
else {
// repeats have happened, see if we should again
if (!((TimeGetTicks() - key->lastRepeat) > s_keyRepeatRate))
continue; // no repeat yet
else
key->lastRepeat = TimeGetTicks(); // repeat
}
}
note: TimeGetTicks() is equivalent to GetTickCount() just redefined to help with portability
and to test if a key should be repeated, my code looks like this:
// go through the keystates and send text messages as
// needed
for (WORD x = 0; x < NUM_KEYS; x++) {
IKey * key = &s_lastKeystate[x];
// deterime if key should be sent or repeated at all
if (!key->isPressed)
continue;
if (!key->wasPressed) {
// first press; send it
}
else {
if (key->lastRepeat == 0) {
// no repeats yet, see if we should
if (!((TimeGetTicks() - key->timePressed) > s_keyRepeatDelay))
continue; // no repeat yet
else
key->lastRepeat = TimeGetTicks(); // repeat
}
else {
// repeats have happened, see if we should again
if (!((TimeGetTicks() - key->lastRepeat) > s_keyRepeatRate))
continue; // no repeat yet
else
key->lastRepeat = TimeGetTicks(); // repeat
}
}
note: TimeGetTicks() is equivalent to GetTickCount() just redefined to help with portability
gotta love how it took all my code spacing out...how do i get it to appear in a text box thing inside the message?
Just a general rule:
don''t use the
if()
else if()
else if()
else if()
style of programming.
Use a switch statement. Its much faster.
switch(key)
{
case ''a'':
// do stuff
break;
case ''b'':
// do stuff
break;
}
don''t use the
if()
else if()
else if()
else if()
style of programming.
Use a switch statement. Its much faster.
switch(key)
{
case ''a'':
// do stuff
break;
case ''b'':
// do stuff
break;
}
Switch is not necessarily faster. If you have case 1 , 2 , 3 etc.. then yes.If you have case 23, 56, 78 then it is slower. Case also only allows integers where if statements allow for any kind of argument. This kind of , don''t do this, don''t do that statements should be done away with. You have no idea what the purpose of that if statement is, or if it will change later. Let him code the way he wants. Also switch statements does have a limit on how many cases you can have. As do if else. It all comes down to planning.
Thanks for the input, I will try my hand on it, but I need to handle special chars (like backspace) myself
AP, I personally don''t care which way he does thing. I just remember reading in my Ansi C book that switch is much faster because the CPU has 1 compare then a jump, instead of doing a compare for each if statement.
Just trying to give some advice, but...
Just trying to give some advice, but...
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement