16

This question has been asked for other languages, and even for those other languages, I have found their answers lacking in how to exactly do it, cleanly (no messed up screen repaints, etc..).

Is it possible to draw onto the Windows Desktop from C#? I am looking for an example if possible.

esac
  • 24,099
  • 38
  • 122
  • 179
  • 7
    There is no officially supported clean way to draw on the desktop window from any language. In practice, most of the methods that achieve the closest to clean drawing on the desktop involve injecting your own dll into the Explorer process and subclassing the window procedure for the desktop window. I would not recommend doing this in C#, though. Also, there's no guarantee that such methods would continue to work on any future versions of Windows, or with any future Service packs or hotfixes for existing versions of Windows. – Franci Penov Oct 08 '09 at 07:46

3 Answers3

29

Try the following:

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;

class Program {

    [DllImport("User32.dll")]
    static extern IntPtr GetDC(IntPtr hwnd);

    [DllImport("User32.dll")]
    static extern int ReleaseDC(IntPtr hwnd, IntPtr dc);

    static void Main(string[] args) {
        IntPtr desktop = GetDC(IntPtr.Zero);
        using (Graphics g = Graphics.FromHdc(desktop)) {
            g.FillRectangle(Brushes.Red, 0, 0, 100, 100);
        }
        ReleaseDC(IntPtr.Zero, desktop);
    }
}
Remco
  • 1,713
  • 1
  • 13
  • 14
Paolo Tedesco
  • 55,237
  • 33
  • 144
  • 193
  • 6
    FYI for those who say you can't, this did work for me, although moving any window over it repaints it immediately :( – esac Oct 08 '09 at 16:06
  • I've just tried this in a WPF, C# 4.0 application and I get "PInvokeStackImbalance was detected" as soon as I moved the mouse after launching it. Just an FYI for others who pass by. – Alex Jun 20 '12 at 13:56
  • I got the same unbalanced stack error. What's the fix? Change your project back to 3.5 client profile? :) – gonzobrains Oct 26 '12 at 23:24
  • 1
    it looks like changing my project to .NET 3.5 made this unbalance issue go away. – gonzobrains Oct 26 '12 at 23:29
  • 6
    The stack imbalance is caused by the fact the ReleaseDC method is defined incorrectly. It should be: static extern int ReleaseDC(IntPtr hwnd, IntPtr dc); – Frank Hagenson Feb 20 '13 at 23:31
  • `void ReleaseDC(IntPtr dc)` causes unbalanced stack error in x86 processes. x64 uses registers to pass parameters therefore it can work if you are lucky. [Msdn](https://msdn.microsoft.com/en-us/library/windows/desktop/dd162920(v=vs.85).aspx) – Atomosk Aug 10 '15 at 15:10
  • I cannot say for sure as this is a pretty old answer, but usually I don't craft my `DllImport` statements myself, so I really don't know why I picked up the wrong signature for ReleaseDC... – Paolo Tedesco Aug 10 '15 at 18:46
  • will it paint UNDER desktop icons, or over them? – Gabriel Mar 17 '17 at 17:02
  • This may just be a me problem, but when I run this code (I tweaked the height and width to 2000,2000) it will only cover about a quarter of the screen. Can you fix that? – FatPancake52 Jul 17 '22 at 04:12
9

You can try:

Graphics.FromHwnd(IntPtr.Zero)
leppie
  • 115,091
  • 17
  • 196
  • 297
  • 3
    Paolo Tedesco's answer used to work for me, but stopped and I couldn't figure out why. Leppie's answer got it working again for me. – chrismead Oct 31 '12 at 14:28
4

You can see a real-world code example within https://uiautomationverify.codeplex.com/SourceControl/latest#UIAVerify/Tools/visualuiverify/utils/screenrectangle.cs

This draws a rectangle that will appear on the screen until the user chooses to remove it at an arbitrary position (wont be repainted over). It uses a windows form thats hidden/ appears as a popup.

This is the code behind the UIAVerify.exe tool in the current Windows SDK.

If you want to use the above, copy the following files into your project:

  • utils\screenboundingrectangle.cs
  • utils\screenrectangle.cs
  • win32\*

Might need to update namespaces accordingly + add references to System.Drawing + System.Windows.Forms

Then you can draw a rectangle with the following code:

namespace Something
{
    public class Highlighter
    {
        ScreenBoundingRectangle _rectangle = new ScreenBoundingRectangle();
        public void DrawRectangle(Rectangle rect)
        {
            _rectangle.Color = System.Drawing.Color.Red;
            _rectangle.Opacity = 0.8;
            _rectangle.Location = rect;
            this._rectangle.Visible = true;
        }
    }
}

and

var rect = Rectangle.FromLTRB(100, 100, 100, 100);
var hi = new Highlighter();
hi.DrawRectangle(rect);
Michael Wasser
  • 1,776
  • 2
  • 21
  • 32
  • 1
    Code can now be found here https://github.com/TestStack/UIAVerify/blob/master/VisualUiaVerify/utils/screenrectangle.cs – frank koch Oct 06 '22 at 11:16