绘制多边形,可以右键拖动点对多边形放大,可以左键点住点对多边形进行位移

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Py_picture
{
    public partial class Form1 : Form
    {
        List<Point> points;
        int index;
        bool draw = false;
        float scale = 1.0f;
        Point lastPoint;
        bool pic_size_change = false; //判断图片是否缩放
        bool isMoving = false; // 用于跟踪是否在移动多边形
        Point offset; // 存储鼠标点击时的偏移量

        public Form1()
        {
            InitializeComponent();
            points = new List<Point>();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            pictureBox1.MouseWheel += pictureBox1_MouseWheel;
        }



        #region 按钮事件
        private void button1_Click(object sender, EventArgs e)
        {
            //选择文件夹,选择图片
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "|*.bmp";
            DialogResult = ofd.ShowDialog();
            if (DialogResult == DialogResult.OK)
            {
                string pic = ofd.FileName;
                //图片自适应大小
                pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
                //展示图片
                pictureBox1.Image = Image.FromFile(pic);
                textBox1.Text = pic;
                // 重新绘制以适应新图像
                pictureBox1.Invalidate();
                pic_size_change = false; // 重置缩放状态
                //pictureBox1.Invalidate();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // 检查是否进行了缩放
            if (pictureBox1.Image==null) 
            {
                MessageBox.Show("请先选择图片后,再进行绘制多边形", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
              return;
            }
             else if (pictureBox1.Image != null&& !pic_size_change)
            {
              
                
                    MessageBox.Show("请使用鼠标滚轮,调整好图片后再进行多边形的绘制!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                
            }
            //开始绘制
            draw = true;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            //停止绘制
            draw = false;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            //清除绘制
            points.Clear();
            draw = false;
            pictureBox1.Invalidate();
        }
        #endregion

        #region picture鼠标事件

        private void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
        {
            float oldScale = scale;

            // 记录缩放状态为 true
            pic_size_change = true;

            if (e.Delta > 0)
            {
                scale *= 1.1f; // 放大
            }
            else if (e.Delta < 0)
            {
                scale = Math.Max(0.14f, scale * 0.9f); //缩小,最小为0.14
            }

            if (pictureBox1.Image != null)
            {
                // 计算图像中心点
                float centerX = (e.X - pictureBox1.Left) / oldScale; // 使用旧缩放比例
                float centerY = (e.Y - pictureBox1.Top) / oldScale; // 使用旧缩放比例

                // 更新 PictureBox 的宽高以反映新的缩放比例
                pictureBox1.Width = (int)(pictureBox1.Image.Width * scale);
                pictureBox1.Height = (int)(pictureBox1.Image.Height * scale);

                // 确保中心点位置不变
                int newX = (int)(centerX * scale);
                int newY = (int)(centerY * scale);
                pictureBox1.Left -= (newX - (e.X - pictureBox1.Left));
                pictureBox1.Top -= (newY - (e.Y - pictureBox1.Top));

                pictureBox1.Invalidate(); // 触发重绘
            }
        }

        //private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        //{
        //    // 计算点击点的缩放后坐标
        //    Point clickpoints = new Point((int)(e.X / scale), (int)(e.Y / scale));
        //    lastPoint = new Point(e.X, e.Y);
        //    pictureBox1.Cursor = Cursors.Hand;

        //    if (e.Button == MouseButtons.Left)
        //    {
        //        if (draw)
        //        {
        //            // 使用缩放后的坐标来添加点
        //            points.Add(clickpoints);
        //            pictureBox1.Invalidate();
        //        }
        //    }
        //    else if (e.Button == MouseButtons.Right)
        //    {
        //        index = GetPointIndex(clickpoints);
        //        if (index != -1)
        //        {
        //            pictureBox1.Capture = true;
        //        }
        //    }
        //}

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            Point clickpoints = new Point((int)(e.X / scale), (int)(e.Y / scale));
            lastPoint = new Point(e.X, e.Y);
            pictureBox1.Cursor = Cursors.Hand;

            if (e.Button == MouseButtons.Left)
            {
                if (draw)
                {
                    points.Add(clickpoints);
                    pictureBox1.Invalidate();
                }
                else
                {
                    index = GetPointIndex(clickpoints);
                    if (index != -1)
                    {
                        isMoving = true;
                        offset = new Point(clickpoints.X - points[index].X, clickpoints.Y - points[index].Y);
                    }
                }
            }
            else if (e.Button == MouseButtons.Right)
            {
                index = GetPointIndex(clickpoints);
                if (index != -1)
                {
                    pictureBox1.Capture = true;
                }
            }
        }
        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (isMoving)
            {
                // 更新所有点的位置
                for (int i = 0; i < points.Count; i++)
                {
                    points[i] = new Point(
                        (int)Math.Round(points[i].X + (e.X - lastPoint.X) / scale),
                        (int)Math.Round(points[i].Y + (e.Y - lastPoint.Y) / scale)
                    );
                }
                pictureBox1.Invalidate(); // 触发重绘
            }
            else if (index != -1 && pictureBox1.Capture)
            {
                points[index] = new Point((int)(e.X / scale), (int)(e.Y / scale));
                pictureBox1.Invalidate();
            }

            if (e.Button == MouseButtons.Left)
            {
                int deltaX = e.X - lastPoint.X;
                int deltaY = e.Y - lastPoint.Y;
                pictureBox1.Location = new Point(pictureBox1.Left + deltaX, pictureBox1.Top + deltaY);
            }
            lastPoint = e.Location; // 更新最后一个点
        }



        //private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        //{
        //    if (index != -1 && pictureBox1.Capture)
        //    {
        //        // 更新点的位置,但仍然使用原始坐标
        //        points[index] = new Point((int)(e.X / scale), (int)(e.Y / scale));
        //        pictureBox1.Invalidate();
        //    }

        //    if (e.Button == MouseButtons.Left)
        //    {
        //        int deltaX = e.X - lastPoint.X;
        //        int deltaY = e.Y - lastPoint.Y;
        //        pictureBox1.Location = new Point(pictureBox1.Left + deltaX, pictureBox1.Top + deltaY);
        //    }
        //    lastPoint = e.Location; // 更新最后一个点
        //}



        //private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        //{
        //    pictureBox1.Cursor = Cursors.Default;
        //    // 释放鼠标捕获
        //    pictureBox1.Capture = false;
        //    index = -1; // 重置选中点索引
        //}
        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            pictureBox1.Cursor = Cursors.Default;
            pictureBox1.Capture = false;
            index = -1; // 重置选中点索引
            isMoving = false; // 重置移动状态
        }


        private void pictureBox1_Paint(object sender, PaintEventArgs e) 
        {
            // 在窗体上绘制所有存储的点
            foreach (Point p in points)
            {
                // 绘制小圆点,考虑缩放
                Point scaledPoint = new Point((int)(p.X * scale), (int)(p.Y * scale));
                e.Graphics.FillEllipse(Brushes.Red, scaledPoint.X - 4, scaledPoint.Y - 4, 7, 7); // 绘制小圆点
            }
            // 如果有足够的点,绘制连接线
            if (points.Count > 1)
            {
                using (Pen pen = new Pen(Color.Blue, 2)) // 创建一支蓝色画笔
                {
                    for (int i = 0; i < points.Count - 1; i++)
                    {
                        Point p1 = new Point((int)(points[i].X * scale), (int)(points[i].Y * scale));
                        Point p2 = new Point((int)(points[i + 1].X * scale), (int)(points[i + 1].Y * scale));
                        e.Graphics.DrawLine(pen, p1, p2); // 连接相邻的点
                    }
                }
            }
            // 连接最后一个点和第一个点形成闭合多边形
            if (points.Count > 2)
            {
                using (Pen pen = new Pen(Color.Blue, 2))
                {
                    Point p1 = new Point((int)(points[points.Count - 1].X * scale), (int)(points[points.Count - 1].Y * scale));
                    Point p2 = new Point((int)(points[0].X * scale), (int)(points[0].Y * scale));
                    e.Graphics.DrawLine(pen, p1, p2);
                }
            }
        }




        #endregion

        public int GetPointIndex(Point location)
        {
            //循环遍历集合中的坐标,判断是否为空
            for (int i = 0; i < points.Count; i++)
            {
                Point point = points[i];
                //Point point = new Point((int)(points[i].X * scale), (int)(points[i].Y * scale));
                // 检查点击位置是否在点的范围内
                if (Math.Abs(location.X - point.X) <= 10 && Math.Abs(location.Y - point.Y) <= 10)
                {
                    return i;
                }
            }
            return -1;
        }



    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值