Reputation: 1340
Im drawing a linear gradient manually by drawing lines with changing colors. However, this is very slow, and i seems to update, when i resize the window. How do i make it faster? The color scale is linear in this example, but later i wan't to make non-linear gradients.
protected override void OnPaintBackground(PaintEventArgs paintEvnt)
{
SuspendLayout();
// Get the graphics object
Graphics gfx = paintEvnt.Graphics;
// Create a new pen that we shall use for drawing the line
// Loop and create a horizontal line 10 pixels below the last one
for (int i = 0; i <= 500; i++)
{
Pen myPen = new Pen(Color.FromArgb(i/2,0,0));
gfx.DrawLine(myPen, 0, i, 132, i);
}
ResumeLayout();
}
Upvotes: 2
Views: 3483
Reputation: 33920
You could pre-compute the color values so you won't have to do it on every redraw. Other than that, there's not much more you can do without resorting to more lowlevel APIs, like XNA.
Update: it is perfectly feasible to host XNA within WinForms controls. There's some nice links forward in this question.
Upvotes: 1
Reputation: 244742
Perhaps specifying a ColorBlend
to use with the LinearGradientBrush
suggested by Pieter will address your concerns about being able to paint non-linear gradients in the future?
You can create a ColorBlend
object that specifies the colors of your choice and an arbitrary position for each. By setting the InterpolationColors
property of the LinearGradientBrush
to your ColorBlend
object, you should be able to get any effect that you want.
MSDN gives the following sample:
protected override void OnPaint(PaintEventArgs e)
{
//Draw ellipse using ColorBlend.
Point startPoint2 = new Point(20, 110);
Point endPoint2 = new Point(140, 110);
Color[] myColors = {Color.Green, Color.Yellow, Color.Yellow, Color.Blue, Color.Red, Color.Red};
float[] myPositions = {0.0f,.20f,.40f,.60f,.80f,1.0f};
ColorBlend myBlend = new ColorBlend();
myBlend.Colors = myColors;
myBlend.Positions = myPositions;
LinearGradientBrush lgBrush2 = new LinearGradientBrush(startPoint2, endPoint2, Color.Green, Color.Red);
lgBrush2.InterpolationColors = myBlend;
Rectangle ellipseRect2 = new Rectangle(20, 110, 120, 80);
e.Graphics.FillEllipse(lgBrush2, ellipseRect2);
}
Upvotes: 0
Reputation: 29632
The problem is that GDI+ is incredibly slow.
You should use high level constructs with GDI+ which are relatively fast (relative to drawing lines like you do now). See http://msdn.microsoft.com/en-us/library/system.drawing.drawing2d.lineargradientbrush.aspx for more information about e.g. the LinearGradientBrush
. There are much more of these brushes and pens which should help you increase your performance.
One more thing: the Suspend/ResumeLayout
doesn't do anything in your example. These methods only apply when you are doing layout by e.g. adding Control
s to the current form or changing properties on existing Control
s like the Dock
property or the Height
and Width
.
Upvotes: 3
Reputation: 2340
If you want to paint it once and only once, without resizing, I suggest you write this to a Bitmap object once, and then draw this bitmap to the background. Also, you can enable double buffering on the form. this should be a property called DoubleBuffering, or something similar. This should reduce the flashing you get when redrawing your form.
Upvotes: 3