173 lines
4.4 KiB
C++
Raw Normal View History

2024-01-08 23:37:00 +08:00
2024-04-02 15:36:52 +08:00
#include "define.h"
bool tryopenclipboard(HWND hwnd = 0)
{
2024-01-08 23:37:00 +08:00
bool success = false;
2024-04-02 15:36:52 +08:00
for (int i = 0; i < 50; i++)
{
if (OpenClipboard(hwnd))
{
2024-01-08 23:37:00 +08:00
success = true;
break;
}
2024-04-02 15:36:52 +08:00
else
{
2024-01-08 23:37:00 +08:00
Sleep(10);
}
}
return success;
}
2024-07-14 15:09:37 +08:00
std::optional<std::wstring> clipboard_get_internal()
2024-04-02 15:36:52 +08:00
{
2024-07-14 15:09:37 +08:00
std::optional<std::wstring> data = {};
2024-04-02 15:36:52 +08:00
if (tryopenclipboard() == false)
2024-07-14 15:09:37 +08:00
return {};
2024-04-02 15:36:52 +08:00
do
{
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
if (hData == 0)
break;
LPWSTR pszText = static_cast<LPWSTR>(GlobalLock(hData));
if (pszText == 0)
break;
2024-09-14 10:39:56 +08:00
data = std::move(std::wstring(pszText));
2024-01-08 23:37:00 +08:00
GlobalUnlock(hData);
} while (false);
CloseClipboard();
return data;
}
2024-07-14 15:09:37 +08:00
bool clipboard_get(void (*cb)(const wchar_t *))
{
auto data = std::move(clipboard_get_internal());
if (!data)
return false;
cb(data.value().c_str());
return true;
}
2024-04-02 15:36:52 +08:00
bool clipboard_set(HWND hwnd, wchar_t *text)
{
2024-01-08 23:37:00 +08:00
bool success = false;
2024-04-02 15:36:52 +08:00
// static HWND hwnd=CreateWindowExA(0,"STATIC",0,0,0,0,0,0,0,0,0,0);
if (tryopenclipboard(hwnd) == false)
return false;
2024-01-08 23:37:00 +08:00
EmptyClipboard();
2024-04-02 15:36:52 +08:00
do
{
2024-01-08 23:37:00 +08:00
HGLOBAL hClipboardData;
size_t len = wcslen(text) + 1;
hClipboardData = GlobalAlloc(GMEM_MOVEABLE, len * sizeof(wchar_t));
2024-04-02 15:36:52 +08:00
if (hClipboardData == 0)
break;
auto pchData = (wchar_t *)GlobalLock(hClipboardData);
if (pchData == 0)
2024-10-01 22:58:41 +08:00
{
GlobalFree(hClipboardData);
2024-04-02 15:36:52 +08:00
break;
2024-10-01 22:58:41 +08:00
}
2024-04-02 15:36:52 +08:00
wcscpy_s(pchData, len, text);
GlobalUnlock(hClipboardData);
2024-10-01 22:58:41 +08:00
if (SetClipboardData(CF_UNICODETEXT, hClipboardData))
success = true;
else
{
GlobalFree(hClipboardData);
}
2024-04-02 15:36:52 +08:00
2024-01-08 23:37:00 +08:00
} while (false);
CloseClipboard();
return success;
2024-06-06 20:58:53 +08:00
}
2024-07-14 15:09:37 +08:00
static void clipboard_callback_1(void (*callback)(const wchar_t *, bool), HANDLE hsema, HWND *hwnd)
2024-06-06 20:58:53 +08:00
{
const wchar_t CLASS_NAME[] = L"LunaClipboardListener";
WNDCLASS wc = {};
wc.lpfnWndProc = [](HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (WM_CLIPBOARDUPDATE == message)
{
2024-07-14 15:09:37 +08:00
auto data = clipboard_get_internal();
2024-06-06 20:58:53 +08:00
auto callback_ = reinterpret_cast<decltype(callback)>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
if (data && callback_)
{
auto ohwnd = GetClipboardOwner();
DWORD pid;
GetWindowThreadProcessId(ohwnd, &pid);
2024-07-14 15:09:37 +08:00
callback_(data.value().c_str(), pid == GetCurrentProcessId());
2024-06-06 20:58:53 +08:00
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
};
wc.hInstance = GetModuleHandle(0);
wc.lpszClassName = CLASS_NAME;
static auto _ = RegisterClass(&wc);
HWND hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE, CLASS_NAME, CLASS_NAME, WS_OVERLAPPEDWINDOW,
0, 0, 0, 0,
NULL, NULL, GetModuleHandle(0), 0);
SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)callback);
*hwnd = hWnd;
ReleaseSemaphore(hsema, 1, 0);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
2024-07-14 15:09:37 +08:00
DECLARE HWND clipboard_callback(void (*callback)(const wchar_t *, bool))
2024-06-06 20:58:53 +08:00
{
HANDLE hsema = CreateSemaphoreW(0, 0, 10, 0);
HWND hwnd;
std::thread(std::bind(clipboard_callback_1, callback, hsema, &hwnd)).detach();
WaitForSingleObject(hsema, INFINITE);
CloseHandle(hsema);
if (AddClipboardFormatListener(hwnd))
return hwnd;
else
return NULL;
}
DECLARE void clipboard_callback_stop(HWND hwnd)
{
if (!hwnd)
return;
RemoveClipboardFormatListener(hwnd);
DestroyWindow(hwnd);
}
2024-10-01 22:58:41 +08:00
DECLARE bool clipboard_set_image(HWND hwnd, void *ptr, size_t size)
{
size -= sizeof(BITMAPFILEHEADER);
HGLOBAL hDib = GlobalAlloc(GMEM_MOVEABLE, size);
if (!hDib)
return false;
void *pDib = GlobalLock(hDib);
if (!pDib)
{
GlobalFree(hDib);
return false;
}
memcpy((char *)pDib, (char *)ptr + sizeof(BITMAPFILEHEADER), size);
if (tryopenclipboard(hwnd) == false)
return false;
EmptyClipboard();
if (!SetClipboardData(CF_DIB, hDib))
{
GlobalFree(hDib);
CloseClipboard();
return false;
}
CloseClipboard();
return true;
}