GetClipboardData() 只返回剪贴板数据的第一个字符

GetClipboardData() returning first character of clipboard data only

我正在尝试使用 GetClipboardData() 函数来检索剪贴板中的任何内容。为了测试这是否有效,我做了一个小函数,它应该将剪贴板打印到控制台 window.

我遇到的是,假设我复制 "test",我现在剪贴板上有 "test",我 运行 程序,程序显示 "t".

我尝试了一个 char 指针,一个 WCHAR 指针,直接类型转换为 std::cout 中的 char*,以及 string class、none其中似乎工作。 (它们都只显示字符串的第一个字符。)

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;

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.

Windows 中的 Unicode 表示 UTF-16LE。您的代码 ((char*)cbData) 将其重新解释为 ASCII 或 ANSI。字符 t 在 UTF-16LE 中编码为 0x74 0x00。第二个字节为空。这就是 std::cout 在打印 t.

后立即停止的原因

要解决此问题,请改用 std::wcout

std::wcout << reinterpret_cast<const wchar_t*>(cbData) << std::endl;

另请注意,您的代码存在许多问题:

  • 您没有检查剪贴板是否以预期格式保存数据 (CF_UNICODETEXT)。致电IsClipboardFormatAvailable一探究竟。
  • GetClipBoardData needs to be passed to GlobalLock的return值接收一个指针。根据内存的类型(GMEM_MOVEABLE vs. GMEM_FIXED),句柄不一定与指向内存的指针相同。
  • 剪贴板数据归剪贴板所有。剪贴板关闭后,从 GetClipboardData 编辑的 HGLOBAL return 将不再有效。同样,由 GlobalLock 编辑的指针 return 仅在调用 GlobalUnlock 之前有效。如果需要保留数据,请复制一份。

代码的固定版本可能如下所示:

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();

所有这些都在 MSDN 的 using the clipboard 下进行了详尽的解释。


必读:The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!).