Буфер обмена Windows не сохраняет символ ASCII - PullRequest
0 голосов
/ 29 августа 2018

Я пишу плагин для клиента TS3, но столкнулся с проблемой ...

В одном из названий каналов есть специальный знак (╠), который, я думаю, является специальным символом из расширенной таблицы ascii.

При входе в INSIDE teampeak этот символ отображается нормально, но при попытке скопировать его в буфер обмена Windows с помощью интерфейса C он возвращает совершенно другой символ (â).

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

Я использую следующий код, чтобы скопировать символ * в буфер обмена, который я нашел где-то и изменил другой код, который я нашел для использования WCHAR:

void SaveClipboard(char* tx)
{
    WCHAR text[140];
    swprintf(text, 140, L"%hs", tx);

    if(OpenClipboard(NULL))
    {
        EmptyClipboard();
        HGLOBAL global = GlobalAlloc(GMEM_DDESHARE, 2 * (wcslen(text) + 1)); //text size + \0 character

        WCHAR* pchData;
        pchData = (WCHAR*)GlobalLock(global);
        wcscpy(pchData, text);
        GlobalUnlock(pchData);

        SetClipboardData(CF_UNICODETEXT, global);
        CloseClipboard();
    }
}

1 Ответ

0 голосов
/ 29 августа 2018

wchar_t кодируется UTF-16, но данные, которые вы получаете, UTF-8 кодируются. Вы не конвертируете между этими двумя кодировками, вы просто интерпретируете байты.

Глядя на кодовые точки для этих символов, должно стать очевидным, что происходит: кодовая точка UTF-8 для равна 0xE2 0x95 0xA0, а кодовая точка UTF-16 для â равна 0x00 0xE2, в то время как Кодовая точка UTF-16 для равна 0x25 0x60.

swprintf(text, 140, L"%hs", tx); <- это просто преобразует каждый <code>char в wchar_t, превращая 3-байтовую UTF-8 кодовую точку 0xE2 0x95 0xA0 в три 2-байтовых UTF-16 кодовых пункта: 0x00 0xE2, 0x00 0x95 и 0x00 0xA0.

Чтобы получить 0x25 0x60 из 0xE2 0x95 0xA0, вам необходимо преобразовать данные:

std::wstring_convert<std::codecvt_utf8_utf16<char16_t>> converter;
std::wstring text = converter.from_bytes(tx);

В качестве альтернативы, поскольку вы уже используете WINAPI, вы можете использовать MultiByteToWideChar:

WCHAR text[140];
int length = MultiByteToWideChar(CP_UTF8, 0, tx, -1, (LPWSTR)text, 140);
...