Graphics creation clear on panel control doesn't work - c#

I have a panel in my widows form. And I'm creating Graphics like in following code by creating a graphics
private void pnlDraw_MouseMove(object sender, MouseEventArgs e)
{
if (startPaint)
{
using (g = Graphics.FromImage(bmp))
{
if ( x != -1 && y != -1)
{
Color mynewcolor = Color.FromName(myColor);
Pen p = new Pen(Color.Black, 5);
g.DrawLine(p, new Point(x, y), e.Location);
x = e.X;
y = e.Y;
}
}
pnlDraw.Invalidate();
}
}
private void pnlDraw_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(bmp, Point.Empty);
}
I'm trying to clear the panel, (clear what I draw on panel) in a button click event like this.
But it doesn't work? What should I do to clear the panel?
private void btnClear_Click(object sender, EventArgs e)
{
pnlDraw.Invalidate();
}

According to using LarsTech's answer
(Graphics g = Graphics.FromImage(bmp)) { g.Clear(pnlDraw.BackColor); }
pnlDraw.Invalidate();
pnlDraw.Update();

Try this:
private void btnClear_Click(object sender, EventArgs e)
{
pnlDraw.Invalidate();
pnlDraw.Update();
}

Related

What is best way to write in windows forms with pen-tablet like wacom intuos in C#

