How to effectively draw on desktop in C#?

落爺英雄遲暮 提交于 2020-01-01 09:07:09

问题


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


回答1:


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.



回答2:


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; 



回答3:


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).




回答4:


This is difficult to do correctly.

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



来源:https://stackoverflow.com/questions/15798119/drawing-to-screen-directly-on-top-of-all-window

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!