I am trying to create a small paint application in Visual Studio 2015. My project falls into the category of Windows Form Applications. I have the following problem:
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (a == 1)
{
if (r == 1 || el == 1)
{
int x = Math.Min(inX, e.X);
int y = Math.Min(inY, e.Y);
int width = Math.Max(inX, e.X) - Math.Min(inX, e.X);
int height = Math.Max(inY, e.Y) - Math.Min(inY, e.Y);
rect = new Rectangle(x, y, width, height);
Refresh();
}
else if (l == 1)
{
ep = e.Location;
Refresh();
}
else
{
ep = e.Location;
g = this.CreateGraphics();
g.DrawLine(p, sp, ep);
sp = ep;
}
}
}
This part of my codes creates a Rectangular (2nd if), a line segment(3rd if) and just a line. It works pretty much the same as MS Paint; the rectangular or the line segment isn not completed until the user releases the left mouse click (Mouse up). But when a rectangular is finally made when I try again to create another one, the form refreshes ( Refresh(); ) and I lose all the previous drawn rectangulars or lines. I tried replacing Refresh(); with Invalidate(rect); and Update();, but I do not get the result I want.
Instead, I get this:
You should do all your drawing to a separate Bitmap
"buffer" that you keep around. Draw your shapes to that bitmap, then when the screen actually needs to be updated, draw the buffer to the screen.
Also, anytime you call Graphics.FromImage
you need to remember to Dispose
, or it will leak resources like crazy.
Incredibly simple example
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
namespace DrawExample
{
public partial class Form1 : Form
{
private Bitmap _canvas; //This is the offscreen drawing buffer
private Point _anchor; //The start point for click-drag operations
private Rectangle? _ghost;
private Brush _ghostBrush;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
_ghostBrush = new SolidBrush(Color.FromArgb(200, 200, 200, 255)); //This creates a slightly blue, transparent brush for the ghost preview
ResizeCanvas();
}
private void Form1_Resize(object sender, EventArgs e)
{
ResizeCanvas();
}
/// <summary>
/// Resizes the offscreen bitmap to match the current size of the window, it preserves what is currently in the bitmap.
/// </summary>
private void ResizeCanvas()
{
Bitmap tmp = new Bitmap(this.Width, this.Height, PixelFormat.Format32bppRgb);
using (Graphics g = Graphics.FromImage(tmp))
{
g.Clear(Color.White);
if (_canvas != null)
{
g.DrawImage(_canvas, 0, 0);
_canvas.Dispose();
}
}
_canvas = tmp;
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_anchor = new Point(e.X, e.Y);
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_ghost = new Rectangle(_anchor.X, _anchor.Y, e.X - _anchor.X, e.Y - _anchor.Y);
this.Invalidate();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
//Create a Graphics for the offscreen bitmap
using (Graphics g = Graphics.FromImage(_canvas))
{
Rectangle rect = new Rectangle(_anchor.X, _anchor.Y, e.X - _anchor.X, e.Y - _anchor.Y);
g.FillRectangle(Brushes.White, rect);
g.DrawRectangle(Pens.Black, rect);
}
_ghost = null;
//This queues up a redraw call for the form
this.Invalidate();
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (_ghost.HasValue)
{
using (Bitmap tmp = new Bitmap(_canvas))
{
using (Graphics g = Graphics.FromImage(tmp))
{
g.FillRectangle(_ghostBrush, _ghost.Value);
g.DrawRectangle(Pens.Black, _ghost.Value);
e.Graphics.DrawImage(tmp, 0, 0);
}
}
}
else
{
e.Graphics.DrawImage(_canvas, 0, 0);
}
}
//This stops the flickering
protected override void OnPaintBackground(PaintEventArgs e)
{
//Do nothing
}
}
}
You are drawing directly onto the form's drawing surface. That surface is not persistent. It lasts until the next paint cycle.
Instead you should:
Paint
event. If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With