0

I have a form that I use a transparent background so I can display texts on screen without hide other applications.

Basically I have a instance of a Form where I set the transparence color etc, then I hava a function addtext("Hello World", X, Y) where it creates a Label object, set the settings and add to this form controls.

this.Controls.Add(newLabel);

Well, now I need to create something to add a retangle so people can "draw" things on screen, so I need something similar to the Label object.

I saw some examples in the internet but all of them need the Paint() event to use the Graphics etc and adding the LAbel it doesn't need everything like that.

I tried to use the event and tried call the Graphic propertie etc but didn't work.

Here are some tests that I made:

private class Line : Control
        {
            public float FromX { get; set; }
            public float FromY { get; set; }
            public float ToX { get; set; }
            public float ToY { get; set; }
            public Pen PenColor { get; set; }

            public Line() { }
        }

Graphics g = this.CreateGraphics();
Line line = (Line)cc;
g.DrawRectangle(line.PenColor, line.FromX, line.FromY, line.ToX, line.ToY);

Edit: The code above works in some cases, not all the time, if I try to debug the code, sometimes after executing the g.DrawRect~ it doesn't move to the next line, looks like it's "executing forever" the g.DrawRectangle() function, the thread who controls this draw keep saying "Running", someone know what might be happening ?

Icemanind
  • 47,519
  • 50
  • 171
  • 296
Kyore
  • 388
  • 2
  • 7
  • 29
  • http://msdn.microsoft.com/en-us/library/ms229728(v=vs.85).aspx – asawyer Aug 01 '13 at 19:59
  • Can you clarify what you are trying to do. In my head, it looks like you are trying to draw on the form or on a image? – StevenTsooo Aug 01 '13 at 20:06
  • Your use of `CreateGraphics` is only going to work if the `Line` control has been added to the form: `myForm.Controls.Add(line);` Further, I wouldn't inherit directly from `Control`. Pick one, such as `private class Line : Panel`. Panel is nice to draw on. – DonBoitnott Aug 01 '13 at 20:11
  • It's in a form, I've edited the first post with new informations that I got. It is drawing sometime, but other time it kinda get stuck. – Kyore Aug 01 '13 at 20:14
  • Add your Line instances to a List() and then in the OnPaint override of the form, draw each of the lines using the graphics instance provided by the override. Do NOT use CreateGraphics. Anything you draw using that method will disappear anytime the form is refreshed, covered by another form or minimized and restored. See this link: http://bobpowell.net/creategraphics.aspx – Chris Dunaway Aug 01 '13 at 21:08
  • @ChrisDunaway have you noticed `Line` is not a business object, that itself a `Control` Why to draw on form? rather Fill a rectangle in `Line Paint` and just add to form. makes sense right? else making it just business object will make sense too – Sriram Sakthivel Aug 01 '13 at 21:11
  • @SriramSakthivel - My mistake, but the custom control can keep an internal list of Lines to be drawn and then draw them on the OnPaint override. My main point is that all drawing should be done in the OnPaint override and that CreateGraphics should be avoided. – Chris Dunaway Aug 01 '13 at 21:13
  • @ChrisDunaway I agree completely, but my point is Deriving from control is irrelevant here. It has to be from `System.Object` or some base class since `Control` will create `Handle` etc – Sriram Sakthivel Aug 01 '13 at 21:19
  • The way you are trying to do this is completely wrong. For a better way (perhaps even the correct way), look at the accepted answer to [this SO Question](http://stackoverflow.com/questions/815667/how-to-draw-graphics-text-on-top-of-another-application) – Icemanind Aug 01 '13 at 22:00
  • @icemanind: That link is not applicable. The OP doesn't want to draw atop *another* application, he wants to draw on controls within his own. Much easier. – Ed S. Aug 01 '13 at 22:21
  • @EdS. `"I have a form that I use a transparent background so I can display texts on screen without hide other applications".` To me, that sounds like he wants to draw on top of these other applications. Perhaps I'm interpreting that wrong though. – Icemanind Aug 01 '13 at 22:30
  • @icemanind: I see what you mean, but I took that as "I want to create a transparent form". On a side note, that's harder than it sounds in WinForms. – Ed S. Aug 02 '13 at 00:25

1 Answers1

2

The code above works in some cases, not all the time

It always "works", you just don't completely understand what you are doing.

If you want to draw on a control then you should be doing it from within the OnPaint handler (or override). Windows are updated by a message loop. When a window gets a WM_PAINT message it redraws itself according to its current OnPaint implementation (message handler).

You draw on it from outside OnPaint, so anything you do is overwritten when the window updates then next time. On a side note, you're leaking a Graphics object every time you call CreateGraphics.

So, to implement a drawing surface you need to track the input in the input handlers (KeyDown, MouseDown, MouseUp, etc). You save this contextual information as data and then draw what that data represents in your OnPaint handler.

You can force a refresh a control by calling Invalidate() on it. This will send it a WM_PAINT message and your OnPaint handler will be called.

Further reading:

Ed S.
  • 122,712
  • 22
  • 185
  • 265