i have a problem.
I'm writing a program that writes on it with a stylus.
First, i create a windows form with a panel.
second, this code:
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
using System.Diagnostics;
using System.Drawing.Drawing2D;
namespace testWrite
{
public partial class Form1 : Form
{
Graphics g;
int x = -1;
int y = -1;
bool moving = false;
Pen pen;
public Form1()
{
InitializeComponent();
g = panel1.CreateGraphics();
pen = new Pen(Color.Black, 5);
pen.SetLineCap(System.Drawing.Drawing2D.LineCap.Round, System.Drawing.Drawing2D.LineCap.Round, System.Drawing.Drawing2D.DashCap.Round);
pen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
pen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
g.DrawLine(pen, new Point(x, y), e.Location);
x = e.X;
y = e.Y;
}
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
x = -1;
y = -1;
moving = false;
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
x = e.X;
y = e.Y;
moving = true;
}
}
}
I use this app with a Wacom intuos
But the result is not so good because a few words are lost...haizzz
toi tên la trần
quang hieu
hello heloo
especially, when i write fast or the text is small.
when i write in Microsoft Paint, it is very good
What is best way to to write in windows forms with pen-tablet like wacom intuos?
UPDATE 1:
With cmt from TaW.
Thanks for your help. But, that's not what I need...
i was change my code to:
public partial class Form1 : Form
{
List<Point> curPoints = new List<Point>();
List<List<Point>> allPoints = new List<List<Point>>();
public Form1()
{
InitializeComponent();
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
// here we should check if the distance is more than a minimum!
curPoints.Add(e.Location);
// let it show
panel1.Invalidate();
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
if (curPoints.Count > 1)
{
// ToList creates a copy
allPoints.Add(curPoints.ToList());
curPoints.Clear();
}
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
if (curPoints.Count > 1)
{
// begin fresh line or curve
curPoints.Clear();
// startpoint
curPoints.Add(e.Location);
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
// here you can use DrawLines or DrawCurve
// current line
if (curPoints.Count > 1) e.Graphics.DrawCurve(Pens.Red, curPoints.ToArray());
// other lines or curves
foreach (List<Point> points in allPoints)
if (points.Count > 1) e.Graphics.DrawCurve(Pens.Red, points.ToArray());
}
}
But nothing better. The result is worse...
I tried to write: "Hello my name is Hieu", but is not run...
Looks like a pen-tablet differs from a mouse when use to write. Because, with mouse i feel that is better in this code...
UPDATE 2:
With code by Idle_Mind. It will be fine if i set pen-tablet:
With setting "Click", it is not OK
How to fix it, i don't want to set "Double Click" to my pen !
Here's my version...worked great for me. You might need to adjust your tablet settings so that it picks up everything correctly:
public partial class FormTablet : Form
{
private Point lastPoint;
private GraphicsPath GP = null;
private List<GraphicsPath> GPs = new List<GraphicsPath>();
public FormTablet()
{
InitializeComponent();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
lastPoint = new Point(e.X, e.Y);
GP = new GraphicsPath();
GP.AddLine(lastPoint, lastPoint);
GPs.Add(GP);
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point pt = new Point(e.X, e.Y);
GP.AddLine(lastPoint, pt);
lastPoint = pt;
pictureBox1.Invalidate();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
GP = null;
pictureBox1.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (checkBox1.Checked)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
}
using(Pen p = new Pen(Color.Black, (int)numericUpDown1.Value))
{
p.LineJoin = LineJoin.Round;
p.MiterLimit = p.Width / 2;
foreach (GraphicsPath path in GPs)
{
if (path.PathPoints.Count() > 2)
{
// draw the path
e.Graphics.DrawPath(p, path);
}
else
{
// just draw a single dot
Rectangle rc = new Rectangle(Point.Round(path.PathPoints[0]), new Size(1, 1));
rc.Inflate((int)numericUpDown1.Value, (int)numericUpDown1.Value);
e.Graphics.FillEllipse(Brushes.Black, rc);
}
}
}
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
private void button1_Click(object sender, EventArgs e)
{
GPs.Clear();
pictureBox1.Invalidate();
}
}

I keep getting a Null exception when using g.FillEllipse();

I am a beginner at this so cut me a little slack please. I am trying to draw a dot on the form window at the location where the mouse is clicked. I keep getting a Null Exception at g.FillEllipse is called. What am I missing or doing wrong?
namespace ConvexHullScan
{
public partial class convexHullForm : Form
{
Graphics g;
//Brush blue = new SolidBrush(Color.Blue);
Pen bluePen = new Pen(Color.Blue, 10);
Pen redPen = new Pen(Color.Red);
public convexHullForm()
{
InitializeComponent();
}
private void mainForm_Load(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
}
private void convexHullForm_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
int x, y;
Brush blue = new SolidBrush(Color.Blue);
x = e.X;
y = e.Y;
**g.FillEllipse(blue, x, y, 20, 20);**
}
}
}
}
Replace Graphics g = this.CreateGraphics(); with just g = this.CreateGraphics(); because otherwise you are defining a new variable that lives only inside the scope of the mainForm_Load function rather than assigning a value to the variable defined at the higher-level scope of convexHullForm
It's not clear what your end goal is, but those dots drawn with CreateGraphics() will only be temporary. They will get erased when the form repaints itself, such as when you minimize and restore, or if another window obscures yours. To make them "persistent", use the supplied e.Graphics in the Paint() Event of the Form:
public partial class convexHullForm : Form
{
private List<Point> Points = new List<Point>();
public convexHullForm()
{
InitializeComponent();
this.Paint += new PaintEventHandler(convexHullForm_Paint);
this.MouseDown += new MouseEventHandler(convexHullForm_MouseDown);
}
private void convexHullForm_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Points.Add(new Point(e.X, e.Y));
this.Refresh();
}
}
void convexHullForm_Paint(object sender, PaintEventArgs e)
{
foreach (Point pt in Points)
{
e.Graphics.FillEllipse(Brushes.Blue, pt.X, pt.Y, 20, 20);
}
}
}

Call paint event from mouse move event

