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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GetClipboardData()仅返回剪贴板数据的第一个字符相关的知识,希望对你有一定的参考价值。

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

我正在经历的是,我说复制“测试”,我现在在剪贴板上“测试”,我运行程序,程序显示“t”。

我已经尝试了一个字符指针,一个WCHAR指针,直接对char*中的std::cout进行类型转换,以及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;
答案

standard clipboard formats中所述:

CF_UNICODETEXT:Unicode文本格式。每条线以回车/换行(CR-LF)组合结束。空字符表示数据的结尾。

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的返回值传递给GlobalLock以接收指针。根据内存类型(GMEM_MOVEABLE与GMEM_FIXED),句柄不一定与指向内存的指针相同。
  • 剪贴板数据归剪贴板所有。剪贴板关闭后,从HGLOBAL返回的GetClipboardData不再有效。同样,GlobalLock返回的指针仅在调用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!)

以上是关于GetClipboardData()仅返回剪贴板数据的第一个字符的主要内容,如果未能解决你的问题,请参考以下文章

python操作剪贴板错误提示:pywintypes.error: (1418, 'GetClipboardData',线程没有打开的剪贴板)

小程序点击复制如何实现

使用 python/win32 从/到剪贴板复制和粘贴

剪切板操作

从剪贴板获取数据并重新设置 - WINAPI,C [重复]

电脑出现cannot open clipboard的错误,该如何解决