From 19a9489aef9b3353171eca5e6b583aadb2828593 Mon Sep 17 00:00:00 2001
From: wells.liu <wells.liu@broconcentric.com>
Date: 星期日, 28 六月 2020 09:33:01 +0800
Subject: [PATCH] Merge branch 'master' of http://gitblit.broconcentric.com:8088/r/M071

---
 src/Bro.M071.Process/Properties/Settings.Designer.cs           |   30 +
 src/Bro.Common.Device/Interface/IMotion.cs                     |   12 
 src/Bro.Common.Model/Selector/ProcessMethodSelector.cs         |    2 
 src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.cs          |  126 ++++
 src/Bro.Process/ProcessConfig.cs                               |    1 
 src/Bro.Common.Model/Model/CustomizedPoint.cs                  |   24 
 src/Bro.M071.Process/packages.config                           |    4 
 src/Bro.M071.Process/Properties/Resources.Designer.cs          |   71 ++
 src/Bro.M071.Process/M071Converters.cs                         |  191 +++++++
 src/Bro.M071.Process/Properties/Resources.resx                 |  117 ++++
 src/Bro.M071.Process/M071Process.cs                            |   27 +
 src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.Designer.cs |  119 ++++
 src/Bro.Device.Gocator/GocatorDriver.cs                        |   12 
 src/Bro.Device.Gocator/Properties/AssemblyInfo.cs              |   36 +
 src/Bro.UI.Model.Winform/Element/CrossHairWithAngle.cs         |   10 
 src/Bro.Common.Model/Helper/PropertyConvertHelper.cs           |   31 
 src/Bro.UI.Model.Winform/Element/PointIndicator.cs             |    8 
 src/Bro.Device.Gocator/Bro.Device.Gocator.csproj               |   49 +
 src/Bro.UI.Model.Winform/Element/ROI_Circle.cs                 |    8 
 src/Bro.Common.Model/Bro.Common.Model.csproj                   |   10 
 src/Bro.Common.Model/Model/DeviceOpBind.cs                     |   88 +++
 src/Bro.Common.Device/DeviceBase/CameraBase.cs                 |    4 
 M071.sln                                                       |   28 +
 src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.resx        |  120 ++++
 src/Bro.Common.Model/Selector/DeviceSelector.cs                |    5 
 src/Bro.Device.Gocator/GocatorConfig.cs                        |   12 
 src/Bro.M071.Process/Properties/Settings.settings              |    7 
 src/Bro.M071.Process/Bro.M071.Process.csproj                   |   95 +++
 src/Bro.M071.Process/M071Config.cs                             |   66 ++
 src/Bro.M071.Process/M071Models.cs                             |  205 +++++++
 src/Bro.UI.Model.Winform/Element/CrossHair.cs                  |    8 
 src/Bro.Common.Device/DeviceBase/PLCBase.cs                    |    2 
 src/Bro.M071.Process/Properties/AssemblyInfo.cs                |   36 +
 33 files changed, 1,520 insertions(+), 44 deletions(-)

diff --git a/M071.sln b/M071.sln
index 492559e..78da12e 100644
--- a/M071.sln
+++ b/M071.sln
@@ -27,6 +27,10 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bro.Process.DataBase", "src\Bro.Process.DBManager\Bro.Process.DataBase.csproj", "{65302D6E-9918-4E4C-92B4-75C8830C6BA7}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bro.M071.Process", "src\Bro.M071.Process\Bro.M071.Process.csproj", "{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bro.Device.Gocator", "src\Bro.Device.Gocator\Bro.Device.Gocator.csproj", "{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -181,6 +185,30 @@
 		{65302D6E-9918-4E4C-92B4-75C8830C6BA7}.Release|x64.Build.0 = Release|Any CPU
 		{65302D6E-9918-4E4C-92B4-75C8830C6BA7}.Release|x86.ActiveCfg = Release|Any CPU
 		{65302D6E-9918-4E4C-92B4-75C8830C6BA7}.Release|x86.Build.0 = Release|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Debug|x64.Build.0 = Debug|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Debug|x86.Build.0 = Debug|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Release|x64.ActiveCfg = Release|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Release|x64.Build.0 = Release|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Release|x86.ActiveCfg = Release|Any CPU
+		{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}.Release|x86.Build.0 = Release|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Debug|x64.Build.0 = Debug|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Debug|x86.Build.0 = Debug|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Release|Any CPU.Build.0 = Release|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Release|x64.ActiveCfg = Release|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Release|x64.Build.0 = Release|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Release|x86.ActiveCfg = Release|Any CPU
+		{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/src/Bro.Common.Device/DeviceBase/CameraBase.cs b/src/Bro.Common.Device/DeviceBase/CameraBase.cs
index c8a80ba..5673c27 100644
--- a/src/Bro.Common.Device/DeviceBase/CameraBase.cs
+++ b/src/Bro.Common.Device/DeviceBase/CameraBase.cs
@@ -616,7 +616,7 @@
     #region Converter & Editor
     public class HalconSerialNumConverter : ComboBoxItemTypeConvert
     {
-        public override Hashtable GetConvertHash()
+        public override Hashtable GetConvertHash(ITypeDescriptorContext context)
         {
             Hashtable table = new Hashtable();
             HTuple deviceList = null;
@@ -654,7 +654,7 @@
 
     public class CameraDeviceConverter : ComboBoxItemTypeConvert
     {
-        public override Hashtable GetConvertHash()
+        public override Hashtable GetConvertHash(ITypeDescriptorContext context)
         {
             Hashtable table = new Hashtable();
             using (var scope = GlobalVar.Container.BeginLifetimeScope())
diff --git a/src/Bro.Common.Device/DeviceBase/PLCBase.cs b/src/Bro.Common.Device/DeviceBase/PLCBase.cs
index 0ea73fa..0273e94 100644
--- a/src/Bro.Common.Device/DeviceBase/PLCBase.cs
+++ b/src/Bro.Common.Device/DeviceBase/PLCBase.cs
@@ -552,7 +552,7 @@
 
     public class PLCDeviceConverter : ComboBoxItemTypeConvert
     {
-        public override Hashtable GetConvertHash()
+        public override Hashtable GetConvertHash(ITypeDescriptorContext context)
         {
             Hashtable table = new Hashtable();
             using (var scope = GlobalVar.Container.BeginLifetimeScope())
diff --git a/src/Bro.Common.Device/Interface/IMotion.cs b/src/Bro.Common.Device/Interface/IMotion.cs
index 7269b65..e6e55f3 100644
--- a/src/Bro.Common.Device/Interface/IMotion.cs
+++ b/src/Bro.Common.Device/Interface/IMotion.cs
@@ -1,4 +1,5 @@
-锘縰sing System;
+锘縰sing Bro.Common.Helper;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -14,9 +15,14 @@
         List<AxisInfo> GetCurrentAxisInfo(params string[] axisName);
     }
 
-    public class AxisInfo
+    public class AxisInfo : IComplexDisplay
     {
         public string AxisName { get; set; }
-        public float AxisLocation { get; set; }
+        public double AxisLocation { get; set; }
+
+        public string GetDisplayText()
+        {
+            return $"{AxisName}:{AxisLocation}";
+        }
     }
 }
diff --git a/src/Bro.Common.Model/Bro.Common.Model.csproj b/src/Bro.Common.Model/Bro.Common.Model.csproj
index 6790069..1f91dd4 100644
--- a/src/Bro.Common.Model/Bro.Common.Model.csproj
+++ b/src/Bro.Common.Model/Bro.Common.Model.csproj
@@ -67,6 +67,12 @@
     <Compile Include="Factory\FactoryHelper.cs" />
     <Compile Include="Factory\ProcessFactory.cs" />
     <Compile Include="Factory\UIFactory.cs" />
+    <Compile Include="Forms\FrmDeviceOpConfigEditor.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Forms\FrmDeviceOpConfigEditor.Designer.cs">
+      <DependentUpon>FrmDeviceOpConfigEditor.cs</DependentUpon>
+    </Compile>
     <Compile Include="Forms\FrmOpConfigEdit.cs">
       <SubType>Form</SubType>
     </Compile>
@@ -103,6 +109,7 @@
     <Compile Include="Log\LoggerHelper.cs" />
     <Compile Include="Model\CustomizedPoint.cs" />
     <Compile Include="Model\CustomizedRectangle.cs" />
+    <Compile Include="Model\DeviceOpBind.cs" />
     <Compile Include="Model\ModbusFrame.cs" />
     <Compile Include="Model\MonitorSet.cs" />
     <Compile Include="Model\PageRequest.cs" />
@@ -128,6 +135,9 @@
     <None Include="packages.config" />
   </ItemGroup>
   <ItemGroup>
+    <EmbeddedResource Include="Forms\FrmDeviceOpConfigEditor.resx">
+      <DependentUpon>FrmDeviceOpConfigEditor.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="Forms\FrmOpConfigEdit.resx">
       <DependentUpon>FrmOpConfigEdit.cs</DependentUpon>
     </EmbeddedResource>
diff --git a/src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.Designer.cs b/src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.Designer.cs
new file mode 100644
index 0000000..e615f6d
--- /dev/null
+++ b/src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.Designer.cs
@@ -0,0 +1,119 @@
+锘縩amespace Bro.Common.Model.Forms
+{
+    partial class FrmDeviceOpConfigEditor
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.btnReset = new System.Windows.Forms.Button();
+            this.btnCancel = new System.Windows.Forms.Button();
+            this.btnConfirm = new System.Windows.Forms.Button();
+            this.propGrid = new System.Windows.Forms.PropertyGrid();
+            this.cboDevice = new System.Windows.Forms.ComboBox();
+            this.SuspendLayout();
+            // 
+            // btnReset
+            // 
+            this.btnReset.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnReset.BackColor = System.Drawing.Color.Red;
+            this.btnReset.ForeColor = System.Drawing.Color.White;
+            this.btnReset.Location = new System.Drawing.Point(231, 14);
+            this.btnReset.Name = "btnReset";
+            this.btnReset.Size = new System.Drawing.Size(75, 23);
+            this.btnReset.TabIndex = 4;
+            this.btnReset.Text = "閲嶇疆閰嶇疆";
+            this.btnReset.UseVisualStyleBackColor = false;
+            this.btnReset.Click += new System.EventHandler(this.btnReset_Click);
+            // 
+            // btnCancel
+            // 
+            this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnCancel.Location = new System.Drawing.Point(312, 14);
+            this.btnCancel.Name = "btnCancel";
+            this.btnCancel.Size = new System.Drawing.Size(75, 23);
+            this.btnCancel.TabIndex = 5;
+            this.btnCancel.Text = "鍙栨秷";
+            this.btnCancel.UseVisualStyleBackColor = true;
+            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+            // 
+            // btnConfirm
+            // 
+            this.btnConfirm.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnConfirm.Location = new System.Drawing.Point(393, 14);
+            this.btnConfirm.Name = "btnConfirm";
+            this.btnConfirm.Size = new System.Drawing.Size(75, 23);
+            this.btnConfirm.TabIndex = 6;
+            this.btnConfirm.Text = "纭";
+            this.btnConfirm.UseVisualStyleBackColor = true;
+            this.btnConfirm.Click += new System.EventHandler(this.btnConfirm_Click);
+            // 
+            // propGrid
+            // 
+            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.propGrid.Location = new System.Drawing.Point(3, 56);
+            this.propGrid.Name = "propGrid";
+            this.propGrid.Size = new System.Drawing.Size(475, 346);
+            this.propGrid.TabIndex = 3;
+            this.propGrid.ToolbarVisible = false;
+            // 
+            // cboDevice
+            // 
+            this.cboDevice.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cboDevice.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboDevice.FormattingEnabled = true;
+            this.cboDevice.Location = new System.Drawing.Point(12, 16);
+            this.cboDevice.Name = "cboDevice";
+            this.cboDevice.Size = new System.Drawing.Size(190, 20);
+            this.cboDevice.TabIndex = 7;
+            // 
+            // FrmDeviceOpConfigEditor
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(480, 404);
+            this.Controls.Add(this.cboDevice);
+            this.Controls.Add(this.btnReset);
+            this.Controls.Add(this.btnCancel);
+            this.Controls.Add(this.btnConfirm);
+            this.Controls.Add(this.propGrid);
+            this.Name = "FrmDeviceOpConfigEditor";
+            this.ShowIcon = false;
+            this.Text = "鎿嶄綔璁惧鍙婇厤缃紪杈戠晫闈�";
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+        private System.Windows.Forms.Button btnReset;
+        private System.Windows.Forms.Button btnCancel;
+        private System.Windows.Forms.Button btnConfirm;
+        private System.Windows.Forms.PropertyGrid propGrid;
+        private System.Windows.Forms.ComboBox cboDevice;
+    }
+}
\ No newline at end of file
diff --git a/src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.cs b/src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.cs
new file mode 100644
index 0000000..10d6598
--- /dev/null
+++ b/src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.cs
@@ -0,0 +1,126 @@
+锘縰sing Autofac;
+using Bro.Common.Base;
+using Bro.Common.Factory;
+using Bro.Common.Helper;
+using Bro.Common.Interface;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace Bro.Common.Model.Forms
+{
+    public partial class FrmDeviceOpConfigEditor : Form
+    {
+        public FrmDeviceOpConfigEditor()
+        {
+            InitializeComponent();
+        }
+
+        //private DeviceOpBind bind = null;
+        public DeviceOpBind Bind { get; set; }
+
+        IOperationConfig backOpConfig = new OperationConfigBase();
+        List<IDevice> deviceList = null;
+        IDevice currentDevice = null;
+        public FrmDeviceOpConfigEditor(DeviceOpBind bind)
+        {
+            InitializeComponent();
+
+            InitialDeviceCbo();
+
+            Bind = bind;
+            if (!string.IsNullOrWhiteSpace(bind.Device))
+            {
+                cboDevice.SelectedValue = bind.Device;
+
+                currentDevice = deviceList.FirstOrDefault(u => u.Id == bind.Device);
+                if (currentDevice != null)
+                {
+                    var attr = currentDevice.GetType().GetCustomAttribute<DeviceAttribute>();
+                    if (attr != null)
+                    {
+                        backOpConfig = ConfigFactory.GetOperationConfig(attr.TypeCode);
+                    }
+                }
+            }
+            else
+            {
+                if (cboDevice.Items.Count > 0)
+                    cboDevice.SelectedIndex = 0;
+            }
+
+            cboDevice.SelectedIndexChanged += CboDevice_SelectedIndexChanged;
+
+            if (bind.OpConfig == null)
+            {
+                bind.OpConfig = new OperationConfigBase();
+
+                if (currentDevice != null)
+                {
+                    var attr = currentDevice.GetType().GetCustomAttribute<DeviceAttribute>();
+                    if (attr != null)
+                        bind.OpConfig = ConfigFactory.GetOperationConfig(attr.TypeCode);
+                }
+            }
+
+            backOpConfig.DataFrom(bind.OpConfig);
+
+            propGrid.SelectedObject = bind.OpConfig;
+        }
+
+        private void CboDevice_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            ChangeOpConfigByDevice();
+        }
+
+        private void ChangeOpConfigByDevice()
+        {
+            var device = deviceList.FirstOrDefault(u => u.Id == cboDevice.SelectedValue.ToString());
+            if (device != null)
+            {
+                var attr = device.GetType().GetCustomAttribute<DeviceAttribute>();
+                if (attr != null)
+                {
+                    propGrid.SelectedObject = ConfigFactory.GetOperationConfig(attr.TypeCode);
+                }
+            }
+        }
+
+        private void InitialDeviceCbo()
+        {
+            using (var scope = GlobalVar.Container.BeginLifetimeScope())
+            {
+                deviceList = scope.Resolve<List<IDevice>>();
+                if (deviceList.Count > 0)
+                {
+                    UIHelper.SetCombo(cboDevice, new List<ISimpleDevice>(deviceList), "Name", "Id");
+                }
+            }
+        }
+
+        private void btnCancel_Click(object sender, EventArgs e)
+        {
+            Bind.OpConfig = backOpConfig;
+            this.DialogResult = DialogResult.Cancel;
+        }
+
+        private void btnConfirm_Click(object sender, EventArgs e)
+        {
+            Bind.Device = cboDevice.SelectedValue.ToString();
+            Bind.OpConfig = propGrid.SelectedObject as IOperationConfig;
+            this.DialogResult = DialogResult.OK;
+        }
+
+        private void btnReset_Click(object sender, EventArgs e)
+        {
+            ChangeOpConfigByDevice();
+        }
+    }
+}
diff --git a/src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.resx b/src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/src/Bro.Common.Model/Forms/FrmDeviceOpConfigEditor.resx
@@ -0,0 +1,120 @@
+锘�<?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>
+</root>
\ No newline at end of file
diff --git a/src/Bro.Common.Model/Helper/PropertyConvertHelper.cs b/src/Bro.Common.Model/Helper/PropertyConvertHelper.cs
index 1f56ef7..e9c9e0e 100644
--- a/src/Bro.Common.Model/Helper/PropertyConvertHelper.cs
+++ b/src/Bro.Common.Model/Helper/PropertyConvertHelper.cs
@@ -112,7 +112,7 @@
         //    set => hash = value;
         //}
 
-        public abstract Hashtable GetConvertHash();
+        public abstract Hashtable GetConvertHash(ITypeDescriptorContext context);
 
         public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
         {
@@ -121,7 +121,7 @@
 
         public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
         {
-            Hash = GetConvertHash();
+            Hash = GetConvertHash(context);
 
             string[] ids = new string[Hash.Values.Count];
             int i = 0;
@@ -216,7 +216,26 @@
                 {
                     return (value as IComplexDisplay).GetDisplayText();
                 }
-                else
+                else if (value is IEnumerable enumList)
+                {
+                    string display = "";
+                    bool iComplexDisplayMatch = false;
+                    var enumrator = enumList.GetEnumerator();
+                    while (enumrator.MoveNext())
+                    {
+                        if (enumrator.Current is IComplexDisplay d)
+                        {
+                            iComplexDisplayMatch = true;
+                            display += $"{d.GetDisplayText()} ";
+                        }
+                    }
+
+                    if (iComplexDisplayMatch)
+                    {
+                        return display.Trim();
+                    }
+                }
+
                 {
                     return JsonConvert.SerializeObject(value);
                 }
@@ -571,7 +590,7 @@
                 }
 
                 form.ShowDialog();
-                List<string> returnStrs = tbox.Text.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
+                List<string> returnStrs = tbox.Text.Split(new char[] { '\r', '\n', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
 
                 switch (typeof(T).Name)
                 {
@@ -816,7 +835,7 @@
         }
     }
 
-    public class DeviceTypeConverter : StringConverter 
+    public class DeviceTypeConverter : StringConverter
     {
         public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
         {
@@ -847,7 +866,7 @@
             return new StandardValuesCollection(devices);
         }
     }
-    
+
     public class DeviceInitialConfigEditor<T> : UITypeEditor where T : class, IInitialConfig
     {
         public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
diff --git a/src/Bro.Common.Model/Model/CustomizedPoint.cs b/src/Bro.Common.Model/Model/CustomizedPoint.cs
index e0a0556..148f60f 100644
--- a/src/Bro.Common.Model/Model/CustomizedPoint.cs
+++ b/src/Bro.Common.Model/Model/CustomizedPoint.cs
@@ -15,10 +15,10 @@
     /// </summary>
     public class CustomizedPoint : IComplexDisplay, ICSVOutput, INotifyPropertyChanged
     {
-        private float x = 0;
+        private double x = 0;
         [Category("鍧愭爣璁剧疆")]
         [Description("X鍧愭爣")]
-        public float X
+        public double X
         {
             get => x;
             set
@@ -31,10 +31,10 @@
             }
         }
 
-        private float y = 0;
+        private double y = 0;
         [Category("鍧愭爣璁剧疆")]
         [Description("Y鍧愭爣")]
-        public float Y
+        public double Y
         {
             get => y;
             set
@@ -49,7 +49,7 @@
 
         public CustomizedPoint() { }
 
-        public CustomizedPoint(float x, float y)
+        public CustomizedPoint(double x, double y)
         {
             X = x;
             Y = y;
@@ -95,7 +95,7 @@
             List<CustomizedPoint> points = new List<CustomizedPoint>();
             for (int i = 0; i < Xs.Count && i < Ys.Count; i++)
             {
-                points.Add(new CustomizedPoint((float)Xs[i], (float)Ys[i]));
+                points.Add(new CustomizedPoint(Xs[i], Ys[i]));
             }
 
             return points;
@@ -333,19 +333,19 @@
     {
         [Category("鏍囧畾鍧愭爣")]
         [Description("骞冲彴鍧愭爣-X")]
-        public float X { get; set; }
+        public double X { get; set; }
 
         [Category("鏍囧畾鍧愭爣")]
         [Description("骞冲彴鍧愭爣-X")]
-        public float Y { get; set; }
+        public double Y { get; set; }
 
         [Category("鍍忕礌鍧愭爣")]
         [Description("鍍忕礌鍧愭爣-U")]
-        public float U { get; set; }
+        public double U { get; set; }
 
         [Category("鍍忕礌鍧愭爣")]
         [Description("鍍忕礌鍧愭爣-V")]
-        public float V { get; set; }
+        public double V { get; set; }
 
         private bool isBasePoint = false;
         [Category("蹇嵎璁剧疆")]
@@ -419,7 +419,7 @@
         //    }
         //}
 
-        public float MainAxisValue
+        public double MainAxisValue
         {
             get => ((Direction ?? PriorityDirection.X) == PriorityDirection.X) ? X : Y;
             set
@@ -435,7 +435,7 @@
             }
         }
 
-        public float MinorAxisValue
+        public double MinorAxisValue
         {
             get => ((Direction ?? PriorityDirection.X) == PriorityDirection.X) ? Y : X;
             set
diff --git a/src/Bro.Common.Model/Model/DeviceOpBind.cs b/src/Bro.Common.Model/Model/DeviceOpBind.cs
new file mode 100644
index 0000000..5b14df8
--- /dev/null
+++ b/src/Bro.Common.Model/Model/DeviceOpBind.cs
@@ -0,0 +1,88 @@
+锘縰sing Autofac;
+using Bro.Common.Helper;
+using Bro.Common.Interface;
+using Bro.Common.Model.Forms;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing.Design;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms.Design;
+
+namespace Bro.Common.Model
+{
+    public class DeviceOpBind : IComplexDisplay
+    {
+        [Category("璁惧鍚嶇О")]
+        [Description("璁惧鍚嶇О")]
+        [TypeConverter(typeof(DeviceSelectorConverter<IDevice>))]
+        public virtual string Device { get; set; }
+
+        [Category("鎿嶄綔閰嶇疆")]
+        [Description("鎿嶄綔閰嶇疆")]
+        public IOperationConfig OpConfig { get; set; } = null;
+
+        public string GetDisplayText()
+        {
+            string msg = "";
+            using (var scope = GlobalVar.Container.BeginLifetimeScope())
+            {
+                List<IDevice> deviceList = scope.Resolve<List<IDevice>>();
+
+                if (Device != null)
+                {
+                    var device = deviceList.FirstOrDefault(u => u.Id == Device);
+
+                    if (device != null)
+                    {
+                        msg += device.Name + " ";
+                    }
+                }
+            }
+
+            if (OpConfig is IComplexDisplay d)
+            {
+                msg += d.GetDisplayText();
+            }
+            else
+            {
+                msg += JsonConvert.SerializeObject(OpConfig);
+            }
+
+            return msg;
+        }
+    }
+    
+    public class IOperationConfigByDeviceEditor : UITypeEditor
+    {
+        public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
+        {
+            return UITypeEditorEditStyle.Modal;
+        }
+
+        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
+        {
+            IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
+
+            if (edSvc != null)
+            {
+                if (value == null)
+                {
+                    value = new DeviceOpBind();
+                }
+
+                if (value is DeviceOpBind bind)
+                {
+                    FrmDeviceOpConfigEditor frmDeviceOpEditor = new FrmDeviceOpConfigEditor(bind);
+                    frmDeviceOpEditor.ShowDialog();
+                    return frmDeviceOpEditor.Bind;
+                }
+            }
+
+            return base.EditValue(context, provider, value);
+        }
+    }
+}
diff --git a/src/Bro.Common.Model/Selector/DeviceSelector.cs b/src/Bro.Common.Model/Selector/DeviceSelector.cs
index 1b289c8..34c25f7 100644
--- a/src/Bro.Common.Model/Selector/DeviceSelector.cs
+++ b/src/Bro.Common.Model/Selector/DeviceSelector.cs
@@ -3,13 +3,14 @@
 using Bro.Common.Interface;
 using System.Collections;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Linq;
 
 namespace Bro.Common.Model
 {
-    public class DeviceSelectorConverter<T> : ComboBoxItemTypeConvert where T : IDevice
+    public class DeviceSelectorConverter<T> : ComboBoxItemTypeConvert //where T : IDevice
     {
-        public override Hashtable GetConvertHash()
+        public override Hashtable GetConvertHash(ITypeDescriptorContext context)
         {
             Hashtable table = new Hashtable();
             using (var scope = GlobalVar.Container.BeginLifetimeScope())
diff --git a/src/Bro.Common.Model/Selector/ProcessMethodSelector.cs b/src/Bro.Common.Model/Selector/ProcessMethodSelector.cs
index ba6b93d..40fcfe8 100644
--- a/src/Bro.Common.Model/Selector/ProcessMethodSelector.cs
+++ b/src/Bro.Common.Model/Selector/ProcessMethodSelector.cs
@@ -10,7 +10,7 @@
 {
     public class ProcessMethodSelectorConverter : ComboBoxItemTypeConvert
     {
-        public override Hashtable GetConvertHash()
+        public override Hashtable GetConvertHash(ITypeDescriptorContext context)
         {
             Hashtable table = new Hashtable();
             using (var scope = GlobalVar.Container.BeginLifetimeScope())
diff --git a/src/Bro.Device.Gocator/Bro.Device.Gocator.csproj b/src/Bro.Device.Gocator/Bro.Device.Gocator.csproj
new file mode 100644
index 0000000..2bdad3e
--- /dev/null
+++ b/src/Bro.Device.Gocator/Bro.Device.Gocator.csproj
@@ -0,0 +1,49 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{112009F0-7902-454B-9A6C-A3AFC8FA8FFF}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Bro.Device.Gocator</RootNamespace>
+    <AssemblyName>Bro.Device.Gocator</AssemblyName>
+    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <Deterministic>true</Deterministic>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="GocatorConfig.cs" />
+    <Compile Include="GocatorDriver.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>
\ No newline at end of file
diff --git a/src/Bro.Device.Gocator/GocatorConfig.cs b/src/Bro.Device.Gocator/GocatorConfig.cs
new file mode 100644
index 0000000..462b025
--- /dev/null
+++ b/src/Bro.Device.Gocator/GocatorConfig.cs
@@ -0,0 +1,12 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Bro.Device.Gocator
+{
+    class GocatorConfig
+    {
+    }
+}
diff --git a/src/Bro.Device.Gocator/GocatorDriver.cs b/src/Bro.Device.Gocator/GocatorDriver.cs
new file mode 100644
index 0000000..678c62c
--- /dev/null
+++ b/src/Bro.Device.Gocator/GocatorDriver.cs
@@ -0,0 +1,12 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Bro.Device.Gocator
+{
+    class GocatorDriver
+    {
+    }
+}
diff --git a/src/Bro.Device.Gocator/Properties/AssemblyInfo.cs b/src/Bro.Device.Gocator/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..08d604e
--- /dev/null
+++ b/src/Bro.Device.Gocator/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+锘縰sing System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 鏈夊叧绋嬪簭闆嗙殑涓�鑸俊鎭敱浠ヤ笅
+// 鎺у埗銆傛洿鏀硅繖浜涚壒鎬у�煎彲淇敼
+// 涓庣▼搴忛泦鍏宠仈鐨勪俊鎭��
+[assembly: AssemblyTitle("Bro.Device.Gocator")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Bro.Device.Gocator")]
+[assembly: AssemblyCopyright("Copyright 漏  2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 灏� ComVisible 璁剧疆涓� false 浼氫娇姝ょ▼搴忛泦涓殑绫诲瀷
+//瀵� COM 缁勪欢涓嶅彲瑙併�傚鏋滈渶瑕佷粠 COM 璁块棶姝ょ▼搴忛泦涓殑绫诲瀷
+//璇峰皢姝ょ被鍨嬬殑 ComVisible 鐗规�ц缃负 true銆�
+[assembly: ComVisible(false)]
+
+// 濡傛灉姝ら」鐩悜 COM 鍏紑锛屽垯涓嬪垪 GUID 鐢ㄤ簬绫诲瀷搴撶殑 ID
+[assembly: Guid("112009f0-7902-454b-9a6c-a3afc8fa8fff")]
+
+// 绋嬪簭闆嗙殑鐗堟湰淇℃伅鐢变笅鍒楀洓涓�肩粍鎴�: 
+//
+//      涓荤増鏈�
+//      娆$増鏈�
+//      鐢熸垚鍙�
+//      淇鍙�
+//
+//鍙互鎸囧畾鎵�鏈夎繖浜涘�硷紝涔熷彲浠ヤ娇鐢ㄢ�滅敓鎴愬彿鈥濆拰鈥滀慨璁㈠彿鈥濈殑榛樿鍊�
+//閫氳繃浣跨敤 "*"锛屽涓嬫墍绀�:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Bro.M071.Process/Bro.M071.Process.csproj b/src/Bro.M071.Process/Bro.M071.Process.csproj
new file mode 100644
index 0000000..168848e
--- /dev/null
+++ b/src/Bro.M071.Process/Bro.M071.Process.csproj
@@ -0,0 +1,95 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{B50C1309-495C-4ADF-8A3D-6F6A06CCC4CC}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>Bro.M071.Process</RootNamespace>
+    <AssemblyName>Bro.M071.Process</AssemblyName>
+    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <Deterministic>true</Deterministic>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <StartupObject />
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Autofac, Version=4.9.4.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\Autofac.4.9.4\lib\net45\Autofac.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Deployment" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="M071Converters.cs" />
+    <Compile Include="M071Config.cs" />
+    <Compile Include="M071Models.cs" />
+    <Compile Include="M071Process.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <None Include="packages.config" />
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Bro.Common.Device\Bro.Common.Device.csproj">
+      <Project>{987308DD-8BAA-463A-94E2-77D62E01A5BF}</Project>
+      <Name>Bro.Common.Device</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Bro.Common.Model\Bro.Common.Model.csproj">
+      <Project>{1A3CBFE7-3F78-42C3-95C5-10360450DBEA}</Project>
+      <Name>Bro.Common.Model</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Bro.Process\Bro.Process.csproj">
+      <Project>{197C5AA8-9609-4D1C-B1E3-5879006EAAF4}</Project>
+      <Name>Bro.Process</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>
\ No newline at end of file
diff --git a/src/Bro.M071.Process/M071Config.cs b/src/Bro.M071.Process/M071Config.cs
new file mode 100644
index 0000000..1c1d42d
--- /dev/null
+++ b/src/Bro.M071.Process/M071Config.cs
@@ -0,0 +1,66 @@
+锘縰sing Bro.Common.Helper;
+using Bro.Common.Model;
+using Bro.Process;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing.Design;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Bro.M071.Process
+{
+    [Process("M071", EnumHelper.DeviceAttributeType.InitialConfig)]
+    public partial class M071Config : ProcessConfigBase
+    {
+        #region 鍏叡瀛楀吀閰嶇疆
+        [Category("鍏叡瀛楀吀閰嶇疆")]
+        [Description("閿洏閿悕闆嗗悎")]
+        [TypeConverter(typeof(SimpleCollectionConvert<string>))]
+        [Editor(typeof(SimpleCollectionEditor<string>), typeof(UITypeEditor))]
+        public List<string> KeyNameCollection { get; set; } = new List<string>();
+
+        [Category("鍏叡瀛楀吀閰嶇疆")]
+        [Description("妫�娴嬫爣鍑嗛泦鍚�")]
+        [TypeConverter(typeof(CollectionCountConvert))]
+        [Editor(typeof(ComplexCollectionEditor<Spec>), typeof(UITypeEditor))]
+        public List<Spec> MeasureSpecCollection { get; set; } = new List<Spec>();
+
+        [Category("鍏叡瀛楀吀閰嶇疆")]
+        [Description("鍗曢敭绠楁硶閰嶇疆闆嗗悎")]
+        [TypeConverter(typeof(CollectionCountConvert))]
+        [Editor(typeof(ComplexCollectionEditor<KeyAlgorithem>), typeof(UITypeEditor))]
+        public List<KeyAlgorithem> KeyAlgorithemCollection { get; set; } = new List<KeyAlgorithem>();
+
+        [Category("鍏叡瀛楀吀閰嶇疆")]
+        [Description("鍗曢敭缁撴灉閰嶇疆闆嗗悎")]
+        [TypeConverter(typeof(CollectionCountConvert))]
+        [Editor(typeof(ComplexCollectionEditor<KeyResult>), typeof(UITypeEditor))]
+        public List<KeyResult> KeyResultCollection { get; set; } = new List<KeyResult>();
+        #endregion
+
+        [Category("鑳屾櫙鍥剧墖璁剧疆")]
+        [Description("杩愯鑳屾櫙鍥剧墖璺緞")]
+        [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))]
+        public string BackgroundImagePath { get; set; }
+
+        [Category("妫�娴嬭缃�")]
+        [Description("鎷嶆憚鐐逛綅璁剧疆闆嗗悎")]
+        [TypeConverter(typeof(CollectionCountConvert))]
+        [Editor(typeof(ComplexCollectionEditor<SnapshotPoint>), typeof(UITypeEditor))]
+        public List<SnapshotPoint> SnapshotPointCollection { get; set; } = new List<SnapshotPoint>();
+
+        [Category("妫�娴嬭缃�")]
+        [Description("瑙嗚妫�娴嬪崟閿厤缃泦鍚�")]
+        [TypeConverter(typeof(CollectionCountConvert))]
+        [Editor(typeof(ComplexCollectionEditor<KeyUnit>), typeof(UITypeEditor))]
+        public List<KeyUnit> KeyUnitCollection { get; set; } = new List<KeyUnit>();
+
+        [Category("妫�娴嬭缃�")]
+        [Description("妫�娴嬮厤缃泦鍚�")]
+        [TypeConverter(typeof(CollectionCountConvert))]
+        [Editor(typeof(ComplexCollectionEditor<MeasurementUint>), typeof(UITypeEditor))]
+        public List<MeasurementUint> MeasurementUnitCollection { get; set; } = new List<MeasurementUint>();
+    }
+}
diff --git a/src/Bro.M071.Process/M071Converters.cs b/src/Bro.M071.Process/M071Converters.cs
new file mode 100644
index 0000000..da87fd1
--- /dev/null
+++ b/src/Bro.M071.Process/M071Converters.cs
@@ -0,0 +1,191 @@
+锘縰sing Autofac;
+using Bro.Common.Helper;
+using Bro.Common.Interface;
+using Bro.Common.Model;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+
+namespace Bro.M071.Process
+{
+    internal class KeyNameDictConverter : StringConverter
+    {
+        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
+        {
+            return true;
+        }
+
+        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
+        {
+            return true;
+        }
+
+        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
+        {
+            using (var scope = GlobalVar.Container.BeginLifetimeScope())
+            {
+                IProcessConfig iConfig = scope.Resolve<IProcessConfig>();
+
+                if (iConfig is M071Config config)
+                {
+                    return new StandardValuesCollection(config.KeyNameCollection);
+                }
+            }
+
+            return base.GetStandardValues(context); ;
+        }
+    }
+
+    internal class SnapshotPointConverter : ComboBoxItemTypeConvert
+    {
+        public override Hashtable GetConvertHash(ITypeDescriptorContext context)
+        {
+            Hashtable table = new Hashtable();
+
+            using (var scope = GlobalVar.Container.BeginLifetimeScope())
+            {
+                IProcessConfig iConfig = scope.Resolve<IProcessConfig>();
+
+                if (iConfig is M071Config config)
+                {
+                    config.SnapshotPointCollection.ForEach(s =>
+                    {
+                        table[s.Id] = s.Name;
+                    });
+                }
+            }
+
+            return table;
+        }
+    }
+
+    internal class KeyAlgorithemConverter : ComboBoxItemTypeConvert
+    {
+        public override Hashtable GetConvertHash(ITypeDescriptorContext context)
+        {
+            Hashtable table = new Hashtable();
+
+            using (var scope = GlobalVar.Container.BeginLifetimeScope())
+            {
+                IProcessConfig iConfig = scope.Resolve<IProcessConfig>();
+
+                if (iConfig is M071Config config)
+                {
+                    config.KeyAlgorithemCollection.ForEach(s =>
+                    {
+                        table[s.Id] = s.Name;
+                    });
+                }
+            }
+
+            return table;
+        }
+    }
+
+    internal class KeyResultConverter : ComboBoxItemTypeConvert
+    {
+        public override Hashtable GetConvertHash(ITypeDescriptorContext context)
+        {
+            Hashtable table = new Hashtable();
+
+            using (var scope = GlobalVar.Container.BeginLifetimeScope())
+            {
+                IProcessConfig iConfig = scope.Resolve<IProcessConfig>();
+
+                if (iConfig is M071Config config)
+                {
+                    config.KeyResultCollection.ForEach(s =>
+                    {
+                        table[s.Id] = s.Name;
+                    });
+                }
+            }
+
+            return table;
+        }
+    }
+
+    //internal class KeyUnitConverter : ComboBoxItemTypeConvert
+    //{
+    //    public override Hashtable GetConvertHash(ITypeDescriptorContext context)
+    //    {
+    //        Hashtable table = new Hashtable();
+
+    //        using (var scope = GlobalVar.Container.BeginLifetimeScope())
+    //        {
+    //            IProcessConfig iConfig = scope.Resolve<IProcessConfig>();
+
+    //            if (iConfig is M071Config config)
+    //            {
+    //                config.KeyUnitCollection.ForEach(s =>
+    //                {
+    //                    table[s.Id] = s.Key;
+    //                });
+    //            }
+    //        }
+
+    //        return table;
+    //    }
+    //}
+
+    internal class KeyUnitResultConverter : ComboBoxItemTypeConvert
+    {
+        public override Hashtable GetConvertHash(ITypeDescriptorContext context)
+        {
+            Hashtable table = new Hashtable();
+
+            using (var scope = GlobalVar.Container.BeginLifetimeScope())
+            {
+                IProcessConfig iConfig = scope.Resolve<IProcessConfig>();
+
+                if (iConfig is M071Config config)
+                {
+                    var resultIds = config.KeyUnitCollection.Where(u => u.Key == (context.Instance as KeyUnitBind).Key).Select(u => u.KeyResult).ToList();
+
+                    var result = config.KeyResultCollection.Where(u => resultIds.Contains(u.Id)).SelectMany(u => u.Results).ToList();
+
+                    if (result != null && result.Count > 0)
+                    {
+                        result.ForEach(r =>
+                        {
+                            table[r] = r;
+                        });
+
+                        table[""] = "";
+                    }
+                }
+            }
+
+            return table;
+        }
+    }
+
+    internal class MeasureTypeConverter : StringConverter
+    {
+        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
+        {
+            return true;
+        }
+
+        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
+        {
+            return true;
+        }
+
+        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
+        {
+            using (var scope = GlobalVar.Container.BeginLifetimeScope())
+            {
+                IProcessConfig iConfig = scope.Resolve<IProcessConfig>();
+
+                if (iConfig is M071Config config)
+                {
+                    return new StandardValuesCollection(config.MeasureSpecCollection.Select(u => u.Code).ToList());
+                }
+            }
+
+            return base.GetStandardValues(context); ;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Bro.M071.Process/M071Models.cs b/src/Bro.M071.Process/M071Models.cs
new file mode 100644
index 0000000..16af13a
--- /dev/null
+++ b/src/Bro.M071.Process/M071Models.cs
@@ -0,0 +1,205 @@
+锘縰sing Autofac;
+using Bro.Common.Base;
+using Bro.Common.Helper;
+using Bro.Common.Interface;
+using Bro.Common.Model;
+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;
+
+namespace Bro.M071.Process
+{
+    public class KeyAlgorithem : IComplexDisplay
+    {
+        [Browsable(false)]
+        public string Id { get; set; } = Guid.NewGuid().ToString();
+
+        [Category("鍗曢敭绠楁硶閰嶇疆")]
+        [Description("绠楁硶鍚嶇О")]
+        public string Name { get; set; }
+
+        [Category("鍗曢敭绠楁硶閰嶇疆")]
+        [Description("绠楁硶璺緞")]
+        [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))]
+        public string AlgorithemPath { get; set; }
+
+        public string GetDisplayText()
+        {
+            return $"{Name} -- {AlgorithemPath}";
+        }
+    }
+
+    public class KeyResult : IComplexDisplay
+    {
+        [Browsable(false)]
+        public string Id { get; set; } = Guid.NewGuid().ToString();
+
+        [Category("鍗曢敭缁撴灉閰嶇疆")]
+        [Description("缁撴灉閰嶇疆鍚嶇О")]
+        public string Name { get; set; }
+
+        [Category("鍗曢敭缁撴灉閰嶇疆")]
+        [Description("缁撴灉閰嶇疆闆嗗悎")]
+        [TypeConverter(typeof(SimpleCollectionConvert<string>))]
+        [Editor(typeof(SimpleCollectionEditor<string>), typeof(UITypeEditor))]
+        public List<string> Results { get; set; } = new List<string>();
+
+        public string GetDisplayText()
+        {
+            return $"{Name} -- {(string.Join(" ", Results))}";
+        }
+    }
+
+    public class SnapshotPoint : IComplexDisplay, IHalconToolPath
+    {
+        public string GetDisplayText()
+        {
+            return Name + " " + string.Join(" ", Destination.Select(u => u.GetDisplayText())) + " " + CameraOp.GetDisplayText();
+        }
+
+        public List<string> GetHalconToolPathList()
+        {
+            if (CameraOp.OpConfig is IHalconToolPath path)
+            {
+                return path.GetHalconToolPathList();
+            }
+            else
+            {
+                return new List<string>();
+            }
+        }
+
+        [Browsable(false)]
+        public string Id { get; set; } = Guid.NewGuid().ToString();
+
+        [Category("鎷嶇収鐐瑰悕绉�")]
+        [Description("鎷嶇収鐐瑰悕绉�")]
+        public string Name { get; set; }
+
+        [Category("璁惧閰嶇疆")]
+        [Description("杩愬姩璁惧")]
+        [TypeConverter(typeof(DeviceSelectorConverter<IMotion>))]
+        public string MotionDevice { get; set; }
+
+        [Category("杩愬姩鐐逛綅")]
+        [Description("杩愬姩鐐逛綅")]
+        [TypeConverter(typeof(ComplexObjectConvert))]
+        [Editor(typeof(ComplexCollectionEditor<AxisInfo>), typeof(UITypeEditor))]
+        public List<AxisInfo> Destination { get; set; } = new List<AxisInfo>();
+
+        [Category("鐩告満鍜屾搷浣滈厤缃�")]
+        [Description("鐩告満鍜屾搷浣滈厤缃�")]
+        [TypeConverter(typeof(ComplexObjectConvert))]
+        [Editor(typeof(IOperationConfigByDeviceEditor), typeof(UITypeEditor))]
+        public DeviceOpBind CameraOp { get; set; } = new DeviceOpBind();
+    }
+
+    public class KeyUnit : IComplexDisplay, IHalconToolPath
+    {
+        private string key = "";
+        [Category("閿悕閰嶇疆")]
+        [Description("鍗曢敭妫�娴嬮敭鍚�")]
+        [TypeConverter(typeof(KeyNameDictConverter))]
+        public string Key
+        {
+            get => key;
+            set
+            {
+                AlignName = key = value;
+            }
+        }
+
+        [Category("閿悕閰嶇疆")]
+        [Description("鍒悕")]
+        public string AlignName { get; set; }
+
+        [Category("鍥惧儚鏉ユ簮")]
+        [Description("鎷嶇収鐐逛綅")]
+        [TypeConverter(typeof(SnapshotPointConverter))]
+        public string SnapshotPoint { get; set; }
+
+        [Category("鍥惧儚鏉ユ簮")]
+        [Description("鎷嶇収鐐逛綅鑾峰彇鐨勫浘鐗囩储寮�")]
+        public int ImageIndex { get; set; } = 0;
+
+        [Category("绠楁硶閰嶇疆")]
+        [Description("鍗曢敭妫�娴嬮厤缃畻娉曠被鍨�")]
+        [TypeConverter(typeof(KeyAlgorithemConverter))]
+        public string KeyAlgorithem { get; set; }
+
+        [Category("绠楁硶閰嶇疆")]
+        [Description("鍗曢敭妫�娴嬮厤缃粨鏋滅被鍨�")]
+        [TypeConverter(typeof(KeyResultConverter))]
+        public string KeyResult { get; set; }
+
+        public string GetDisplayText()
+        {
+            return $"{AlignName}";
+        }
+
+        public List<string> GetHalconToolPathList()
+        {
+            return null;
+        }
+    }
+
+    public class MeasurementUint : IComplexDisplay
+    {
+        [Category("鍚嶇О")]
+        [Description("鍚嶇О")]
+        public string Name { get; set; } = "";
+
+        [Category("绠楁硶閰嶇疆")]
+        [Description("妫�娴嬪拰鏍囧噯绫诲瀷")]
+        [TypeConverter(typeof(MeasureTypeConverter))]
+        public string MeasureType { get; set; }
+
+        [Category("绠楁硶閰嶇疆")]
+        [Description("娑夊強鍗曢敭闆嗗悎")]
+        [TypeConverter(typeof(ComplexObjectConvert))]
+        [Editor(typeof(ComplexCollectionEditor<KeyUnitBind>), typeof(UITypeEditor))]
+        public List<KeyUnitBind> KeyUnitCollection { get; set; } = new List<KeyUnitBind>();
+
+        [Browsable(false)]
+        public RectangleF DisplayLocation { get; set; } = new RectangleF();
+
+        public string GetDisplayText()
+        {
+            if (string.IsNullOrWhiteSpace(Name))
+            {
+                return string.Join("-", KeyUnitCollection.Select(u => u.GetDisplayText())) + "-" + MeasureType.ToString();
+            }
+            else
+            {
+                return Name;
+            }
+        }
+    }
+
+    public class KeyUnitBind : IComplexDisplay
+    {
+        [Category("鍗曢敭閰嶇疆")]
+        [Description("鍗曢敭閰嶇疆")]
+        [TypeConverter(typeof(KeyNameDictConverter))]
+        public string Key { get; set; }
+
+        [Category("鍗曢敭閰嶇疆")]
+        [Description("鍗曢敭缁撴灉閰嶇疆")]
+        [TypeConverter(typeof(KeyUnitResultConverter))]
+        public string KeyResult { get; set; } = "";
+
+        public string GetDisplayText()
+        {
+            string msg = Key;
+
+            msg += string.IsNullOrWhiteSpace(KeyResult) ? "" : $"-{KeyResult}";
+
+            return msg;
+        }
+    }
+}
diff --git a/src/Bro.M071.Process/M071Process.cs b/src/Bro.M071.Process/M071Process.cs
new file mode 100644
index 0000000..33827af
--- /dev/null
+++ b/src/Bro.M071.Process/M071Process.cs
@@ -0,0 +1,27 @@
+锘縰sing Bro.Common.Helper;
+using Bro.Common.Model;
+using Bro.Process;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Bro.M071.Process
+{
+    [Process("M071", EnumHelper.DeviceAttributeType.Device)]
+    public partial class M071Process : ProcessControl
+    {
+        #region 鏋勯�犲嚱鏁�
+        public M071Process() : base() { }
+        public M071Process(string productionCode) : base(productionCode) { }
+        #endregion
+
+        #region 閰嶇疆
+        M071Config Config
+        {
+            get => IConfig as M071Config;
+        }
+        #endregion
+    }
+}
diff --git a/src/Bro.M071.Process/Properties/AssemblyInfo.cs b/src/Bro.M071.Process/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8d31d69
--- /dev/null
+++ b/src/Bro.M071.Process/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+锘縰sing System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 鏈夊叧绋嬪簭闆嗙殑涓�鑸俊鎭敱浠ヤ笅
+// 鎺у埗銆傛洿鏀硅繖浜涚壒鎬у�煎彲淇敼
+// 涓庣▼搴忛泦鍏宠仈鐨勪俊鎭��
+[assembly: AssemblyTitle("Bro.M071.Process")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Bro.M071.Process")]
+[assembly: AssemblyCopyright("Copyright 漏  2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 灏� ComVisible 璁剧疆涓� false 浼氫娇姝ょ▼搴忛泦涓殑绫诲瀷
+//瀵� COM 缁勪欢涓嶅彲瑙併�傚鏋滈渶瑕佷粠 COM 璁块棶姝ょ▼搴忛泦涓殑绫诲瀷
+//璇峰皢姝ょ被鍨嬬殑 ComVisible 鐗规�ц缃负 true銆�
+[assembly: ComVisible(false)]
+
+// 濡傛灉姝ら」鐩悜 COM 鍏紑锛屽垯涓嬪垪 GUID 鐢ㄤ簬绫诲瀷搴撶殑 ID
+[assembly: Guid("b50c1309-495c-4adf-8a3d-6f6a06ccc4cc")]
+
+// 绋嬪簭闆嗙殑鐗堟湰淇℃伅鐢变笅鍒楀洓涓�肩粍鎴�: 
+//
+//      涓荤増鏈�
+//      娆$増鏈�
+//      鐢熸垚鍙�
+//      淇鍙�
+//
+//鍙互鎸囧畾鎵�鏈夎繖浜涘�硷紝涔熷彲浠ヤ娇鐢ㄢ�滅敓鎴愬彿鈥濆拰鈥滀慨璁㈠彿鈥濈殑榛樿鍊�
+//閫氳繃浣跨敤 "*"锛屽涓嬫墍绀�:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Bro.M071.Process/Properties/Resources.Designer.cs b/src/Bro.M071.Process/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..60f0045
--- /dev/null
+++ b/src/Bro.M071.Process/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+锘�//------------------------------------------------------------------------------
+// <auto-generated>
+//     姝や唬鐮佺敱宸ュ叿鐢熸垚銆�
+//     杩愯鏃剁増鏈�: 4.0.30319.42000
+//
+//     瀵规鏂囦欢鐨勬洿鏀瑰彲鑳藉鑷翠笉姝g‘鐨勮涓猴紝濡傛灉
+//     閲嶆柊鐢熸垚浠g爜锛屽垯鎵�鍋氭洿鏀瑰皢涓㈠け銆�
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Bro.M071.Process.Properties
+{
+
+
+    /// <summary>
+    ///   寮虹被鍨嬭祫婧愮被锛岀敤浜庢煡鎵炬湰鍦板寲瀛楃涓茬瓑銆�
+    /// </summary>
+    // 姝ょ被鏄敱 StronglyTypedResourceBuilder
+    // 绫婚�氳繃绫讳技浜� ResGen 鎴� Visual Studio 鐨勫伐鍏疯嚜鍔ㄧ敓鎴愮殑銆�
+    // 鑻ヨ娣诲姞鎴栧垹闄ゆ垚鍛橈紝璇风紪杈� .ResX 鏂囦欢锛岀劧鍚庨噸鏂拌繍琛� ResGen
+    // (浠� /str 浣滀负鍛戒护閫夐」)锛屾垨閲嶆柊鐢熸垚 VS 椤圭洰銆�
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources
+    {
+
+        private static global::System.Resources.ResourceManager resourceMan;
+
+        private static global::System.Globalization.CultureInfo resourceCulture;
+
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources()
+        {
+        }
+
+        /// <summary>
+        ///   杩斿洖姝ょ被浣跨敤鐨勭紦瀛� ResourceManager 瀹炰緥銆�
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager
+        {
+            get
+            {
+                if ((resourceMan == null))
+                {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Bro.M071.Process.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+
+        /// <summary>
+        ///   瑕嗙洊褰撳墠绾跨▼鐨� CurrentUICulture 灞炴��
+        ///   浣跨敤姝ゅ己绫诲瀷鐨勮祫婧愮被鐨勮祫婧愭煡鎵俱��
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture
+        {
+            get
+            {
+                return resourceCulture;
+            }
+            set
+            {
+                resourceCulture = value;
+            }
+        }
+    }
+}
diff --git a/src/Bro.M071.Process/Properties/Resources.resx b/src/Bro.M071.Process/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/src/Bro.M071.Process/Properties/Resources.resx
@@ -0,0 +1,117 @@
+锘�<?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.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: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" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </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" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/src/Bro.M071.Process/Properties/Settings.Designer.cs b/src/Bro.M071.Process/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..88f45a6
--- /dev/null
+++ b/src/Bro.M071.Process/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+锘�//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Bro.M071.Process.Properties
+{
+
+
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+    {
+
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+        public static Settings Default
+        {
+            get
+            {
+                return defaultInstance;
+            }
+        }
+    }
+}
diff --git a/src/Bro.M071.Process/Properties/Settings.settings b/src/Bro.M071.Process/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/src/Bro.M071.Process/Properties/Settings.settings
@@ -0,0 +1,7 @@
+锘�<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>
diff --git a/src/Bro.M071.Process/packages.config b/src/Bro.M071.Process/packages.config
new file mode 100644
index 0000000..62a076c
--- /dev/null
+++ b/src/Bro.M071.Process/packages.config
@@ -0,0 +1,4 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Autofac" version="4.9.4" targetFramework="net452" />
+</packages>
\ No newline at end of file
diff --git a/src/Bro.Process/ProcessConfig.cs b/src/Bro.Process/ProcessConfig.cs
index dcff227..ff3918d 100644
--- a/src/Bro.Process/ProcessConfig.cs
+++ b/src/Bro.Process/ProcessConfig.cs
@@ -75,6 +75,7 @@
 
             configs.AddRange(CameraConfigCollection);
             configs.AddRange(PLCConfigCollection);
+            configs.AddRange(DeviceConfigs);
 
             return configs;
         }
diff --git a/src/Bro.UI.Model.Winform/Element/CrossHair.cs b/src/Bro.UI.Model.Winform/Element/CrossHair.cs
index 4142c28..ec2749f 100644
--- a/src/Bro.UI.Model.Winform/Element/CrossHair.cs
+++ b/src/Bro.UI.Model.Winform/Element/CrossHair.cs
@@ -117,15 +117,15 @@
 
         public override void Draw(Graphics g)
         {
-            g.DrawRectangle(Pen, CenterPoint.U - HalfRectangleSize, CenterPoint.V - HalfRectangleSize, HalfRectangleSize * 2, HalfRectangleSize * 2);
+            g.DrawRectangle(Pen, (float)CenterPoint.U - HalfRectangleSize, (float)CenterPoint.V - HalfRectangleSize, HalfRectangleSize * 2, HalfRectangleSize * 2);
 
-            g.DrawLine(Pen, CenterPoint.U, CenterPoint.V - HalfLength, CenterPoint.U, CenterPoint.V + HalfLength);
-            g.DrawLine(Pen, CenterPoint.U - HalfLength, CenterPoint.V, CenterPoint.U + HalfLength, CenterPoint.V);
+            g.DrawLine(Pen, (float)CenterPoint.U, (float)CenterPoint.V - HalfLength, (float)CenterPoint.U, (float)CenterPoint.V + HalfLength);
+            g.DrawLine(Pen, (float)CenterPoint.U - HalfLength, (float)CenterPoint.V, (float)CenterPoint.U + HalfLength, (float)CenterPoint.V);
 
             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(CenterPoint.U + FontDistance, CenterPoint.V + FontDistance));
+                g.DrawString(info, new Font("NewRoman", FontSize), new SolidBrush(Pen.Color), new PointF((float)CenterPoint.U + FontDistance, (float)CenterPoint.V + FontDistance));
             }
         }
 
diff --git a/src/Bro.UI.Model.Winform/Element/CrossHairWithAngle.cs b/src/Bro.UI.Model.Winform/Element/CrossHairWithAngle.cs
index 60f3e5c..0ad45e8 100644
--- a/src/Bro.UI.Model.Winform/Element/CrossHairWithAngle.cs
+++ b/src/Bro.UI.Model.Winform/Element/CrossHairWithAngle.cs
@@ -179,18 +179,18 @@
 
         public override void Draw(Graphics g)
         {
-            g.DrawRectangle(Pen, ImagePoint.X - HalfRectangleSize, ImagePoint.Y - HalfRectangleSize, HalfRectangleSize * 2, HalfRectangleSize * 2);
+            g.DrawRectangle(Pen, (float)ImagePoint.X - HalfRectangleSize, (float)ImagePoint.Y - HalfRectangleSize, HalfRectangleSize * 2, HalfRectangleSize * 2);
 
-            g.DrawLine(Pen, ImagePoint.X, ImagePoint.Y - HalfLength, ImagePoint.X, ImagePoint.Y + HalfLength);
-            g.DrawLine(Pen, ImagePoint.X - HalfLength, ImagePoint.Y, ImagePoint.X + HalfLength, ImagePoint.Y);
+            g.DrawLine(Pen, (float)ImagePoint.X, (float)ImagePoint.Y - HalfLength, (float)ImagePoint.X, (float)ImagePoint.Y + HalfLength);
+            g.DrawLine(Pen, (float)ImagePoint.X - HalfLength, (float)ImagePoint.Y, (float)ImagePoint.X + HalfLength, (float)ImagePoint.Y);
 
             Pen arrowPen = new Pen(Pen.Color, Pen.Width + 3.5f);
             arrowPen.StartCap = System.Drawing.Drawing2D.LineCap.AnchorMask;
             arrowPen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
-            g.DrawLine(arrowPen, ImagePoint.X, ImagePoint.Y, ImagePoint.X + (float)(HalfLength * Math.Cos(Angle * Math.PI / 180.0)), ImagePoint.Y - (float)(HalfLength * Math.Sin(Angle * Math.PI / 180.0)));
+            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(ImagePoint.X + FontDistance, ImagePoint.Y + FontDistance));
+            g.DrawString(info, new Font("NewRoman", FontSize), new SolidBrush(Pen.Color), new PointF((float)ImagePoint.X + FontDistance, (float)ImagePoint.Y + FontDistance));
         }
 
         public override bool IsMouseHover(Point p)
diff --git a/src/Bro.UI.Model.Winform/Element/PointIndicator.cs b/src/Bro.UI.Model.Winform/Element/PointIndicator.cs
index adb66bb..f01b8f5 100644
--- a/src/Bro.UI.Model.Winform/Element/PointIndicator.cs
+++ b/src/Bro.UI.Model.Winform/Element/PointIndicator.cs
@@ -68,12 +68,12 @@
 
         public override void Draw(Graphics g)
         {
-            g.DrawEllipse(Pen, new RectangleF(Center.X - Radius, Center.Y - Radius, Radius * 2, Radius * 2));
-            g.DrawLine(Pen, Center.X, Center.Y - Radius, Center.X, Center.Y + Radius);
-            g.DrawLine(Pen, Center.X - Radius, Center.Y, Center.X + Radius, Center.Y);
+            g.DrawEllipse(Pen, new RectangleF((float)Center.X - Radius, (float)Center.Y - Radius, Radius * 2, Radius * 2));
+            g.DrawLine(Pen, (float)Center.X, (float)Center.Y - Radius, (float)Center.X, (float)Center.Y + Radius);
+            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(Center.X - Radius - FontDistance, Center.Y - Radius - FontDistance));
+            g.DrawString(info, new Font("NewRoman", FontSize), 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 488958b..bfe99c0 100644
--- a/src/Bro.UI.Model.Winform/Element/ROI_Circle.cs
+++ b/src/Bro.UI.Model.Winform/Element/ROI_Circle.cs
@@ -45,7 +45,7 @@
 
         public override void Draw(Graphics g)
         {
-            g.FillEllipse(new SolidBrush(Color.Red), new RectangleF(Center.X, Center.Y, 1.0f, 1.0f));
+            g.FillEllipse(new SolidBrush(Color.Red), new RectangleF((float)Center.X, (float)Center.Y, 1.0f, 1.0f));
 
             Pen pen = null;
             if (ROI_Index == "1")
@@ -56,7 +56,7 @@
                     "P1",
                     new Font(new FontFamily("瀹嬩綋"), 40.0f),
                     new SolidBrush(Color.Red),
-                    new PointF(Center.X - Radius - 80, Center.Y - Radius - 40)
+                    new PointF((float)Center.X - Radius - 80, (float)Center.Y - Radius - 40)
                     );
             }
             else
@@ -65,11 +65,11 @@
             }
 
             pen.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDot;
-            g.DrawEllipse(pen, Center.X - Radius, Center.Y - Radius, Radius * 2, Radius * 2);
+            g.DrawEllipse(pen, (float)Center.X - Radius, (float)Center.Y - Radius, Radius * 2, Radius * 2);
 
             if (ROI_Index == "1")
             {
-                g.DrawEllipse(pen, Center.X - Radius - 15, Center.Y - Radius - 15, Radius * 2 + 30, Radius * 2 + 30);
+                g.DrawEllipse(pen, (float)Center.X - Radius - 15, (float)Center.Y - Radius - 15, Radius * 2 + 30, Radius * 2 + 30);
             }
         }
 

--
Gitblit v1.8.0