Windows剪贴板纯文本读写必须使用Win32 API,首选CF_UNICODETEXT格式;需严格配对OpenClipboard/CloseClipboard、GlobalLock/GlobalUnlock,且全程在同一线程执行。

用 OpenClipboard + GetClipboardData 读取纯文本
Windows 剪贴板文本读取必须走 Win32 API,不能直接访问内存。核心流程是打开剪贴板、请求 CF_TEXT 或更推荐的 CF_UNICODETEXT 格式数据、再用 GlobalLock 取出内容。
常见错误是没检查 IsClipboardFormatAvailable 就直接调 GetClipboardData,结果返回 NULL;或者忘了 GlobalUnlock 和 CloseClipboard,导致后续操作失败(比如其他程序无法写入)。
-
CF_UNICODETEXT是首选:支持中文、emoji、全角符号,CF_TEXT只能处理 ANSI 编码(基本废了) - 返回的
HGLOBAL指针需用GlobalLock转成LPCWSTR,且不能直接当 C++ 字符串用——它不带长度信息,得用wcslen或按 null 终止判断 - 必须在同一线程中完成
OpenClipboard→ 读取 →CloseClipboard全流程,跨线程调用会失败
if (OpenClipboard(NULL)) {
if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
if (hData) {
LPCWSTR lpcwstr = static_cast(GlobalLock(hData));
if (lpcwstr) {
std::wstring text(lpcwstr); // 自动截断到第一个 \0
GlobalUnlock(hData);
}
}
}
CloseClipboard();
} 用 SetClipboardData 写入 Unicode 文本
写入比读取更易出错:必须先 OpenClipboard,再 GlobalAlloc 分配可移动内存(GMEM_MOVEABLE),GlobalLock 后 memcpy 内容,GlobalUnlock,最后 SetClipboardData。漏掉任意一步都会导致写入失败或剪贴板卡死。
关键点在于分配的内存大小:要包含末尾的 \0,且单位是字节(wchar_t 是 2 字节),所以长度是 (text.length() + 1) * sizeof(wchar_t)。
立即学习“C++免费学习笔记(深入)”;
- 不要用
GMEM_FIXED:系统要求剪贴板数据必须是可移动(GMEM_MOVEABLE)内存块 -
SetClipboardData接管内存所有权,你不能再GlobalFree它,否则系统崩溃 - 如果写入后立刻被其他程序清空,大概率是没调
CloseClipboard,或调用前已有程序占着剪贴板没释放
std::wstring text = L"你好,clipboard!";
if (OpenClipboard(NULL)) {
EmptyClipboard();
size_t size = (text.length() + 1) * sizeof(wchar_t);
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, size);
if (hMem) {
LPWSTR lpMem = static_cast(GlobalLock(hMem));
if (lpMem) {
memcpy(lpMem, text.c_str(), size);
GlobalUnlock(hMem);
SetClipboardData(CF_UNICODETEXT, hMem); // 系统接管 hMem
}
}
CloseClipboard();
}
为什么 CF_OEMTEXT 和 CF_LOCALE 基本不用
CF_OEMTEXT 对应 DOS 时代 OEM 字符集(如 GBK 的变体),现在 Windows 默认用 Unicode,该格式只在极老终端程序里出现;CF_LOCALE 是辅助信息,存区域设置 ID,单独存在无意义,且现代应用完全不依赖它做编码推断。
真正需要多格式支持时(比如粘贴进 Word 要保留粗体),得用 CF_HTML 或 CF_RTF,但它们结构复杂,需手动构造 MIME 头或 RTF 控制字——对纯文本场景属于过度设计。
- 只要目标是“人眼可读的字符串”,坚持用
CF_UNICODETEXT就够了 - 试图兼容
CF_TEXT反而引入乱码风险:系统不会自动转码,只会原样返回 ANSI 字节流 - 某些远程桌面或沙盒环境会禁用非 Unicode 格式,
CF_UNICODETEXT是唯一稳定选项
常见报错:OpenClipboard 返回 false 或 GetClipboardData 返回 NULL
这不是代码写错了,而是系统级阻塞。最常见三种情况:剪贴板正被另一进程独占(如微信、钉钉后台监听)、当前线程没消息循环(GUI 程序必须有 GetMessage 循环)、或调用发生在 DLL 的 DllMain / 静态构造函数中(Windows 明确禁止)。
- 调试时可在调用前加
printf("open: %d\n", OpenClipboard(NULL));快速确认是否被占用 - 控制台程序也能用剪贴板,但必须确保不是以“管理员权限”运行的 GUI 程序正在拖拽——UAC 隔离会导致跨权限访问失败
- 没有异常处理机制,所有 API 调用后都应检查返回值,尤其
OpenClipboard和GetClipboardData
真正麻烦的不是 API 调用本身,而是状态管理:开没开、锁没锁、关没关、内存谁释放——每一步都得严格配对。稍有遗漏,剪贴板就进入不可用状态,连 Ctrl+V 都失灵。











