我开发了一个 C++ 应用程序,可以在屏幕上创建水印。水印在当前桌面上正确显示,但是当我使用 Windows 10 的内置虚拟桌面功能创建新的虚拟桌面时,水印仅出现在第一个虚拟桌面上,不会延续到新的虚拟桌面上。
我正在使用 Windows API 来管理水印显示并处理虚拟桌面更改。尽管我付出了努力,水印并没有出现在新创建的虚拟桌面上。
这是我的用于显示水印的代码的简化版本:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// Create a memory DC and bitmap for drawing
HDC memDC = CreateCompatibleDC(hdc);
if (!memDC) {
DebugOutput(L"Failed to create memory DC\n");
EndPaint(hWnd, &ps);
return 0;
}
HBITMAP memBitmap = CreateCompatibleBitmap(hdc, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top);
if (!memBitmap) {
DebugOutput(L"Failed to create compatible bitmap\n");
DeleteDC(memDC);
EndPaint(hWnd, &ps);
return 0;
}
HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap);
// Create Graphics object
Graphics graphics(memDC);
// Fill the background with black color
graphics.Clear(BackgroundColor); // Black background
// Draw the watermark
std::wstring watermarkText = EnsureTextLength(GetWatermarkText());
DrawWatermarks(graphics, watermarkText, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top);
// Copy the memory DC to the screen DC
BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, memDC, 0, 0, SRCCOPY);
// Cleanup
SelectObject(memDC, oldBitmap);
DeleteObject(memBitmap);
DeleteDC(memDC);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
UnregisterVirtualDesktopNotification();
PostQuitMessage(0);
break;
case WM_DISPLAYCHANGE:
RefreshWatermarkWindows(hInst); // Refresh watermark windows on display change
break;
case WM_ACTIVATEAPP:
case WM_NEXTDLGCTL:
case WM_SHOWWINDOW:
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
break;
case WM_VIRTUAL_DESKTOP_CHANGED:
RefreshWatermarkWindows(hInst); // Handle virtual desktop change
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
HWND CreateWatermarkWindow(HINSTANCE hInstance, RECT screenRect) {
HWND hWnd = CreateWindowExW(
WS_EX_LAYERED | WS_EX_NOACTIVATE | WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT, // Add WS_EX_TRANSPARENT here
szWindowClass,
szTitle,
WS_POPUP,
screenRect.left,
screenRect.top,
screenRect.right - screenRect.left,
screenRect.bottom - screenRect.top,
nullptr,
nullptr,
hInstance,
nullptr
);
// Set layered window attributes with black background and opacity
BYTE alpha = static_cast<BYTE>(OpacityLevel * 255); // Compute opacity
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), alpha, LWA_COLORKEY | LWA_ALPHA);
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
windows.push_back(hWnd);
return hWnd;
}
void RefreshWatermarkWindows(HINSTANCE hInstance) {
// Destroy all existing windows
for (HWND hWnd : windows) {
DestroyWindow(hWnd);
}
// Ensure all messages related to destruction are processed
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
windows.clear(); // Clear the windows vector
// Create watermark windows for all monitors`your text`
EnumDisplayMonitors(NULL, NULL, [](HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -> BOOL {
HINSTANCE hInstance = reinterpret_cast<HINSTANCE>(dwData);
CreateWatermarkWindow(hInstance, *lprcMonitor);
return TRUE;
}, reinterpret_cast<LPARAM>(hInstance));
}
我尝试监听
WM_VIRTUAL_DESKTOP_CHANGED
消息来检测用户何时切换或创建虚拟桌面,但水印仍然没有出现在新桌面上。
IVirtualDesktopManager::MoveWindowToDesktop()
在特定虚拟桌面上显示窗口。
您可以使用 undocumented
IVirtualDesktopManagerInternal::GetCurrentDesktop()
和 IVirtualDesktop::GetId()
来获取当前活动虚拟桌面的 ID。