将 unicode 字符串复制到剪贴板不起作用
Copy unicode string to clipboard isn't working
我不知道为什么这段代码不能正常工作:
#define UNICODE
#include <iostream>
#include <sstream>
#include <windows.h>
void main(void)
{
wchar_t* strData = L"CreateWindowExA";
MessageBox(NULL, strData, L"Warning", MB_OK);
if (OpenClipboard(0)) {
EmptyClipboard();
HGLOBAL hClipboardData;
hClipboardData = GlobalAlloc(GMEM_DDESHARE,
wcslen(strData) + 1);
char* pchData;
pchData = (char*)GlobalLock(hClipboardData);
strcpy(pchData, LPCSTR(strData));
GlobalUnlock(hClipboardData);
SetClipboardData(CF_TEXT, hClipboardData);
CloseClipboard();
}
MessageBox(NULL, L"Copied to Clipboard", L"Title", MB_OK);
}
strcpy(pchData, LPCSTR(strData));
不是 UTF16 数据的好选择。
使用 wcscpy
并移除演员表。
更改此部分:
hClipboardData = GlobalAlloc(GMEM_DDESHARE, sizeof(WCHAR) * (wcslen(strData) + 1));
WCHAR* pchData;
pchData = (WCHAR*)GlobalLock(hClipboardData);
wcscpy(pchData, strData);
GlobalUnlock(hClipboardData);
SetClipboardData(CF_UNICODETEXT, hClipboardData);
为 WCHAR
分配 2*
字节数。使用 WCHAR
而不是 char
。使用 wcscpy
而不是 strcpy
。使用 CF_UNICODETEXT
.
而不是 CF_TEXT
您需要应用以下更改来修复您的代码:
if (OpenClipboard(0)) {
您需要提供有效的 window 句柄,才能获得剪贴板的所有权。需要所有权,以便您可以更改剪贴板的内容。
HGLOBAL hClipboardData;
hClipboardData = GlobalAlloc(GMEM_DDESHARE,
wcslen(strData) + 1);
有 2 个错误需要修复。正如使用 GMEM_MOVEABLE 标志的 Memory and the Clipboard, when placing an object into the clipboard, memory should be allocated by using the GlobalAlloc 函数中所解释的那样。另一方面,GMEM_DDESHARE 被忽略,并且在不传递任何标志的情况下调用默认使用 GMEM_FIXED。这将 return 一个内存指针,并将其传递给 GlobalLock
随后将失败。
其次,此 API 调用需要 字节 的大小。 Windows中的一个Unicode编码单元是2个字节。你需要 (wcslen(strData) + 1) * sizeof(wchar_t)
.
char* pchData;
pchData = (char*)GlobalLock(hClipboardData);
strcpy(pchData, LPCSTR(strData));
strcpy
复制单字节单元,直到第一个 NUL 字符。使用 UTF-16LE 编码(在 Windows 中使用),您正在复制单个字符。您应该改用 wcscpy,并将目标转换为 wchar_t*
:
wchar_t* pchData;
pchData = (wchar_t*)GlobalLock(hClipboardData);
wcscpy(pchData, strData);
SetClipboardData(CF_TEXT, hClipboardData);
由于您复制了 UTF-16LE 编码的文本,因此剪贴板格式应为 CF_UNICODETEXT
。
参考文献:
- MSDN 中 Clipboard (Windows) 下提供了详尽的文档。
我在 C++ MFC
中尝试了@Joseph Willcoxson 的回答,感谢您的代码,我发现第一次调用剪贴板功能时有效。但是当第二次调用时,它会抛出没有特定错误消息的奇怪异常。经过一番查找和测试,我发现 wcscpy
会出现编译错误 C4996 : function may be unsafe. Consider using wcscpy_s instead.
而且我发现wcscpy_s
用法,修改为使用wcscpy_s
,另外注释掉GlobalFree()
使剪贴板功能可以多次成功调用不报错:
void toClipboardWStr(const wchar_t* strData) {
if (OpenClipboard(0)) {
EmptyClipboard();
int size_m = sizeof(WCHAR) * (wcslen(strData) + 1);
HGLOBAL hClipboardData = GlobalAlloc(GMEM_DDESHARE, size_m);
WCHAR* pchData;
pchData = (WCHAR*)GlobalLock(hClipboardData);
//wcscpy(pchData, strData);
wcscpy_s(pchData, size_m / sizeof(wchar_t), strData);
GlobalUnlock(hClipboardData);
SetClipboardData(CF_UNICODETEXT, hClipboardData);
CloseClipboard();
// if you need to call this function multiple times, I test no need to GlobalFree, or will occur error
//GlobalFree(hClipboardData);
}
}
我不知道为什么这段代码不能正常工作:
#define UNICODE
#include <iostream>
#include <sstream>
#include <windows.h>
void main(void)
{
wchar_t* strData = L"CreateWindowExA";
MessageBox(NULL, strData, L"Warning", MB_OK);
if (OpenClipboard(0)) {
EmptyClipboard();
HGLOBAL hClipboardData;
hClipboardData = GlobalAlloc(GMEM_DDESHARE,
wcslen(strData) + 1);
char* pchData;
pchData = (char*)GlobalLock(hClipboardData);
strcpy(pchData, LPCSTR(strData));
GlobalUnlock(hClipboardData);
SetClipboardData(CF_TEXT, hClipboardData);
CloseClipboard();
}
MessageBox(NULL, L"Copied to Clipboard", L"Title", MB_OK);
}
strcpy(pchData, LPCSTR(strData));
不是 UTF16 数据的好选择。
使用 wcscpy
并移除演员表。
更改此部分:
hClipboardData = GlobalAlloc(GMEM_DDESHARE, sizeof(WCHAR) * (wcslen(strData) + 1));
WCHAR* pchData;
pchData = (WCHAR*)GlobalLock(hClipboardData);
wcscpy(pchData, strData);
GlobalUnlock(hClipboardData);
SetClipboardData(CF_UNICODETEXT, hClipboardData);
为 WCHAR
分配 2*
字节数。使用 WCHAR
而不是 char
。使用 wcscpy
而不是 strcpy
。使用 CF_UNICODETEXT
.
CF_TEXT
您需要应用以下更改来修复您的代码:
if (OpenClipboard(0)) {
您需要提供有效的 window 句柄,才能获得剪贴板的所有权。需要所有权,以便您可以更改剪贴板的内容。
HGLOBAL hClipboardData;
hClipboardData = GlobalAlloc(GMEM_DDESHARE,
wcslen(strData) + 1);
有 2 个错误需要修复。正如使用 GMEM_MOVEABLE 标志的 Memory and the Clipboard, when placing an object into the clipboard, memory should be allocated by using the GlobalAlloc 函数中所解释的那样。另一方面,GMEM_DDESHARE 被忽略,并且在不传递任何标志的情况下调用默认使用 GMEM_FIXED。这将 return 一个内存指针,并将其传递给 GlobalLock
随后将失败。
其次,此 API 调用需要 字节 的大小。 Windows中的一个Unicode编码单元是2个字节。你需要 (wcslen(strData) + 1) * sizeof(wchar_t)
.
char* pchData;
pchData = (char*)GlobalLock(hClipboardData);
strcpy(pchData, LPCSTR(strData));
strcpy
复制单字节单元,直到第一个 NUL 字符。使用 UTF-16LE 编码(在 Windows 中使用),您正在复制单个字符。您应该改用 wcscpy,并将目标转换为 wchar_t*
:
wchar_t* pchData;
pchData = (wchar_t*)GlobalLock(hClipboardData);
wcscpy(pchData, strData);
SetClipboardData(CF_TEXT, hClipboardData);
由于您复制了 UTF-16LE 编码的文本,因此剪贴板格式应为 CF_UNICODETEXT
。
参考文献:
- MSDN 中 Clipboard (Windows) 下提供了详尽的文档。
我在 C++ MFC
中尝试了@Joseph Willcoxson 的回答,感谢您的代码,我发现第一次调用剪贴板功能时有效。但是当第二次调用时,它会抛出没有特定错误消息的奇怪异常。经过一番查找和测试,我发现 wcscpy
会出现编译错误 C4996 : function may be unsafe. Consider using wcscpy_s instead.
而且我发现wcscpy_s
用法wcscpy_s
,另外注释掉GlobalFree()
使剪贴板功能可以多次成功调用不报错:
void toClipboardWStr(const wchar_t* strData) {
if (OpenClipboard(0)) {
EmptyClipboard();
int size_m = sizeof(WCHAR) * (wcslen(strData) + 1);
HGLOBAL hClipboardData = GlobalAlloc(GMEM_DDESHARE, size_m);
WCHAR* pchData;
pchData = (WCHAR*)GlobalLock(hClipboardData);
//wcscpy(pchData, strData);
wcscpy_s(pchData, size_m / sizeof(wchar_t), strData);
GlobalUnlock(hClipboardData);
SetClipboardData(CF_UNICODETEXT, hClipboardData);
CloseClipboard();
// if you need to call this function multiple times, I test no need to GlobalFree, or will occur error
//GlobalFree(hClipboardData);
}
}