When mouse move over a panel2, I need to draw lines. So far I have done following
public Form1()
{
InitializeComponent();
}
private void panel2_Paint(object sender, PaintEventArgs e)
{
if (isDragging)
{
letsPaint(sender, e);
}
}
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
mouseMoveX = e.X;
mouseMoveY = e.Y;
this.Paint += new PaintEventHandler(panel2_Paint);
}
}
private void letsPaint(object sender, PaintEventArgs e)
{
Pen blackpen = new Pen(Color.Black, 3);
Graphics g = e.Graphics;
g.DrawLine(blackpen, mouseClickedX, mouseClickedY, mouseMoveX, mouseMoveY);
g.Dispose();
}
But nothing happens when I move mouse. I think I did something wrong PaintEventHandler() here. Please tell me how to do this and also if there is any better way for this.
Also I think my method will drawline on the form but I need to draw line on the panel2. How to do? Thanks in advance.
You invalidate:
public Form1()
{
InitializeComponent();
panel2.Paint += new letsPaint;
}
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging) {
mouseMoveX = e.X;
mouseMoveY = e.Y;
panel2.Invalidate();
}
}
and you don't dispose the graphic object (you didn't create it), but you do the pen:
private void letsPaint(object sender, PaintEventArgs e) {
using (Pen blackpen = new Pen(Color.Black, 3)) {
e.Graphics.DrawLine(blackpen,
mouseClickedX, mouseClickedY, mouseMoveX, mouseMoveY);
}
}
Here is a quick little method that works with a bitmap:
Bitmap bmp;
Point lastPoint;
public Form1() {
InitializeComponent();
bmp = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
panel1.MouseDown += panel1_MouseDown;
panel1.MouseMove += panel1_MouseMove;
panel1.Paint += panel1_Paint;
}
void panel1_Paint(object sender, PaintEventArgs e) {
e.Graphics.DrawImage(bmp, Point.Empty);
}
void panel1_MouseMove(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
using (Graphics g = Graphics.FromImage(bmp)) {
g.DrawLine(Pens.Black, lastPoint, e.Location);
}
lastPoint = e.Location;
panel1.Invalidate();
}
}
void panel1_MouseDown(object sender, MouseEventArgs e) {
lastPoint = e.Location;
}
This will flicker, so you would want to replace your panel with a double-buffered panel. Something like this:
public class PanelEx : Panel {
public PanelEx() {
this.DoubleBuffered = true;
}
}

How to pan Image inside PictureBox

I have a custom PictureBox which can zoom in using MouseWheel event. Now I want to add a panning feature to it. I mean when PictureBox is in zoomed state, if user left clicks and holds the click then move the mouse, the image would pan within the picturebox.
Here is my code but unfortunately it does not work! I don't know where to look anymore...
private Point _panStartingPoint = Point.Empty;
private bool _panIsActive;
private void CurveBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Focus();
_panIsActive = true;
_panStartingPoint = e.Location;
}
}
private void CurveBox_MouseUp(object sender, MouseEventArgs e)
{
_panIsActive = false;
}
private void CurveBox_MouseLeave(object sender, EventArgs e)
{
_panIsActive = false;
}
private void CurveBox_MouseMove(object sender, MouseEventArgs e)
{
if(_panIsActive && IsZoomed)
{
var g = CreateGraphics(); //Create graphics from PictureBox
var nx = _panStartingPoint.X + e.X;
var ny = _panStartingPoint.Y + e.Y;
var sourceRectangle = new Rectangle(nx, ny, Image.Width, Image.Height);
g.DrawImage(Image, nx, ny, sourceRectangle, GraphicsUnit.Pixel);
}
}
I am suspecting the MouseMove event...I am not sure if anything happens in this event and/or nx and ny does contain correct point.
Any helps/tips is really appriciated!
I think the math is backwards. Try it like this:
private Point startingPoint = Point.Empty;
private Point movingPoint = Point.Empty;
private bool panning = false;
void pictureBox1_MouseDown(object sender, MouseEventArgs e) {
panning = true;
startingPoint = new Point(e.Location.X - movingPoint.X,
e.Location.Y - movingPoint.Y);
}
void pictureBox1_MouseUp(object sender, MouseEventArgs e) {
panning = false;
}
void pictureBox1_MouseMove(object sender, MouseEventArgs e) {
if (panning) {
movingPoint = new Point(e.Location.X - startingPoint.X,
e.Location.Y - startingPoint.Y);
pictureBox1.Invalidate();
}
}
void pictureBox1_Paint(object sender, PaintEventArgs e) {
e.Graphics.Clear(Color.White);
e.Graphics.DrawImage(Image, movingPoint);
}
You aren't disposing your graphic object, and CreateGraphics is just a temporary drawing anyway (minimizing would erase it) so I moved the drawing code to the Paint event and am just invalidating as the user is panning.

Draw a User Defined Rectangle

