领胜LDS 键盘AOI检测项目
wells.liu
2020-07-02 22658ee90bd0f8b7b89a6030c2edc7fbf6719c3a
Merge branch 'master' of http://gitblit.broconcentric.com:8088/r/M071
2个文件已添加
16个文件已修改
787 ■■■■ 已修改文件
src/Bro.M071.Process/Bro.M071.Process.csproj 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Process.cs 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/UI/KeyIndicator.cs 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/UI/M071_MainForm.Designer.cs 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/UI/M071_MainForm.cs 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/UI/M071_MainForm.resx 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Config/MenuForms/FrmConfig.Designer.cs 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Config/MenuForms/FrmConfig.resx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Config/MenuForms/FrmLog.Designer.cs 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Config/MenuForms/FrmLog.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Config/MenuForms/FrmLog.resx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Config/MenuForms/FrmOperation.resx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Model.Winform/Element/CrossHair.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Model.Winform/Element/CrossHairWithAngle.cs 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Model.Winform/Element/PointIndicator.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Model.Winform/Element/ROI_Circle.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Model.Winform/Element/ROI_Rectangle.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Model.Winform/ElementBase.cs 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/Bro.M071.Process.csproj
@@ -111,6 +111,7 @@
    <Compile Include="M071Models.cs" />
    <Compile Include="M071Process.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="UI\KeyIndicator.cs" />
    <Compile Include="UI\M071Node.cs" />
    <Compile Include="UI\M071_MainForm.cs">
      <SubType>Form</SubType>
@@ -127,6 +128,9 @@
      <AutoGen>True</AutoGen>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <EmbeddedResource Include="UI\M071_MainForm.resx">
      <DependentUpon>M071_MainForm.cs</DependentUpon>
    </EmbeddedResource>
    <None Include="packages.config" />
    <None Include="Properties\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
src/Bro.M071.Process/M071Process.cs
@@ -154,6 +154,8 @@
            }
        }
        List<ProductionMeasurement> productionList = new List<ProductionMeasurement>();
        [ProcessMethod("", "StartJob", "开始扫描", InvokeType.TestInvoke)]
        public ProcessResponse StartJob(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice)
        {
@@ -175,6 +177,16 @@
                Barcode = BarCode,
                Measurements = measurements,
            };
            var existedProduction = productionList.FirstOrDefault(u => u.Barcode == pMeasure.Barcode);
            if (existedProduction != null)
            {
                productionList.Remove(existedProduction);
                existedProduction.Dispose();
                existedProduction = null;
            }
            productionList.Add(pMeasure);
            pMeasure.InitialMeasurementsPropertyChanged();
            pMeasure.PropertyChanged += MeasureProduction_PropertyChanged;
@@ -200,10 +212,6 @@
                      CameraBase camera = DeviceCollection.FirstOrDefault(u => u.Id == s.CameraOp.Device) as CameraBase;
                      if (camera == null)
                          return;
                      //IImageSet imgSet = camera.Snapshot(s.CameraOp.OpConfig);
                      //if (imgSet == null)
                      //    return;
                      HImage hImage = CollectHImage(camera, s.CameraOp.OpConfig, out string imgSetId);
                      if (string.IsNullOrWhiteSpace(imgSetId))
@@ -294,8 +302,12 @@
                                    }
                                }
                                LogAsync(DateTime.Now, $"{m.GetDisplayText()}检测结果", $"{((m.Spec.MeasureResult ?? false) ? "OK" : "NG")}");
                                IShapeElement indicator = null;
                                pMeasure.ElementList.Add(indicator);
                                //输出图形基元到界面 todo
                                OnElementUpdated?.BeginInvoke(null, null, null);
                                OnElementUpdated?.BeginInvoke(indicator, null, null);
                                SaveKeyImages(pMeasure.Barcode, m);
@@ -309,8 +321,6 @@
                        return;
                    }
                    //MES输出 todo
                    //Excel报表输出 todo
@@ -318,6 +328,8 @@
                    //数据库保存 todo
                    SaveWholeImage(pMeasure);
                    productionList.RemoveAll(p => p.Barcode == pMeasure.Barcode);
                    pMeasure.Dispose();
                }
            }
