Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Today I've tried Visual Studio + WinForms (I've been using Xamarin)
I dont use designer, just create empty project and link needed libraries.
So, my timer doesn't work properly, it ticks only in minimized form.
App.cs
using System;
using System.Windows.Forms;
namespace Line
{
class App
{
[STAThread]
public static void Main()
{
Application.Run(new Window());
}
}
}
Window.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
namespace Line
{
class Window : Form
{
Timer timer;
PictureBox pictureBox;
Bitmap bmp;
public struct Circle
{
public PointF position;
public SizeF size;
};
List<Circle> circles;
public Window()
{
this.Text = "Line";
this.Size = SizeFromClientSize(new Size(640, 480));
pictureBox = new PictureBox();
pictureBox.Dock = DockStyle.Fill;
pictureBox.BackColor = Color.White;
pictureBox.Paint += new PaintEventHandler(pictureBox_Paint);
this.Controls.Add(pictureBox);
this.Load += new EventHandler(Window_Load);
this.Resize += new EventHandler(Window_Resize);
circles = new List<Circle>();
timer = new Timer();
timer.Interval = 15;
timer.Enabled = true;
timer.Tick += new EventHandler(timer_Tick);
}
private void pictureBox_Paint(object sender, PaintEventArgs e)
{
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.Black);
foreach (Circle c in circles)
{
g.DrawEllipse(Pens.White, new RectangleF(c.position, c.size));
}
pictureBox.Image = bmp;
}
private void timer_Tick(object sender, EventArgs e)
{
Circle c;
Console.WriteLine("Works");
for (int i = 0; i < circles.Count; i++)
{
c = circles[i];
c.size.Width = (c.size.Width > 200) ? 100 : c.size.Width + 1;
circles[i] = c;
}
pictureBox.Invalidate();
}
private void Window_Load(object sender, EventArgs e)
{
bmp = new Bitmap(this.Width, this.Height);
circles.Add(new Circle());
Circle c = circles[0];
c.position = new PointF(100, 100);
c.size = new SizeF(100, 100);
circles[0] = c;
}
private void Window_Resize(object sender, EventArgs e)
{
bmp = new Bitmap(this.Width, this.Height);
pictureBox.Invalidate();
}
}
}
Same code worked fine in Xamarin.
1) in timer_Tick remove line: pictureBox.Invalidate();
2) cut code from pictureBox_Paint and paste at the end of timer_Tick
3) fix variable name collision c
Related
I want my simple program to take X and Y coordinates from serial port and draw them in window (like paint but with other device than mouse).
I managed to create code that recive and transforms data however I can't handle drawing that data on form.
Program works until Form1 window shows up. Then i recieve only "data_recived" and data value in console but rest of the datarecived event don't execute.
I know it is something wrong with DataReceivedHandler but i tried so many solution and none of them worked. (in comments you can see my attempts to use timer trigerred event to do that).
Could anyone give me at least some tips how to solve my problem? I would be really grateful
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO.Ports;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public string data;
private List<Point> points;
private Bitmap bmp;
private Pen pen;
private PictureBox pictureBox1 = new PictureBox();
//private System.Timers.Timer _timer;
//private DateTime _startTime;
public Form1()
{
InitializeComponent();
SerialPort serialPort1 = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
serialPort1.Open();
serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
DoubleBuffered = true;
pen = new Pen(Color.Black, 3);
points = new List<Point>();
// _startTime = DateTime.Now;
// _timer = new System.Timers.Timer(100); // 0.1 s
// _timer.Elapsed += new System.Timers.ElapsedEventHandler (timer_Elapsed);
// _timer.Start();
// Console.WriteLine("Czas Start");
}
public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort serialPort1 = (SerialPort)sender;
Console.WriteLine("data_recived");
data = serialPort1.ReadLine();
Console.WriteLine(data);
pointlist_reciver();
}
// void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
//{
// Console.WriteLine("Czas");
// TimeSpan timeSinceStart = DateTime.Now - _startTime;
//string output = string.Format("{0},{1}\r\n", DateTime.Now.ToLongDateString(), (int)Math.Floor(timeSinceStart.TotalMinutes));
// pointlist_reciver();
// }
public void pointlist_reciver()
{
int x1;
int y1;
points = new List<Point>();
string[] coordinates = new string[2];
coordinates = data.Split(',');
string x = coordinates[0];
string y = coordinates[1];
Int32.TryParse(x, out x1);
Int32.TryParse(y, out y1);
points.Add(new Point(x1, y1));
if (points.Count >= 2)
{
this.Paint += new PaintEventHandler(Form1_Paint);
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
PaintP(e);
}
public void PaintP ( PaintEventArgs e)
{
bmp = new Bitmap(1500, 1500);
using (Graphics g = Graphics.FromImage(bmp))
g.Clear(Color.White);
e.Graphics.DrawLines(pen, points.ToArray());
points.Clear();
}
}
}
points.Count >= 2
would never happen
this.Paint += new PaintEventHandler(Form1_Paint)
this does not make sense here, you need to register it only once on form load. What you are looking for is Invalidate(). Just beware you may be on different thread, so may need to Invoke first.
bmp = new Bitmap(1500, 1500);
using (Graphics g = Graphics.FromImage(bmp))
g.Clear(Color.White);
e.Graphics.DrawLines(pen, points.ToArray());
points.Clear();
you create bitmap you do not even use. Not sure what exactly you are trying to achieve here.
Example
You have two options. Either you draw on bitmap and paste that bitmap on the form. Or you just draw on the form. I made a simple example how to use the latter option. When you move mouse on the form it draws points. Just register the eventhandlers - Load, MouseMove, Paint.
List<Point> points = new List<Point>();
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
points.Add(e.Location);
Invalidate();
}
private void Form1_Load(object sender, EventArgs e)
{
this.DoubleBuffered = true;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
int radius = 3;
for (int i = points.Count - 1; i >= 0; --i)
{
Point p = points[i];
p.Y += 1;
if (p.Y > Height)
{
points.RemoveAt(i);
continue;
}
points[i] = p;
e.Graphics.FillEllipse(
Brushes.Red,
p.X - radius,
p.Y - radius,
2 * radius,
2 * radius
);
}
}
I managed to make my code work thanks to your suggestions. It still needs some work becasue it draws seperate lines instead of continuous one.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO.Ports;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public string data;
private List<Point> points = new List<Point>();
public string[] coordinates;
private Pen pen;
public Bitmap obrazek;
public int i = 0;
public Form1()
{
InitializeComponent();
obrazek = new Bitmap(1000, 1000);
using (Graphics g = Graphics.FromImage(obrazek))
g.Clear(Color.White);
SerialPort serialPort1 = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
serialPort1.Open();
serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
DoubleBuffered = true;
pen = new Pen(Color.Black, 3);
points = new List<Point>();
}
public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort TempSerialPort = (SerialPort)sender;
//Console.WriteLine("data_recived");
data = TempSerialPort.ReadLine();
Console.WriteLine(data);
pointlist_reciver();
//this.Invalidate();
pictureBox2.Invalidate();
}
public void pointlist_reciver()
{
int x1;
int y1;
string[] coordinates = data.Split(',');
string x = coordinates[0];
string y = coordinates[1];
Int32.TryParse(x, out x1);
Int32.TryParse(y, out y1);
points.Add(new Point(x1, y1));
Console.WriteLine(points.Count.ToString());
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(obrazek, 0, 0);
if (points.Count >= 2)
{
List<Point> points2 = points.GetRange(0, 2);
using (Graphics g = Graphics.FromImage(obrazek))
g.DrawLines(pen, points2.ToArray());
points.Clear();
}
}
}
}
Later i will post final version.
I'm trying to create a simple Windows Forms graphics app that basically will draw a circle every time the user clicks and it expands, while slowly fading away.
When I tried to use the Paint() Event for my graphics functionality, nothing happened, so I created a separate function called "Render" that is called in my main update Timer.
The app worked but the graphics flickered. After some researched I realized that I had to enable Double Buffering so that it would render to a buffer and then the buffer would be rendered to the screen.
The flickering still didn't stop!
Is this because double buffering only works for Paint() events and if so how do I get the Paint() event to work or am I not enabling Double Buffering right?
Here's my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Widget
{
public class Circle
{
public float X;
public float Y;
public float Radius;
public int Alpha;
public Circle(float X, float Y, float Radius, int Alpha)
{
this.X = X;
this.Y = Y;
this.Radius = Radius;
this.Alpha = Alpha;
}
}
public partial class Form1 : Form
{
public static readonly int ScreenX = Screen.PrimaryScreen.Bounds.Width;
public static readonly int ScreenY = Screen.PrimaryScreen.Bounds.Height;
public int WindowWidth = 500, WindowHeight = 500;
public Graphics G;
private Pen Pen;
private Timer timer = new Timer();
private List<Circle> Circles;
public Form1()
{
this.Text = "Widget - Sam Brandt";
this.Size = new Size(WindowWidth, WindowHeight);
this.StartPosition = FormStartPosition.Manual;
this.Location = new Point(ScreenX - WindowWidth - 100, 0);
this.FormBorderStyle = FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.Icon = new Icon("C:\\Users\\Admin\\Desktop\\Code Repositories\\Visual Studios\\Widget\\Widget\\Properties\\WidgetIcon.ico");
Pen = new Pen(Color.Black, 1);
G = CreateGraphics();
//this.Paint += new PaintEventHandler(OnPaint);
ConstructMouse();
FormWithTimer();
DoubleBuffered = true;
Circles = new List<Circle>();
}
public void ConstructMouse()
{
this.MouseUp += new MouseEventHandler(OnMouseUp);
this.MouseMove += new MouseEventHandler(OnMouseMove);
this.MouseDown += new MouseEventHandler(OnMouseDown);
}
public void FormWithTimer()
{
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = (10);
timer.Enabled = true;
timer.Start();
}
protected void OnMouseUp(object sender, MouseEventArgs e)
{
}
protected void OnMouseMove(object sender, MouseEventArgs e)
{
}
public void OnMouseDown(object sender, MouseEventArgs e)
{
Circles.Add(new Circle(e.Location.X, e.Location.Y, 0, 255));
}
/*public void OnPaint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
for (int i = 0; i < Circles.Count; i++)
{
Circle C = Circles[i];
e.Graphics.DrawEllipse(new Pen(Color.FromArgb(C.Alpha, 0, 0, 0), 1), C.X - C.Radius, C.Y - C.Radius, 2 * C.Radius, 2 * C.Radius);
}
}*/
private void Tick()
{
for (int i = 0; i < Circles.Count; i++)
{
Circle C = Circles[i];
C.Radius++;
C.Alpha -= 3;
if (C.Alpha == 0)
{
Circles.RemoveAt(i);
}
}
}
public void Render()
{
G.Clear(Color.White);
for (int i = 0; i < Circles.Count; i++)
{
Circle C = Circles[i];
G.DrawEllipse(new Pen(Color.FromArgb(C.Alpha, 0, 0, 0), 1), C.X - C.Radius, C.Y - C.Radius, 2 * C.Radius, 2 * C.Radius);
}
}
public void timer_Tick(object sender, EventArgs e)
{
Render();
Tick();
}
}
}
Short answer - keep DoubleBuffered = true and use Paint event.
When I tried to use a PaintEvent for my graphics functionality, nothing happened
When you do some modifications and want to reflect them, use Control.Invalidate method, which according to the documentation
Invalidates the entire surface of the control and causes the control to be redrawn.
In your case, something like this
void timer_Tick(object sender, EventArgs e)
{
Tick();
Invalidate();
}
More observations here but probably will be the answer.
Why Timer?
Use the Paint event, it is called when the GDI+ determines it needs to, you are constantly painting with your code as-is.
Your code makes it look like you are not using double buffering.
I'd do all your drawing to a separate Graphics object, and then copy that to your main Graphics object on the timer tick event only if there's been a change. You may need to keep track of that with a boolean member. This means your background drawing will have to be triggered by some other event.
If your picture is actually changing every 10 milliseconds, I'd slow down the timer a bit and set it to 50 milliseconds.
Try this (in VB):
Dim aProp = GetType(Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance)
aProp.SetValue(Me, True, Nothing)
Also had problems with double buffering, and usual setting property DoubleBuffered to true do not work. I have found this solution somewhere on web
I have a little problem of mine to solve. I have a button which has an image background.I tried to color the whole button but the image can not be seen after coloring the whole button. How can I edit this "imagebutton" like in this example? http://i.stack.imgur.com/XaQQQ.png
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace bura
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
if (button2.BackgroundImage != null)
{
button2.BackgroundImage = null;
button2.BackColor = Color.Black;
}
else {
button2.BackgroundImageLayout = ImageLayout.Stretch;
button2.BackgroundImage = Image.FromFile("C:\\Users\\rati\\Desktop\\ks.png");
}
}
private void button3_Click(object sender, EventArgs e)
{
button2.BackgroundImageLayout = ImageLayout.Stretch;
button2.BackgroundImage = Image.FromFile("C:\\Users\\rati\\Desktop\\ks.png");
}
}
}
This
Just made a button by using the designer with the following code:
this.button1.BackColor = System.Drawing.Color.DodgerBlue;
this.button1.BackgroundImage = global::WindowsFormsApplication.Properties.Resources.ChargeImage;
this.button1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.button1.Image = global::WindowsFormsApplication.Properties.Resources.DatabaseImage;
this.button1.Location = new System.Drawing.Point(12, 12);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(264, 160);
this.button1.TabIndex = 0;
this.button1.UseVisualStyleBackColor = false;
And that is the result:
So what is your problem?
You can edit your pictures with a method like this:
private static void DrawLinesOnBitmap(Bitmap bmp)
{
using (var p = new Pen(Color.Black, 5))
{
using (var g = Graphics.FromImage(bmp))
{
g.DrawLine(p, 0, 0, bmp.Width, bmp.Height);
}
}
}
This method adds a line from the left top corner to the right bottom corner. Just draw some more lines and you should get your wanted result.
I am stuck at trying to call a procedure and use some parameters in a new thread in C#. There is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Random_colored_rectangles
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Thread th;
Random rand;
System.Drawing.Color[] colors = new System.Drawing.Color[5] {Color.Orange, Color.Red, Color.Pink, Color.Black, Color.Gold };
private void DrawColor(Color color)
{
for (int i = 0; i < 100; i++)
{
DrawRectangle(color, 3 , rand.Next(0, this.Width), rand.Next(0, this.Height), 10, 10);
Thread.Sleep(100);
}
MessageBox.Show(color + " done");
}
private void DrawRectangle(Color barva, float width, int pos_x, int pos_y, int size_x, int size_y)
{
Pen myPen = new Pen(barva, width);
Graphics formGraphics;
formGraphics = plocha.CreateGraphics();
formGraphics.DrawRectangle(myPen, new Rectangle(pos_x, pos_y, size_x, size_y));
myPen.Dispose();
formGraphics.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
rand = new Random();
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.R)
{
th = new Thread(DrawColor);
th.Name = Convert.ToString(threadCount);
threadList.Add(th);
threadCount = threadCount + 1;
th.Start(colors[rand.Next(0, colors.Length)]);
}
}
}
}
This code should (after pressing R) make 100 random colored rectangles (the color is chosen from an array of few colors). But, I am unable to make my thread start the procedure DrawColor with a parameter of the random color select.
Can you please help me?
You could do it by using a Task.
Color theColorToPass = someColor;
Task.Factory.StartNew(color => {
DrawColor(color);
}, theColorToPass);
You could aswell access the array directly from within the Task though. I see no point in passing it to the Thread.
Using the advice of those more familiar with the do's and don'ts of C# (that is not me trying to sound mean or anything), I have devised a way to accomplish what you want without the need of CreateGraphics() or Thread.Sleep(). Unfortunately, this throws an OutOfMemoryException when it hits e.Graphics.DrawRectangle(penToUse, rectanglesToUse[0]);. What does that mean?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace Colors
{
public partial class Form1 : Form
{
Timer timer = new Timer { Interval = 100 };
Random rand = new Random();
Color[] colors = new Color[5]
{
Color.Black,
Color.Blue,
Color.Green,
Color.Purple,
Color.Red
};
List<Pen> usedPens = new List<Pen>();
List<Rectangle> usedRectangles = new List<Rectangle>();
Pen penToUse;
List<Rectangle> rectanglesToUse = new List<Rectangle>();
public Form1()
{
InitializeComponent();
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
penToUse = new Pen(GetRandomColor(), 3);
rectanglesToUse.Clear();
for (int i = 0; i < 100; i++)
rectanglesToUse.Add(GetRandomRectangle());
this.Refresh();
}
}
private Color GetRandomColor()
{
return colors[rand.Next(0, colors.Length)];
}
private Rectangle GetRandomRectangle()
{
return new Rectangle(rand.Next(0, Width), rand.Next(0, Height), 10, 10);
}
protected override void OnPaint(PaintEventArgs e)
{
for (int i = 0; i < usedRectangles.Count; i++)
e.Graphics.DrawRectangle(usedPens[i % 100], usedRectangles[i]);
timer.Tick += delegate
{
if (rectanglesToUse.Count > 0)
{
e.Graphics.DrawRectangle(penToUse, rectanglesToUse[0]);
usedRectangles.Add(rectanglesToUse[0]);
rectanglesToUse.RemoveAt(0);
}
else
{
usedPens.Add(penToUse);
timer.Stop();
}
};
timer.Start();
}
}
}
I have written the following simple program, which draws lines on the screen every 100 milliseconds (triggered by timer1). I noticed that the drawing flickers a bit (that is, the window is not always completely blue, but some gray shines through). So my idea was to use double-buffering. But when I did that, it made things even worse. Now the screen was almost always gray, and only occasionally did the blue color come through (demonstrated by timer2, switching the DoubleBuffered property every 2000 milliseconds).
What could be an explanation for this?
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e) {
Graphics g = CreateGraphics();
Pen pen = new Pen(Color.Blue, 1.0f);
Random rnd = new Random();
for (int i = 0; i < Height; i++)
g.DrawLine(pen, 0, i, Width, i);
}
// every 100 ms
private void timer1_Tick(object sender, EventArgs e) {
Invalidate();
}
// every 2000 ms
private void timer2_Tick(object sender, EventArgs e) {
DoubleBuffered = !DoubleBuffered;
this.Text = DoubleBuffered ? "yes" : "no";
}
}
}
I would just draw all of your items to your own buffer, then copy it all in at once. I've used this for graphics in many applications, and it has always worked very well for me:
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
Invalidate();// every 100 ms
}
private void Form1_Load(object sender, EventArgs e)
{
DoubleBuffered = true;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Bitmap buffer = new Bitmap(Width, Height);
Graphics g = Graphics.FromImage(buffer);
Pen pen = new Pen(Color.Blue, 1.0f);
//Random rnd = new Random();
for (int i = 0; i < Height; i++)
g.DrawLine(pen, 0, i, Width, i);
BackgroundImage = buffer;
}
EDIT: After further investigation, it looks like your problem is what you're setting your Graphics object to:
Graphics g = CreateGraphics();
needs to be:
Graphics g = e.Graphics();
So your problem can be solved by either creating a manual buffer like I did above, or simply changing you Graphics object. I've tested both and they both work.
No need to use multiple buffers or Bitmap objects or anything.
Why don't you use the Graphics object provided by the Paint event? Like this:
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen pen = new Pen(Color.Blue, 1.0f);
Random rnd = new Random();
for (int i = 0; i < Height; i++)
g.DrawLine(pen, 0, i, Width, i);
}
Try setting the double buffered property to true just once in the constructor while you're testing.
You need to make use of the back buffer. Try this:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DoubleBufferTest
{
public partial class Form1 : Form
{
private BufferedGraphicsContext context;
private BufferedGraphics grafx;
public Form1()
{
InitializeComponent();
this.Resize += new EventHandler(this.OnResize);
DoubleBuffered = true;
// Retrieves the BufferedGraphicsContext for the
// current application domain.
context = BufferedGraphicsManager.Current;
UpdateBuffer();
}
private void timer1_Tick(object sender, EventArgs e)
{
this.Refresh();
}
private void OnResize(object sender, EventArgs e)
{
UpdateBuffer();
this.Refresh();
}
private void UpdateBuffer()
{
// Sets the maximum size for the primary graphics buffer
// of the buffered graphics context for the application
// domain. Any allocation requests for a buffer larger
// than this will create a temporary buffered graphics
// context to host the graphics buffer.
context.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);
// Allocates a graphics buffer the size of this form
// using the pixel format of the Graphics created by
// the Form.CreateGraphics() method, which returns a
// Graphics object that matches the pixel format of the form.
grafx = context.Allocate(this.CreateGraphics(),
new Rectangle(0, 0, this.Width, this.Height));
// Draw the first frame to the buffer.
DrawToBuffer(grafx.Graphics);
}
protected override void OnPaint(PaintEventArgs e)
{
grafx.Render(e.Graphics);
}
private void DrawToBuffer(Graphics g)
{
//Graphics g = grafx.Graphics;
Pen pen = new Pen(Color.Blue, 1.0f);
//Random rnd = new Random();
for (int i = 0; i < Height; i++)
g.DrawLine(pen, 0, i, Width, i);
}
}
}
It's a slightly hacked around version of a double buffering example on MSDN.