FrmOpenCamera.cs 11.4 KB
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 Asa.Camera
{
    public partial class FrmOpenCamera : Form
    {
        private int id;
        private string name;
        public List<CameraRegion> regions;
        private float zoom = 0.5f;
        private Bitmap bmp;
        private int selectIdx;
        private Point oldPoint;
        private FieldMargin fieldMargin = FieldMargin.Outside;

        private const int FIELD_MARGIN = 5;
        private readonly Font TEXT_FONT = new("宋体", 12f);
        
        public FrmOpenCamera()
        {
            InitializeComponent();
        }

        public FrmOpenCamera(string cameraName, List<CameraRegion> regions) : this()
        {
            name = cameraName;
            this.regions = new();
            foreach (CameraRegion reg in regions)
                this.regions.Add(reg.Clone());
            selectIdx = -1;
            Common.visionLib.Open();
            bmp = Common.visionLib.GetImage(name);
            NudZoom.Value = (decimal)zoom;
        }




        private void ChangeNameRatio()
        {
            if (selectIdx == -1)
            {
                TxtName.Text = "";
                NudRatio.Value = 0;
            }
            else
            {
                TxtName.Text = regions[selectIdx].RegionName;
                NudRatio.Value = (decimal)regions[selectIdx].Ratio;
            }
        }

        private void FindFieldMargin(Point pt)
        {
            fieldMargin = FieldMargin.Outside;
            RectangleF rect = new(regions[selectIdx].X * zoom, regions[selectIdx].Y * zoom, regions[selectIdx].Width * zoom, regions[selectIdx].Height * zoom);

            if (Math.Abs(rect.X - pt.X) < FIELD_MARGIN)
            {
                if (Math.Abs(rect.Y - pt.Y) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.LeftTop;
                else if (Math.Abs(pt.Y - rect.Y - rect.Height) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.LeftBottom;
                else if (pt.Y > rect.Y && pt.Y < rect.Y + rect.Height)
                    fieldMargin = FieldMargin.Left;
            }
            else if (Math.Abs(rect.X + rect.Width - pt.X) < FIELD_MARGIN)
            {
                if (Math.Abs(rect.Y - pt.Y) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.RightTop;
                else if (Math.Abs(pt.Y - rect.Y - rect.Height) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.RightBottom;
                else if (pt.Y > rect.Y && pt.Y < rect.Y + rect.Height)
                    fieldMargin = FieldMargin.Right;
            }
            else if (pt.X > rect.X && pt.X < rect.X + rect.Width)
            {
                if (Math.Abs(rect.Y - pt.Y) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.Top;
                else if (Math.Abs(pt.Y - rect.Y - rect.Height) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.Bottom;
                else if (pt.Y > rect.Y && pt.Y < rect.Y + rect.Height)
                    fieldMargin = FieldMargin.Inside;
            }

            switch (fieldMargin)
            {
                case FieldMargin.Left: PicShow.Cursor = Cursors.SizeWE; break;
                case FieldMargin.LeftTop: PicShow.Cursor = Cursors.SizeNWSE; break;
                case FieldMargin.LeftBottom: PicShow.Cursor = Cursors.SizeNESW; break;
                case FieldMargin.Right: PicShow.Cursor = Cursors.SizeWE; break;
                case FieldMargin.RightBottom: PicShow.Cursor = Cursors.SizeNWSE; break;
                case FieldMargin.RightTop: PicShow.Cursor = Cursors.SizeNESW; break;
                case FieldMargin.Top: PicShow.Cursor = Cursors.SizeNS; break;
                case FieldMargin.Bottom: PicShow.Cursor = Cursors.SizeNS; break;
                case FieldMargin.Inside: PicShow.Cursor = Cursors.SizeAll; break;
                case FieldMargin.Outside: PicShow.Cursor = Cursors.Default; break;
            }
        }

        private void ChangeFieldMargin(int x, int y)
        {
            switch (fieldMargin)
            {
                case FieldMargin.Left:
                    regions[selectIdx].X += x;
                    regions[selectIdx].Width -= x;
                    break;
                case FieldMargin.Top:
                    regions[selectIdx].Y += y;
                    regions[selectIdx].Height -= y;
                    break;
                case FieldMargin.Right:
                    regions[selectIdx].Width += x;
                    break;
                case FieldMargin.Bottom:
                    regions[selectIdx].Height += y;
                    break;
                case FieldMargin.LeftTop:
                    regions[selectIdx].X += x;
                    regions[selectIdx].Width -= x;
                    regions[selectIdx].Y += y;
                    regions[selectIdx].Height -= y;
                    break;
                case FieldMargin.RightTop:
                    regions[selectIdx].Y += y;
                    regions[selectIdx].Height -= y;
                    regions[selectIdx].Width += x;
                    break;
                case FieldMargin.LeftBottom:
                    regions[selectIdx].X += x;
                    regions[selectIdx].Width -= x;
                    regions[selectIdx].Height += y;
                    break;
                case FieldMargin.RightBottom:
                    regions[selectIdx].Width += x;
                    regions[selectIdx].Height += y;
                    break;
                case FieldMargin.Inside:
                    regions[selectIdx].X += x;
                    regions[selectIdx].Y += y;
                    break;
            }
        }

        private void FrmOpenCamera_FormClosing(object sender, FormClosingEventArgs e)
        {
            Common.visionLib.Close();
        }

        private void BtnGrabOne_Click(object sender, EventArgs e)
        {
            bmp = Common.visionLib.GetImage(name);
            PicShow.Refresh();
        }

        private void BtnAdd_Click(object sender, EventArgs e)
        {
            CameraRegion region = new()
            {
                CameraName = name,
                RegionName = "name" + ++id,
                X = 0,
                Y = 0,
                Width = 100,
                Height = 100,
                Ratio = 0.3f
            };
            regions.Add(region);
            selectIdx = regions.Count - 1;
            ChangeNameRatio();
            PicShow.Refresh();
        }

        private void BtnDel_Click(object sender, EventArgs e)
        {
            if (selectIdx == -1) return;
            regions.RemoveAt(selectIdx);
            selectIdx = regions.Count == 0 ? -1 : 0;
            ChangeNameRatio();
            PicShow.Refresh();
        }

        private void TxtName_TextChanged(object sender, EventArgs e)
        {
            if (selectIdx == -1) return;
            regions[selectIdx].RegionName = TxtName.Text;
            PicShow.Refresh();
        }

        private void NudRatio_ValueChanged(object sender, EventArgs e)
        {
            if (selectIdx == -1) return;
            regions[selectIdx].Ratio = (float)NudRatio.Value;
            PicShow.Refresh();
        }

        private void NudZoom_ValueChanged(object sender, EventArgs e)
        {
            zoom = (float)NudZoom.Value;
            PicShow.Refresh();
        }

        private void BtnOK_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.OK;
        }

        private void BtnCancel_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
        }

        private void PicShow_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left) return;
            oldPoint = e.Location;
            if (fieldMargin != FieldMargin.Outside) return;

            float x = e.X / zoom;  //放大到正常大小
            float y = e.Y / zoom;  //放大到正常大小
            selectIdx = regions.FindIndex(match => match.X < x && match.Y < y && match.X + match.Width > x && match.Y + match.Height > y);
            ChangeNameRatio();
            if (selectIdx > -1)
                FindFieldMargin(e.Location);
            PicShow.Refresh();
        }

        private void PicShow_MouseMove(object sender, MouseEventArgs e)
        {
            if (selectIdx == -1) return;

            if (e.Button == MouseButtons.Left)
            {
                int x = Convert.ToInt32((e.X - oldPoint.X) / zoom);
                int y = Convert.ToInt32((e.Y - oldPoint.Y) / zoom);
                ChangeFieldMargin(x, y);
                oldPoint = e.Location;
                PicShow.Refresh();
            }
            else if (e.Button == MouseButtons.None)
            {
                FindFieldMargin(e.Location);
            }
        }

        private void PicShow_MouseUp(object sender, MouseEventArgs e)
        {

        }

        private void PicShow_Paint(object sender, PaintEventArgs e)
        {
            if (bmp == null) return;
            RectangleF destRect = new(0, 0, bmp.Width * zoom, bmp.Height * zoom);
            RectangleF srcRect = new(0, 0, bmp.Width, bmp.Height);
            e.Graphics.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel);

            float x, y, width, height;
            for (int i = 0; i < regions.Count; i++)
            {
                x = regions[i].X * zoom;
                y = regions[i].Y * zoom;
                width = regions[i].Width * zoom;
                height = regions[i].Height * zoom;
                string s = regions[i].ToString();
                SizeF sf = e.Graphics.MeasureString(s, TEXT_FONT);
                e.Graphics.FillRectangle(Brushes.White, x, y - sf.Height, sf.Width, sf.Height);
                e.Graphics.DrawString(s, TEXT_FONT, Brushes.Black, x, y - sf.Height);

                if (i == selectIdx)
                {
                    e.Graphics.DrawRectangle(Pens.Red, x, y, width, height);
                    //4个角的矩形
                    e.Graphics.FillRectangle(Brushes.White, x - FIELD_MARGIN, y - FIELD_MARGIN, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.FillRectangle(Brushes.White, x + width, y - FIELD_MARGIN, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.FillRectangle(Brushes.White, x - FIELD_MARGIN, y + height, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.FillRectangle(Brushes.White, x + width, y + height, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.DrawRectangle(Pens.Black, x - FIELD_MARGIN, y - FIELD_MARGIN, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.DrawRectangle(Pens.Black, x + width, y - FIELD_MARGIN, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.DrawRectangle(Pens.Black, x - FIELD_MARGIN, y + height, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.DrawRectangle(Pens.Black, x + width, y + height, FIELD_MARGIN, FIELD_MARGIN);
                }
                else
                {
                    e.Graphics.DrawRectangle(Pens.LimeGreen, x, y, width, height);
                }

            }

        }


        private enum FieldMargin
        {
            Outside,
            Inside,
            Left,
            Top,
            Right,
            Bottom,
            LeftTop,
            RightTop,
            LeftBottom,
            RightBottom
        }


    }
}