src/Bro.M071.Process/UI/KeyIndicator.cs
New file
@@ -0,0 +1,142 @@
using Bro.Common.Helper;
using Bro.Common.Model;
using Bro.UI.Model.Winform;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Bro.M071.Process.UI
{
    public class KeyIndicator : ElementBase
    {
        [Browsable(false)]
        public override string ID { get => base.ID; set => base.ID = value; }
        [Browsable(false)]
        public override string Name { get => base.Name; set => base.Name = value; }
        [Browsable(false)]
        public override Font Font { get => base.Font; set => base.Font = value; }
        [Browsable(false)]
        public override int FontDistance { get => base.FontDistance; set => base.FontDistance = value; }
        [Browsable(false)]
        public override int Index { get => base.Index; set => base.Index = value; }
        [Browsable(false)]
        public override bool IsShowRemark { get => base.IsShowRemark; set => base.IsShowRemark = value; }
        [Browsable(false)]
        public override bool IsEnabled { get => base.IsEnabled; set => base.IsEnabled = value; }
        //[Category("显示设置")]
        //[Description("左上/开始点位")]
        //[TypeConverter(typeof(ComplexObjectConvert))]
        //[Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
        //[Browsable(false)]
        //public CustomizedPoint StartPoint { get; set; } = new CustomizedPoint();
        //[Category("显示设置")]
        //[Description("显示区域大小")]
        //[TypeConverter(typeof(ComplexObjectConvert))]
        //[Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
        //public CustomizedPoint Size { get; set; } = new CustomizedPoint();
        [Category("显示设置")]
        [Description("标签显示区域")]
        [DisplayName("标签显示区域")]
        public Rectangle DisplayRect { get; set; } = new Rectangle();
        [Browsable(false)]
        public string Text { get; set; } = "";
        [Browsable(false)]
        public bool? ResultState { get; set; } = null;
        public KeyIndicator() { }
        public KeyIndicator(string id, Rectangle rect)
        {
            ID = id;
            DisplayRect = rect;
        }
        public override object Clone()
        {
            return new KeyIndicator()
            {
                DisplayRect = this.DisplayRect,
            };
        }
        public override void Draw(Graphics g)
        {
            g.DrawRectangle(Pen, DisplayRect);
            RectangleF rectFill = new RectangleF(DisplayRect.X + 1, DisplayRect.Y + 1, DisplayRect.Width - 2, DisplayRect.Height - 2);
            if (ResultState != null)
            {
                var txtSize = g.MeasureString(Text, Font);
                Color backColor = Color.Green;
                Color foreColor = Color.Black;
                if (!ResultState.Value)
                {
                    backColor = Color.Red;
                    foreColor = Color.White;
                }
                g.DrawString(Text, Font, new SolidBrush(foreColor), (float)(DisplayRect.X + DisplayRect.Width / 2.0 - txtSize.Width / 2.0), (float)(DisplayRect.Y + DisplayRect.Height / 2.0 - txtSize.Height / 2.0));
                g.FillRectangle(new SolidBrush(Color.FromArgb(55, backColor)), rectFill);
            }
        }
        public override string GetDisplayText()
        {
            return $"{DisplayRect.X} {DisplayRect.Y} {DisplayRect.Width} {DisplayRect.Height}";
        }
        public override bool IsIntersect(Rectangle rect)
        {
            return false;
        }
        public override bool IsMouseHover(Point p)
        {
            return false;
        }
        public override bool IsMouseInSide(Point p)
        {
            return false;
        }
        public override void OnKeyDown(object sender, KeyEventArgs e)
        {
        }
        public override void OnKeyUp(object sender, KeyEventArgs e)
        {
        }
        public override void OnMouseDownWhenNew(Point p)
        {
        }
        public override void OnMouseMoveWhenNew(Point p)
        {
        }
        public override void OnMouseUpWhenNew(Point p)
        {
        }
        public override void Translate(int x, int y)
        {
        }
        protected override void DrawResult(Graphics g)
        {
        }
    }
}
src/Bro.M071.Process/UI/M071_MainForm.Designer.cs
@@ -29,11 +29,197 @@
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.tsmiShowToolBar = new System.Windows.Forms.ToolStripMenuItem();
            this.tsmiShowStatusBar = new System.Windows.Forms.ToolStripMenuItem();
            this.tsmiShowEditor = new System.Windows.Forms.ToolStripMenuItem();
            this.tscEditLocation = new System.Windows.Forms.ToolStripContainer();
            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
            this.btnConfirmEdit = new System.Windows.Forms.Button();
            this.btnCancelEdit = new System.Windows.Forms.Button();
            this.splitContainer1 = new System.Windows.Forms.SplitContainer();
            this.lvMeasures = new System.Windows.Forms.ListView();
            this.propGridKeyIndicator = new System.Windows.Forms.PropertyGrid();
            this.contextMenuStrip1.SuspendLayout();
            this.tscEditLocation.ContentPanel.SuspendLayout();
            this.tscEditLocation.SuspendLayout();
            this.tableLayoutPanel1.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
            this.splitContainer1.Panel1.SuspendLayout();
            this.splitContainer1.Panel2.SuspendLayout();
            this.splitContainer1.SuspendLayout();
            this.SuspendLayout();
            //
            // contextMenuStrip1
            //
            this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.tsmiShowToolBar,
            this.tsmiShowStatusBar,
            this.tsmiShowEditor});
            this.contextMenuStrip1.Name = "contextMenuStrip1";
            this.contextMenuStrip1.Size = new System.Drawing.Size(149, 70);
            //
            // tsmiShowToolBar
            //
            this.tsmiShowToolBar.CheckOnClick = true;
            this.tsmiShowToolBar.Name = "tsmiShowToolBar";
            this.tsmiShowToolBar.Size = new System.Drawing.Size(148, 22);
            this.tsmiShowToolBar.Text = "显示工具条";
            this.tsmiShowToolBar.CheckedChanged += new System.EventHandler(this.tsmiShowToolBar_CheckedChanged);
            //
            // tsmiShowStatusBar
            //
            this.tsmiShowStatusBar.CheckOnClick = true;
            this.tsmiShowStatusBar.Name = "tsmiShowStatusBar";
            this.tsmiShowStatusBar.Size = new System.Drawing.Size(148, 22);
            this.tsmiShowStatusBar.Text = "显示状态栏";
            this.tsmiShowStatusBar.CheckedChanged += new System.EventHandler(this.tsmiShowStatusBar_CheckedChanged);
            //
            // tsmiShowEditor
            //
            this.tsmiShowEditor.CheckOnClick = true;
            this.tsmiShowEditor.Name = "tsmiShowEditor";
            this.tsmiShowEditor.Size = new System.Drawing.Size(148, 22);
            this.tsmiShowEditor.Text = "编辑显示点位";
            this.tsmiShowEditor.CheckedChanged += new System.EventHandler(this.tsmiShowEditor_CheckedChanged);
            //
            // tscEditLocation
            //
            //
            // tscEditLocation.ContentPanel
            //
            this.tscEditLocation.ContentPanel.Controls.Add(this.tableLayoutPanel1);
            this.tscEditLocation.ContentPanel.Size = new System.Drawing.Size(209, 326);
            this.tscEditLocation.Dock = System.Windows.Forms.DockStyle.Right;
            this.tscEditLocation.Location = new System.Drawing.Point(591, 0);
            this.tscEditLocation.Name = "tscEditLocation";
            this.tscEditLocation.Size = new System.Drawing.Size(209, 351);
            this.tscEditLocation.TabIndex = 0;
            this.tscEditLocation.Text = "toolStripContainer1";
            this.tscEditLocation.Visible = false;
            //
            // tableLayoutPanel1
            //
            this.tableLayoutPanel1.ColumnCount = 2;
            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
            this.tableLayoutPanel1.Controls.Add(this.btnConfirmEdit, 0, 1);
            this.tableLayoutPanel1.Controls.Add(this.btnCancelEdit, 1, 1);
            this.tableLayoutPanel1.Controls.Add(this.splitContainer1, 0, 0);
            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
            this.tableLayoutPanel1.Name = "tableLayoutPanel1";
            this.tableLayoutPanel1.RowCount = 2;
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
            this.tableLayoutPanel1.Size = new System.Drawing.Size(209, 326);
            this.tableLayoutPanel1.TabIndex = 0;
            //
            // btnConfirmEdit
            //
            this.btnConfirmEdit.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
            | System.Windows.Forms.AnchorStyles.Left)
            | System.Windows.Forms.AnchorStyles.Right)));
            this.btnConfirmEdit.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btnConfirmEdit.Location = new System.Drawing.Point(3, 293);
            this.btnConfirmEdit.Name = "btnConfirmEdit";
            this.btnConfirmEdit.Size = new System.Drawing.Size(98, 30);
            this.btnConfirmEdit.TabIndex = 0;
            this.btnConfirmEdit.Text = "确认修改";
            this.btnConfirmEdit.UseVisualStyleBackColor = true;
            this.btnConfirmEdit.Click += new System.EventHandler(this.btnConfirmEdit_Click);
            //
            // btnCancelEdit
            //
            this.btnCancelEdit.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
            | System.Windows.Forms.AnchorStyles.Left)
            | System.Windows.Forms.AnchorStyles.Right)));
            this.btnCancelEdit.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btnCancelEdit.Location = new System.Drawing.Point(107, 293);
            this.btnCancelEdit.Name = "btnCancelEdit";
            this.btnCancelEdit.Size = new System.Drawing.Size(99, 30);
            this.btnCancelEdit.TabIndex = 0;
            this.btnCancelEdit.Text = "取消修改";
            this.btnCancelEdit.UseVisualStyleBackColor = true;
            this.btnCancelEdit.Click += new System.EventHandler(this.btnCancelEdit_Click);
            //
            // splitContainer1
            //
            this.tableLayoutPanel1.SetColumnSpan(this.splitContainer1, 2);
            this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.splitContainer1.Location = new System.Drawing.Point(3, 3);
            this.splitContainer1.Name = "splitContainer1";
            this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
            //
            // splitContainer1.Panel1
            //
            this.splitContainer1.Panel1.Controls.Add(this.lvMeasures);
            //
            // splitContainer1.Panel2
            //
            this.splitContainer1.Panel2.Controls.Add(this.propGridKeyIndicator);
            this.splitContainer1.Size = new System.Drawing.Size(203, 284);
            this.splitContainer1.SplitterDistance = 164;
            this.splitContainer1.TabIndex = 1;
            //
            // lvMeasures
            //
            this.lvMeasures.Dock = System.Windows.Forms.DockStyle.Fill;
            this.lvMeasures.Font = new System.Drawing.Font("Tahoma", 16F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, ((byte)(134)));
            this.lvMeasures.FullRowSelect = true;
            this.lvMeasures.HideSelection = false;
            this.lvMeasures.Location = new System.Drawing.Point(0, 0);
            this.lvMeasures.MultiSelect = false;
            this.lvMeasures.Name = "lvMeasures";
            this.lvMeasures.Size = new System.Drawing.Size(203, 164);
            this.lvMeasures.TabIndex = 0;
            this.lvMeasures.UseCompatibleStateImageBehavior = false;
            this.lvMeasures.View = System.Windows.Forms.View.List;
            this.lvMeasures.SelectedIndexChanged += new System.EventHandler(this.lvMeasures_SelectedIndexChanged);
            //
            // propGridKeyIndicator
            //
            this.propGridKeyIndicator.Dock = System.Windows.Forms.DockStyle.Fill;
            this.propGridKeyIndicator.Location = new System.Drawing.Point(0, 0);
            this.propGridKeyIndicator.Name = "propGridKeyIndicator";
            this.propGridKeyIndicator.Size = new System.Drawing.Size(203, 116);
            this.propGridKeyIndicator.TabIndex = 0;
            this.propGridKeyIndicator.ToolbarVisible = false;
            //
            // M071_MainForm
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.ClientSize = new System.Drawing.Size(800, 351);
            this.ContextMenuStrip = this.contextMenuStrip1;
            this.Controls.Add(this.tscEditLocation);
            this.Name = "M071_MainForm";
            this.Text = "M071_MainForm";
            this.contextMenuStrip1.ResumeLayout(false);
            this.tscEditLocation.ContentPanel.ResumeLayout(false);
            this.tscEditLocation.ResumeLayout(false);
            this.tscEditLocation.PerformLayout();
            this.tableLayoutPanel1.ResumeLayout(false);
            this.splitContainer1.Panel1.ResumeLayout(false);
            this.splitContainer1.Panel2.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
            this.splitContainer1.ResumeLayout(false);
            this.ResumeLayout(false);
        }
        #endregion
        private System.Windows.Forms.ToolStripContainer tscEditLocation;
        private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
        private System.Windows.Forms.ToolStripMenuItem tsmiShowEditor;
        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
        private System.Windows.Forms.Button btnConfirmEdit;
        private System.Windows.Forms.Button btnCancelEdit;
        private System.Windows.Forms.SplitContainer splitContainer1;
        private System.Windows.Forms.PropertyGrid propGridKeyIndicator;
        private System.Windows.Forms.ListView lvMeasures;
        private System.Windows.Forms.ToolStripMenuItem tsmiShowToolBar;
        private System.Windows.Forms.ToolStripMenuItem tsmiShowStatusBar;
    }
}
src/Bro.M071.Process/UI/M071_MainForm.cs
@@ -1,4 +1,5 @@
using Bro.UI.Model.Winform;
using Bro.Common.Helper;
using Bro.UI.Model.Winform;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -14,9 +15,115 @@
    [MenuNode("M071_MainForm", "键盘检测主界面", 3, "M071Node", true)]
    public partial class M071_MainForm : MenuFrmBase
    {
        Canvas cvImage = new Canvas();
        M071Config Config => Process?.IConfig as M071Config;
        public M071_MainForm()
        {
            InitializeComponent();
            cvImage.IsShowElementList = false;
            tsmiShowStatusBar.Checked = cvImage.IsShowStatusBar = false;
            tsmiShowToolBar.Checked = cvImage.IsShowToolBar = false;
            cvImage.Dock = DockStyle.Fill;
            this.Controls.Add(cvImage);
            tscEditLocation.Visible = tsmiShowEditor.Checked = false;
        }
        public override void OnProcessUpdated()
        {
            base.OnProcessUpdated();
            if (Config == null)
                return;
            if (string.IsNullOrWhiteSpace(Config.BackgroundImagePath))
                return;
            try
            {
                Bitmap image = (Bitmap)Image.FromFile(Config.BackgroundImagePath);
                cvImage.LoadImage(image);
            }
            catch (Exception ex)
            {
                LogAsync(new LogMsg(DateTime.Now, "载入背景图异常", ex.Message));
                return;
            }
            cvImage.Elements.Clear();
            lvMeasures.Items.Clear();
            Config.MeasurementUnitCollection.ForEach(u =>
            {
                if (!u.IsEnabled)
                    return;
                var ele = new KeyIndicator(u.Id, u.DisplayLocation);
                cvImage.Elements.Add(ele);
                ListViewItem item = new ListViewItem(u.GetDisplayText());
                item.Tag = u.Id;
                lvMeasures.Items.Add(item);
            });
        }
        private void lvMeasures_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lvMeasures.SelectedItems.Count <= 0)
                return;
            var ele = cvImage.Elements.FirstOrDefault(u => u.ID == lvMeasures.SelectedItems[0].Tag.ToString());
            propGridKeyIndicator.SelectedObject = ele;
        }
        private void tsmiShowToolBar_CheckedChanged(object sender, EventArgs e)
        {
            cvImage.IsShowToolBar = tsmiShowToolBar.Checked;
        }
        private void tsmiShowStatusBar_CheckedChanged(object sender, EventArgs e)
        {
            cvImage.IsShowStatusBar = tsmiShowStatusBar.Checked;
        }
        private void tsmiShowEditor_CheckedChanged(object sender, EventArgs e)
        {
            tscEditLocation.Visible = tsmiShowEditor.Checked;
        }
        private void btnCancelEdit_Click(object sender, EventArgs e)
        {
            cvImage.Elements.Clear();
            lvMeasures.Items.Clear();
            Config.MeasurementUnitCollection.ForEach(u =>
            {
                if (!u.IsEnabled)
                    return;
                var ele = new KeyIndicator(u.Id, u.DisplayLocation);
                cvImage.Elements.Add(ele);
                ListViewItem item = new ListViewItem(u.GetDisplayText());
                item.Tag = u.Id;
                lvMeasures.Items.Add(item);
            });
            //tscEditLocation.Visible = false;
        }
        private void btnConfirmEdit_Click(object sender, EventArgs e)
        {
            cvImage.Elements.ToList().ForEach(ele =>
            {
                var measure = Config.MeasurementUnitCollection.FirstOrDefault(u => u.Id == ele.ID);
                if (measure != null)
                {
                    measure.DisplayLocation = (ele as KeyIndicator).DisplayRect;
                }
            });
            //tscEditLocation.Visible = false;
        }
    }
}
src/Bro.M071.Process/UI/M071_MainForm.resx
New file
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
  <!--
    Microsoft ResX Schema
    Version 2.0
    The primary goals of this format is to allow a simple XML format
    that is mostly human readable. The generation and parsing of the
    various data types are done through the TypeConverter classes
    associated with the data types.
    Example:
    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>
    There are any number of "resheader" rows that contain simple
    name/value pairs.
    Each data row contains a name, and value. The row also contains a
    type or mimetype. Type corresponds to a .NET class that support
    text/value conversion through the TypeConverter architecture.
    Classes that don't support this are serialized and stored with the
    mimetype set.
    The mimetype is used for serialized objects, and tells the
    ResXResourceReader how to depersist the object. This is currently not
    extensible. For a given mimetype the value must be set accordingly:
    Note - application/x-microsoft.net.object.binary.base64 is the format
    that the ResXResourceWriter will generate, however the reader can
    read any of the formats listed below.
    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with
            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.
    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.
    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array
            : using a System.ComponentModel.TypeConverter
            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" use="required" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <value>17, 17</value>
  </metadata>
