I'm new to c++ and I'm not sure how WM_KEYDOWN works. I want to have a case for each arrow key (UP,DOWN,LEFT,RIGHT)
Thanks
As noted in the WM_KEYDOWN documentation, the wParam of the message loop contains the virtual code key - therefore, you can use the following:
case WM_KEYDOWN:
switch (wParam) {
case VK_UP:
// up was pressed
break;
case VK_DOWN:
// down was pressed
break;
// etc.
}
break;
The whole reference on virtual key codes can be found on MSDN.
Related
I'm developing a simple game in OpenGL and using the SDL library to handle my input.
The game uses several keyboard buttons for input. Two arrow keys, the space bar, the 'r' button to reset the game and escape to close it.
What's currently happening is that the output or the methods being called when these buttons are pressed when I first launch the game are mismatched. (i.e left arrow performs the right arrow's method). This random behaviour ends once I press each of the buttons the game uses apart from the escape button once.
I'm wondering if there is something I'm missing as it feels like I have to 'assign' each button on each launch of the game. I've provided my input handling code below.
if (e.type == SDL_KEYDOWN) {
switch (e.key.keysym.sym) {
case SDLK_ESCAPE:
m_isClosed = true;
break;
case SDLK_SPACE:
m_selection = true;
break;
case SDLK_LEFT:
m_leftPressed = true;
break;
case SDLK_RIGHT:
m_rightPressed = true;
break;
case SDLK_r:
m_reset = true;
break;
}
}
if(e.type == SDL_KEYUP)
switch (e.key.keysym.sym)
{
case SDLK_LEFT:
m_leftPressed = false;
m_keydown = false;
break;
case SDLK_RIGHT:
m_rightPressed = false;
m_keydown = false;
break;
case SDLK_SPACE:
m_selection = false;
m_keydown = false;
break;
case SDLK_r:
m_reset = false;
m_keydown = false;
break;
}
}
Each event handler simply sets a boolean used for the game logic in another class. If you think you need to see anymore code in order to help me let me know.
It turns out that I had not initialised the booleans corresponding to the button listeners to false. A silly mistake but I thought I should provide the solution nonetheless.
I have a dialog-based MFC project. I have the ON_WM_KEYDOWN() function working and when I press the down key it does what it should.
Now I want to change the down key to the 'w' key, and the left key to 'a', etc. I have very basic MFC knowledge, I am not sure what function I should add and what part of the program to change.
My ON_WM_KEYDOWN() function looks as follows:
if(pMsg->message == WM_KEYDOWN)
{
switch(pMsg->wParam)
{
// Disable OK & Cancel function
case VK_ESCAPE:
case VK_RETURN:
return TRUE;
}
}
The variable pMsg->wParam contains the key that has been pressed. You can look up the key codes here. As a result, you need some code similar to the following in your ON_WM_KEYDOWN handler:
if(pMsg->message == WM_KEYDOWN)
{
switch(pMsg->wParam)
{
case 0x57:
// W key. Put code for "up" here...
break;
case 0x41:
// A key. Put code for "left" here...
break;
case 0x53:
// S key. Put code for "down" here...
break;
case 0x44:
// D key. Put code for "right" here...
break;
// Disable OK & Cancel function
case VK_ESCAPE:
case VK_RETURN:
return TRUE;
}
}
If you want the A key to perform the same action of the cursor-left key, for example, then you could do that by sending a VK_LEFT via a WM_KEYDOWN message with the PostMessage function:
PostMessage(WM_KEYDOWN, VK_LEFT, 0);
However, I didn't try this and I don't know if it's a good style to do so.
I have got a small problem with my game.
It is not a big deal but I'd love to sort this out.
So this is my input processing function:
void MainGame::processInput()
{
SDL_Event evnt;
while (SDL_PollEvent(&evnt)) {
switch (evnt.type) {
case SDL_QUIT:
_gameState = GameState::EXIT;
break;
case SDL_MOUSEMOTION:
break;
case SDL_KEYDOWN:
switch (evnt.key.keysym.sym) {
case SDLK_RIGHT:
player.movePlayer(1);
break;
case SDLK_LEFT:
player.movePlayer(2);
break;
}
}
}
}
and it works just fine, but as you can probably imagine, when I press an arrow key, it moves once (calls the player.movePlayer(); function once) then pauses for a fraction of a second and then continues to read input.
I don't really know how to word it but I hope you know what I mean.
You can also see this effect when you hold any letter in word.
Let's say you press W, it will display the first W instantly and then remaining ones after a fraction of a second something like that:
w wwwwwwwwwwwwwwwwwwwww
I really don't know how to explain it.
So the question is, is there a way to read the raw input from the keyboard so the function will be called continuously straight away?
I often use code like this:
bool keyboard[1<<30]; // EDIT: as noted in the comments this code might not be the most efficient
and in the event loop
while (SDL_PollEvent(&evnt)) {
switch (evnt.type) {
case SDL_QUIT:
_gameState = GameState::EXIT;
break;
case SDL_MOUSEMOTION:
break;
case SDL_KEYDOWN:
keyboard[evnt.key.keysym.sym] = true;
break;
case SDL_KEYUP:
keyboard[evnt.key.keysym.sym] = false;
break;
}
step();
}
and the step function:
void step() {
if(keyboard[SDLK_RIGHT]) player.movePlayer(1);
else if(keyboard[SDLK_LEFT]) player.movePlayer(2);
}
I have buy this keyboard http://www.mobilitylab.eu/mini-design-touch-silver.html of 107 touch,
and I want a keypad to put it on my left hand.
but when we activate the numlock of the keypad, it activates the numlock on the keyboard.
So we have 456- instead of uiop.
I have found this program but it don't work on a 64 bits OS. http://www.bellamyjc.org/fr/systeme.html#knumlock.
So i want to do my own program with C++, but it don't work fine, the hook is allright (WH_GETMESSAGE) but i don't understand how we can change the keycode and how we can find if it's a key of the keypad or the keybord ?
Here this is my code where i try to change the message :
//-----------------Keyboard Hook Callback---------------//
Hookmsg_API LRESULT CALLBACK Hookmsg(int ncode,WPARAM wparam,LPARAM lparam){
//if(ncode>=0) //
if(ncode<0)
return CallNextHookEx(hook,ncode,wparam,lparam);
MSG *msg;
msg=(MSG *)lparam;
WORD newVK,oldVK;
WORD newSC,oldSC;
if(ncode==HC_ACTION)
{
if((msg->message == WM_KEYUP))//Check whether key was pressed(not released).)
{
oldVK=msg->wParam;
oldSC=SCANCODE(msg->lParam);
bool extendkey=false;
if(((HIWORD(msg->wParam) & 0x0100) == 0x0100))
{
extendkey=true;
}
if(!extendkey)
{
bool modif=true;
switch(oldVK)//wparam
{
case VK_INSERT: newVK=VK_NUMPAD0; break;
case VK_END: newVK=VK_NUMPAD1; break;
case VK_DOWN: newVK=VK_NUMPAD2; break;
case VK_NEXT: newVK=VK_NUMPAD3; break;
case VK_LEFT: newVK=VK_NUMPAD4; break;
case VK_CLEAR: newVK=VK_NUMPAD5; break;
case VK_RIGHT: newVK=VK_NUMPAD6; break;
case VK_HOME: newVK=VK_NUMPAD7; break;
case VK_UP: newVK=VK_NUMPAD8; break;
case VK_PRIOR: newVK=VK_NUMPAD9; break;
case VK_DELETE: newVK=VK_DECIMAL; break;
default: modif=false;
}
if(modif==true)
{
msg->wParam = VK_NUMPAD0;
UINT newSC=MapVirtualKey(VK_NUMPAD0,MAPVK_VK_TO_VSC);
msg->lParam &= 0xFF00;
msg->lParam += (newSC << 16 );
//MessageBox( NULL, TEXT("OK"), TEXT("Error!"), MB_OK);
}
}
}
}
return ( CallNextHookEx(hook,ncode,wparam,lparam) );//pass control to next hook in the hook chain.
}
cant understand u...
u have 2 keyboards? if yes, try to use Raw Input (raw data from USB HID device)
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645543(v=vs.85).aspx
Lparam and wparam are not visible for other applications.
Keyboard input is much more than just windows messages. Modifying the messages will work in some cases, but is a vastly incomplete solution. You also need to consider driver state, GetKeyboardState, and others.
If you want to remap keys on your keyboard, you can create a new keyboard layout and assign it to a locale.
If keyboard layouts don't satisfy your needs, you will need to write a keyboard device driver.
If you only need this functionality in a specific application (not system globally), then you might be able to get lucky and only modify windows messages.
The function below is logging the "0", "z" and the "1" ok... but its not capturing the "Z" (shift-z)... any help would be appreciated...
__declspec(dllexport)
LRESULT CALLBACK HookProc (UINT nCode, WPARAM wParam, LPARAM lParam)
{
if ((nCode == HC_ACTION) && (wParam == WM_KEYUP))
{
// This Struct gets infos on typed key
KBDLLHOOKSTRUCT hookstruct = *((KBDLLHOOKSTRUCT*)lParam);
// Bytes written counter for WriteFile()
DWORD Counter;
wchar_t Logger[1];
switch (hookstruct.vkCode)
{
case 060: Logger[0] = L'0'; break;
case 061: Logger[0] = L'1'; break;
case 90: Logger[0] = L'z'; break;
case 116: Logger[0] = L'Z'; break;
}
// Opening of a logfile. Creating it if it does not exists
HANDLE hFile = CreateFile(L"C:\\logfile.txt", GENERIC_WRITE,
FILE_SHARE_READ, NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// put the file pointer to the end
SetFilePointer(hFile,NULL,NULL,FILE_END);
// Write the hFile typed in logfile
WriteFile(hFile,&Logger,sizeof(Logger),&Counter,NULL);
//WriteFile(hFile,&hookstruct.vkCode,sizeof(hookstruct.vkCode),&Counter,NULL);
// Close the file
CloseHandle(hFile);
}
}
The keyboard does not send characters. It sends keys. Whether you're typing z or Z, you're still pressing the same key, and that key has the same VK code both times.
You should also get notification when the Shift key is pressed or released. You can use those notifications to translate the keystrokes into characters. The caps-lock state will also be relevant for that. You may also be concerned about dead keys.
You can check whether the Shift key is pressed. GetAsyncKeyState will tell you the state of the key right now, and GetKeyState will tell you the state of the key as of the last message removed from the message queue.
There's no virtual key code for Z.
Try something like this:
case 90:
if(GetKeyState(VK_LSHIFT|VK_RSHIFT)
Logger[0] = L'Z'; break;
else
Logger[0] = L'z'; break;