// ClipboardTest.cpp // #ifndef UNICODE #define UNICODE #endif #include #include LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); int main() { std::cout << "Process ID = " << GetCurrentProcessId() << std::endl; WNDCLASS wc = {}; wc.lpfnWndProc = WindowProc; wc.hInstance = GetModuleHandle(NULL); wc.lpszClassName = TEXT("ClipboardTestClass"); if (!RegisterClass(&wc)) { std::cerr << "Could not register window class." << std::endl; return 1; } HWND hwnd = CreateWindowEx(0, TEXT("ClipboardTestClass"), TEXT("Clipboard Test Window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL); if (hwnd == NULL) { std::cerr << "Could not create window." << std::endl; return 1; } ShowWindow(hwnd, SW_HIDE); MSG msg = {}; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: std::cout << "hwnd = " << hwnd << std::endl; if (!AddClipboardFormatListener(hwnd)) { std::cerr << "Could not AddClipboardFormatListener." << std::endl; return -1; } std::cout << "Listening to clipboard..." << std::endl; return 0; case WM_DESTROY: RemoveClipboardFormatListener(hwnd); return 0; case WM_CLIPBOARDUPDATE: { std::cout << "Clipboard update detected." << std::endl; while (!OpenClipboard(hwnd)) { DWORD lastError = GetLastError(); std::cout << "Could not OpenClipboard, error " << lastError << " GetOpenClipboardWindow = " << GetOpenClipboardWindow() << " Will retry." << std::endl; Sleep(100); // Not production code: retry forever. } std::cout << "GetClipboardSequenceNumber = " << GetClipboardSequenceNumber() << std::endl; UINT format = 0; while (format = EnumClipboardFormats(format)) { std::cout << "Clipboard format = " << format << std::endl; } DWORD lastErrorEnum = GetLastError(); if (lastErrorEnum != ERROR_SUCCESS) { std::cout << "Could not EnumClipboardFormats, error " << lastErrorEnum << std::endl; } std::cout << "Done listing formats." << std::endl; // This holds the clipboard open and is more than long enough to provoke the problem in LibreOffice. // Actually, the problem often happens for me even when this sleep is omitted. Sleep(500); CloseClipboard(); return 0; } } return DefWindowProc(hwnd, uMsg, wParam, lParam); }