</root>
src/Bro.UI.Config/MenuForms/FrmConfig.Designer.cs
@@ -34,6 +34,7 @@
            this.btnSave = new System.Windows.Forms.Button();
            this.imgList = new System.Windows.Forms.ImageList(this.components);
            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
            this.button1 = new System.Windows.Forms.Button();
            this.tableLayoutPanel1.SuspendLayout();
            this.SuspendLayout();
            // 
@@ -42,6 +43,7 @@
            this.propGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.tableLayoutPanel1.SetColumnSpan(this.propGrid, 3);
            this.propGrid.Location = new System.Drawing.Point(2, 44);
            this.propGrid.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
            this.propGrid.Name = "propGrid";
@@ -73,10 +75,13 @@
            // 
            // tableLayoutPanel1
            // 
            this.tableLayoutPanel1.ColumnCount = 1;
            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
            this.tableLayoutPanel1.ColumnCount = 3;
            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
            this.tableLayoutPanel1.Controls.Add(this.propGrid, 0, 1);
            this.tableLayoutPanel1.Controls.Add(this.btnSave, 0, 0);
            this.tableLayoutPanel1.Controls.Add(this.btnSave, 2, 0);
            this.tableLayoutPanel1.Controls.Add(this.button1, 0, 0);
            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
            this.tableLayoutPanel1.Name = "tableLayoutPanel1";
