Клавиши со стрелками как широкие символы

Я пытаюсь определить, можно ли взять клавиши со стрелками и преобразовать их в широкие символы. Я использую conio.h для его функции getch(), мне просто нравится, как она работает по сравнению с аналогичными функциями, и ее нужно вызывать дважды, чтобы получить клавиши со стрелками.

Клавиши со стрелками при нажатии возвращают 0xE0 (-32) в качестве первого символа, а затем {влево = 'K', вверх = 'H', вправо = 'M', вниз = 'P'}

Поэтому я пытался найти способ объединить двух персонажей в один. Это самое близкое, что я придумал. Однако функциональные клавиши не работают с ним, он всегда возвращает одни и те же значения независимо от того, какая функциональная клавиша нажата. {F1-12 = 0, Arrows = 224} Я вытащил верный калькулятор Windows и смог определить, что 224 эквивалентно -32 в двоичном формате. Я просто сократил его до байта и использовал десятичную систему, и получил 100 + 124, и это было = -32.

Так что, может быть, кто-нибудь поможет мне понять, почему преобразование учитывает только первый символ в массиве. Я наверняка сделал что-то не так. Хватит говорить, извините за слишком длинное, если это так, и теперь вот код.

#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;
            }
        }
    }
}

Редактировать:

Я нашел способ объединить 2 байта с помощью союза. Я не знал, что такое профсоюз, когда писал это. Объединение позволяет мне использовать одно и то же пространство памяти для двух разных типов данных. Как это работает, описано здесь: http://www.cplusplus.com/doc/tutorial/other_data_types/


person Josh C    schedule 23.10.2013    source источник
comment
mbrlen(NULL,0,&mbst); - я думаю, вам это вообще не нужно, или используйте после memset   -  person purec    schedule 12.04.2018


Ответы (1)


Я смог решить свою проблему, но не так, как я пытался. Если кто-то хочет помочь понять, что я делал неправильно, это было бы здорово.

Однако, читая каждый ключ как уникальную 2-байтовую переменную, я смог обойти это. Я нашел вопрос о смещении битов и использовал его для объединения двух моих символов. Затем я понял, что числа не сочетаются должным образом, я обнаружил, что это произошло потому, что я использовал знаковые символы вместо беззнаковых. Я не хотел использовать символы без знака, поэтому нашел новое решение, используя объединение.

Это мое профсоюзное решение. Это очень просто.

#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;
}

wide_C возвращает биты для C[2] в следующем порядке {C[1],C[0]}, это здорово, потому что это означает, что F1-12 может быть прочитан однозначно (первый возврат символа равен 0 для F1-12) Вероятно, можно было бы заменить короткое на wchar_t, но я подумал, зачем исправлять то, что не сломано. Я мог бы сделать это, когда/если решу повторно реализовать код в новом решении для другой программы.

Это также означает, что все символы a-Z и 0-9 могут быть прочитаны как их обычные значения char.

person Josh C    schedule 23.10.2013