如何在Windows应用程序中跨所有虚拟桌面显示应用程序?

问题描述 投票:0回答:1

我开发了一个 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
消息来检测用户何时切换或创建虚拟桌面,但水印仍然没有出现在新桌面上。

c++ winapi windows-virtual-desktop
1个回答
0
投票

您需要使用

IVirtualDesktopManager::MoveWindowToDesktop()
在特定虚拟桌面上显示窗口。

您可以使用 undocumented

IVirtualDesktopManagerInternal::GetCurrentDesktop()
IVirtualDesktop::GetId()
来获取当前活动虚拟桌面的 ID。

请注意,虚拟桌面是一种最终用户窗口管理功能,而不是编程功能

© www.soinside.com 2019 - 2024. All rights reserved.