在图片框图像上绘图

ZFRKNC

新成员
已加入
2020年7月12日
留言内容
2
编程经验
Beginner
您好,我正在尝试提出一个解决我的数学问题的应用程序。
我想做这个 ;
一个用于将图像上传到图片框的按钮,然后我要用鼠标在此图像上绘制。还有一个用于注释的橡皮擦(不是pixboxbox图像)。因为很多图像程序都使用橡皮擦作为白色。我的代码是
C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using 系统绘图;
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, 图片.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 = 图片.FromFile(resimkonumu[listView1.SelectedIndices[0]]);
        }
    }
}
你能帮忙吗?
 
由主持人最后编辑:

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,500
地点
弗吉尼亚州切萨皮克
编程经验
10+
请在以后的帖子中将代码放入代码标签中。

通常,要执行这样的操作,您不想使用图片框,而是要覆盖paint事件处理程序。如果您坚持使用画框的想法,那么您将不得不让画框自己绘画,然后在画框上绘画;或者您操纵图片框正在显示的图片图像中的像素,然后替换该图像以使图片框绘制新图像。无论哪种方式,您都需要做一些绘画。

另外,我相信MSDN或CodeProject都具有用于非常简单的绘图程序的示例代码。如果没有这些资料,Petzold的涵盖WinForms的最新版本的Programming Windows也有一个简单的绘图程序。
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,501
地点
悉尼,澳大利亚
编程经验
10+
用一个 图片框 是正确的方法,但您应该处理 涂料 该控件的事件。基本上,您将代表图形的数据存储在一个或多个字段中,然后在 涂料 事件处理程序,您将读取该数据并执行绘图。每次图形更改时,您都相应地更新字段,然后调用 无效图片框 安排一个 涂料 事件。擦除仅表示从字段中删除数据。这是一个非常简单的示例,可让您在 图片框 并将它们转移到 图片 在里面 图片框.
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 涂料EventHandler(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 在里面 图片框 control.
            this.pictureBox1.Image = new Bitmap(this.pictureBox1.Width, this.pictureBox1.Height);
        }
        private void 图片框1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            //Remember the point at which the line started.
            this.start = e.Location;
        }
        private void 图片框1_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 图片框1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            //Draw each line 在 control.
            this.DrawLines(e.Graphics);
        }
        private void Save()
        {
            //Create a 图形 object from the 图片 在里面 图片框.
            using (Graphics g = 图形.FromImage(this.pictureBox1.Image))
            {
                //Draw each line 在 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;
    }
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,500
地点
弗吉尼亚州切萨皮克
编程经验
10+
But all you are doing is letting the 图片框 do is call the 图形.DrawImage... Something that you could just as easily do yourself.
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,501
地点
悉尼,澳大利亚
编程经验
10+
图片框控件针对GDI +进行了优化。在其上进行绘制通常比窗体或其他控件更平滑。我建议使用PictureBox进行绘制,即使它不在现有Image上完成也是如此。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,500
地点
弗吉尼亚州切萨皮克
编程经验
10+
Really? Seems to just call 图形.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();
                图片Animator.UpdateFrames(this.Image);
                
                // Error and initial image are drawn centered, non-stretched.
                Rectangle drawingRect =
                    (imageInstallationType == 图片InstallationType.ErrorOrInitial)
                    ? 图片RectangleFromSizeMode(PictureBoxSizeMode.CenterImage)
                    : 图片Rectangle;
                
                pe.Graphics.DrawImage(image, drawingRect);
                
            }
 
            // Windows draws the border for us (see CreateParams)
            base.OnPaint(pe); // raise 涂料 event
        }

 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,500
地点
弗吉尼亚州切萨皮克
编程经验
10+
并且, 图形 类调用GDI +:
图形类
定义
命名空间:系统绘图
程序集:System.Drawing.Common.dll

封装GDI +绘图表面。

并由 源代码:

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);
}
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,501
地点
悉尼,澳大利亚
编程经验
10+
我好一阵子都没有试过,但是我记得很早以前做了一些测试,发现某些情况在未在PictureBox上平滑绘制的PictureBox上绘制时会产生闪烁。我相当确定那是在窗体上将DoubleBuffered设置为True的情况。一直都无法回忆起具体情况。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,500
地点
弗吉尼亚州切萨皮克
编程经验
10+
是的,当绘制PictureBox时,当您需要等待在Paint事件上进行绘制时(就像您在上面的代码示例中所做的那样)。在学习过程中,大多数人会在鼠标事件期间尝试进行绘制,并且会因后来引起的闪烁而感到沮丧。 (我相信有一个最近的CodeProject示例,其中有人正在执行此操作-在鼠标事件期间进行绘制。)
 
最佳 底部