c++console-applicationconio

Why can't I read all Ctrl + 'letters'


I've made a program that allows me to read all the stand-alone function keys (that I thought to test, at least) on my keyboard. I have it designed so that I can refer to any single key input as a single value. It handles Return, F1-F12, delete, backspace, arrows etc

I just thought to test modifications of input. I already made sure shift works, but now I decided to test Ctrl and Alt.

Question 1 Why does Alt not modify any of the input key codes?

Question 2 Why can I not capture certain Ctrl + combinations? Eg. Ctrl + s; Ctrl + 1-9;

Ctrl + 2 works, but I think it might be due to having my keyboard set as UK.

This is the code I am using.

Please note, I am not necessarily asking how to capture these key combinations (unless it is a simple modification or two). I only want to know why I am unable to.

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

union wide_char
{
    short Result;
    char C[2];
}; 

int main()
{
    wchar_t R;
    int N;
    wide_char user_input;
                                                    //Loops forever, this is only a proof of concept program proving this is possible to incorporate into a larger program
    while(true)
    {
        user_input.C[0] = 0;
        user_input.C[1] = 0;
                                                    //Loop twice, or until code causes the loop to exit
                                                        //Two times are neccessary for function keys unfortunately
        for(int i = 0; i < 2; ++i)
        {
                                                    //While there isn't a key pressed, loop doing nothing
            while(!kbhit()){}
                                                    //Grab the next key from the buffer
                                                        //Since the loop is done, there must be at least one
            user_input.C[i] = getch();
            switch(user_input.C[i])
            {
                case 0:
                case -32:
                                                    //The key pressed is a Function key because it matches one of these two cases
                                                        //This means getch() must be called twice
                                                        //Break switch, run the for loop again ++i
                    break;
                default:
                                                    //The character obtained from getch() is from a regular key
                                                        //Or this is the second char from getch() because the for loop is on run #2
                                                        //Either way we need a wide char (16 bits / 2 Bytes)
                    if(user_input.C[1] != 0)
                                                    //Function keys {Arrows, F1-12, Esc}
                                                    //We now combine the bits of both chars obtained
                                                        //They must be combined Second+First else the F1-12 will be duplicate
                                                        //This is because on F1-12 getch() returns 0 thus won't affect the combination
                        R = user_input.Result;
                    else
                                                    //Regular key press
                        R = user_input.C[0];
                                                    //Display our unique results from each key press
                    N = R;
                    std::cout << R << " R = N " << N << std::endl;

                    if( R == 'a' )
                        std::cout << "a = " << N << std::endl;
                                                    //Manually break for loop
                    i = 3;
                    break;
            }
        }
                                                    //We need to reset the array in this situation
                                                        //Else regular key presses will be affected by the last function key press
    }
}

Solution

  • This is very specific to your environment. You're using conio which is specific to DOS / Windows.

    Most of the Ctrl + alpha key values are bound to characters 1 - 26, and certain others are bound to other values under 31, to map to ASCII control characters. But some, like Ctrl + S have special meaning (Ctrl + S is XOFF in ASCII), and so might get 'eaten' by your environment.

    Fundamentally, the issue you're facing is the fact that getch approximates an old-school serial terminal interface. They only expose keyboard events at a "least common denominator" level, as opposed to a lower level that would allow you to distinguish modifier keys, etc. and give you a better way to deal with special keys such as function keys.

    (As you've noticed, function keys, have special multi-byte sequences. Again, this is due to emulating old-school serial terminals, where the keyboard might be at the other end of a remote link.)

    To get a lower-level (and therefore more direct and flexible interface) you need to use a more platform-specific library, or a richer library such as SDL. Either would give you a lower level view of the inputs from the keyboard.