I have a panel in which I do some custom drawing. To make sure the graphics scale proportionally when the panel is resized I use the Transform
property of my Graphics
.
private void panelGraph_Paint(object sender, PaintEventArgs e)
{
var gfx = e.Graphics;
gfx.Transform = BuildTransform(e.ClipRectangle);
var width = 1.0f / gfx.Transform.Elements[0];
var white = new Pen(Color.White, width);
gfx.DrawLine(white, new PointF(-1.0f, -1.0f), new PointF(1.0f, -1.0f));
gfx.DrawLine(white, new PointF(-1.0f, -1.0f), new PointF(-1.0f, 1.0f));
}
The matrix from BuildTransform
maps an area with width and height [-2, 2] to the area of e.ClipRectangle
.
The code works, sort of. The problem is that when I resize the panel the scaling of my graphics isn't smooth but happens in discrete steps. If I add the following line in my paint-function:
Console.WriteLine("Paint {0} {1}", e.ClipRectangle.Width, e.ClipRectangle.Height);
I get output like this when开发者_高级运维 I slowly resize the window:
Paint 1 815
Paint 1 815
Paint 1 815
Paint 751 815
Paint 1 815
Paint 753 815
Paint 1 813
Paint 754 811
What's causing this and how can I fix it?
EDIT: The problem isn't deterministic but seems to be dependent on how fast I resize the window(!). If I slowly, slowly resize the window I can get it nearly arbitrarily large without the size of my graphics changing.
AFAIK, ClipRectangle
isn't what you need, use Bounds
instead.
Paint message always comes with clipping area that is required to REPAINT, and it is less or equal to whole control area, depending of how much of the control was obscured and was now revealed and needs repainting.
When you resize your window, the control will only invalidate the area that needs to be invalidated. Hence if you make it larger, it will assume that the already existing rectangle is ok and will invalidate the new area that the enlargement made visible. Since you obviously need to invalidate your entire control when you resize it, add a resize eventhandler and invalidate your control there. This should solve your problem.
Set the Form.DoubleBuffer
property to true.
Here's a composite of other people's correct answers:
- You should override/handle the resizing event and invalidate the whole window
- You should use ClientRectangle and not e.ClipRectangle when calculating the scaling for the window.
精彩评论