drawing on picture box image

ZFRKNC

New member
Joined
Jul 12, 2020
Messages
2
Programming Experience
Beginner
hello, i'm trying to make an application for solving my math questions.
i want to do this ;
a button for uploading image to picturebox ,then i want to draw on this image with mouse.And a eraser for annotate (not pixturebox image).Because lot of image program using eraser as white color.my codes are
C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace resim_galerisi
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        Color renk = Color.Red;
        int resimsayar = 0;
        List<string> resimkonumu = new List<string>();
        
        private void Form1_Load(object sender, EventArgs e)
        {
            openFileDialog1.Multiselect = true;
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                foreach (string DosyaYolu in openFileDialog1.FileNames)
                {
                    imageList1.Images.Add(DosyaYolu, Image.FromFile(DosyaYolu));
                    resimkonumu.Add(DosyaYolu);
                    ListViewItem önizleme = new ListViewItem();
                    listView1.Items.Add(önizleme);
                    önizleme.ImageIndex = resimsayar;
                    resimsayar=resimsayar+1;
                }
            }
        }
        
        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count < 1)
            {
                return;
            }
            
            pictureBox1.Image = Image.FromFile(resimkonumu[listView1.SelectedIndices[0]]);
        }
    }
}
can u help pls?
 
Last edited by a moderator:
Please put your code in code tags in your future posts.

Normally, to do something like this, you do not want to use a picture box, but rather override the paint event handler. If you stick with the picture box idea, you'll be left with the situation of letting the picture box to paint itself, and then you painting over the picture box; or you manipulating the pixels in the image of picture being displayed by the picture box, and then replacing the image to let the picture box draw the new image. Either way, you'll need to do some painting.

Also, I believe either MSDN or CodeProject has sample code for a very simple drawing program. And if not those sources, Petzold's latest edition of Programming Windows which covers WinForms also has a simple drawing program.
 
Using a PictureBox is the right way to go but you should be handling the Paint event of that control. Basically, you store the data that represents the drawing in one or more fields and then, in the Paint event handler, you read that data and perform the drawing. Every time the drawing changes, you update the field(s) accordingly and then call Invalidate on the PictureBox to schedule a Paint event. Erasing just means removing the data from the field(s). Here's a very simple example that allows you to draw lines on a PictureBox and transfer them to the Image in the PictureBox.
C#:
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            //Add EventHandlers
            this.pictureBox1.MouseDown += new MouseEventHandler(this.PictureBox1_MouseDown);
            this.pictureBox1.MouseUp += new MouseEventHandler(this.PictureBox1_MouseUp);
            this.pictureBox1.Paint += new PaintEventHandler(this.PictureBox1_Paint);
        }
 
        //The lines that have been drawn but not saved.
        private List<Line> lines = new List<Line>();
 
        //The start point of the line currently being drawn.
        private Point start;
 
        private void Form1_Load(object sender, EventArgs e)
        {
            //Place a blank image in the PictureBox control.
            this.pictureBox1.Image = new Bitmap(this.pictureBox1.Width, this.pictureBox1.Height);
        }
        private void PictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            //Remember the point at which the line started.
            this.start = e.Location;
        }
        private void PictureBox1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            //Remember the point at which the line ended.
            Point end = e.Location;
 
            //Add the new line to the list.
            this.lines.Add(new Line(this.start, end));
 
            Rectangle area = new Rectangle(Math.Min(this.start.X, end.X),
                                           Math.Min(this.start.Y, end.Y),
                                           Math.Abs(this.start.X - end.X),
                                           Math.Abs(this.start.Y - end.Y));
 
            //Inflate the rectangle by 1 pixel in each direction to ensure every changed pixel will be redrawn.
            area.Inflate(1, 1);
 
            //Force the control to repaint so the new line is drawn.
            this.pictureBox1.Invalidate(area);
            this.pictureBox1.Update();
        }
        private void PictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            //Draw each line on the control.
            this.DrawLines(e.Graphics);
        }
        private void Save()
        {
            //Create a Graphics object from the Image in the PictureBox.
            using (Graphics g = Graphics.FromImage(this.pictureBox1.Image))
            {
                //Draw each line on the image to make them permanent.
                this.DrawLines(g);
            }
 
            //Clear the temporary lines that were just saved.
            this.Clear();
        }
        private void Clear()
        {
            //Clear all unsaved lines.
            this.lines.Clear();
 
            //Force the control to repaint so the lines are removed.
            this.pictureBox1.Refresh();
        }
        private void DrawLines(Graphics g)
        {
            foreach (Line line in this.lines)
            {
                g.DrawLine(Pens.Black, line.start, line.end);
            }
        }
 
    }
 
    public class Line
    {
        //The line's start point.
        public Point start
        {
            get { return _start; }
            set { _start = value; }
        }
        //The line's end point.
        public Point end
        {
            get { return _end; }
            set { _end = value; }
        }
 
        public Line() : this(Point.Empty, Point.Empty)
        {
        }
 
        public Line(Point start, Point end)
        {
            this._end = end;
            this._start = start;
        }
 
        private Point _start;
        private Point _end;
    }
 
