starBackground icon indicating copy to clipboard operation
starBackground copied to clipboard

Error retrieving HWND

Open darclander opened this issue 4 years ago • 3 comments

For some versions of windows (incorrectly installed or non-purchased versions) it seems like the function get_wallpaper_window() does not return a correct HWND to the windows wallpaper but instead returns 0.

https://github.com/darclander/starBackground/blob/main/src/ui.cpp

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

Any solutions for this would be greatly appreciated.

  • [ ] Find the issue.
  • [ ] Fix it.

darclander avatar Sep 04 '21 19:09 darclander

Spy++ reveals the layouts/differences across machines. Try something like this:


// See if WorkerW (class) is a child of program manager ('progman').

IntPtr workerW = Win32.FindWindowEx(GetProgramManagerWindowHandle(), IntPtr.Zero, "WorkerW", null);

// If that doesn't work, try searching alternative layout.

if (workerW == IntPtr.Zero)
{
    // Enumerate top-level windows until finding SHELLDLL_DefView as child. 

    Win32.EnumWindows(new Win32.EnumWindowsProc((topHandle, topParamHandle) =>
    {
        IntPtr SHELLDLL_DefView = Win32.FindWindowEx(topHandle, IntPtr.Zero, "SHELLDLL_DefView", null);

        if (SHELLDLL_DefView != IntPtr.Zero)
        {
            // If found, take next sibling as workerW.
            // > Gets the WorkerW Window after the current one.

            workerW = Win32.FindWindowEx(IntPtr.Zero, topHandle, "WorkerW", null);
        }

        return true;

    }), IntPtr.Zero);
}

It should be found now, if it exists. You can SetParent to this handle to get live wallpapers.

MirzaBeig avatar Apr 14 '24 22:04 MirzaBeig

@MirzaBeig wow thank you very much! I had in mind a similar solution but sadly I have been offline for too long to even attempt to solve this... :D I will see if I can implement your suggestion soon!

All the best!

  • Luke

darclander avatar May 06 '24 19:05 darclander