@@ -85,6 +90,16 @@
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
            this.tableLayoutPanel1.Size = new System.Drawing.Size(800, 487);
            this.tableLayoutPanel1.TabIndex = 2;
            //
            // button1
            //
            this.button1.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.button1.Location = new System.Drawing.Point(3, 3);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(175, 35);
            this.button1.TabIndex = 2;
            this.button1.Text = "从当前配置派生新产品";
            this.button1.UseVisualStyleBackColor = true;
            // 
            // FrmConfig
            // 
@@ -105,5 +120,6 @@
        private System.Windows.Forms.Button btnSave;
        private System.Windows.Forms.ImageList imgList;
        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
        private System.Windows.Forms.Button button1;
    }
}
src/Bro.UI.Config/MenuForms/FrmConfig.resx
@@ -125,7 +125,7 @@
        AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
        LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
        ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACY
        CAAAAk1TRnQBSQFMAwEBAAEoAQABKAEAARgBAAEYAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA
        CAAAAk1TRnQBSQFMAwEBAAEwAQABMAEAARgBAAEYAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA
        AWADAAEYAwABAQEAAQgGAAEJGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHAAdwBwAEA
        AfABygGmAQABMwUAATMBAAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANCAQADOQEA
        AYABfAH/AQACUAH/AQABkwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ATMDAAFm
