1

我正在用 C++ 实现我自己的文本编辑器。它会……好的。;P

我需要一种将键码(特别是 Allegro,他们称之为扫描码)转换为 ASCII 字符的方法。我可以轻松地完成 AZ,并且将它们转换为 az 也很容易。我目前所做的是在 Allegro 中使用一个函数,该函数从扫描码 (al_keycode_to_name) 中返回一个名称,这意味着如果按下的键是 AZ,它将返回“A”到“Z”。这很容易,但我不能简单地阅读特殊字符,如“,”,“;” 等等,这就是我遇到困难的地方。

有没有办法自动做到这一点?也许是一个这样做的图书馆?真正的诀窍是考虑不同的布局。

这是我到目前为止所拥有的,以防万一有人感兴趣。InputState 类基本上是 Allegro 输入状态的副本,具有附加功能(例如 keyDown、keyUp、keyPress):

    void AllegroInput::TextInput(const InputState &inputState, int &currentCharacter, int &currentRow, std::string &textString)
    {
        static int keyTimer = 0;
        static const int KEY_TIMER_LIMIT = 15;
        for (int i = 0; i < 255; i++)
        {
            if (inputState.key[i].keyDown)
            {
                keyTimer++;
            }
            if (inputState.key[i].keyPress)
            {
                keyTimer = 0;
            }

            if ((inputState.key[i].keyPress) || ((inputState.key[i].keyDown) && (keyTimer >= KEY_TIMER_LIMIT)))
            {
                std::string ASCII = al_keycode_to_name(i);

                if ((ASCII.c_str()[0] >= 32) && (ASCII.c_str()[0] <= 126) && (ASCII.length() == 1))
                {
                    textString = textString.substr(0, currentCharacter) + ASCII + textString.substr(currentCharacter, textString.length());
                    currentCharacter++;
                }
                else 
                {
                    switch(i)
                    {
                        case ALLEGRO_KEY_DELETE:
                            if (currentCharacter >= 0) 
                            {
                                textString.erase(currentCharacter, 1);
                            }
                            break;

                        case ALLEGRO_KEY_BACKSPACE:
                            if (currentCharacter > 0) 
                            {
                                currentCharacter--;
                                textString.erase(currentCharacter, 1);
                            }
                            break;

                        case ALLEGRO_KEY_RIGHT:
                            if (currentCharacter < textString.length())
                            {
                                currentCharacter++;
                            }
                            break;

                        case ALLEGRO_KEY_LEFT:
                            if (currentCharacter > 0)
                            {
                                currentCharacter--;
                            }
                            break;
                        case ALLEGRO_KEY_SPACE:
                            if (currentCharacter > 0)
                            {

                                textString = textString.substr(0, currentCharacter) + " " + textString.substr(currentCharacter, textString.length());
                                currentCharacter++;
                            }
                            break;


                    }
                }
            }
        }
    }
4

1 回答 1

1

您应该使用ALLEGRO_EVENT_KEY_CHAR带有event.keyboard.unichar值的事件来读取文本输入。ALLEGRO_EVENT_KEY_DOWNALLEGRO_EVENT_KEY_UP对应于被按下的物理键。它们与可打印字符之间没有 1:1 的对应关系。

假设使用死键将两个键转换e'é. 您将获得两个用于eand的按键事件'(并且对于捕获正确的输入都没有用),但一个按键 char 事件带有é. 或者相反,也许有人映射F4到一个释放整段文本的宏。在这种情况下,您将有多个字符来按下一个键。

或者一个简单的测试:如果你按住一个键五秒钟,你会得到一个ALLEGRO_EVENT_KEY_DOWN但多个ALLEGRO_EVENT_KEY_CHAR,因为操作系统的键盘驱动程序发送重复事件。

您可以使用ALLEGRO_USTR这些 un​​icode 字符串轻松存储。

ALLEGRO_USTR *input = al_ustr_new("");

// in the event loop
al_ustr_append_chr(input, event.keyboard.unichar);

如果按下退格键等,还有删除字符的方法。您可以直接通过字体插件使用 ustr 数据类型al_draw_ustr(font, color, x, y, flags, input),或者您可以使用al_cstr(input)获取指向 UTF-8 字符串的只读指针。

于 2012-07-14T17:32:00.360 回答