I’m currently developing an application in C++ using Windows API.
My goal is to have the app have its own clipboard – users of the app should not be able to copy (CTRL+C/CTRL+X / Right Click -> Copy/Cut) content and paste it outside of the application.
My first approach was to call AddClipboardFormatListener on the main window. However, the window received copy/paste from outside of the app (e.g. when user did CTRL+C in a different app).
Eventually, I worked it out by subclassing every control in the app and handling WM_COPY, WM_PASTE and WM_CLIPBOARDUPDATE events like this:
char clipboard_data[1024];
LRESULT (*g_OldWndProc)(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK NewWndProc( HWND hwnd, UINT mesg, WPARAM wParam, LPARAM lParam )
{
switch( mesg )
{
case WM_COPY:
AddClipboardFormatListener(hwnd);
break;
case WM_CLIPBOARDUPDATE:
if(IsClipboardFormatAvailable(CF_TEXT) ||
IsClipboardFormatAvailable(CF_UNICODETEXT))
{
if (!OpenClipboard(nullptr)) break;
HGLOBAL hglb = GetClipboardData(CF_TEXT);
if (hglb != nullptr)
{
char* lptstr = (char*) GlobalLock(hglb);
if (lptstr != nullptr)
{
strcpy(clipboard_data, lptstr);
}
GlobalUnlock(hglb);
}
EmptyClipboard();
CloseClipboard();
RemoveClipboardFormatListener(hwnd);
}
break;
case WM_PASTE:
{
int nStrLen = strlen(clipboard_data);
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, nStrLen + 1);
char* pCopyTo = (char*) GlobalLock(hMem);
memcpy(pCopyTo, clipboard_data, nStrLen + 1);
GlobalUnlock(hMem);
if(!OpenClipboard(hwnd)) break;
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();
auto status = CallWindowProc(g_OldWndProc, hwnd, mesg, wParam, lParam);
if(!OpenClipboard(nullptr)) break;
EmptyClipboard();
CloseClipboard();
if(hMem) GlobalFree(hMem);
return status;
}
}
return CallWindowProc(g_OldWndProc, hwnd, mesg, wParam, lParam);
}
I subclassed the controls like this:
g_OldWndProc = (decltype(g_OldWndProc)) SetWindowLongPtr( hSomeControl, GWLP_WNDPROC,( LONG_PTR ) NewWndProc );
(Note: I am yet to write a code that preserves what was in clipboard before copying)
That way, I am able to handle copy/paste action on UI controls I made.
However, it’s a bit tedious to subclass every UI component like this.
Is there a way to do it generically?
2