#include #include #include namespace clip { using format = UINT; inline CRITICAL_SECTION& GetClipLock() { static CRITICAL_SECTION cs; static std::once_flag flag; std::call_once(flag, [] { InitializeCriticalSection(&cs); }); return cs; } inline format text_format() { return CF_TEXT; } inline bool has(format f) { return IsClipboardFormatAvailable(f) != FALSE; } inline bool set_text(const std::string& value) { EnterCriticalSection(&GetClipLock()); bool result = false; if (OpenClipboard(NULL)) { EmptyClipboard(); HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, value.size() + 1); if (hMem) { char* p = (char*)GlobalLock(hMem); if (p) { memcpy(p, value.c_str(), value.size() + 1); GlobalUnlock(hMem); SetClipboardData(CF_TEXT, hMem); result = true; } else { GlobalFree(hMem); } } CloseClipboard(); } LeaveCriticalSection(&GetClipLock()); return result; } inline bool get_text(std::string& value) { EnterCriticalSection(&GetClipLock()); bool result = false; if (OpenClipboard(NULL)) { // 优先尝试 Unicode HANDLE h = GetClipboardData(CF_UNICODETEXT); if (h) { const wchar_t* pw = (const wchar_t*)GlobalLock(h); if (pw) { int len = WideCharToMultiByte(CP_UTF8, 0, pw, -1, NULL, 0, NULL, NULL); if (len > 0) { value.resize(len - 1); WideCharToMultiByte(CP_UTF8, 0, pw, -1, &value[0], len, NULL, NULL); } GlobalUnlock(h); result = true; } } else { // 回退 ANSI h = GetClipboardData(CF_TEXT); if (h) { const char* p = (const char*)GlobalLock(h); if (p) { SIZE_T size = GlobalSize(h); value.assign(p, strnlen(p, size)); GlobalUnlock(h); result = true; } } } CloseClipboard(); } LeaveCriticalSection(&GetClipLock()); return result; } /** * 将 UTF-8 字符串安全地设置到 Windows 剪切板 */ inline bool set_text_utf8(const std::string& utf8_str) { if (utf8_str.empty()) return false; // 1. 将 UTF-8 转换为 UTF-16 (因为 Windows 剪切板原生支持 UTF-16) int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8_str.c_str(), -1, NULL, 0); if (wlen <= 0) return false; // 2. 分配全局内存 HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, wlen * sizeof(wchar_t)); if (!hMem) return false; // 3. 执行转换并锁定内存 wchar_t* pMem = (wchar_t*)GlobalLock(hMem); MultiByteToWideChar(CP_UTF8, 0, utf8_str.c_str(), -1, pMem, wlen); GlobalUnlock(hMem); // 4. 操作剪切板 bool success = false; if (OpenClipboard(NULL)) { EmptyClipboard(); if (SetClipboardData(CF_UNICODETEXT, hMem)) { success = true; } CloseClipboard(); } // 如果 SetClipboardData 失败,需要手动释放内存;成功则由系统接管 if (!success) { GlobalFree(hMem); } return success; } } // namespace clip