@Recardo_Recoly

Как превратить то что вернет WM_CHAR в юникод?

Есть WndProc и в нем есть обработка WM_CHAR.
Только если перевести код символа который оно выдает то будет кракозявра. (это если русская раскладка)B085aBi.png
А код русских букв вообще с 1к начинается.
YSCKCz3.png
Как это пофиксить ?
  • Вопрос задан
  • 466 просмотров
Решения вопроса 1
@Mercury13
Программист на «си с крестами» и не только
Recardo_Recoly,
Понятно.
1. Лучше использовать WM_UNICHAR, он работает и с кодами более 65535. Поддерживается как минимум WinXP.
2. Как превратить кодовую позицию в UTF-8, есть много вариантов. Сейчас найду свой.

enum {
    SURROGATE_MIN = 0xD800,
    SURROGATE_MAX = 0xDFFF,
    SURROGATE_LO_MIN = SURROGATE_MIN,
    SURROGATE_HI_MIN = 0xDC00,
    SURROGATE_LO_MAX = SURROGATE_HI_MIN - 1,
    SURROGATE_HI_MAX = SURROGATE_MAX,
    UNICODE_MAX = 0x10FFFF,
    U8_1BYTE_MAX = 0x7F,
    U8_2BYTE_MIN = 0x80,
    U8_2BYTE_MAX = 0x7FF,
    U8_3BYTE_MIN = 0x800,
    U8_3BYTE_MAX = 0xFFFF,
    U8_4BYTE_MIN = 0x10000,
    U8_4BYTE_MAX = UNICODE_MAX,
    U16_1WORD_MAX = 0xFFFF,
    U16_2WORD_MIN = 0x10000,
    U16_2WORD_MAX = UNICODE_MAX,
};

void str::putCpNe (char*& p, unsigned long aCp)
{
    if (aCp <= U8_2BYTE_MAX) {  // 1 or 2 bytes, the most frequent case
        if (aCp <= U8_1BYTE_MAX) {  // 1 byte
            *(p++) = static_cast<char>(aCp);
        } else { // 2 bytes
            *(p++) = static_cast<char>((aCp >> 6)   | 0xC0);
            *(p++) = static_cast<char>((aCp & 0x3F) | 0x80);
        }
    } else {  // 3 or 4 bytes
        if (aCp <= U8_3BYTE_MAX) {  // 3 bytes
            *(p++) = static_cast<char>( (aCp >> 12)        | 0xE0);
            *(p++) = static_cast<char>(((aCp >> 6) & 0x3F) | 0x80);
            *(p++) = static_cast<char>( (aCp       & 0x3F) | 0x80);
        } else {    // 4 bytes
            *(p++) = static_cast<char>(((aCp >> 18) & 0x07) | 0xF0);
            *(p++) = static_cast<char>(((aCp >> 12) & 0x3F) | 0x80);
            *(p++) = static_cast<char>(((aCp >> 6)  & 0x3F) | 0x80);
            *(p++) = static_cast<char>( (aCp        & 0x3F) | 0x80);
        }
    }
}

void str::appendCp(std::string & s, unsigned long aCp)
{
    char c[5];
    char* end = c;
    putCpNe(end, aCp);
    s.append(c, end);
}

Слово Cp у меня означает code point, кодовая позиция Юникода. Ne — no error-checking, без проверки кодовых позиций на корректность.

В Си++ есть и штатные функции преобразования кодовых позиций Юникода в UTF-8 и UTF-16. Но страшны, как чёрт, и половина из них в C++17 deprecated :(

И последнее, что я хочу сказать.
Вы путаете две вещи: Юникод и его кодовые позиции, и форматы записи юникодных строк UTF-8 и UTF-16. Соотношение «один символ Юникода — один char» только в UTF-32!
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы