From 9d05b4e5a7b667afb6d13cbcb460e377c175c170 Mon Sep 17 00:00:00 2001
From: xcd <834800634@qq.com>
Date: 星期三, 01 七月 2020 19:44:26 +0800
Subject: [PATCH] 添加M071主界面和标签指示,

---
 src/Bro.UI.Config/MenuForms/FrmLog.resx                |    3 
 src/Bro.M071.Process/UI/M071_MainForm.cs               |  109 +++++++
 src/Bro.UI.Model.Winform/Element/PointIndicator.cs     |   17 -
 src/Bro.UI.Config/MenuForms/FrmConfig.resx             |    2 
 src/Bro.UI.Model.Winform/Element/ROI_Circle.cs         |    4 
 src/Bro.M071.Process/UI/M071_MainForm.Designer.cs      |  188 +++++++++++++
 src/Bro.UI.Config/MenuForms/FrmOperation.resx          |    4 
 src/Bro.M071.Process/UI/M071_MainForm.resx             |  123 ++++++++
 src/Bro.UI.Config/MenuForms/FrmLog.cs                  |    2 
 src/Bro.UI.Config/MenuForms/FrmConfig.Designer.cs      |   22 +
 src/Bro.UI.Config/MenuForms/FrmLog.Designer.cs         |   40 +-
 src/Bro.M071.Process/M071Process.cs                    |   26 +
 src/Bro.UI.Model.Winform/Element/ROI_Rectangle.cs      |    4 
 src/Bro.UI.Model.Winform/ElementBase.cs                |   51 +++
 src/Bro.M071.Process/Bro.M071.Process.csproj           |    4 
 src/Bro.M071.Process/UI/KeyIndicator.cs                |  142 ++++++++++
 src/Bro.UI.Model.Winform/Element/CrossHair.cs          |    4 
 src/Bro.UI.Model.Winform/Element/CrossHairWithAngle.cs |   42 --
 18 files changed, 682 insertions(+), 105 deletions(-)

diff --git a/src/Bro.M071.Process/Bro.M071.Process.csproj b/src/Bro.M071.Process/Bro.M071.Process.csproj
index c4f1e16..028f4f4 100644
--- a/src/Bro.M071.Process/Bro.M071.Process.csproj
+++ b/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>
diff --git a/src/Bro.M071.Process/M071Process.cs b/src/Bro.M071.Process/M071Process.cs
index 2667c4f..0c615a6 100644
--- a/src/Bro.M071.Process/M071Process.cs
+++ b/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();
                 }
             }
diff --git a/src/Bro.M071.Process/UI/KeyIndicator.cs b/src/Bro.M071.Process/UI/KeyIndicator.cs
new file mode 100644
index 0000000..3e66348
--- /dev/null
+++ b/src/Bro.M071.Process/UI/KeyIndicator.cs
@@ -0,0 +1,142 @@
+锘縰sing 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)
+        {
+        }
+    }
+}
diff --git a/src/Bro.M071.Process/UI/M071_MainForm.Designer.cs b/src/Bro.M071.Process/UI/M071_MainForm.Designer.cs
index 45eef01..996ca15 100644
--- a/src/Bro.M071.Process/UI/M071_MainForm.Designer.cs
+++ b/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;
     }
 }
\ No newline at end of file
diff --git a/src/Bro.M071.Process/UI/M071_MainForm.cs b/src/Bro.M071.Process/UI/M071_MainForm.cs
index 92c0b25..fbc7bd2 100644
--- a/src/Bro.M071.Process/UI/M071_MainForm.cs
+++ b/src/Bro.M071.Process/UI/M071_MainForm.cs
@@ -1,4 +1,5 @@
-锘縰sing Bro.UI.Model.Winform;
+锘縰sing 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;
         }
     }
 }