My current code allows me to draw rectangles from a user defined spot but not in the way in whihc i desire. I need it to be like you would do it in paint, here is my current code:
namespace SimpleDraw2
{
///
/// Description of MainForm.
///
public partial class MainForm : Form
{
bool IsMouseDown = false;
Point MousePosition;
int DrawShape = 0;
Bitmap StoredImage;
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
pictureBox1.Image = new Bitmap (pictureBox1.Width,pictureBox1.Height);
StoredImage = new Bitmap(pictureBox1.Width,pictureBox1.Height);
}
void PictureBox1MouseDown(object sender, MouseEventArgs e)
{
IsMouseDown = true;
MousePosition = e.Location;
Graphics gStored = Graphics.FromImage(StoredImage);
gStored.Clear(Color.Transparent);
gStored.DrawImage(pictureBox1.Image, 0, 0);
}
void PictureBox1MouseUp(object sender, MouseEventArgs e)
{
IsMouseDown = false;
}
void PictureBox1MouseMove(object sender, MouseEventArgs e)
{
Graphics g = Graphics.FromImage(pictureBox1.Image);
if (DrawShape == 0)
{
Pen p = new Pen(Color.Red, 10);
if (IsMouseDown)
{
g.DrawLine(p,MousePosition,e.Location);
MousePosition = e.Location;
}
}
if (DrawShape == 1)
{
g.Clear(Color.Transparent);
g.DrawImage(StoredImage,0,0);
g.DrawRectangle(Pens.Green,MousePosition.X,MousePosition.Y,e.X,e.Y);
}
if (DrawShape == 2)
{
g.Clear(Color.Transparent);
g.DrawImage(StoredImage, 0, 0);
g.DrawEllipse(Pens.HotPink, MousePosition.X, MousePosition.Y, e.X, e.Y);
}
if (DrawShape == 3)
{
g.Clear(Color.Transparent);
g.DrawImage(StoredImage, 0, 0);
g.DrawArc(Pens.Indigo,pictureBox1.Bounds, e.Y, e.X);
}
//if (DrawShape == 4)
//{
// g.Clear(Color.Transparent);
// g.DrawImage(StoredImage, 0, 0);
// g.DrawPolygon(Pens.Indigo, Point[] e.X);
//}
this.Refresh();
}
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
axWindowsMediaPlayer1.URL = ofd.FileName;
}
}
private void button1_Click(object sender, EventArgs e)
{
axWindowsMediaPlayer1.Ctlcontrols.pause();
Bitmap bmp = new Bitmap(axWindowsMediaPlayer1.Width, axWindowsMediaPlayer1.Height);
Graphics gfx = Graphics.FromImage(bmp);
gfx.CopyFromScreen(PointToScreen(axWindowsMediaPlayer1.Location), new Point(0, 0), axWindowsMediaPlayer1.Bounds.Size, CopyPixelOperation.SourceCopy);
pictureBox1.BackgroundImage = bmp;
//axWindowsMediaPlayer1.Visible = false;
//pictureBox1.Visible = true;
}
private void button3_Click(object sender, EventArgs e)
{
Graphics gg = Graphics.FromImage(pictureBox1.BackgroundImage);
gg.Clear(Color.Transparent);
Graphics gStored = Graphics.FromImage(StoredImage);
gStored.Clear(Color.Transparent);
Graphics g = Graphics.FromImage(pictureBox1.Image);
g.Clear(Color.Transparent);
}
private void button4_Click(object sender, EventArgs e)
{
DrawShape = 1;
}
private void button6_Click(object sender, EventArgs e)
{
DrawShape = 2;
}
private void button8_Click(object sender, EventArgs e)
{
DrawShape = 3;
}
private void button7_Click(object sender, EventArgs e)
{
DrawShape = 0;
}
}
}
If someone could help me edit my code to iron out the issue to make it easy drag and draw system it would me much appreciate.
Thanks in Advance
Chris
From msdn:
Draws a rectangle specified by a
coordinate pair, a width, and a
height.
So your code won't work:
g.DrawRectangle(Pens.Green,MousePosition.X,MousePosition.Y,e.X,e.Y);
Should be something like
g.DrawRectangle(Pens.Green, MousePosition.X, MousePosition.Y, Math.Abs(e.X - MousePosition.X), Math.Abs(e.Y - MousePosition.Y));
The biggest problem I see is that you're trying to draw in the mouse events. This means your drawing will be wiped away the instant you get a refresh event.
Only draw in Paint events, never in mouse events. If you want your app to draw as a result of mouse events, set a point, rectangle, or whatever in the mouse events (like you start to do with IsMouseDown), invalidate the area you want to change in your MouseMoved event, then draw your rectangle or whatever in your Paint event.

Categories

Resources