【问题标题】:Drawing on the desktop background as wallpaper replacement (Windows/C#)在桌面背景上绘制作为壁纸替换 (Windows/C#)
【发布时间】:2010-12-13 14:49:02
【问题描述】:

我正在尝试制作一个需要在桌面上绘制的应用程序,位于图标后面,以便它看起来取代桌面墙纸。我找到了一些解决方案,但大多数都没有很好地工作(很多闪烁)。一种解决方案seems to be what I'm looking for,但我真的不明白。我主要使用更高级别的图形库或仅使用 Windows 窗体和一些 C++,但仅在非 Windows 平台上完成了 C# 应用程序。

如果有人可以为我“翻译”它或为我提供替代解决方案,将不胜感激!

【问题讨论】:

    标签: c# windows desktop wallpaper


    【解决方案1】:

    我从未找到我想要的解决方案,但这里有最好的(唯一的?)替代方案:

    • 绘制到“SysListView32”窗口(ProgMan -> SHELLDLL_DefView -> SysListView32)。这将在桌面图标后面绘制,但在使用动画时会闪烁。如何:Link(您必须在 .NET 中使用互操作)。

    • 使用 DirectDraw 覆盖。您将桌面颜色设置为某种晦涩的颜色,具有该颜色的所有内容都将替换为叠加层上的内容。这在我的问题和 VLC 壁纸模式中的示例中使用。但是,这与 Aero 不兼容。如何:Link(我猜你可以在 .NET 中使用托管 DirectX?)。

    【讨论】:

    • 遗憾的是,据我所知不是。我有点放弃了我想做的事情,似乎这不太可能。
    • 这已经很晚了,但我可以用这个link 做到这一点。
    • @Clark 在我看来,您可以将其发布为答案。这是这个问题的答案,并且可以更容易地找到最终进入此页面的人。 OP也应该将其设置为正确答案。
    【解决方案2】:

    我知道这是一个很晚的答案,但我最近自己研究了一下,如果其他用户有同样的问题,这可能会对他们有所帮助。

    注意:此答案适用于 C++,但也许它可以帮助您在 C# 中做同样的事情

    正如上面评论中提到的,我跟随This guide了解我将如何打开 windows 壁纸窗口。

    通过使用这两种方法:

    BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
        HWND p = FindWindowEx(hwnd, NULL, "SHELLDLL_DefView", NULL);
        HWND* ret = (HWND*)lParam;
    
        if (p)
            {
            // Gets the WorkerW Window after the current one.
            *ret = FindWindowEx(NULL, hwnd, "WorkerW", NULL);
            }
        return true;
    }
    
    HWND get_wallpaper_window() {
            // Fetch the Progman window
            HWND progman = FindWindow("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;
    }
    

    我能够检索到 Windows 句柄。

    由于我只熟悉 SDL,这是我找到的唯一解决方案,但我相信任何允许您基于另一个窗口创建/修改窗口的方法都应该有效。

    window = SDL_CreateWindowFrom((void*)get_wallpaper_window());
    

    上面的行允许我从get_wallpaper_window() 方法检索到的 HWND 在 SDL 中创建一个窗口。

    由于涉及大量代码,我将链接my solution on github。这可以在您的桌面图标后面画出很多星星(尽管我相信它可以改进)。

    【讨论】:

      【解决方案3】:

      您可以在 VLC 媒体播放器代码中找到灵感。有一个 wallpaper mode 可以满足您的需求。

      【讨论】:

        【解决方案4】:

        顺便看到了这个问题,我确实部分解决了这个问题(但我不能提供任何有用的代码)来制作一些很酷的游戏,尽管可能没有你想要的应用程序:

        • 将桌面背景恢复正常并截取桌面截图
        • 将桌面背景设为黑色并截取桌面
        • 设置桌面背景为白色并截取桌面截图
        • 结合黑白版本制作蒙版和第一个屏幕截图作为覆盖设置不同透明的像素值。

        现在在您的表单上按顺序绘制以下内容:

        1. 绘制第一张截图
        2. 绘制表单内容
        3. 绘制您创建的桌面叠加层

        这是我为全屏表单所做的,但我认为可以很容易地适应非全屏表单。从本质上讲,您已经重新创建了桌面,但能够用它做任何事情,包括一些很酷的游戏。任何应用程序的绘制速度和性能都令人满意,但桌面交互性是一个问题...... :( 这是使用该原理的坦克游戏图片,除了我将背景设置为白色并使所有白色背景也透明!

        My Tanks Game

        【讨论】:

          【解决方案5】:

          是的,使用互操作,请参阅this 线程。

          【讨论】:

          • 这将在一切之上;我希望在所有内容(桌面壁纸除外)背后画图。
          猜你喜欢
          • 1970-01-01
          • 2019-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多