简体   繁体   中英

Copy unicode string to clipboard isn't working

I don't know why this code isn't working properly:

#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);
}

Change this section:

hClipboardData = GlobalAlloc(GMEM_DDESHARE, 2 * (wcslen(strData) + 1));

WCHAR* pchData;
pchData = (WCHAR*)GlobalLock(hClipboardData);
wcscpy(pchData, strData);
GlobalUnlock(hClipboardData);
SetClipboardData(CF_UNICODETEXT, hClipboardData);

Allocate 2* number of bytes for WCHAR . Instead of char , use WCHAR . Instead of strcpy , use wcscpy . Instead of CF_TEXT , use CF_UNICODETEXT .

You need to apply the following changes, to fix your code:

if (OpenClipboard(0)) {

You need to provide a valid window handle, to take ownership of the clipboard. Ownership is required, so that you can change the contents of the clipboard.

    HGLOBAL hClipboardData;
    hClipboardData = GlobalAlloc(GMEM_DDESHARE,
                                 wcslen(strData) + 1);

There are 2 bugs, that need to be fixed. As explained under Memory and the Clipboard , when placing an object into the clipboard, memory should be allocated by using the GlobalAlloc function with the GMEM_MOVEABLE flag. GMEM_DDESHARE , on the other hand, is ignored, and without passing any flags the call defaults to using GMEM_FIXED . This will return a memory pointer, and passing it to GlobalLock will subsequently fail.

Second, this API call requires the size in bytes . A Unicode code unit in Windows is 2 bytes. You need (wcslen(strData) + 1) * sizeof(wchar_t) .

    char* pchData;
    pchData = (char*)GlobalLock(hClipboardData);
    strcpy(pchData, LPCSTR(strData));

strcpy copies single-byte units, up to the first NUL character. With UTF-16LE encoding (as used in Windows), you are copying a single character. You should be using wcscpy instead, and cast the destination to wchar_t* :

    wchar_t* pchData;
    pchData = (wchar_t*)GlobalLock(hClipboardData);
    wcscpy(pchData, strData);

    SetClipboardData(CF_TEXT, hClipboardData);

Since you copied UTF-16LE encoded text, the clipboard format should be CF_UNICODETEXT .


References:

strcpy(pchData, LPCSTR(strData));  

isn't a good choice for UTF16 data.

Use wcscpy and remove the cast.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM