Reputation: 2042
I have a strange problem. I made my own user control deriving from UserControl
. I override OnPaint
. Now I draw something in OnPaint
. Let's say at position 0, 0.
If I call base.OnPaint
after my custom drawing everything is fine. But if I call base.OnPaint
before the stuff I'm drawing, it seems to ignore the containing control and the location is relative to the form instead of relative to the client area of the parent control. So when I draw at position (0, 0) it will effectively be drawn at negative x and y and I will only see a part of it. The base.OnPaint
is UserControl.OnPaint
. So I don't call my code there.
Here is an example:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var rect = new System.Drawing.Rectangle(this.ClientSize.Width - 16,
this.ClientSize.Height - 16, 16, 16);
e.Graphics.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.Red), rect);
//base.OnPaint(e);
}
In this case the red rectangle is displayed somewhere inside the client area but not at the lower right corner. If I uncomment the last line and comment the first line the red rectangle is displayed at the lower right corner as expected.
I don't get it. I did this many times and it always worked. So I tried to find any differences. The only I found is that I don't add my control in the designer but add it programmatically to another control with theContainingControl.Controls.Add(myMessedUpControl);
.
This also happens for every parent-child-level I add. So if I create another control (another class) and also override OnPaint
the behavior is the same if I add it to another user control.
Does anyone had this behavior before? How can I fix this? The problem is that I want to call base.OnPaint
first and also everyone suggest this. But as I said I can't without messing the coordinates up.
One note: The coordinates are really 0, 0 in the debugger at the draw calls like DrawLine
, DrawImage
oder DrawString
. But the result is displayed at negative coordinates (relative to the client area). It looks like the client coordinates are interpreted as client coordinates of the form. But I don't know why.
Found the problem
In my project there is a graphical overlay class which connects Paint
event handlers to all controls in my form (the whole hierarchy). In this handler a transformation is performed. This graphical overlay kept me sleepless so many times. I guess I will remove it.
Upvotes: 1
Views: 450
Reputation: 63742
The Graphics
object has a lot of mutable state. The order of operations matters if you mess with this mutable state - for example, you can use the Transform
matrix to change the offset of everything rendered on the surface.
It sounds like your ascendant changes one of those during its own OnPaint
handler without resetting it back. Try doing a e.Graphics.ResetTransform();
before you start your own painting. Make sure all the other state is also the way you want it (clip, DPI, ...).
Upvotes: 2