【问题标题】:How can I detect wallpaper changing as a result of the Windows 7 slideshow?如何检测由于 Windows 7 幻灯片放映而导致的墙纸变化?
【发布时间】:2011-07-29 02:42:51
【问题描述】:

我正在编写一个程序,它需要知道桌面墙纸何时发生变化。经过一番搜索,我找到了部分解决方案: http://www.neowin.net/forum/topic/567779-net-detect-wallpaper-change/

基本上,它表示要收听WM_SETTINGCHANGE message,并检查壁纸。不幸的是,当由于 Windows 7 壁纸幻灯片放映而更改壁纸时,似乎不会发送此消息。事实上,似乎根本没有向我的应用程序发送任何消息(这是我见过的唯一一次WndProc不断收到消息:))。

所以我的问题是,没有轮询注册表和壁纸文件以进行更改,有没有办法检测何时发生这种情况?有谁知道我在哪里可以找到列出调用什么函数的 API 文档?

【问题讨论】:

标签: .net wpf winapi windows-7 wallpaper


【解决方案1】:

这是一个很好的问题,我暂时没有回答它,看看是否有人知道我不知道的事情。

但不幸的是,我想您会发现无法接收与此事件对应的通知消息。墙纸幻灯片实际上不会更改系统主题或任何系统设置,因此不会发送WM_SETTINGCHANGE 消息。它被设计为在后台发生,不需要通知任何应用程序。如果用户选择了“幻灯片”选项,则可以合理地假设他们期望定期更改背景,无需交互或通知。简而言之,在至少 99% 的情况下,您的应用程序不应因幻灯片选项引起的壁纸更改而做出任何不同的响应。

我能想到的最好的办法是确定他们指定的更换壁纸的时间间隔,然后让您的应用程序在该时间过去后做出相应的响应。本质上,您必须创建并响应您自己的通知。

强烈建议不鼓励对注册表进行轮询。这不仅完全没有记录,因此可能会在未来的 Windows 版本(甚至 Windows 更新!)上被破坏,而且它也不是一个可靠的指标。如果有任何替代方案(包括完全省略该功能),这就是我将采取的路径。

【讨论】:

    【解决方案2】:

    实际上,我找到了解决此问题的方法。实际上有一个注册表通知机制,因此可以在指定的键/值更改时引发事件。 HKEY_CURRENT_USER\Control Panel\Desktop\Wallpaper 是关键。当幻灯片更改墙纸时,这不会更改,但该位置的文件确实会更改。通过监视文件的更改,您实际上可以收到有关此更改的通知。

    顺便说一句,我正在编写的应用程序的全部意义都依赖于此,因此省略它不是一个选择:)。

    不过,感谢您的回复 - 让我的良心得以安息,因为我不得不经历如此迂回的做事方式。

    【讨论】:

    • 啊,你是说RegNotifyChangeKeyValue function?是的,这绝对是比轮询自己更优雅的选择。请注意这样的实现细节;如果未来版本的 Windows 更改位置,您的应用可能会中断。
    • FileSystemWatcher 类在这里很有用。
    • 我已经成功地使用了这里描述的技术,但请记住,如果您在technet.microsoft.com/en-us/sysinternals/cc817881 上运行像 Desktops 2.0 这样的应用程序,它将为每个桌面生成一个资源管理器外壳。每个资源管理器实例可以以不同的速率和不同的幻灯片循环播放,因此文件可能与您在当前查看的桌面上看到的内容不同步。该文件由所有资源管理器实例更新。不幸的是,我还没有找到解决方案,但需要注意。
    • 我刚刚了解到多个监视器的行为与我上面描述的多个资源管理器实例的行为相同。我无法弄清楚最新背景显示在哪个显示器上。有什么想法吗?
    【解决方案3】:

    我有个更好的主意,不久前我编写了一个小程序,它可以自动更改我在 LogonScreen 上的背景,并希望通过自动检测背景上的墙纸并在 Windows 更改我的背景时设置相同的能力来改进这一点。于是,我开始调查,发现:

    1. %USERDIR%\AppData\Roaming\Microsoft\Windows\Themes - 存放来自 bg 和 slideshow.ini 的当前转码图像的位置,其中包含有关当前主题的少量信息
    2. %USERDIR%\AppData\Local\Microsoft\Windows\Themes - 包含此系统上安装的主题的文件夹

    所以,算法如下:

    1. 读取 slideshow.ini 并在 [Slideshow] 下获取值
    2. 读取所有主题文件并比较每个主题的 [Slideshow] 值,如果相等 - 我们找到了当前主题文件
    3. 从当前主题的文件中读取 Interval=1800000 的值(在我的例子中是 30 分钟)(顺便说一句,间隔放置在 [Slideshow] 之后,因此可以在同一行迭代中完成)
    4. 从 bg 上的当前图像读取修改时间:%USERDIR%\AppData\Roaming\Microsoft\Windows\Themes\TranscodedWallpaper.jpg
    5. 所以,我们有下一次更改的时间(current_time - modify_time + Interval),并且可以在墙纸更改时执行任何代码(如果设置更改或更改被禁用,也不要忘记捕获情况 - 因为它可能导致异常,作为改进我们可以每分钟或类似的方式重新检查此文件)
    6. 如果您尝试编写相同的程序,请不要忘记压缩图像大小,因为它需要最大 256Kb。

    【讨论】:

      猜你喜欢
      • 2012-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-29
      • 1970-01-01
      • 1970-01-01
      • 2014-07-14
      相关资源
      最近更新 更多