Robert S. Robert S. - 1 year ago 168
C# Question

base.OnPaint order changes drawing location

I have a strange problem. I made my own user control deriving from

. I override
. Now I draw something in
. Let's say at position 0, 0.

If I call
after my custom drawing everything is fine. But if I call
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
. So I don't call my code there.

Here is an example:

protected override void OnPaint(PaintEventArgs 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);


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

This also happens for every parent-child-level I add. So if I create another control (another class) and also override
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
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
. 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.

Answer Source

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

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download