i am trying to make signature panel in c# windowsform application where input is from drawing tablet
my code as below this code working for line drawing not dot created.
So please suggest how dot and line both are create.
{
Graphics graphics;
Boolean cusorMoving = false;
Pen cursorPen;
int cursorX = -1;
int cursorY = -1;
public SignPad()
{
InitializeComponent();
graphics = panel2.CreateGraphics();
cursorPen = new Pen(Color.Black, 2);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
cursorPen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
cursorPen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
}
Mouse Down event
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
cusorMoving = true;
cursorX = e.X;
cursorY = e.Y;
}
private void panel2_MouseUp(object sender, MouseEventArgs e)
{
cusorMoving = false;
cursorX = -1;
cursorY = -1;
}
Mouse Move event
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (cursorX != -1 && cursorY != -1 && cusorMoving == true)
{
graphics.DrawLine(cursorPen, new Point(cursorX, cursorY), e.Location);
cursorX = e.X;
cursorY = e.Y;
}
}
You need to store individual points in a collection and draw them separately in the Paint handler. Every time you add a point to the collection, you also need to tell the panel to draw the area where the new segment was added. Something like this:
using System.Collections.Generic;
using System.Drawing;
namespace Lines
{
public partial class SignPad : Form
{
Pen cursorPen = SystemPens.ControlText;
List<Point> points = new List<Point>();
bool cursorMoving = false;
public SignPad()
{
InitializeComponent();
cursorPen = new Pen(Color.Black, 2);
cursorPen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
cursorPen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
}
private void panel2_Paint(object? sender, PaintEventArgs e)
{
var g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
for (int i = 1; i < points.Count; ++i)
g.DrawLine(cursorPen, points[i - 1], points[i]);
}
private void panel2_MouseDown(object? sender, MouseEventArgs e)
{
if (!cursorMoving)
{
cursorMoving = true;
points.Clear();
points.Add(e.Location);
panel2.Invalidate();
}
}
private void panel2_MouseMove(object? sender, MouseEventArgs e)
{
if (cursorMoving && points.Count > 0)
{
var p = e.Location;
var q = points[points.Count - 1];
var r = Rectangle.FromLTRB(Math.Min(p.X, q.X), Math.Min(p.Y, q.Y), Math.Max(p.X, q.X), Math.Max(p.Y, q.Y));
r = Rectangle.Inflate(r, (int)cursorPen.Width, (int)cursorPen.Width);
points.Add(p);
panel2.Invalidate(r);
}
}
private void panel2_MouseUp(object? sender, MouseEventArgs e)
{
cursorMoving = false;
}
}
}
Don't forget to add the Paint handler the same way you added MouseMove, MouseDown and MouseUp handlers - in the Designer.
Before starting a project, I want to know beforehand whether the following would work.
The application creates a System.Drawing.Bitmap and paints on it.
The Bitmap is much larger than the PictureBox. The Height of the Bitmap and the PictureBox are the same. Now I would like to be able to move the Image from left to right within (along) the PictureBox by pressing the left mouse button and moving it.
See the drawing:
I just realized that I haven't answered yet, which I am trying to make up for.
As a solution, I use Jimi's solution. I've shortened the code here to meet my needs.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Windows.Forms;
namespace Zoom_an_image_from_the_mouse_location
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
string imagePath = "C:\\Users\\yourPath\\Pictures\\....jpeg";
drawingImage = (Bitmap)Image.FromStream(new MemoryStream(File.ReadAllBytes(imagePath)));
imageRect = new RectangleF(Point.Empty, drawingImage.Size);
canvas = new PictureBoxEx(new Size(525,700));
canvas.Location = new Point(10, 10);
canvas.MouseMove += this.canvas_MouseMove;
canvas.MouseDown += this.canvas_MouseDown;
canvas.MouseUp += this.canvas_MouseUp;
canvas.Paint += this.canvas_Paint;
this.Controls.Add(canvas);
}
private void FormMain_Load(object sender, EventArgs e)
{
this.BackColor = Color.FromArgb(174, 184, 177);
}
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
}
private float rotationAngle = 0.0f;
private float zoomFactor = 1.0f;
private RectangleF imageRect = RectangleF.Empty;
private PointF imageLocation = PointF.Empty;
private PointF mouseLocation = PointF.Empty;
private Bitmap drawingImage = null;
private PictureBoxEx canvas = null;
private void canvas_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
mouseLocation = e.Location;
imageLocation = imageRect.Location;
canvas.Cursor = Cursors.NoMove2D;
}
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
imageRect.Location =
new PointF(imageLocation.X + (e.Location.X - mouseLocation.X),
imageLocation.Y); //+ (e.Location.Y - mouseLocation.Y));
canvas.Invalidate();
}
private void canvas_MouseUp(object sender, MouseEventArgs e) =>
canvas.Cursor = Cursors.Default;
private void canvas_Paint(object sender, PaintEventArgs e)
{
var drawingRect = GetDrawingImageRect(imageRect);
using (var mxRotation = new Matrix())
using (var mxTransform = new Matrix())
{
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.PixelOffsetMode = PixelOffsetMode.Half;
mxRotation.RotateAt(rotationAngle, GetDrawingImageCenterPoint(drawingRect));
mxTransform.Multiply(mxRotation);
e.Graphics.Transform = mxTransform;
e.Graphics.DrawImage(drawingImage, drawingRect);
}
}
#region Drawing Methods
public RectangleF GetScaledRect(RectangleF rect, float scaleFactor) =>
new RectangleF(rect.Location,
new SizeF(rect.Width * scaleFactor, rect.Height * scaleFactor));
public RectangleF GetDrawingImageRect(RectangleF rect) =>
GetScaledRect(rect, zoomFactor);
public PointF GetDrawingImageCenterPoint(RectangleF rect) =>
new PointF(rect.X + rect.Width / 2f, rect.Y + rect.Height / 2f);
#endregion
}
}
[DesignerCategory("Code")]
public class PictureBoxEx : PictureBox
{
public PictureBoxEx() : this(new Size(525, 700)) { }
public PictureBoxEx(Size size)
{
SetStyle(ControlStyles.Selectable | ControlStyles.UserMouse, true);
this.BorderStyle = BorderStyle.FixedSingle;
this.Size = size;
}
}
How would I approach making an eraser for a Paint-type application, when my free drawing is done with lines stored in a GraphicsPath?
I've tried the following, but it looks like the Points IEnumerable is read-only. The tricky part is that I have to keep a thin border around the painted strokes so the eraser would have to maintain the border around the remaining GraphicsPath.
Here's what I tried to remove part of the GraphicsPath:
private void Testform_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
List <PointF> list = _drawingPath.PathData.Points.ToList<PointF>();
for (int i = 0; i < 50; i++)
{
list.RemoveAt(i);
}
Invalidate();
}
}
That bit is just for testing hence no exception handling and the arbitrary use of 50. If you scribble a bit on the form you'll end up with more than 50 points to test.
And here is my complete code:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;
namespace Cartographer
{
public partial class testform : Form
{
private GraphicsPath _drawingPath = new GraphicsPath();
private Point lastMouseLocation;
private bool drawing = false;
public testform()
{
InitializeComponent();
}
private void testform_Load(object sender, EventArgs e)
{
this.Paint += Testform_Paint;
this.MouseMove += Testform_MouseMove;
this.MouseDown += Testform_MouseDown;
this.DoubleBuffered = true;
}
private void Testform_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
List <PointF> list = _drawingPath.PathData.Points.ToList<PointF>();
for (int i = 0; i < 50; i++)
{
list.RemoveAt(i);
}
Invalidate();
}
}
private void Testform_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
drawing = true;
_drawingPath.AddLine(lastMouseLocation, e.Location);
Invalidate();
}
if (e.Button == MouseButtons.None && drawing)
{
drawing = false;
_drawingPath.StartFigure();
}
lastMouseLocation = e.Location;
}
private void Testform_Paint(object sender, PaintEventArgs e)
{
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
using (SolidBrush b = new SolidBrush(Color.Blue))
using (Pen p = new Pen(b, 51))
{
p.StartCap = System.Drawing.Drawing2D.LineCap.Round;
p.EndCap = System.Drawing.Drawing2D.LineCap.Round;
p.Alignment = System.Drawing.Drawing2D.PenAlignment.Inset;
e.Graphics.DrawPath(p, _drawingPath);
}
using (SolidBrush b = new SolidBrush(Color.LightGreen))
using (Pen p = new Pen(b, 50))
{
p.StartCap = System.Drawing.Drawing2D.LineCap.Round;
p.EndCap = System.Drawing.Drawing2D.LineCap.Round;
p.Alignment = System.Drawing.Drawing2D.PenAlignment.Inset;
e.Graphics.DrawPath(p, _drawingPath);
}
}
}
}
If you try it for yourself you'll notice the border I need to maintain. All I need to figure out is how to erase parts of the drawing while maintaining the border.
Thank you!
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 UTUResultWithCoordinates
{
public partial class GetCoordinates : Form
{
private string sem;
private string branch;
private int mouseisdown = 0;
private int recx = 0;
private int recy = 0;
private int mousemovingwhilepressed = 0;
public GetCoordinates()
{
InitializeComponent();
}
public GetCoordinates(string p, string p_2)
{
// TODO: Complete member initialization
InitializeComponent();
branch = p;
sem = p_2;
pictureBox1.Controls.Add(pictureBox2);
pictureBox2.Location = new Point(0, 0);
pictureBox2.BackColor = Color.Transparent;
pictureBox2.Width = 1191;
pictureBox2.Height = 842;
}
private void GetCoordinates_Load(object sender, EventArgs e)
{
pictureBox1.ImageLocation = #"D:\DotNet\UTUResultWithCoordinates\UTUResultWithCoordinates\bin\Debug\ComputerScience6.jpg";
}
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
if (mouseisdown == 1 && mousemovingwhilepressed==1)
{
System.Drawing.Graphics graphicsObj;
graphicsObj = this.CreateGraphics();
Pen myPen = new Pen(System.Drawing.Color.Blue, 100);
Rectangle myRectangle = new Rectangle(recx, recy, 20, 20);
e.Graphics.DrawRectangle(myPen, myRectangle);
}
}
private void pictureBox2_MouseDown(object sender, MouseEventArgs e)
{
mouseisdown = 1;
recx = e.X;
recy = e.Y;
pictureBox2.CreateGraphics();
}
private void pictureBox2_MouseMove(object sender, MouseEventArgs e)
{
label1.Text = e.X + "," + e.Y;
mousemovingwhilepressed = 1;
recx = e.X;
recy = e.Y;
pictureBox2.CreateGraphics();
}
private void pictureBox2_MouseUp(object sender, MouseEventArgs e)
{
mousemovingwhilepressed = 0;
mouseisdown = 0;
pictureBox2.CreateGraphics();
}
}
}
I have created a pictureBox1 in which an image is displayed. Then I have created a pictureBox2 inside it so that I can paint on that image a rectangle by dragging the mouse. But nothing is happening on clicking the mouse. What is the error?
Calling CreateGraphics does not trigger the painting of the PictureBox.
Use Invalidate to cause a redraw.
For a full example see: How to select an area on a PictureBox.Image with mouse in C#
Side notes:
Calling InitializeControl in a method other than the constructor is not a good idea.
when you need a boolean use a boolean, not an integer.
Objects that implement IDisposable (such as Pen) should be created as few times as possible and be disposed when no longer needed/used.
I'm trying to draw a single line using OnMouseMove() event. My Problem is that everytime I move the mouse It leaves a trail. I tried to use the refresh method, but when I stop moving the mouse the line is gone. I don't want the line to be drawn OnPaint();, Just want to draw it OnMouseMove().
EDIT: I'm using a transparent panel(cp.ExStyle |= 0x20;), so I cant use the graphics.Clear() and BackColor()
Here's a Sample Image without the Refresh():
Here's my code:
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
Graphics g = panel1.CreateGraphics();
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
using (var p = new Pen(Color.Black, 3))
{
p.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
g.DrawLine(p, st, e.Location);
}
Thread.Sleep(30);
Invalidate();
//this.Refresh();
g.Dispose();
}
Regards
The following works for me. Basically keep track of the last line drawn and draw over it with the background color of the panel (gives the effect of clearing it).
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private const int PEN_WIDTH = 3;
private const LineCap START_CAP = LineCap.ArrowAnchor;
private const LineCap END_CAP = LineCap.ArrowAnchor;
Point mAnchorPoint = new Point(10, 10);
Point mPreviousPoint = Point.Empty;
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
using (Graphics g = panel1.CreateGraphics())
{
// Clear last line drawn
using (Pen clear_pen = new Pen(panel1.BackColor, PEN_WIDTH))
{
clear_pen.StartCap = START_CAP;
clear_pen.EndCap = END_CAP;
g.DrawLine(clear_pen, mAnchorPoint, mPreviousPoint);
}
// Update previous point
mPreviousPoint = e.Location;
// Draw the new line
using (Pen draw_pen = new Pen(Color.Black, PEN_WIDTH))
{
draw_pen.StartCap = START_CAP;
draw_pen.EndCap = END_CAP;
g.DrawLine(draw_pen, mAnchorPoint, e.Location);
}
}
}
}
If you panel's background color is set to Transparent, you will need to change panel1.BackColor to panel1.Parent.BackColor
If the Transparent Panel is not working, you could use the DrawReversibleLine function (although this doesn't allow the color or thickness of the line to be changed, it should have no issues with drawing/erasing even if the panel is Transparent:
Point mAnchorPoint = new Point(200, 200);
Point mPreviousPoint = Point.Empty;
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (mPreviousPoint != Point.Empty)
{
// Clear last line drawn
ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
}
// Update previous point
mPreviousPoint = e.Location;
mPreviousPoint.Offset(myPanel1.Location);
// Draw the new line
ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
}
Another simple way to draw a line with mouse in C#:
public partial class Form1 : Form
{
Options_c o = new Options_c();
public Form1()
{
InitializeComponent();
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
o.Allow = false;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
o.Allow = true;
o.X = e.X;
o.Y = e.Y;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (o.Allow == true)
{
Graphics g = pictureBox1.CreateGraphics();
Pen p1 = new Pen(o.color, 5);
g.DrawLine(p1, o.X,o.Y, e.X, e.Y);
o.X = e.X;
o.Y = e.Y;
}
}
}
class Options_c
{
public Boolean Allow = false;
public Int32 X;
public Int32 Y;
public Color color = Color.Bisque;
}
After
g.DrawLine(p, st, e.Location);
put:
st = e.Location;
Does that fix the problem?
The problem with the line disappearing is that when the panel is repainted, the line is not redrawn. What you really need is to update the end-point of the line-segment when the mouse is moved across the panel and to invalidate the panel. Of course, this will mean that you do handle the Paint event on the panel.
Code here, without the event-handler registration:
Point endPoint;
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
using (var p = new Pen(Color.Black, 3))
{
p.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
g.DrawLine(p, st, endPoint);
}
Thread.Sleep(30);
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
endPoint = e.Location;
panel1.Invalidate();
}
OKaie, i got it! If you have to draw a line between two geopoint
location on tocuhing these two location, then u have to use the
overlay class in this shape... MY CODE IS :
in Main activity write this code also:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mapView = (MapView) findViewById(R.id.mapView1);
mapView.setBuiltInZoomControls(true);
mapOverlays = mapView.getOverlays();//it get the mapview all overlays...
mc = mapView.getController();
mc.setZoom(13);
GeoPoint p = new GeoPoint(34159000,73220000);//starting point Abbottabad
GeoPoint p1 = new GeoPoint(41159000,43220000);//starting point Abbottabad
List<Overlay> mapOverlays2 ;
mapOverlays2 = mapView.getOverlays();
projection = mapView.getProjection();
myoverlay = new MarkerOverlay(p,p1);
mapOverlays2.add(myoverlay);//*/
}
class MarkerOverlay extends Overlay
{
GeoPoint p,p1;
private GeoPoint pa;
public MarkerOverlay(GeoPoint p,GeoPoint p1)
{
this.p = p;
this.p1=p1;
Toast.makeText(GoogleMapShowActivity.this, "point value is "+p +"-->"+p1, Toast.LENGTH_LONG).show();
}
public void draw(Canvas canvas, MapView mapView,boolean shadow)//), long when)
{
super.draw(canvas, mapView, shadow);
Paint mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4);
GeoPoint gP1 = new GeoPoint(p.getLatitudeE6(),p.getLongitudeE6());//starting point Abbottabad
GeoPoint gP2 = new GeoPoint(p1.getLatitudeE6(),p1.getLongitudeE6());//(33695043,73050000);//End point Islamabad
Point p1 = new Point();
Point p2 = new Point();
Path path1 = new Path();
projection.toPixels(gP1, p1); //changing the latitude into the screen pixels.
projection.toPixels(gP2, p2);
path1.moveTo(p1.x, p1.y);//Moving to Abbottabad location
path1.lineTo(p2.x,p2.y);//Path till Islamabad
canvas.drawPath(path1, mPaint);//Actually drawing the path from Abbottabad to Islamabad
}
//--------------------------//
public boolean onTouchEvent(MotionEvent event, MapView mapView)
{
location_touch++;//this is called two times before executing other codes in thsi method(),
// Toast.makeText(GoogleMapShowActivity.this, "this is mmmm"+location_touch, Toast.LENGTH_LONG).show();
if (event.getAction() == 1)
{
// Toast.makeText(GoogleMapShowActivity.this, "this is me ..."+location_touch, Toast.LENGTH_LONG).show();
GeoPoint p = mapView.getProjection().fromPixels((int) event.getX(), (int) event.getY());
if((location_touch%2)!=0)
{
location_touch=0;
Toast.makeText(GoogleMapShowActivity.this, "VALUE 2..."+location_touch+"gp is "+p+",,"+p1, Toast.LENGTH_LONG).show();
mapView.getOverlays().add(new MarkerOverlay(p,pa));
mapView.invalidate();
}
else //if((location_touch==0 ))
{
pa=p;
Toast.makeText(GoogleMapShowActivity.this, "VALUE 1.."+location_touch+",,,"+p1, Toast.LENGTH_LONG).show();
location_touch++;
}