Windows平台调用GetClipboardData获取纯文本必须先OpenClipboard获取所有权,否则直接调用会因ERROR_ACCESS_DENIED失败;正确流程为OpenClipboard→IsClipboardFormatAvailable→GetClipboardData→GlobalLock→复制→GlobalUnlock→CloseClipboard,且应优先使用CF_UNICODETEXT避免中文乱码。

Windows平台用GetClipboardData获取纯文本必须先打开剪贴板
直接调用GetClipboardData(CF_TEXT)会失败,因为Windows要求线程必须先拥有剪贴板所有权。典型错误是返回NULL且GetLastError()为ERROR_ACCESS_DENIED。
正确流程是:调用OpenClipboard(NULL) → 检查是否成功 → 调用GetClipboardData(CF_TEXT) → 用GlobalLock拿到指针 → 复制内容 → GlobalUnlock → CloseClipboard。
-
OpenClipboard传NULL表示当前线程获取所有权;若失败,其他程序可能正占用剪贴板(比如正在粘贴中) -
CF_TEXT只支持ANSI编码,中文会乱码;要UTF-8或Unicode,必须用CF_UNICODETEXT并处理wchar_t* - 拿到的内存块以
\0结尾,但长度不包含这个终止符,GlobalSize返回的是字节数(对CF_UNICODETEXT是字节数,不是字符数)
用CF_UNICODETEXT读取中文需转换wchar_t*到std::string
Windows剪贴板默认用UTF-16存储文本,CF_UNICODETEXT比CF_TEXT更可靠,尤其含中文、emoji时。
关键点在于:不能直接把wchar_t*当char*用;转UTF-8推荐用WideCharToMultiByte(CP_UTF8, ...),避免依赖locale或std::wstring_convert(C++17已弃用)。
- 调用
GetClipboardData(CF_UNICODETEXT)后,用static_cast取地址(GlobalLock(hMem)) -
WideCharToMultiByte第一个参数必须是CP_UTF8,缓冲区大小要传0先获取所需字节数,再分配内存 - 如果目标是
std::string,记得末尾加\0;若只是临时使用,可直接构造std::string_view避免拷贝
Linux下用X11的XConvertSelection需要事件循环配合
Linux没有全局“剪贴板句柄”概念,X11协议要求异步响应:你发请求→等待SelectionNotify事件→再取数据。直接阻塞等待会导致程序卡死。
常见错误是调用XConvertSelection后立刻XGetWindowProperty,此时数据还没就绪,返回空或BadValue错误。
- 必须监听
SelectionNotify事件,通常放在主消息循环里用XNextEvent捕获 - 目标选择器用
XA_STRING(纯文本)或utf8_string(UTF-8),后者需先用XInternAtom获取atom - 注意
XGetWindowProperty返回的bytes_after为0才表示读完;否则需分片读取(少见但可能)
macOS用NSPasteboard需在主线程调用且链接AppKit
macOS不允许后台线程访问剪贴板,[NSPasteboard generalPasteboard]在非主线程调用会静默失败或崩溃。
即使代码编译通过,运行时若不在主线程,stringForType:返回nil,且无明确错误提示。
- 必须确保调用栈在主线程(可用
dispatch_get_main_queue()或[NSThread isMainThread]检查) - 链接时加
-framework AppKit,头文件用#import,不能只靠objc运行时 -
NSString*默认是UTF-16,转std::string用[str UTF8String]最安全;若为空,说明剪贴板无NSStringPboardType类型数据
跨平台统一处理最难的不是API差异,而是线程模型和编码假设——Windows默认宽字符、Linux默认locale编码、macOS强制UTF-16字符串对象,连“纯文本”定义都不一致。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











