使用 C++ 在 Windows 10 壁纸上绘图

Bar*_*ack 7 c++ windows winapi desktop-wallpaper

有没有办法在 C++ 中处理 Windows 的墙纸(图标后面)以便在它上面绘图?这将允许制作等效的活动桌面(在 Windows XP 之后停止使用)、等效的墙纸引擎或任何其他类似工具。(在我的情况下,墙纸上的温度和资源使用情况监控)。

注意:返回的句柄返回GetDesktopWindow()桌面图标级别的窗口,而不是在它后面。

类似问题的解决方案对我不起作用。具体来说,我尝试了 VLC 媒体播放器的墙纸模式代码。

关键代码是:

hwnd = FindWindow( _T("Progman"), NULL );
 if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SHELLDLL_DefView"), NULL );
 if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SysListView32"), NULL );
 if( !hwnd )
 {
     msg_Warn( p_vout, "couldn't find \"SysListView32\" window, "
               "wallpaper mode not supported" );
     return;
 }
Run Code Online (Sandbox Code Playgroud)

但它不会在壁纸上绘制。

Bar*_*ack 8

归功于此在桌面图标 C#页面后面绘制作为参考。文章解释了解决方案背后的理论,无论使用哪种编程语言,它都适用。

长话短说,您在更改壁纸时在 Windows 10 上看到的平滑淡入淡出动画是通过创建一个新窗口来实现的,该窗口完全符合您的要求,并在图标下绘制。该窗口实现了新墙纸的淡入效果,由程序管理器创建。

在提到的文章中,您可以与 C# 实现一起看到每一步的解释。在这里,我将编写一个 C++ 等效项,保留来自源代码的注释。

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
    {
    HWND p = FindWindowEx(hwnd, NULL, L"SHELLDLL_DefView", NULL);
    HWND* ret = (HWND*)lParam;

    if (p)
        {
        // Gets the WorkerW Window after the current one.
        *ret = FindWindowEx(NULL, hwnd, L"WorkerW", NULL);
        }
    return true;
    }

HWND get_wallpaper_window()
    {
    // Fetch the Progman window
    HWND progman = FindWindow(L"ProgMan", NULL);
    // Send 0x052C to Progman. This message directs Progman to spawn a 
    // WorkerW behind the desktop icons. If it is already there, nothing 
    // happens.
    SendMessageTimeout(progman, 0x052C, 0, 0, SMTO_NORMAL, 1000, nullptr);
    // We enumerate all Windows, until we find one, that has the SHELLDLL_DefView 
    // as a child. 
    // If we found that window, we take its next sibling and assign it to workerw.
    HWND wallpaper_hwnd = nullptr;
    EnumWindows(EnumWindowsProc, (LPARAM)&wallpaper_hwnd);
    // Return the handle you're looking for.
    return wallpaper_hwnd;
    }
Run Code Online (Sandbox Code Playgroud)

reinterpret_cast根据您的编码偏好,可以用s替换类似 C 的强制转换。


文章中没有提到的一个注意事项:由于在更改壁纸时会生成一个新的 WorkerW 窗口以实现淡入淡出效果,如果用户在您的程序正在主动绘制和刷新您的 WorkerW 实例时尝试更改壁纸,则用户设置背景将放置在您的绘图之上,开始淡入直到达到 100% 不透明度,最后被销毁,让您的 WorkerW 仍在运行。