Link to home
Start Free TrialLog in
Avatar of CC
CC

asked on

Scancodes under Windows

I am trying to write a procedure to return keystrokes under Visual C++, easy enough, except I also want the scancode of every key hit. I have tryed using __asm statements and simply calling interupt 16h, however windows does not appear to like that, is there a C function that can do this?
Avatar of nil_dib
nil_dib

look at MapVirtualKey, MapVirtualKeyEx
Avatar of CC

ASKER

Sorry, for 300 points im gonna want a bit more detailed response then that :)
Looking at the docco, it refers to a virtual keyboard, is this something that I have to set up, or does it defual to a mapping of the standard keyboard?
If the computer is set up correctly the mapping will be correct for the keyboard in use.  Most keyboards use the same mapping anyways, it is just that some of the foreign keyboards use slightly different mappings.

VC generates 32 bit applications only.  Most DOS service interrupts cannot be called from a 32 bit application, so I don't recommend you try.  You need to resort to the windows API for getting your characters from the user.  If this is for a console program, you can use ReadConsole() or ReadConsoleInput() to get characters entered by the user (among other posibilities)..  For a windows GUI application, you need to process windows messages to get the user input.  What sort of application is this?
To translate an ASCII letter, digit, or symbol value to its scan code use

int ASCIIChr = 'a';
int ScanCode = MapVirtualKey(toupper(ASCIIChr),0);
Avatar of CC

ASKER

It is for a guy who is using fortran. He needs a function that will return both the ASCII and Scancode of any key hit, or null both if none have been hit, just like the dos int16h (function 1 or 0, I cant remember now). He can use dlls, and I can write them, and I normally use c++ version 3 if I go up to 3gls at all,.... I just kinda figured that since I can get scancodes in c++ v3, I would be able to in VC. Next time I will not assume so much. So is the MapVirtualx stuff suitable? A code chunk?
Is the fortran program a console program?  I'll assume so for the moment.

Do you want the input to be buffered an echoed?  this will be.  i.e. the user will be able to type several characters and they wil be displayed.  The user can correct mistakes by backspacing an retyping.  Your program does not "see" any of this goo on.  Once the user presses enter the characters typed will be read by your program.  Is that what you want?  if not, I can show you how to read it unbuffered, in which case you get 1 character a time and the user cannot correct mistakes (without you knowing about it i.e. you have to handle the correction.)

example follows.
DllExport char GetChr(void)
{
   char  Chr;
   DWORD ChrRed;
   HANDLE StdInpHnd = GetStdHandle(STD_INPUT_HANDLE);
 
   ReadConsole(StdInpHnd,&Chr,1,&ChrRed,NULL);
   return Chr;
};

DllExport void GetChrAndCod(char &Chr,char &Cod)
{
   Chr = GetChr():
   Cod = MapVirtualKey(toupper(Chr),0);
};

Let me know if you have any questions.
Avatar of CC

ASKER

Sorry, I need it unbuffered, logic for the entire call:
if(_kbhit())
{
  SCode = the scancode of the key that was hit.
  ACode = the ascii of whatever was hit.
}
else
{
  return nulls.
}
It needs to be able to read in arrow keys and whatnot as well.
#include <windows.h>
#include <conio.h>

void main ()
{
    while( !_kbhit() );  
    unsigned uASCII = _getch();
    unsigned uScan = MapVirtualKey(toupper(uASCII),0);
}

nil_dib
>> Sorry, I need it unbuffered, logic for the entire call:
Don't you think it was a bit unfair to state that after I answered?  In my answer I specifically stated that I could give you an unbuffered version too, but wasn't sure what you wanted.
Avatar of CC

ASKER

Sorry, but _getch() will only get me alphanumeric characters, and the reason I want actual (not calculated) scancode is that I need to know what key was pressed, including arrow keys etc. Also apologies for rejecting the last one as well, but I dont use this site real often, and didnt know that I had any alternative? Apologies.
Look at my solution again.  It will return the arrow keys or any other key.  You can also get mouse input if you would like.
But the problem was that was buffer and echoed.  To turn that off you use SetConsoleMode().  Like the following function for example turns buffering and echoing on or off.  (Both are on or both are off.).

void
SetWatMod(bool WatFlg)
{
   DWORD Mod;
   HANDLE StdInpHnd = GetStdHandle(STD_INPUT_HANDLE);
       
   GetConsoleMode(StdInpHnd,&Mod);
   if (WatFlg)
      Mod |= ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT;
   else
      Mod &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
   SetConsoleMode(StdInpHnd,Mod);
}

If you turn off buffering and echoing you will probably want to write your own procedures for obtaining data from the user.  These procedure will probably have to do the buffering and echoing manually.  That is, they will probably have to store the characters entered as the user is typing and look for backspaces and/or arrow keys and make corrections as the user types them.  they will also have to output the results as the user types.  
CC, next is pure DOS programm, that i use in all my Dos
function. It is ~ same thing, that nil_dib/nietod prepose,
only in DOS and don't use MapVirtualKey.
For me it works good, but nil_dib/nietod solutions are good,
too.

   if (bioskey(1))
     {
       if ((key = getch())==0)  /* Function key is pressed (NULL + key).   */
       {
         key = getch();        /* Skip the NULL key.     */
         key |= 0xFF00;        /* Set uper byte in ret-val to 0xFF - func-key. */
       } /* endif */
        break;
      }
//    Returned key i analize, using next enum:

