Hello.
I am exploring .NET programming using C# and GDI+. My end program is going to be a vector drawing program (similiar to Adobe Illustrator, although not that complex). Ive started learning about GDI+, and it seems to have all the functions I want (alpha, gradients, beziers, antialiasing, etc.), but I am struggling with this performance problem when I used doublebuffering. Whenever my form is large (i.e. maximized), there is a noticable effort when refreshing the screen. Ive tried without doublebuffering, but the screen flicker is also unacceptable.
Here is some sample code that demonstrates this (not complete code, only what youd have to add to a new project):
When you move the shape with the maximized window, it isnt locked to the mouse, its jumpy and laggs behind and then catches up (like its on a chain). The cause seems to be the amount of time it takes to redraw the form. I have tried this on several computers (all of which we would hope to support in the end product), and it seems that the CPU is the only thing that makes a difference. Ive ran it on a) P4, 1.6GHz, 256MB RAM, 64MB Video; b) P3, 1.1GHz, 512MB RAM, 64MB Video, this is my development machine; c) P3, 733MHz, 384MB RAM, 128MB Video. On computer a) best performance; b) unacceptable drawing delays; c) brutal.
This seems to be a common problem with DoubleBuffering. Ive downloaded and ran Bob Powells example (from http://www.bobpowell.net/doublebuffer.htm), and it too has this problem when I run it maximized (his rotations are very choppy as opposed to when running in the initial window size)...and hes doing his own manual double buffering in that example. Ive also found this newsgroup post (http://groups.google.ca/groups?hl=e...&seekm=#22klulACHA.2228@tkmsftngp02&frame=off) about the same problem with no real solution (I tried the PixelFormat.Format32bppPArgb with no luck). And I cant revert to using GDI, because I need the alpha and antialising stuff, right?
Ive heard a suggestion that I should not be repainting (invalidating) the entire form all the time and that this might be a cause of the problem. Using the above example as an example, it would be more efficient if I only invalidated the union of the shapes original bounding rect and the shapes new bounding rect. My question is how do I do this? Ive tried using the System.Drawing.Region class, but I could only fill the region..I want to be able to tell the form to actually only repaint a part of the display. Could someone point me in the right direction so I can try this out to see if this will solve my problem.
Alternatively, does anyone have any other suggestions? I am thinking about investigating DirectX as I hear that it is much faster (although does it have all the capabilities, like anti-aliasing and alpha?). I would really like to stick with GDI+ as it seems to be a good and simple object model to follow.
Thanks for any info...
- Matt Budd
I am exploring .NET programming using C# and GDI+. My end program is going to be a vector drawing program (similiar to Adobe Illustrator, although not that complex). Ive started learning about GDI+, and it seems to have all the functions I want (alpha, gradients, beziers, antialiasing, etc.), but I am struggling with this performance problem when I used doublebuffering. Whenever my form is large (i.e. maximized), there is a noticable effort when refreshing the screen. Ive tried without doublebuffering, but the screen flicker is also unacceptable.
Here is some sample code that demonstrates this (not complete code, only what youd have to add to a new project):
Code:
using System.Drawing;
using System.Drawing.Drawing2D;
namespace GDI__Test
{
public class Form1 : Form
{
private GraphicsPath _oShape;
private Pen _oPen;
private SolidBrush _oBrush;
public Form1()
{
base.SetStyle(ControlStyles.DoubleBuffer, true);
base.SetStyle(ControlStyles.UserPaint, true);
base.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
_oShape = new GraphicsPath();
_oPen = new Pen(Color.Black, 2.0F);
_oBrush = new SolidBrush(Color.Yellow);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
_oShape.Dispose();
_oShape = new GraphicsPath();
_oShape.AddEllipse(e.X, e.Y, 100, 150);
_oShape.CloseFigure();
this.Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics loGraphics = e.Graphics;
loGraphics.SmoothingMode = SmoothingMode.AntiAlias;
loGraphics.FillPath(_oBrush, _oShape);
loGraphics.DrawPath(_oPen, _oShape);
}
}
}
When you move the shape with the maximized window, it isnt locked to the mouse, its jumpy and laggs behind and then catches up (like its on a chain). The cause seems to be the amount of time it takes to redraw the form. I have tried this on several computers (all of which we would hope to support in the end product), and it seems that the CPU is the only thing that makes a difference. Ive ran it on a) P4, 1.6GHz, 256MB RAM, 64MB Video; b) P3, 1.1GHz, 512MB RAM, 64MB Video, this is my development machine; c) P3, 733MHz, 384MB RAM, 128MB Video. On computer a) best performance; b) unacceptable drawing delays; c) brutal.
This seems to be a common problem with DoubleBuffering. Ive downloaded and ran Bob Powells example (from http://www.bobpowell.net/doublebuffer.htm), and it too has this problem when I run it maximized (his rotations are very choppy as opposed to when running in the initial window size)...and hes doing his own manual double buffering in that example. Ive also found this newsgroup post (http://groups.google.ca/groups?hl=e...&seekm=#22klulACHA.2228@tkmsftngp02&frame=off) about the same problem with no real solution (I tried the PixelFormat.Format32bppPArgb with no luck). And I cant revert to using GDI, because I need the alpha and antialising stuff, right?
Ive heard a suggestion that I should not be repainting (invalidating) the entire form all the time and that this might be a cause of the problem. Using the above example as an example, it would be more efficient if I only invalidated the union of the shapes original bounding rect and the shapes new bounding rect. My question is how do I do this? Ive tried using the System.Drawing.Region class, but I could only fill the region..I want to be able to tell the form to actually only repaint a part of the display. Could someone point me in the right direction so I can try this out to see if this will solve my problem.
Alternatively, does anyone have any other suggestions? I am thinking about investigating DirectX as I hear that it is much faster (although does it have all the capabilities, like anti-aliasing and alpha?). I would really like to stick with GDI+ as it seems to be a good and simple object model to follow.
Thanks for any info...
- Matt Budd