src/Bro.UI.Config/MenuForms/FrmLog.Designer.cs
@@ -28,41 +28,48 @@
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.txtLog = new System.Windows.Forms.TextBox();
            this.btnClearLog = new System.Windows.Forms.Button();
            this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.tsmiClearLog = new System.Windows.Forms.ToolStripMenuItem();
            this.contextMenuStrip1.SuspendLayout();
            this.SuspendLayout();
            // 
            // txtLog
            // 
            this.txtLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
            | System.Windows.Forms.AnchorStyles.Left)
            | System.Windows.Forms.AnchorStyles.Right)));
            this.txtLog.Location = new System.Drawing.Point(0, 33);
            this.txtLog.BorderStyle = System.Windows.Forms.BorderStyle.None;
            this.txtLog.ContextMenuStrip = this.contextMenuStrip1;
            this.txtLog.Dock = System.Windows.Forms.DockStyle.Fill;
            this.txtLog.Location = new System.Drawing.Point(0, 0);
            this.txtLog.Multiline = true;
            this.txtLog.Name = "txtLog";
            this.txtLog.ReadOnly = true;
            this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.txtLog.Size = new System.Drawing.Size(800, 455);
            this.txtLog.Size = new System.Drawing.Size(800, 488);
            this.txtLog.TabIndex = 0;
            // 
            // btnClearLog
            // contextMenuStrip1
            // 
            this.btnClearLog.Location = new System.Drawing.Point(21, 4);
            this.btnClearLog.Name = "btnClearLog";
            this.btnClearLog.Size = new System.Drawing.Size(75, 23);
            this.btnClearLog.TabIndex = 1;
            this.btnClearLog.Text = "清空日志";
            this.btnClearLog.UseVisualStyleBackColor = true;
            this.btnClearLog.Click += new System.EventHandler(this.btnClearLog_Click);
            this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.tsmiClearLog});
            this.contextMenuStrip1.Name = "contextMenuStrip1";
            this.contextMenuStrip1.Size = new System.Drawing.Size(125, 26);
            //
            // tsmiClearLog
            //
            this.tsmiClearLog.Name = "tsmiClearLog";
            this.tsmiClearLog.Size = new System.Drawing.Size(180, 22);
            this.tsmiClearLog.Text = "清空日志";
            this.tsmiClearLog.Click += new System.EventHandler(this.tsmiClearLog_Click);
            // 
            // FrmLog
            // 
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
            this.ClientSize = new System.Drawing.Size(800, 488);
            this.Controls.Add(this.btnClearLog);
            this.Controls.Add(this.txtLog);
            this.Name = "FrmLog";
            this.Text = "FrmLog";
            this.contextMenuStrip1.ResumeLayout(false);
            this.ResumeLayout(false);
            this.PerformLayout();
