Live wallpaper apps like EWRE play a video behind your desktop icons, but in front of the static wallpaper. Windows has no public API for that. So how is it done?
This post explains the well-known technique that wallpaper engines use. It relies on undocumented shell behavior, so treat it as a field guide rather than a contract.
The desktop is made of windows
Your desktop is a stack of ordinary windows owned by Explorer:
- Progman: the Program Manager window, the root of the desktop.
- SHELLDLL_DefView: the window that draws your icons.
- WorkerW: a helper window. The static wallpaper is painted into one of these.
The goal is to place your own window behind the icons (SHELLDLL_DefView) and in front of the static wallpaper.
Step 1: Ask Progman to create a WorkerW
Sending Progman an undocumented message, 0x052C, makes it spawn a WorkerW window sitting behind the icon layer.
HWND progman = FindWindowW(L"Progman", nullptr);
SendMessageTimeoutW(progman, 0x052C, 0, 0, SMTO_NORMAL, 1000, nullptr);
Step 2: Find the right WorkerW
After that message, there are several WorkerW windows. The one you want is the sibling that comes after the WorkerW that contains SHELLDLL_DefView.
#include <windows.h>
static HWND g_workerw = nullptr;
BOOL CALLBACK EnumProc(HWND hwnd, LPARAM) {
HWND defView = FindWindowExW(hwnd, nullptr, L"SHELLDLL_DefView", nullptr);
if (defView) {
g_workerw = FindWindowExW(nullptr, hwnd, L"WorkerW", nullptr);
}
return TRUE;
}
HWND GetWallpaperHost() {
HWND progman = FindWindowW(L"Progman", nullptr);
SendMessageTimeoutW(progman, 0x052C, 0, 0, SMTO_NORMAL, 1000, nullptr);
EnumWindows(EnumProc, 0);
return g_workerw;
}
Step 3: Parent your window to it
Once you have the handle, make your rendering window a child of it:
HWND host = GetWallpaperHost();
if (host) {
SetParent(myWindow, host);
// Resize myWindow to cover the monitor
}
Your Direct3D swap chain, or any renderer, now draws into a window that sits between the icons and the static wallpaper. A video player on top of this is a live wallpaper.
What the renderer does next
The window trick only places the surface. The actual playback is a separate problem. EWRE, for example, uses Direct3D 11 rendering with Media Foundation and hardware decoding, and supports multi-monitor setups either with independent wallpapers or spanning. See my other post on why that pipeline keeps overhead low.
Gotchas
-
Windows versions differ. The shell's window hierarchy has changed over time, and newer Windows 11 builds behave differently from older ones (for example, where the
WorkerWends up in the tree). Test on every version you support instead of trusting one snippet. - Explorer restarts. If Explorer crashes or restarts, the host window disappears. A robust engine watches for that and re-attaches.
- Multiple monitors and DPI. Size your window using the virtual desktop bounds, and handle per-monitor DPI.
- Undocumented behavior. Microsoft can change this at any time. Keep the code isolated so it's easy to patch.
- Be a good citizen. Pause rendering when the desktop isn't visible, such as a fullscreen game, a locked PC, or displays off. EWRE does exactly this, plus pausing on battery power.
Wrap up
A live wallpaper is just a window with a clever parent. The hard parts are everything around it: decoding efficiently, handling monitors, and knowing when to stop drawing.
If you want to see the result, EWRE is free on the Microsoft Store. Developer: github.com/StayElite.
Have you worked with the Progman/WorkerW approach? Share your experience in the comments. 👇
Top comments (0)