Jump to content
  • Advertisement
Sign in to follow this  
Eric Poitras

Arrow Keys and getch

This topic is 4250 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

Hey, I'm writing a win32 console app with VC++ Express Edition and I'm trying to get the arrow keys to work with getch but it's not working, I can get any other key to respond but not the arrow keys. Any Ideas?

Share this post


Link to post
Share on other sites
Advertisement
I don't think int86() will work with 32-bit applications any more.

I once put the following together that sort of simulates the codes the getch() used to return for the arrow keys. getch() used to return first a zero, then on the second call one of 72, 80, 75 or 77 for the arrow keys. The following creates a structure with x and y members that represent the two calls. A normal key will have its ASCII code in x. If x is zero, y will contain the old code for the arrow key. The struct also has boolean members that represent the state of the shift and control keys:

keys.h

#ifndef keys_H
#define keys_H

namespace keys
{

class code
{
public:
code(int a=0,int b=0,bool s=false,bool c=false)
: x(a),y(b),shift(s),ctrl(c) { }

int x,y; bool shift,ctrl;
};

void acquire();
code get();

}

#endif




keys.cpp

#include "keys.h"

#include <windows.h>

namespace
{

HANDLE hIn;
INPUT_RECORD InRec;
DWORD NumRead;

}

void keys::acquire()
{
hIn=GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(hIn,0);
}

keys::code keys::get()
{
code c;
while(true)
{
ReadConsoleInput(hIn,&InRec,1,&NumRead);

if(InRec.EventType==KEY_EVENT)
{
if(InRec.Event.KeyEvent.bKeyDown==0) continue;

if(InRec.Event.KeyEvent.wVirtualKeyCode==16) continue;
if(InRec.Event.KeyEvent.wVirtualKeyCode==17) continue;
if(InRec.Event.KeyEvent.wVirtualKeyCode==18) continue;

c.x=InRec.Event.KeyEvent.uChar.AsciiChar;
c.y=0;
c.shift=bool(InRec.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED);
c.ctrl=bool(InRec.Event.KeyEvent.dwControlKeyState & LEFT_CTRL_PRESSED);

if(InRec.Event.KeyEvent.wVirtualKeyCode==38)
{
c.x=0; c.y=72;
}

if(InRec.Event.KeyEvent.wVirtualKeyCode==40)
{
c.x=0; c.y=80;
}

if(InRec.Event.KeyEvent.wVirtualKeyCode==37)
{
c.x=0; c.y=75;
}

if(InRec.Event.KeyEvent.wVirtualKeyCode==39)
{
c.x=0; c.y=77;
}

return c;
}
}
}




You need to call keys::acquire() at the start of the program. You can then call get() like:


void f()
{
keys::code c=keys::get();

switch(c.x)
{
case 0:
switch(c.y)
{
case 72: /* up */ break;
case 80: /* down */ break;
case 75: /* left */ break;
case 77: /* right */ break;
}
break;

case 'a': break;
case 'z': break;
}
}


Obviously you can extend the get() function to convert other scan codes into the old getch() double codes for the other extended keys if you need to.

Equally of course you could (unlike me) move out of the 1980s and actually just respond to the scan codes directly instead.

HTH

Share this post


Link to post
Share on other sites
Is there an easier way to get all keyboard input to work in a console app without all that extra code, I don't care if i'm not using getch.

Also I'm having this link error now and I don't know why, any ideas?

pdcurses.lib(initscr.obj) : error LNK2019: unresolved external symbol __iob referenced in function _Xinitscr
1>pdcurses.lib(pdcscrn.obj) : error LNK2001: unresolved external symbol __iob
1>pdcurses.lib(terminfo.obj) : error LNK2001: unresolved external symbol __iob
1>C:\Documents and Settings\Eric\My Documents\Visual Studio 2005\Projects\SoA\Debug\SoA.exe : fatal error LNK1120: 1 unresolved externals

Share this post


Link to post
Share on other sites
ok I fixed the linking errors. all I need know is to get the arrow keys to work. I'm just writing a rogue-like game with pdcurses btw and I can't seem to ge the arrow keys to work to get my character to move... I tried with wasd and that works but i really want to use the arrow keys instead.

Share this post


Link to post
Share on other sites
The way I've described above is the only way I could ever find to respond to all the keyboard keys.

Borland's compiler has a getch() that works under 32-bit and will respond to the arrow keys as well, but it may be that it just sits on top of code like the above.

Share this post


Link to post
Share on other sites
you know, with slight modification, that code still works with getch()....
You dont need all that console setup and console specific reads.

Atleast on my machine i never had any problems.(VS2005ee)

void f()
{ char c=getch();

switch(c)
{
case 0:
char y = getch()

switch(y)
{
case 72: /* up */ break;
case 80: /* down */ break;
case 75: /* left */ break;
case 77: /* right */ break;
}
break;
}
}

Share this post


Link to post
Share on other sites
Having just tested this, KulSeran is quite correct. _getch() under VS2005 Express does in fact respond to the keypresses. According to my test, it is returning 224 first, then 72, 80, 75 or 77 as above.

The code I posted above was from when I was using Digital Mars compiler to write a text editor. The DM getch() would not respond to arrow keys (or any extended keys) at all, so I'd just assumed that VS was the same based on the OP's post. Sorry about that.

To the OP, what exactly is the problem you are having with using _getch() (or getch()) to respond to the arrow keys? Seems to work fine for me:


#include <conio.h>
#include <iostream>

int main()
{
int x=_getch();

while(x!=27)
{
std::cout << x << std::endl;
x=_getch();
}

return 0;
}



Pressing the UP arrow key in the above program prints:

224
72

Same with Insert, Delete and so on - first you get 224, then a subsequent press gives a code that identifies the key. I wonder why I'm getting 224 instead of 0 though?

Share this post


Link to post
Share on other sites
arg... that's not working, I used that code and you have to press the keys like 4 times before anything happens... here's my code:

void CheckForInput( void )
{
c = getch(); // Get Input
/* Act depending on the last key received. */

switch (c)
{
case 'd': //Right arrow key
g_cPlayer.x++;
break;

case 'a': //Left arrow key
g_cPlayer.x--;
break;

case 72: //Up arrow key
g_cPlayer.y--;
break;

case 's': //Down arrow key
g_cPlayer.y++;
break;

default:
break;
}
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!