Open NyaMisty opened 6 years ago
The Slideshow setting is stored in /AppData/Roaming/Microsoft/Windows/Themes/slideshow.ini
https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/cb564e1a-778b-47a9-a0de-0a815159e46a/windows-7-theme-modification?forum=windowsgeneraldevelopmentissues
But its inner struct is not published. Some reverse engineering is needed.
Slideshow setting storing is implemented in themeui.dll
and shell32.dll
, but the themeui.dll is never used. shell32.dll
has exactly same implementation.
The slide show is for all desktops so I fell like there would be a struggle trying to allow this for different desktops. I'm open for a better implementation so I will take a look down this path. Thank you so much for digging into this for me. None of my friends are developers and I don't even do development in my day job. Well I do, but it's not my job to do so. So even my coworkers are not developers. This leaves me with nobody to bounce ideas off of so it's nice to have someone like you come in and examine the code and provide tips.
Well why don't you say that wallpaper is for all desktops. We can save the tick when switching the desktop, and restore them when switched back, just like the current implementation ;)
Well I thought you are a professional programmer, as your tool is the only one that is easy-to-use and with up-to-date support catching every windows update. And you said you don't work to programming, which is really impressing. I guess actually there are bunch of skilled programmers using this tool ;) Finally I'm very pleased to come here for communication. Helping with the development of one of my ideal tool is quite happy. PS: digging into this is for me, too (I can't stand the wallpaper switching without animation)
Well we needn't to reverse engineering it.... IDesktopWallpaper Microsoft has a public interface already :(
The SetSlideshow method has only one method, which is IShellItemArray *items You can create an instance of it through
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr ILCreateFromPath([In, MarshalAs(UnmanagedType.LPWStr)] string pszPath);
And calling it
var pIdl = ILCreateFromPath("D:\\Pics");
Other methods are quite easy to follow.
Thanks for this. Let me test how it works. Looks pretty easy.
Yeah that's quite disappointing after 8 hours work :(
I can offer you a free license for your work. Just send me an email to zVirtualDesktop@gmail.com and I'll set you up.
Well in fact I'm still in trial period, and your tool did a pretty good job. I've decided to buy it to support you, and I'll make the purchase when I got some spare money~ Thanks for your kindly and also surprise offer ;)
It means a lot to me to hear this. You are a great person and I wish good things for you and your family.
Oh I missed a critical step
We'll need to convert the result from ILCreateFromPath
, which is LPITEMIDLIST
, to the needed IShellItemArray *
, which is achieved using SHCreateShellItemArrayFromIDLists
.
The following is working code to change the slideshow directory.
HRESULT hr = CoInitialize(nullptr);
LPCITEMIDLIST ret = ILCreateFromPath(_T("D:\\Pics"));
IDesktopWallpaper *pDesktopWallpaper = nullptr;
IShellItemArray *pitemArr = nullptr;
SHCreateShellItemArrayFromIDLists(1, &ret, &pitemArr);
hr = CoCreateInstance(__uuidof(DesktopWallpaper), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pDesktopWallpaper));
hr = pDesktopWallpaper->SetSlideshow(pitemArr);
return 0;
And that's exactly the implementation of SystemSettings app Also don't forget to enable the wallpaper before doing anything ;)
I found a c# implementation
https://github.com/xupefei/Bing-Wallpaper/blob/master/BingWallpaper/DesktopWallpaper.cs
Yeah that's the wrapper of the interface, and you still need to use steps above to build the parameter IntPtr items
This should do it. Found in this repository. https://github.com/dahall/Vanara/blob/master/Windows.Shell/ShellItemArray.cs
// [DllImport(Lib.Shell32, CharSet = CharSet.Unicode, ExactSpelling = true)] [SecurityCritical, SuppressUnmanagedCodeSecurity]
// [PInvokeData("Shlobj.h", MSDNShortId = "bb762141")] public static extern HRESULT SHCreateShellFolderView([In] ref SFV_CREATE
// pcsfv, [MarshalAs(UnmanagedType.Interface)] out object ppvItem);
/// <summary>Creates a Shell item array object from a list of ITEMIDLIST structures.</summary>
/// <param name="cidl">The number of elements in the array.</param>
/// <param name="rgpidl">A list of cidl constant pointers to ITEMIDLIST structures.</param>
/// <param name="ppsiItemArray">When this function returns, contains an IShellItemArray interface pointer.</param>
[DllImport(Lib.Shell32, CharSet = CharSet.Unicode, ExactSpelling = true)]
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[PInvokeData("Shobjidl.h", MSDNShortId = "bb762146")]
public static extern HRESULT SHCreateShellItemArrayFromIDLists(uint cidl, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] rgpidl, out IShellItemArray ppsiItemArray);
Yeah Vanara and PInvoke are collection of wrappers for most Windows API, and actually you can directly use them as a whole in your project. PS: I’ve finished my purchase, fantastic!
I'll have to take pieces of what I need. I don't want to have zVD dependent on a DLL.
Oh vanara has a DLL? Maybe we can use only its PInvoke part?
The project compiles to a DLL. I'm going to grab pieces that I need to tweak it to fit in zVD.
OK that's fine ~
How's going? Are you facing some problems implementing this?
I'm trying to get to it today. I work a lot with my regular day job and I do consulting and dev work on the side.
Before I can add to zVD I need to create a working c# project based off the new implementation. Once I have that project completed then getting into zVD will be pretty easy for the most part. To make it easier on myself, everyone will have to configure the wallpapers settings in zVD again as the update will likely make the previous config invalid.
Oh I'm so sorry for bothering you too much. I thought that we needn't to invalidate the old config, and maybe we can upgrade them. The explorer's wallpaper source are folders, which aren't convenient for us to change wallpaper dynamically, but we can use multiple temp folders.
You're not bothering me at all. Your feedback is greatly appreciated and it's ok to ask for progress updates. That will encourage me to get it done.
I think I can ensure that the wallpaper part of the config that becomes invalid will only happen for the desktops that are currently configured for slideshow.
While invalid, the program would simply skip that portion and the desktop would fall back to the "Not set" option.
Wow thank you for valuing my suggestions. And your way is quite acceptable if there’s adequate explanation ;) Thanks again for your great passion on my idea.
I've been super busy, however, this will be the next enhancement that gets done. I just got to make the time. Should be no more than a couple weeks.
We should abandon the old manually wallpaper switching techniques, and use the original one provided by Shell Infrastructure.