0

I'm trying to paint over an external application's window, in my case more specifically the desktop and behind all visible icons.

I figured out after trial and error that you can use:

WinDef.HWND desktop = User32.INSTANCE.FindWindow(null, "Desktop");
WinDef.HDC desktopWindow = User32.INSTANCE.GetDC(desktop);
for (int i=0; i<1920; i++) {
    for (int j=0; j<1080; j++) {
        GDI32.INSTANCE.SetPixel(desktopWindow, i, j, 155);
    }
}

However, this draws above everything in front of the screen and is extremely slow. It takes around 22 seconds to fill my screen.

Is there a correct way of drawing shapes or images directly on the desktop? (Behind the icons)

EDIT: I've found a way of painting behind the icons, thanks to this article: https://www.codeproject.com/articles/856020/draw-behind-desktop-icons-in-windows

But there is still the problem that SetPixel is too slow

import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.GDI32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;

public class Main {

    private static WinDef.HWND workerw = null;

    public static void main(String[] args) {

        init();

        if (workerw != null) {
            WinDef.HDC desktopWindow = User32.INSTANCE.GetDC(workerw);

            for (int i=0; i<1920; i++) {
                for (int j=0; j<1080; j++) {
                    GDI32.INSTANCE.SetPixel(desktopWindow, i, j, 100);
                }
            }
            User32.INSTANCE.ReleaseDC(workerw, desktopWindow);
        }
    }

    private static void init() {
        WinDef.HWND progman = User32.INSTANCE.FindWindow("Progman", null);


        User32.INSTANCE.PostMessage(progman, 0x052C, new WinDef.WPARAM(0), new WinDef.LPARAM(0));
        User32.INSTANCE.SendMessageTimeout(progman, 0x052C, new WinDef.WPARAM(0), new WinDef.LPARAM(0), User32.SMTO_NORMAL, 1000, new WinDef.DWORDByReference());


        User32.INSTANCE.EnumWindows((hwnd, pntr) -> {

            WinDef.HWND p = User32.INSTANCE.FindWindowEx(hwnd, new WinDef.HWND(Pointer.createConstant(0)), "SHELLDLL_DefView", null);

            if (p != null) {
                workerw = User32.INSTANCE.FindWindowEx(new WinDef.HWND(Pointer.createConstant(0)), hwnd, "WorkerW", null);
            }

            return true;
        }, Pointer.createConstant(0));
    }

}

If there's an alternative to GDI32.INSTANCE.SetPixel it would be great.

Edit2: I read about the BitBlt function (which is included in JNA), I am unsure how to use it to copy an bitmap to the HDC. https://msdn.microsoft.com/en-us/library/windows/desktop/dd183370(v=vs.85).aspx

Bloc97
  • 274
  • 1
  • 13
  • 1
    No, this can never work. All it takes is for a paint cycle to come along and your painting will be lost. SetPixel is never going to be useful here. The idiom is to paint to an in memory bitmap and blit that to the device. That will still suffer the problem that the shell is going to paint over what you paint. What you need to do is change the desktop background. Trying to develop this in Java is a bad idea. Do the prototyping development in C++ against the native sdk. Much more productive. If you must have the code in java, port it at the last minute. – David Heffernan Feb 22 '18 at 07:42
  • [`SetPixelV` is faster than `SetPixel` because it does not need to return the color value of the point actually painted.](https://msdn.microsoft.com/en-us/library/windows/desktop/dd145079.aspx) Not that this solves any of your *real* issues, as explained in the comment above. – IInspectable Feb 22 '18 at 09:26
  • I know that using setpixel will never work, I'm just lost on how to get the GDI Graphics instance of any external window using JNA. It looks like it is not yet implemented in JNA but I might be wrong. What would help is if I could use *new Graphics(HDC hdc)* as described here https://msdn.microsoft.com/en-us/library/windows/desktop/ms534453(v=vs.85).aspx – Bloc97 Feb 22 '18 at 23:48
  • *"GDI Graphics instance"* is not a term that has a meaning in the Windows API. GDI rendering is done through device contexts, and your code shows how to get the device context of any window. It's unclear why you think that GDI+ adds any relevant features on top of the GDI. – IInspectable Feb 23 '18 at 09:09
  • By GDI Graphics I mean the Graphics class that is related to the Native GDI api, and not the Java Graphics class. It is easy to confuse them. By using new Graphics(HDC hdc) in C++ I can draw on any window, but it is not possible to do that in JNA since it is not implemented. – Bloc97 Feb 23 '18 at 18:26

0 Answers0