I'm trying to use the GetClipboardData()
function to retrieve whatever is inside the clipboard. To test whether this worked or not I made a small function which is supposed to print the clipboard into the console window.
What I'm experiencing is that, say I copy "test", I now have "test" on the clipboard, I run the program, and the program shows "t".
I've tried a char pointer, a WCHAR pointer, direct typecast to char*
inside std::cout
, and the string
class, none of which seem to work. (They all only display the first character of the string.)
if (!OpenClipboard(NULL))
{
ExitWithError("Could not open clipboard."); //My own function, works fine, not the issue
}
HANDLE cbData = GetClipboardData(CF_UNICODETEXT);
if (!cbData)
{
ExitWithError("Could not retrieve clipboard data.");
}
CloseClipboard();
std::cout << (char*)cbData << std::endl;
As documented in the standard clipboard formats:
CF_UNICODETEXT
: Unicode text format. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data.
Unicode in Windows means UTF-16LE. Your code ((char*)cbData
) reinterprets that as ASCII or ANSI. The character t
is encoded as 0x74 0x00
in UTF-16LE. The second byte is null. That's why the std::cout
stops right after printing t
.
To fix this, use std::wcout instead:
std::wcout << reinterpret_cast<const wchar_t*>(cbData) << std::endl;
Note also, that there are a number of issues with your code:
CF_UNICODETEXT
). Call IsClipboardFormatAvailable to find out.HGLOBAL
returned from GetClipboardData
is no longer valid. Likewise, the pointer returned by GlobalLock
is only valid until calling GlobalUnlock
. If you need to persist the data, make a copy of it.A fixed version of the code might look like this:
if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
{
ExitWithError("Clipboard format not available.");
}
if (!OpenClipboard(NULL))
{
ExitWithError("Could not open clipboard."); // My own function, works fine,
// not the issue
}
HGLOBAL hglb = GetClipboardData(CF_UNICODETEXT);
if (!hglb)
{
CloseClipboard();
ExitWithError("Could not retrieve clipboard data.");
}
const wchar_t* lpStr = static_cast<const wchar_t*>(GlobalLock(hglb));
if (!lpStr)
{
CloseClipboard();
ExitWithError("Could not lock clipboard data.");
}
// Output data before closing the clipboard. Clipboard data is owned by the clipboard.
std::wcout << lpStr << std::endl;
GlobalUnlock(hglb);
CloseClipboard();
All of this is explained in exhaustive detail under using the clipboard in the MSDN.
Mandatory reading: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!).