You know, we can easily to make line cursor for Chart (ex: Fig). But with PictureBox, how can I do it? Is there anyone has the solution?

- 187,200
- 47
- 362
- 445

- 25
- 3
-
You need to code the MouseMove event and use a Graphics object created with pbox.CreateGraphics(), usually not a good idea.. – TaW Dec 29 '21 at 16:01
-
@Luke: This is a terrible 'duplicate'..! – TaW Dec 29 '21 at 16:02
-
@TaW CreateGraphics isn't needed, just use the MouseMove and Paint event. – Jeroen van Langen Dec 29 '21 at 16:57
-
Well, it depends on whether the cursor is supposed to be persistent or not. Ususally it isn't. – TaW Dec 29 '21 at 16:59
-
The problem is that when you move the mouse, you always need to recreate the cursor (because the point of crossing of the two lines is changed when moving the mouse. (because the lines are always drawn from 0->width and 0->Height. – Jeroen van Langen Dec 29 '21 at 17:05
-
@Cong Hoan Nguyen it looks like you have never accepted or upvoted an answer. You may want to take a [tour] to learn how to upvote and accept. Then that would be nice to review the answers and upvote/accept. – Reza Aghaei Jan 10 '22 at 22:38
3 Answers
You can intercept the MouseMove and the Paint events. Just draw the cross on the paint.
The advantage of using the Paint method, is that the original image is not changed, so no need to restore the overwritten pixels by the crosshair.
Here's an example:
I dropped a picturebox on a winform and linked some events.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace MouseCrosshair
{
public partial class Form1 : Form
{
// to store the latest mouse position
private Point? _mousePos;
// the pen to draw the crosshair.
private Pen _pen = new Pen(Brushes.Red);
public Form1()
{
InitializeComponent();
}
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
// when the mouse enters the picturebox, we just hide it.
Cursor.Hide();
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
var pictureBox = (PictureBox)sender;
// on a mouse move, save the current location (to be used when drawing the crosshair)
_mousePos = e.Location;
// force an update to the picturebox.
pictureBox.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
// if the mousepos is assigned (meaning we have a mouse pos, draw the crosshair)
if (_mousePos.HasValue)
{
var pictureBox = (PictureBox)sender;
// draw a vertical line
e.Graphics.DrawLine(_pen, new Point(_mousePos.Value.X, 0), new Point(_mousePos.Value.X, pictureBox.Height));
// draw a horizontal line
e.Graphics.DrawLine(_pen, new Point(0, _mousePos.Value.Y), new Point(pictureBox.Width, _mousePos.Value.Y));
}
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
// when the mouse is outside the picturebox, clear the mousepos
_mousePos = null;
// repaint the picturebox
pictureBox1.Invalidate();
// show the mouse cursor again.
Cursor.Show();
}
}
}
Because the events are using the sender
, you can link multiple pictureboxes to these events.
It's also possible to inherit from the PictureBox
, and write a new CrosshairPictureBox
control, which has a crosshair by default.
If you want to draw charts in a PictureBox
, use a Bitmap
and draw on that using the Graphics.FromImage(bitmap)
and put it in the PictureBox.Image
. Don't forget to dispose the Graphics object.

- 21,446
- 3
- 42
- 57
You can achieve this by storing the position of the last point received, and then draw a line using the Graphics.DrawLine
method between the old position and the new one.
Please also note, that when the mouse is moving, the Control.MouseMove
event for every single pixel traveled by the mouse pointer isn't received for every single move. You do receive the Control.MouseMove
events at a fairly consistent time interval. That means that the faster the mouse moves, the further apart the points you'll be actually receiving.
Check out this walkthrough for some examples - https://www.c-sharpcorner.com/UploadFile/mahesh/drawing-lines-in-gdi/

- 14,906
- 5
- 47
- 53
-
I don't think OP want to draw a line with the mouse. He wants to replace the mouse cursor with a big crosshair. – Jeroen van Langen Dec 29 '21 at 16:26
If I understand the question correctly, you are interested to draw x-axis and y-axis for a chart, but not using a chat control.
In this case, what you need to do is: Handle the Paint event of the PictureBox and draw the line from top middle to bottom middle and from left middle to right middle.
Here is the code which I write to produce above chart, y = Sin(x) :
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var axisWidth = 3;
var axisColor = Color.Red;
var chartLineWidth = 2;
var chartLineColor = Color.Blue;
var scale = 90;
var gridSize = 45;
var gridLineWidth = 1;
var gridLineColor = Color.LightGray;
var g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
var w = pictureBox1.ClientRectangle.Width / 2;
var h = pictureBox1.ClientRectangle.Height / 2;
g.TranslateTransform(w, h);
g.ScaleTransform(1, -1);
//Draw grid
for (int i = -w / gridSize; i <= w / gridSize; i++)
using (var axisPen = new Pen(gridLineColor, gridLineWidth))
g.DrawLine(axisPen, i * gridSize, -h, i * gridSize, h);
for (int i = -h / gridSize; i <= h / gridSize; i++)
using (var axisPen = new Pen(gridLineColor, gridLineWidth))
g.DrawLine(axisPen, -w, i * gridSize, w, i * gridSize);
//Draw axis
using (var axisPen = new Pen(axisColor, axisWidth))
{
g.DrawLine(axisPen, -w, 0, w, 0); //X-Asxis
g.DrawLine(axisPen, 0, -h, 0, h); //Y-Asxis
}
//Draw y = Sin(x)
var points = new List<PointF>();
for (var x = -w; x < w; x++)
{
var y = System.Math.Sin(x * Math.PI / 180);
points.Add(new PointF(x, scale * (float)y));
}
using (var chartLinePen = new Pen(chartLineColor, chartLineWidth))
{
g.DrawCurve(chartLinePen, points.ToArray());
}
g.ResetTransform();
}
You also need the following piece of code to handle resizing of the picture box:
private void MyForm_Load(object sender, EventArgs e)
{
this.pictureBox1.GetType().GetProperty("ResizeRedraw",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance).SetValue(
this.pictureBox1, true);
}
You can also add a crosshair and rubber-band rectangle to the control, like the following image:

- 120,393
- 18
- 203
- 398