@@ -71,6 +78,7 @@
        #endregion
        private System.Windows.Forms.TextBox txtLog;
        private System.Windows.Forms.Button btnClearLog;
        private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
        private System.Windows.Forms.ToolStripMenuItem tsmiClearLog;
    }
}
src/Bro.UI.Config/MenuForms/FrmLog.cs
@@ -56,7 +56,7 @@
            }
        }
        private void btnClearLog_Click(object sender, EventArgs e)
        private void tsmiClearLog_Click(object sender, EventArgs e)
        {
            txtLog.Clear();
        }
src/Bro.UI.Config/MenuForms/FrmLog.resx
@@ -117,4 +117,7 @@
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <value>17, 17</value>
  </metadata>
</root>
src/Bro.UI.Config/MenuForms/FrmOperation.resx
@@ -125,7 +125,7 @@
        AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
        LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
        ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADm
        CgAAAk1TRnQBSQFMAgEBAgEAAcABAAHAAQABGAEAARgBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
        CgAAAk1TRnQBSQFMAgEBAgEAAdABAAHQAQABGAEAARgBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
        AwABYAMAARgDAAEBAQABCAYAAQkYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
        AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
        AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
@@ -182,7 +182,7 @@
        AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
        LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
        ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAD4
        CAAAAk1TRnQBSQFMAwEBAAHAAQABwAEAARgBAAEYAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA
        CAAAAk1TRnQBSQFMAwEBAAHQAQAB0AEAARgBAAEYAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA
        AWADAAEYAwABAQEAAQgGAAEJGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHAAdwBwAEA
        AfABygGmAQABMwUAATMBAAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANCAQADOQEA
        AYABfAH/AQACUAH/AQABkwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ATMDAAFm
