Windows 剪贴板不会保留 ASCII 字符
Windows Clipboard won't preserve ASCII character
我正在为 TS3 客户端编写一个插件,但我 运行 遇到了问题...
其中一个频道名称中有一个特殊符号(╠),这是扩展ascii的特殊字符table我认为。
在 teamspeak 中记录它时,该字符显示正常,但当尝试使用其 C 接口将其复制到 windows 剪贴板时,它 returns 完全不同的字符 (â)。
在得知扩展 ascii table 使用的字节数比常规字符多后,我曾尝试将其转换为 WCHAR,但这也不起作用。
我使用以下代码将 char* 复制到我在某处找到的剪贴板,并用我发现的使用 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 + [=11=] character
WCHAR* pchData;
pchData = (WCHAR*)GlobalLock(global);
wcscpy(pchData, text);
GlobalUnlock(pchData);
SetClipboardData(CF_UNICODETEXT, global);
CloseClipboard();
}
}
wchar_t
是UTF-16
编码的,但是你得到的数据是UTF-8
编码的。您不需要在这两种编码之间进行转换,您只需重新解释字节即可。
查看这些字符的代码点,应该清楚发生了什么:╠
的 UTF-8 代码点是 0xE2 0x95 0xA0
,[=17= 的 UTF-16 代码点] 是 0x00 0xE2
,而 ╠
的 UTF-16 代码点是 0x25 0x60
.
swprintf(text, 140, L"%hs", tx);
<- 这只是将每个 char
转换为一个 wchar_t
,将 3 字节 UTF-8
代码点 0xE2 0x95 0xA0
转换为三个 2 字节 UTF-16
代码点:0x00 0xE2
、0x00 0x95
和 0x00 0xA0
.
要从 0xE2 0x95 0xA0
得到 0x25 0x60
,您需要实际转换数据:
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);
我正在为 TS3 客户端编写一个插件,但我 运行 遇到了问题...
其中一个频道名称中有一个特殊符号(╠),这是扩展ascii的特殊字符table我认为。
在 teamspeak 中记录它时,该字符显示正常,但当尝试使用其 C 接口将其复制到 windows 剪贴板时,它 returns 完全不同的字符 (â)。
在得知扩展 ascii table 使用的字节数比常规字符多后,我曾尝试将其转换为 WCHAR,但这也不起作用。
我使用以下代码将 char* 复制到我在某处找到的剪贴板,并用我发现的使用 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 + [=11=] character
WCHAR* pchData;
pchData = (WCHAR*)GlobalLock(global);
wcscpy(pchData, text);
GlobalUnlock(pchData);
SetClipboardData(CF_UNICODETEXT, global);
CloseClipboard();
}
}
wchar_t
是UTF-16
编码的,但是你得到的数据是UTF-8
编码的。您不需要在这两种编码之间进行转换,您只需重新解释字节即可。
查看这些字符的代码点,应该清楚发生了什么:╠
的 UTF-8 代码点是 0xE2 0x95 0xA0
,[=17= 的 UTF-16 代码点] 是 0x00 0xE2
,而 ╠
的 UTF-16 代码点是 0x25 0x60
.
swprintf(text, 140, L"%hs", tx);
<- 这只是将每个 char
转换为一个 wchar_t
,将 3 字节 UTF-8
代码点 0xE2 0x95 0xA0
转换为三个 2 字节 UTF-16
代码点:0x00 0xE2
、0x00 0x95
和 0x00 0xA0
.
要从 0xE2 0x95 0xA0
得到 0x25 0x60
,您需要实际转换数据:
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);