diff --git a/src/Bro.M071.Process/UI/M071_MainForm.resx b/src/Bro.M071.Process/UI/M071_MainForm.resx
new file mode 100644
index 0000000..ad53752
--- /dev/null
+++ b/src/Bro.M071.Process/UI/M071_MainForm.resx
@@ -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>
\ No newline at end of file
diff --git a/src/Bro.UI.Config/MenuForms/FrmConfig.Designer.cs b/src/Bro.UI.Config/MenuForms/FrmConfig.Designer.cs
index 33915bc..bb84267 100644
--- a/src/Bro.UI.Config/MenuForms/FrmConfig.Designer.cs
+++ b/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;
     }
 }
\ No newline at end of file
diff --git a/src/Bro.UI.Config/MenuForms/FrmConfig.resx b/src/Bro.UI.Config/MenuForms/FrmConfig.resx
index 924a2d9..0cdf229 100644
--- a/src/Bro.UI.Config/MenuForms/FrmConfig.resx
+++ b/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
diff --git a/src/Bro.UI.Config/MenuForms/FrmLog.Designer.cs b/src/Bro.UI.Config/MenuForms/FrmLog.Designer.cs
index 476fc51..c105e7a 100644
--- a/src/Bro.UI.Config/MenuForms/FrmLog.Designer.cs
+++ b/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;
     }
 }
\ No newline at end of file
diff --git a/src/Bro.UI.Config/MenuForms/FrmLog.cs b/src/Bro.UI.Config/MenuForms/FrmLog.cs
index 569cc58..0e6d95e 100644
--- a/src/Bro.UI.Config/MenuForms/FrmLog.cs
+++ b/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();
         }
diff --git a/src/Bro.UI.Config/MenuForms/FrmLog.resx b/src/Bro.UI.Config/MenuForms/FrmLog.resx
index 1af7de1..ad53752 100644
--- a/src/Bro.UI.Config/MenuForms/FrmLog.resx
+++ b/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>
\ No newline at end of file
diff --git a/src/Bro.UI.Config/MenuForms/FrmOperation.resx b/src/Bro.UI.Config/MenuForms/FrmOperation.resx
index 0e0a0e7..b1a77b1 100644
--- a/src/Bro.UI.Config/MenuForms/FrmOperation.resx
+++ b/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
diff --git a/src/Bro.UI.Model.Winform/Element/CrossHair.cs b/src/Bro.UI.Model.Winform/Element/CrossHair.cs
index ec2749f..c38a119 100644
--- a/src/Bro.UI.Model.Winform/Element/CrossHair.cs
+++ b/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));
         }
diff --git a/src/Bro.UI.Model.Winform/Element/CrossHairWithAngle.cs b/src/Bro.UI.Model.Winform/Element/CrossHairWithAngle.cs
index 0ad45e8..2f54570 100644
--- a/src/Bro.UI.Model.Winform/Element/CrossHairWithAngle.cs
+++ b/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));
         }
diff --git a/src/Bro.UI.Model.Winform/Element/PointIndicator.cs b/src/Bro.UI.Model.Winform/Element/PointIndicator.cs
index f01b8f5..9559b7d 100644
--- a/src/Bro.UI.Model.Winform/Element/PointIndicator.cs
+++ b/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()
diff --git a/src/Bro.UI.Model.Winform/Element/ROI_Circle.cs b/src/Bro.UI.Model.Winform/Element/ROI_Circle.cs
index bfe99c0..0bd2da7 100644
--- a/src/Bro.UI.Model.Winform/Element/ROI_Circle.cs
+++ b/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();
diff --git a/src/Bro.UI.Model.Winform/Element/ROI_Rectangle.cs b/src/Bro.UI.Model.Winform/Element/ROI_Rectangle.cs
index 1399f1f..c7fd1b5 100644
--- a/src/Bro.UI.Model.Winform/Element/ROI_Rectangle.cs
+++ b/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()
diff --git a/src/Bro.UI.Model.Winform/ElementBase.cs b/src/Bro.UI.Model.Winform/ElementBase.cs
index 521dda8..eb02a2f 100644
--- a/src/Bro.UI.Model.Winform/ElementBase.cs
+++ b/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 鍥剧墖淇濆瓨

--
Gitblit v1.8.0