src/Bro.UI.Model.Winform/Element/CrossHair.cs
@@ -125,7 +125,7 @@
            if (IsShowRemark)
            {
                string info = Index.ToString() + ":(" + CenterPoint.X.ToString() + ";" + CenterPoint.Y.ToString() + ")";
                g.DrawString(info, new Font("NewRoman", FontSize), new SolidBrush(Pen.Color), new PointF((float)CenterPoint.U + FontDistance, (float)CenterPoint.V + FontDistance));
                g.DrawString(info, Font, new SolidBrush(Pen.Color), new PointF((float)CenterPoint.U + FontDistance, (float)CenterPoint.V + FontDistance));
            }
        }
@@ -148,7 +148,7 @@
            return rect.IntersectsWith(BaseRectangle);
        }
        public override void CalculateBaseRectangle()
        public void CalculateBaseRectangle()
        {
            BaseRectangle = new Rectangle(new Point((int)CenterPoint.U - HalfLength, (int)CenterPoint.V - HalfLength), new Size(HalfLength * 2, HalfLength * 2));
        }
src/Bro.UI.Model.Winform/Element/CrossHairWithAngle.cs
@@ -133,44 +133,6 @@
        #endregion
        #region ElementBase
        //private void CenterPoint_PropertyChanged(object sender, PropertyChangedEventArgs e)
        //{
        //    SetNormalPen();
        //}
        //protected override void SetNormalPen()
        //{
        //    if (CenterPoint.IsBasePoint)
        //    {
        //        HalfRectangleSize = 20;
        //        HalfLength = 80;
        //        Pen = new Pen(Color.DarkGreen, 1);
        //    }
        //    else
        //    {
        //        HalfRectangleSize = 10;
        //        HalfLength = 30;
        //        base.SetNormalPen();
        //    }
        //}
        public override void Calculate(string imagePath)
        {
            //throw new NotImplementedException();
        }
        public override void Calculate(Bitmap image)
        {
            //throw new NotImplementedException();
        }
        public override void Calculate(IntPtr imagePtr, int ptrSize, int imageWidth, int imageHeight)
        {
            //throw new NotImplementedException();
        }
        public override object Clone()
        {
            //throw new NotImplementedException();
@@ -190,7 +152,7 @@
            g.DrawLine(arrowPen, (float)ImagePoint.X, (float)ImagePoint.Y, (float)ImagePoint.X + (float)(HalfLength * Math.Cos(Angle * Math.PI / 180.0)), (float)ImagePoint.Y - (float)(HalfLength * Math.Sin(Angle * Math.PI / 180.0)));
            string info = $"{Index}  图像坐标:{ImagePoint.X},{ImagePoint.Y}\r\n机台坐标:{PlatPoint.X},{PlatPoint.Y}\r\n角度:{Angle}";
            g.DrawString(info, new Font("NewRoman", FontSize), new SolidBrush(Pen.Color), new PointF((float)ImagePoint.X + FontDistance, (float)ImagePoint.Y + FontDistance));
            g.DrawString(info, Font, new SolidBrush(Pen.Color), new PointF((float)ImagePoint.X + FontDistance, (float)ImagePoint.Y + FontDistance));
        }
        public override bool IsMouseHover(Point p)
