【问题标题】:Draw on Windows 10 wallpaper in C++在 C++ 中绘制 Windows 10 壁纸
【发布时间】:2019-10-01 14:36:26
【问题描述】:

有没有办法在 C++ 中获取 Windows 壁纸(图标后面)的句柄以便在其上绘图? 这将允许制作等效的活动桌面(在 Windows XP 之后停止)、等效的 Wallpaper Engine 或任何其他类似工具。 (以我为例,对壁纸进行温度和资源使用监控)。

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

similar questions 的解决方案对我不起作用。 具体来说,我尝试了 VLC 媒体播放器的 wallpaper mode 代码。

关键代码是:

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;
 }

但它不会在壁纸上绘制。

【问题讨论】:

    标签: c++ windows winapi desktop-wallpaper


    【解决方案1】:

    感谢此 draw behind desktop icons C# 页面作为参考。本文解释了解决方案背后的理论,无论使用何种编程语言,该理论都适用。

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

    在上述文章中,您可以看到每一步的解释以及 C# 实现。在这里,我将编写一个 C++ 等效项,从源代码中保留 cmets。

    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;
        }
    

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


    一篇文章中未提及的注释: 由于在更换墙纸时会生成一个新的 WorkerW 窗口以实现淡入淡出效果,如果用户在您的程序正在积极绘制并刷新您的 WorkerW 实例时尝试更换墙纸,则用户设置的背景将放置在您的绘图之上,开始淡入直到达到 100% 的不透明度,最后被销毁,让您的 WorkerW 仍在运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-13
      • 1970-01-01
      • 1970-01-01
      • 2020-12-25
      • 1970-01-01
      • 2011-07-10
      相关资源
      最近更新 更多