tags:

views:

858

answers:

3

I am using the following code to draw on a single monitor:

Point cursorLocation;
NativeMethods.GetCursorPos(out cursorLocation);
Screen screen = Screen.FromPoint(cursorLocation);

Point h1 = new Point(screen.Bounds.Left, cursorLocation.Y);
Point h2 = new Point(screen.Bounds.Right, cursorLocation.Y);
Point v1 = new Point(cursorLocation.X, screen.Bounds.Top);
Point v2 = new Point(cursorLocation.X, screen.Bounds.Bottom);

using (Graphics graphics = Graphics.FromHwnd(NativeMethods.GetDesktopWindow())) {
    NativeMethods.SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero);
    graphics.DrawLine(Pens.Red, h1, h2);
    graphics.DrawLine(Pens.Red, v1, v2);
}

Natively, this should theoretically draw on either monitor. However, it only draws on the primary. So, to fix this I am getting the DC of all the displays and trying to do it this way.

IntPtr hdc = NativeMethods.CreateDC("DISPLAY", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
Graphics graphics = Graphics.FromHdc(hdc);
graphics.DrawLine(Pens.Red, h1, h2);
graphics.DrawLine(Pens.Red, v1, v2);
graphics.Dispose();
NativeMethods.ReleaseDC(IntPtr.Zero, hdc);

Go figure, this doesn't even draw to the screen at all. I have tried various overloads for CreateDC, as well as searched SO and other resources and I'm stumped.


Once this is resolved, anyone know how to get rid of flicker by refreshing the desktop using SHCHangeNotify? I'm only drawing two lines and it flickers like mad..)

A: 

Cannot help on the first part. I assume you are drawing the lines in the Paint event. Use double buffering to get rid of the flicker.

danish
+2  A: 

This is not an answer to your question but if you have no problem with it, I would recomment trying using WPF to solve this. I have played with other kind of desktop interaction like transparency and WPF is lightning fast compared to the GDI alternative.

You place your wpf application and resize it to fit all the area you need to be painting on. Then set it to transparent, and make sure its clickthrough (i think that is default on 100% transparency). That way as long as you dont have anything on this big WPF canvas/form all mouse events will click through to desktop.

Then just start painting on it. (i liked it because it was very easy to add effects to lines and images). Guaranteed no flickering.

Alternatively you could use the same scheme on normal Windows Forms instead.

This way you wont have to turn to GDI to do your work.

I think the only way you would be able to do this flickerfree as you are approaching it now, would be to hook into the window messaging on the desktops WM_PAINT and do your work there.

Wolf5
A: 

Unfortunately neither answer is of any help for the following reasons:

I am limited to Windows Forms, as this is a base framework built for WF. I've tried the TransparencyKey/Form trick, still flickers too much.

I've seriously tried almost ten different methods, and even my search results in Google for DirectX/Direct3D, C# Desktop Hooks, and others have brought me to no avail.

All I'm trying to do is draw a crosshair that spans the whole desktop, 1px x 1px.. surely someone has to have some sort of example of how to do this without flickering and good performance:? D3D, DX, GDI or otherwise? :\

David Anderson