开发者

How to effectively draw on desktop in C#?

I want to draw directly on the desktop in C#. From searching a bit, I ended up using a Graphics object from the Desktop HDC (null). Then, I painted normally using this Graphics object.

The problem is that my shapes get lost when any part of the screen is redrawn. I tried a While loop, but it actually ends up drawing as fast as the application can, which is not the update rate of the desktop.

Normally, I would need to put my drawing code in a "OnPaint" event, but such thing does not exist for the desktop.

How would I do it?

开发者_开发知识库

Example code: https://stackoverflow.com/questions/1536141/how-to-draw-directly-on-the-windows-desktop-c


I posted two solutions for a similar requirement here

Basically you have two options.

1- Get a graphics object for the desktop and start drawing to it. The problem is if you need to start clearing what you have previously drawn etc.

Point pt = Cursor.Position; // Get the mouse cursor in screen coordinates 

using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) 
{         
  g.DrawEllipse(Pens.Black, pt.X - 10, pt.Y - 10, 20, 20); 
}

2- The second option that I provide in the link above is to create a transparent top-most window and do all your drawing in that window. This basically provides a transparent overlay for the desktop which you can draw on. One possible downside to this, as I mention in the original answer, is that other windows which are also top-most and are created after your app starts will obscure your top most window. This can be solved if it is a problem though.

For option 2, making the form transparent is as simple as using a transparency key, this allows mouse clicks etc. to fall through to the underlying desktop.

BackColor = Color.LightGreen; 
TransparencyKey = Color.LightGreen; 


When you draw to HDC(NULL) you draw to the screen, in an unmanaged way. As you've discovered, as soon as windows refreshes that part of the screen, your changes are overwritten.

There are a couple of options, depending upon what you want to achieve:

  1. create a borderless, possibly non-rectangular window. (Use SetWindowRgn to make a window non-rectangular.) You can make this a child of the desktop window.
  2. subclass the desktop window. This is not straightforward, and involves injecting a DLL into the Explorer.exe process.


To get an OnPaint for the desktop you would need to subclass the desktop window and use your drawing logic when it receives a WM_PAINT/WM_ERASEBKGND message.

As the thread you linked to says, you can only intercept messages sent to a window of an external process using a hook (SetWindowsHookEx from a DLL).

As mentioned a transparent window is another way to do it, or (depending on the update frequency) copying, drawing and setting a temporary wallpaper (as bginfo does).


This is difficult to do correctly.

It will be far easier, and more reliable, to make your own borderless form instead.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