enum  V_KBD_KEYS {  /* Keybord code definitions.   */
   BS         = 8,
   TAB        = 9,
   FF            = 12,
   CR         = 13,
   S_CR            = 0xFF00 +  13,
   ESC        = 27,
   F1    = 0xFF00 +  59,
   F2    = 0xFF00 +  60,
   F3    = 0xFF00 +  61,
   F4    = 0xFF00 +  62,
   F5    = 0xFF00 +  63,
   F6    = 0xFF00 +  64,
   F7    = 0xFF00 +  65,
   F8    = 0xFF00 +  66,
   F9    = 0xFF00 +  67,
   F10   = 0xFF00 +  68,
   HOME  = 0xFF00 +  71,
   CRUP  = 0xFF00 +  72,
   PGUP  = 0xFF00 +  73,
   CRLT  = 0xFF00 +  75,
   CRRT  = 0xFF00 +  77,
   END   = 0xFF00 +  79,
   CRDN  = 0xFF00 +  80,
   PGDN  = 0xFF00 +  81,
   INS   = 0xFF00 +  82,
   DEL   = 0xFF00 +  83,
   S_DEL = 0xFF00 +  46,
   C_ENTER  = 10,
   C_A      = 1,
   C_B      = 2,
   C_C      = 3,
   C_D      = 4,
   C_E      = 5,
   C_F      = 6,
   C_G      = 7,
   C_H      = 8,
   C_J      = 10,
   C_K      = 11,
   C_L      = 12,
   C_N      = 14,
   C_O      = 15,
   C_P      = 16,
   C_R      = 18,
   C_S      = 19,
   C_T      = 20,
   C_U      = 21,
   C_V      = 22,
   C_W      = 23,
   C_X      = 24,
   C_Y      = 25,
   C_Z      = 26,
   C_PGDN= 0xFF00 + 118,
   C_PGUP= 0xFF00 + 132,      //
   C_F1  = 0xFF00 +  94,        /* Control-Fn keys... */
   C_F2  = 0xFF00 +  95,        /* Control-Fn keys... */
   C_F3  = 0xFF00 +  96,        /* Control-Fn keys... */
   C_F4  = 0xFF00 +  97,        /* Control-Fn keys... */
   C_F5  = 0xFF00 +  98,        /* Control-Fn keys... */
   C_F6  = 0xFF00 +  99,        /* Control-Fn keys... */
   C_F7  = 0xFF00 + 100,        /* Control-Fn keys... */
   C_F8  = 0xFF00 + 101,        /* Control-Fn keys... */
   C_F9  = 0xFF00 + 102,        /* Control-Fn keys... */
   C_F10 = 0xFF00 + 103,        /* Control-Fn keys... */
   ALT_A = 0xFF00 +  30,
   ALT_B = 0xFF00 +  48,
   ALT_C = 0xFF00 +  0x2E,
   ALT_D = 0xFF00 +  32,
   ALT_E = 0xFF00 +  18,
   ALT_F = 0xFF00 +  33,
   ALT_G = 0xFF00 +  34,
   ALT_H = 0xFF00 +  35,
   ALT_L = 0xFF00 +  38,
   ALT_M = 0xFF00 +  50,
   ALT_N = 0xFF00 +  49,
   ALT_O = 0xFF00 +  24,
   ALT_P = 0xFF00 +  25,
   ALT_Q = 0xFF00 +  16,
   ALT_R = 0xFF00 +  19,
   ALT_S = 0xFF00 +  31,
   ALT_T = 0xFF00 +  20,
   ALT_X = 0xFF00 +  45,
   ALT_Y = 0xFF00 +  21,
   ALT_Z = 0xFF00 +  44,
   ALT_F1 = 0xFF00+ 104,
   C_CRLT   = 0xFF00 +  115,
   C_CRRT   = 0xFF00 +  116,
   C_CRDN   = 0xFF00 +  117,
   C_CRUP   = 0xFF00 +  118,
   C_HOME   = 0xFF00 + 0x77,                  //ctrl+HOME
   C_END    = 0xFF00 + 0x75,                  //ctrl+END
   S_F1     = 0xFF00 + 0x54,                  //shift + F1
   S_F2     = 0xFF00 + 0x55,                  //shift + F2
   S_F3     = 0xFF00 + 0x56,                  //shift + F3
   S_F4     = 0xFF00 + 0x57,                  //shift + F4
   S_F5     = 0xFF00 + 0x58,                  //shift + F5
   S_F6     = 0xFF00 + 0x59,                  //shift + F6
   S_F7     = 0xFF00 + 0x5a,                  //shift + F7
   S_F8     = 0xFF00 + 0x5b,                  //shift + F8
   S_F9     = 0xFF00 + 0x5c,                  //shift + F9
   S_F10    = 0xFF00 + 0x5d,                  //shift + F10
   S_CRDN   = 50,                        //shift + DOWN
   S_PGDN   = 51,                        //shift + PgDn
   S_CRLT   = 52,                        //shift + LEFT
   S_CRRT   = 54,                        //shift + RIGHT
   S_CRUP   = 56,                        //shift + UP
   S_PGUP   = 57,                        //shift + PGUP
   S_TAB   = 0xFF00 + 15                  //shift + TAB
}
To nietod : i don't want offend to anyone, and send
my programm, as one of possible solutions.
Alex
Except this is a windows program.  He says that in the question and title.

CC are you out there?
Avatar of CC

ASKER

I have returned.

Alex, thankyou for the help. I too would normally prefer to use a DOS based program, just that I know the environment and all much better, however as neitod says, I had to write it in a Win environment.

Neitod, I would like to award you the points, do you want to pretend to answer again so I can mark it as satisfactory?
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of CC

ASKER

And thus the points are yours. Cheers.