我不知道为什么这段代码没有正常工作:
#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);
}
答案 0 :(得分:4)
更改此部分:
hClipboardData = GlobalAlloc(GMEM_DDESHARE, 2 * (wcslen(strData) + 1));
WCHAR* pchData;
pchData = (WCHAR*)GlobalLock(hClipboardData);
wcscpy(pchData, strData);
GlobalUnlock(hClipboardData);
SetClipboardData(CF_UNICODETEXT, hClipboardData);
为2*
分配WCHAR
个字节数。而不是char
,请使用WCHAR
。而不是strcpy
,请使用wcscpy
。而不是CF_TEXT
,请使用CF_UNICODETEXT
。
答案 1 :(得分:4)
您需要应用以下更改来修复代码:
if (OpenClipboard(0)) {
您需要提供有效的窗口句柄,以取得剪贴板的所有权。所有权是必需的,因此您可以更改剪贴板的内容。
HGLOBAL hClipboardData;
hClipboardData = GlobalAlloc(GMEM_DDESHARE,
wcslen(strData) + 1);
有2个错误,需要修复。如Memory and the Clipboard中所述,将对象放入剪贴板时,应使用带有 GMEM_MOVEABLE 标志的GlobalAlloc函数分配内存。另一方面, GMEM_DDESHARE 会被忽略,如果没有传递任何标记,则调用默认使用 GMEM_FIXED 。这将返回一个内存指针,并将其传递给GlobalLock
将随后失败。
其次,此API调用需要 bytes 中的大小。 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
。
<小时/> 参考文献:
答案 2 :(得分:1)
strcpy(pchData, LPCSTR(strData));
不是UTF16数据的好选择。
使用wcscpy
并移除演员。
答案 3 :(得分:0)
我在 C++ MFC
中尝试了 @Joseph Willcoxson 的答案,感谢提供代码,我发现第一次调用剪贴板功能有效。但是当第二次调用时它会抛出奇怪的异常而没有特定的错误消息。经过一番搜索和测试,我发现 wcscpy
会得到编译错误 C4996 : function may be unsafe. Consider using wcscpy_s instead.
我发现wcscpy_s
用法HERE,修改为使用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);
}
}