@@ -212,7 +174,7 @@
            return rect.IntersectsWith(BaseRectangle);
        }
        public override void CalculateBaseRectangle()
        public void CalculateBaseRectangle()
        {
            BaseRectangle = new Rectangle(new Point((int)ImagePoint.X - HalfRectangleSize, (int)ImagePoint.Y - HalfRectangleSize), new Size(HalfRectangleSize * 2, HalfRectangleSize * 2));
        }
src/Bro.UI.Model.Winform/Element/PointIndicator.cs
@@ -38,21 +38,6 @@
        }
        #region ElementBase
        public override void Calculate(Bitmap image)
        {
        }
        public override void Calculate(IntPtr imagePtr, int ptrSize, int imageWidth, int imageHeight)
        {
        }
        public override void Calculate(string imagePath)
        {
        }
        public override void CalculateBaseRectangle()
        {
        }
        public override object Clone()
        {
@@ -73,7 +58,7 @@
            g.DrawLine(Pen, (float)Center.X - Radius, (float)Center.Y, (float)Center.X + Radius, (float)Center.Y);
            string info = GetDisplayText();
            g.DrawString(info, new Font("NewRoman", FontSize), new SolidBrush(Pen.Color), new PointF((float)Center.X - Radius - FontDistance, (float)Center.Y - Radius - FontDistance));
            g.DrawString(info, Font, new SolidBrush(Pen.Color), new PointF((float)Center.X - Radius - FontDistance, (float)Center.Y - Radius - FontDistance));
        }
        public override string GetDisplayText()
src/Bro.UI.Model.Winform/Element/ROI_Circle.cs
@@ -28,10 +28,6 @@
        {
        }
        public override void CalculateBaseRectangle()
        {
        }
        public override object Clone()
        {
            ROI_Circle circle = new ROI_Circle();
src/Bro.UI.Model.Winform/Element/ROI_Rectangle.cs
@@ -18,10 +18,6 @@
        public override void Calculate(string imagePath)
        {
        }
        public override void CalculateBaseRectangle()
        {
        }
        #endregion
        public override object Clone()
src/Bro.UI.Model.Winform/ElementBase.cs
@@ -140,13 +140,20 @@
        //[JsonIgnore]
        //protected Pen PenTextNG = new Pen(Color.Red, 2);
        ///// <summary>
        ///// 字体大小
        ///// </summary>
        //[Category("显示属性")]
        //[Description("字体大小")]
        ////[Browsable(false)]
        //public virtual float FontSize { get; set; } = 15;
        /// <summary>
        /// 字体大小
        /// </summary>
        [Category("显示属性")]
        [Description("字体大小")]
        //[Browsable(false)]
        public virtual float FontSize { get; set; } = 15;
        [Description("字体设置")]
        public virtual Font Font { get; set; } = new Font(new FontFamily("Tahoma"), 15, GraphicsUnit.World);
        /// <summary>
        /// 字体和基元的距离
        /// </summary>
@@ -358,8 +365,38 @@
        public abstract bool IsMouseInSide(Point p);
        public abstract bool IsIntersect(Rectangle rect);
        #region Move & Stretch & Move Anchor
        public virtual bool IsMouseCanMoveElement()
        {
            return false;
        }
        public abstract void CalculateBaseRectangle();
        public virtual bool IsMouseCanStretchLeft()
        {
            return false;
        }
        public virtual bool IsMouseCanStretchRight()
        {
            return false;
        }
        public virtual bool IsMouseCanStretchTop()
        {
            return false;
        }
        public virtual bool IsMouseCanStretchBottom()
        {
            return false;
        }
        public virtual bool IsMouseCanMoveAnchor()
        {
            return false;
        }
        #endregion
        #endregion
        #region 变形操作
@@ -386,11 +423,11 @@
        /// 算法
        /// </summary>
        /// <param name="paras">计算参数</param>
        public abstract void Calculate(Bitmap image);
        public virtual void Calculate(Bitmap image) { }
        public abstract void Calculate(IntPtr imagePtr, int ptrSize, int imageWidth, int imageHeight);
        public virtual void Calculate(IntPtr imagePtr, int ptrSize, int imageWidth, int imageHeight) { }
        public abstract void Calculate(string imagePath);
        public virtual void Calculate(string imagePath) { }
        #endregion
        #region 图片保存