Pergunta

I am trying to determine if it is possible to take arrow keys and convert them to wide characters. I am using conio.h for its getch() function, I just like how it works compared to similar functions, and it has to be called twice to retrieve arrow keys.

Arrow keys when pressed return 0xE0 (-32) as the first character, and then {Left = 'K', Up = 'H', Right = 'M', Down = 'P'}

So I've been trying to find a way to merge the two characters into one. This is the closest thing I came up with. Function keys don't work with it though, it always returns the same values no matter the function key pressed. {F1-12 = 0, Arrows = 224} I Pulled out the trusty windows calculator and was able to determine that 224 is equivalent to -32 in binary. I just put it down to a byte and used the decimal system and went 100+124 and it was = -32.

So maybe somebody can help me figure out why the conversion is only considering the first character in the array. I have surely done something wrong. Enough talk, sorry for going on too long if that was the case and now here is the code.

#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <wincon.h>
#include <conio.h>
#include <cwchar>

/**int main()
{
    int N;
    char C;
    wchar_t R;

    while(true)
    {
        while(!kbhit()){}
        //C = getch();

        //if((R == 0) || (R == 224))

        std::cout << R << std::endl;
        N = R;
        std::cout << R << " = " << N << std::endl;
    }
}*/



int main()
{
    int N = 0;
    char C[2];
    wchar_t R;
    mbstate_t mbst;

    while(true)
    {
        mbrlen(NULL,0,&mbst);
        memset(&mbst,0,sizeof(mbst));

        for(int i = 0; i < 2; ++i)
        {
            while(!kbhit()){}
            C[i] = getch();
            N = C[i];
            switch(N)
            {
                case 0:
                    break;
                case -32:
                    break;
                default:
                    //input needs to be converted
                    mbrtowc(&R,C,2,&mbst);
                    N = R;
                    std::cout << R << " = " << N << std::endl;
                    i = 3;
                    break;
            }
        }
    }
}

Edit:

I found a way to combine the 2 bytes using a union. I didn't know what a union was at the time I posted this. The union allows me using the same memory space for two different data types. How it works is here - http://www.cplusplus.com/doc/tutorial/other_data_types/

Foi útil?

Solução

I was able to resolve my own issue, but not in the way I had been attempting. If somebody wants to help to figure out what I was doing wrong that'd be great.

As far as reading each and every key as a unique 2 byte variable however, I was able to make a work around. I found a question about shifting bits, and used it to combine my two chars. Then I figured out that the numbers were not combining properly, I found that it was because I was using signed chars instead of unsigned chars. I didn't want to use unsigned chars, so I found a new solution using a union.

This is my union solution. It is very simple.

#include <iostream>
#include <conio.h> //getch() & kbhit()
#include "rndgen.h"
#define FN_ESCAPE 27
#define FN_UP_ARROW 18656
#define FN_DOWN_ARROW 20704
#define FN_LEFT_ARROW 19424
#define FN_RIGHT_ARROW 19936
                                                                    //This union allows for two 8-bit values to be read as one 16-bit value 
union wide_char
{
    short wide_C;
    char C[2];
};
                                                                    //Function waits for a key to be pressed
inline short key_wait()
{
    wchar_t R;
    wide_char user_input;
    user_input.wide_C = 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:
                R = user_input.wide_C;
                return R;
                break;
        }
    }
    return -1;
}

The wide_C returns the bits for C[2] in this order {C[1],C[0]} this is great, because it means F1-12 can be read uniquely (the first char return is 0 for F1-12) It could probably stand to have the short replaced with wchar_t, but I figured why fix something that isn't broken. I might do that when/if I decide to re-implement the code in a new solution for a different program.

This also means that a-Z & 0-9 can all be read as their regular char values.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top