Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing on the desktop background as wallpaper replacement (Windows/C#)

I'm trying to make an application that needs to draw on the desktop, behind the icons so it appears to replace the desktop wallpaper. I've found a few solutions to this, but most of them didn't work very well (lots of flickering). One solution seems to be what I'm looking for, but I don't really get it. I've done mostly C# applications using either higher-level graphics libraries or just Windows Forms, and some C++ but only on non-Windows platforms.

If anyone could "translate" it for me or provide me with an alternative solution, it would be much appreciated!

like image 897
nardi Avatar asked Nov 05 '09 21:11

nardi


People also ask

How to set a wallpaper as your desktop background in Windows?

If you want to set a picture as your desktop background in Windows 10, the fastest way to do it is probably by using the right-click menu. Open File Explorer and browse to the picture that you want to use as your wallpaper.

How do I change the background image on my computer?

Using Windows 7 and 8 Right-click an empty space on the desktop. Doing so will prompt a drop-down menu. Click Personalize. This option is at the bottom of the drop-down menu. Click "Desktop Background". This link should be in the bottom-left corner of the window. Click a picture. Doing so will select it as your desktop background.

Is there a way to draw on Windows's wallpaper in C++?

Is there a way to get an handle to Windows's wallpaper (behind icons) in C++ in order to draw on it? That would allow to make an active desktop (discontinued after Windows XP) equivalent, a Wallpaper Engine equivalent, or any other similar tool. (Temperature and resources usage monitoring on the wallpaper in my case).

How do I change the default wallpaper on Windows 11?

To use a default Windows 11 wallpaper if you don't see it in the settings, go into this folder: From there, you can right-click the picture you want to use and follow the steps above to use it as the desktop background.


2 Answers

I know this is a pretty late answer but I recently looked into it myself and if further user's have the same issue this might help them.

NOTE: This answer is for C++ but maybe it might help you do the same in C#

As mentioned in a comment above I followed This guide to understand how I would be able to draw ON the windows wallpaper window.

By using these two methods:

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
    HWND p = FindWindowEx(hwnd, NULL, "SHELLDLL_DefView", NULL);
    HWND* ret = (HWND*)lParam;

    if (p)
        {
        // Gets the WorkerW Window after the current one.
        *ret = FindWindowEx(NULL, hwnd, "WorkerW", NULL);
        }
    return true;
}

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

I was able to retrieve the windows handle.

Since I was only familiar with SDL this was the only solution I found but I believe that any ways that allows you to create / modify a window based on another window should work.

window = SDL_CreateWindowFrom((void*)get_wallpaper_window());

The line above allowed me to create a window in SDL from the HWND retrieved by the get_wallpaper_window() method.

Since there is a lot of code involved I will link my solution on github. This can draw a lot of stars (although I believe it can be improved) behind your desktop icons.

like image 89
darclander Avatar answered Sep 22 '22 05:09

darclander


Seen this question in passing and I did partially solve the problem (But not in a way I can give any useful code) to make some cool games although might not have the application you want:

  • Set desktop background back to normal and take a screenshot of the desktop
  • Set desktop background black and take a screenshot of the desktop
  • Set desktop background white and take a screenshot of the desktop
  • Combine the black and white versions to make a mask and the first screenshot as the overlay setting pixel values that are different transparent.

Now on your form draw the following in order:

  1. Draw the first screenshot
  2. Draw your form stuff
  3. Draw the desktop overlay you created

This is what I did for a full screen form but could be adapted for non full screen forms quite easily I think. Essentially you have recreated the desktop but with the ability to do anything with it including some cool games. The draw speed and performance is satisfactory for any application but desktop interactivity is an issue... :( Here is a pic of a tanks game using the principle except I set the background white and made all white backgrounds transparent too!

My Tanks Game

like image 29
William Jarvis Avatar answered Sep 21 '22 05:09

William Jarvis