But all you are doing is letting the PictureBox do is call the Graphics.DrawImage... Something that you could just as easily do yourself.
 
The PictureBox control is optimised for GDI+. Drawing on it is generally smoother than a form or other control. I would suggest using a PictureBox for drawing even if it's not being done over an existing Image.
 
Really? Seems to just call Graphics.DrawImage() to me:
C#:
       protected override void OnPaint(PaintEventArgs pe) {
 
            if (pictureBoxState[PICTUREBOXSTATE_needToLoadImageLocation])
            {
                try
                {
                    if (WaitOnLoad)
                    {
                        Load();
                    }
                    else
                    {
                        LoadAsync();
                    }
                }
                catch (Exception ex)
                {   //Dont throw but paint error image LoadAsync fails....
                    // Microsoft FXCOP 
 
 
                    if (ClientUtils.IsCriticalException(ex))
                    {
                        throw;
                    }
                    image = ErrorImage;
                }
            }
            
            if (image != null) {
                Animate();
                ImageAnimator.UpdateFrames(this.Image);
                
                // Error and initial image are drawn centered, non-stretched.
                Rectangle drawingRect =
                    (imageInstallationType == ImageInstallationType.ErrorOrInitial)
                    ? ImageRectangleFromSizeMode(PictureBoxSizeMode.CenterImage)
                    : ImageRectangle;
                
                pe.Graphics.DrawImage(image, drawingRect);
                
            }
 
            // Windows draws the border for us (see CreateParams)
            base.OnPaint(pe); // raise Paint event
        }

 
And also, Graphics class calls GDI+:
Graphics Class
Definition
Namespace:System.Drawing
Assembly:System.Drawing.Common.dll

Encapsulates a GDI+ drawing surface.

and backed up by the source code:

Graphics.DrawImage():
public void DrawImage(Image image, float x, float y) {
    if (image == null)
        throw new ArgumentNullException("image");

    int status = SafeNativeMethods.Gdip.GdipDrawImage(new HandleRef(this, this.NativeGraphics), new HandleRef(image, image.nativeImage),
                                                      x, y);

    //ignore emf metafile error
    IgnoreMetafileErrors(image, ref status);

    //check error status sensitive to TS problems
    CheckErrorStatus(status);
}
 
I haven't tried in a good while but I recall doing some testing a good while ago and finding that certain situations produced flickering when not drawn on a PictureBox that were smooth on a PictureBox. I'm fairly certain that that was with DoubleBuffered set to True on the form. Can't recall the specifics after all this time.
 
Yes, when drawing the PictureBox, when you need to wait to draw on on the Paint event (like you have done in your code sample above). While learning, most people attempt to do the draw during the mouse events and are frustrated by the flicker caused later. (I believe there is a recent CodeProject example where someone is doing exactly this -- drawing during the mouse events.)
 
Back
Top Bottom