mzomparelli / zVirtualDesktop

Windows 10 Virtual Desktop Hotkeys, System Tray Icon, Wallpapers, and Task View replacement
463 stars 45 forks source link

Better way to implement slideshow #213

Open NyaMisty opened 6 years ago

NyaMisty commented 6 years ago

We should abandon the old manually wallpaper switching techniques, and use the original one provided by Shell Infrastructure.

NyaMisty commented 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.

mzomparelli commented 6 years ago

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.

NyaMisty commented 6 years ago

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

NyaMisty commented 6 years ago

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)

NyaMisty commented 6 years ago
NyaMisty commented 6 years ago

Well we needn't to reverse engineering it.... IDesktopWallpaper Microsoft has a public interface already :(

NyaMisty commented 6 years ago

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.

mzomparelli commented 6 years ago

Thanks for this. Let me test how it works. Looks pretty easy.

NyaMisty commented 6 years ago

Yeah that's quite disappointing after 8 hours work :(

mzomparelli commented 6 years ago

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.

NyaMisty commented 6 years ago

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

mzomparelli commented 6 years ago

It means a lot to me to hear this. You are a great person and I wish good things for you and your family.

NyaMisty commented 6 years ago

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

mzomparelli commented 6 years ago

I found a c# implementation

https://github.com/xupefei/Bing-Wallpaper/blob/master/BingWallpaper/DesktopWallpaper.cs

NyaMisty commented 6 years ago

Yeah that's the wrapper of the interface, and you still need to use steps above to build the parameter IntPtr items

mzomparelli commented 6 years ago

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);
NyaMisty commented 6 years ago

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!

mzomparelli commented 6 years ago

I'll have to take pieces of what I need. I don't want to have zVD dependent on a DLL.

NyaMisty commented 6 years ago

Oh vanara has a DLL? Maybe we can use only its PInvoke part?

mzomparelli commented 6 years ago

The project compiles to a DLL. I'm going to grab pieces that I need to tweak it to fit in zVD.

NyaMisty commented 6 years ago

OK that's fine ~

NyaMisty commented 6 years ago

How's going? Are you facing some problems implementing this?

mzomparelli commented 6 years ago

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.

NyaMisty commented 6 years ago

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.

mzomparelli commented 6 years ago

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.

mzomparelli commented 6 years ago

While invalid, the program would simply skip that portion and the desktop would fall back to the "Not set" option.

NyaMisty commented 6 years ago

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.

mzomparelli commented 6 years ago

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.