How to draw directly on the Windows desktop, C#?
Asked Answered
M

3

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.

Muraida answered 8/10, 2009 at 7:24 Comment(1)
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.Resorcinol
B
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);
    }
}
Bevatron answered 8/10, 2009 at 7:35 Comment(9)
FYI for those who say you can't, this did work for me, although moving any window over it repaints it immediately :(Muraida
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.Mellins
I got the same unbalanced stack error. What's the fix? Change your project back to 3.5 client profile? :)Poyssick
it looks like changing my project to .NET 3.5 made this unbalance issue go away.Poyssick
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);Pomcroy
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. MsdnTaxation
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...Bevatron
will it paint UNDER desktop icons, or over them?Ockham
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?Lansing
P
9

You can try:

Graphics.FromHwnd(IntPtr.Zero)
Peraza answered 8/10, 2009 at 7:37 Comment(1)
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.Abelabelard
M
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);
Moschatel answered 8/6, 2016 at 15:50 Comment(1)
Code can now be found here github.com/TestStack/UIAVerify/blob/master/VisualUiaVerify/…Uncontrollable

© 2022 - 2024 — McMap. All rights reserved.