领胜LDS 键盘AOI检测项目
相机运行界面基类添加操作配置
gocator驱动修正长宽比例,输出进行复制插值处理
显示基元添加8个方向的拉伸和移动处理
标签基元实现3个方向的拉伸和移动
20个文件已修改
922 ■■■■ 已修改文件
.gitignore 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Device/DeviceBase/CameraBase.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Device/Helper/AspectHelper.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Common.Model/Helper/EnumHelper.cs 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Device.Gocator/Bro.Device.Gocator.csproj 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Device.Gocator/GocatorDriver.cs 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Models.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Process.cs 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Process_MotionCard.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/UI/KeyIndicator.cs 72 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/UI/M071_MainForm.Designer.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/UI/M071_MainForm.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Process/Bro.Process.csproj 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/CtrlCameraRunBase.Designer.cs 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/CtrlCameraRunBase.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/CtrlCameraRunBase.resx 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Model.Winform/ElementBase.cs 312 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Model.Winform/UI/Canvas.cs 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Model.Winform/UI/CanvasImage.cs 211 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Model.Winform/UI/DockContent/MenuFrmBase.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -188,3 +188,5 @@
# Microsoft Fakes
FakesAssemblies/
/src/Images/20200706/Test/Origin
/src/Images
src/Bro.Common.Device/DeviceBase/CameraBase.cs
@@ -152,7 +152,7 @@
            set.IsOriginSaved = !set.ImageSaveOption.IsSaveOriginImage;
            set.IsFitSaved = !set.ImageSaveOption.IsSaveFitImage;
            set.IsAddtionalSaved = !string.IsNullOrWhiteSpace(set.ImageSaveOption.AddtionalSaveType);
            set.IsAddtionalSaved = string.IsNullOrWhiteSpace(set.ImageSaveOption.AddtionalSaveType);
            set.OnImageSetTimeout += ImageSet_OnImageSetTimeout;
            _imageSetList.Add(set);
@@ -181,7 +181,7 @@
        {
            set.IsOriginSaved = !set.ImageSaveOption.IsSaveOriginImage;
            set.IsFitSaved = !set.ImageSaveOption.IsSaveFitImage;
            set.IsAddtionalSaved = !string.IsNullOrWhiteSpace(set.ImageSaveOption.AddtionalSaveType);
            set.IsAddtionalSaved = string.IsNullOrWhiteSpace(set.ImageSaveOption.AddtionalSaveType);
            set.OnImageSetTimeout += ImageSet_OnImageSetTimeout;
            _imageSetList.Add(set);
        }
@@ -539,7 +539,7 @@
            });
        }
        protected async void Generate16GrayImageByPointer(int width, int height, IntPtr dataPtr, string imgSetId)
        protected async Task Generate16GrayImageByPointer(int width, int height, IntPtr dataPtr, string imgSetId)
        {
            await Task.Run(() =>
            {
@@ -897,7 +897,7 @@
        public ImageSet()
        {
            autoDisposeTimer = new Timer(OnAutoDispose, null, -1, 10 * 1000);
            autoDisposeTimer = new Timer(OnAutoDispose, null, 10 * 1000, -1);
        }
        public virtual void Dispose()
src/Bro.Common.Device/Helper/AspectHelper.cs
@@ -88,7 +88,7 @@
            //    new ProcessException(ex);
            //}
            args.FlowBehavior = FlowBehavior.Return;
            args.FlowBehavior = FlowBehavior.ThrowException;
        }
    }
    #endregion
src/Bro.Common.Model/Helper/EnumHelper.cs
@@ -392,6 +392,26 @@
            Measuring = 21,
            MeasureDoneOK = 22,
            MeasureDoneNG = 23,
            CanStretchLeft = 41,
            CanStretchRight = 42,
            CanStretchTop = 43,
            CanStretchBottom = 44,
            CanStretchLeftUpperCorner = 45,
            CanStretchLeftLowerCorner = 46,
            CanStretchRightUpperCorner = 47,
            CanStretchRightLowerCorner = 48,
            StretchingLeft = 31,
            StretchingRight = 32,
            StretchingTop = 33,
            StretchingBottom = 34,
            StretchingLeftUpperCorner = 35,
            StretchingLeftLowerCorner = 36,
            StretchingRightUpperCorner = 37,
            StretchingRightLowerCorner = 38,
        }
        public enum MouseState
@@ -400,15 +420,21 @@
            HoverElement = 2,
            InSideElement = 3,
            MoveElement = 4,
            StretchingLeft = 11,
            StretchingRight = 12,
            StretchingUp = 13,
            StretchingDown = 14,
            MoveElement = 15,
            StretchingTop = 13,
            StretchingBottom = 14,
            StretchingLeftUpperCorner = 15,
            StretchingLeftLowerCorner = 16,
            StretchingRightUpperCorner =17,
            StretchingRightLowerCorner = 18,
            New = 21,
            Editing = 22,
            SelectedElement = 23,
            //SelectedElement = 23,
            MovingAll = 31,
src/Bro.Device.Gocator/Bro.Device.Gocator.csproj
@@ -22,6 +22,7 @@
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <PlatformTarget>x64</PlatformTarget>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
src/Bro.Device.Gocator/GocatorDriver.cs
@@ -86,18 +86,88 @@
                            long bufferSize = width * height;
                            IntPtr bufferPointer = surfaceMsg.Data;
                            float zoomFactor = (float)((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution);
                            int zoomHeight = (int)(zoomFactor * height);
                            IntPtr zoomPtr = Marshal.AllocHGlobal(zoomHeight * (int)width * 2);
                            //没有插值,默认0
                            //Parallel.For(0, height, h =>
                            //  {
                            //      CopyMemory((IntPtr)((long)zoomPtr + width * 2 * Math.Floor(h * zoomFactor)), (IntPtr)((long)bufferPointer + width * 2 * h), width * 2);
                            //  });
                            //使用上一行原有数据
                            Parallel.For(0, zoomHeight, h =>
                            {
                                int originHeightIndex = (int)Math.Floor((double)height * h / (double)zoomHeight);
                                CopyMemory((IntPtr)((long)zoomPtr + width * 2 * h), (IntPtr)((long)bufferPointer + width * 2 * originHeightIndex), width * 2);
                            });
                            if (imgSet != null)
                            {
                                imgSet.HImage = new HImage();
                                imgSet.HImage.GenImage1("uint2", (int)width, (int)height, bufferPointer);
                                imgSet.HImage.GenImage1("uint2", (int)width, zoomHeight, zoomPtr);
                                //imgSet.HImage = imgSet.HImage.ZoomImageSize((int)width, zoomHeight, "constant");
                                imgSet.HImage_2 = new HImage();
                                imgSet.HImage_2.GenImage1("uint2", (int)width, (int)height, bufferPointer);
                                imgSet.HImage_2.GenImage1("uint2", (int)width, zoomHeight, zoomPtr);
                                //imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant");
                            }
                            Generate16GrayImageByPointer((int)width, (int)height, bufferPointer, imgSet?.Id);
                            Generate16GrayImageByPointer((int)width, zoomHeight, zoomPtr, imgSet?.Id).ContinueWith(t =>
                            {
                                Marshal.FreeHGlobal(zoomPtr);
                            });
                            //int zoomHeight = (int)(((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution) * (double)surfaceMsg.Length);
                            //if (imgSet != null)
                            //{
                            //    imgSet.HImage = new HImage();
                            //    imgSet.HImage.GenImage1("uint2", (int)width, (int)height, bufferPointer);
                            //    imgSet.HImage = imgSet.HImage.ZoomImageSize((int)width, zoomHeight, "constant");
                            //    imgSet.HImage_2 = new HImage();
                            //    imgSet.HImage_2.GenImage1("uint2", (int)width, (int)height, bufferPointer);
                            //    imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant");
                            //}
                            //Generate16GrayImageByPointer((int)width, (int)height, bufferPointer, imgSet?.Id);
                        }
                        break;
                        //case GoDataMessageType.SurfaceIntensity:
                        //    {
                        //        GoSurfaceIntensityMsg surfaceMsg = (GoSurfaceIntensityMsg)dataObj;
                        //        long width = surfaceMsg.Width;
                        //        long height = surfaceMsg.Length;
                        //        long bufferSize = width * height;
                        //        IntPtr bufferPointer = surfaceMsg.Data;
                        //        //int zoomHeight = (surfaceMsg.YResolution * (int)surfaceMsg.Length * 10) / surfaceMsg.XResolution;
                        //        int zoomHeight = (int)(((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution) * (double)surfaceMsg.Length);
                        //        if (imgSet != null)
                        //        {
                        //            imgSet.HImage = new HImage();
                        //            imgSet.HImage.GenImage1("uint2", (int)width, (int)height, bufferPointer);
                        //            imgSet.HImage = imgSet.HImage.ZoomImageSize((int)width, zoomHeight, "constant");
                        //            imgSet.HImage_2 = new HImage();
                        //            imgSet.HImage_2.GenImage1("uint2", (int)width, (int)height, bufferPointer);
                        //            imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant");
                        //        }
                        //        Generate16GrayImageByPointer((int)width, (int)height, bufferPointer, imgSet?.Id);
                        //    }
                        //    break;
                }
            }
        }
@@ -336,9 +406,9 @@
        public override async void SaveOriginImage(Bitmap map, Bitmap showImage, string imgSetId)
        {
            Task.Run(() =>
            {
                OnImageUpdated?.Invoke(this, showImage, imgSetId);
            });
             {
                 OnImageUpdated?.Invoke(this, showImage, imgSetId);
             });
            GoImageSet set = _imageSetList.FirstOrDefault(u => u.Id == imgSetId) as GoImageSet;
src/Bro.M071.Process/M071Models.cs
@@ -137,13 +137,13 @@
            get => key;
            set
            {
                AlignName = key = value;
                AliasName = key = value;
            }
        }
        [Category("键名配置")]
        [Description("别名")]
        public string AlignName { get; set; }
        public string AliasName { get; set; }
        [Category("启用设置")]
        [Description("true:启用 false:禁用")]
@@ -178,7 +178,7 @@
        public string GetDisplayText()
        {
            return $"{AlignName}";
            return $"{AliasName}";
        }
        public List<string> GetHalconToolPathList()
src/Bro.M071.Process/M071Process.cs
@@ -58,8 +58,8 @@
        private void InitialSetting()
        {
            //数据库迁移检查
            DatabaseInitialize.Initialize();
            ////数据库迁移检查
            //DatabaseInitialize.Initialize();
            MotionCardSettingCheck();
@@ -78,21 +78,21 @@
                var snapshotPoint = Config.SnapshotPointCollection.FirstOrDefault(s => s.Id == u.SnapshotPointId && s.IsEnabled);
                if (snapshotPoint == null)
                    throw new ProcessException($"{u.AlignName}未设置可用拍照点位");
                    throw new ProcessException($"{u.AliasName}未设置可用拍照点位");
                if (u.ImageSeq < 1)
                    throw new ProcessException($"{u.AlignName}图片序号小于1");
                    throw new ProcessException($"{u.AliasName}图片序号小于1");
                var algo = Config.KeyAlgorithemCollection.FirstOrDefault(a => a.Id == u.KeyAlgorithemId);
                if (algo == null)
                    throw new ProcessException($"{u.AlignName}未设置检测算法");
                    throw new ProcessException($"{u.AliasName}未设置检测算法");
                u.KeyAlgorithemPath = algo.AlgorithemPath;
                LoadHalconTool(u.KeyAlgorithemPath, u.AlignName);
                LoadHalconTool(u.KeyAlgorithemPath, u.AliasName);
                var resultSet = Config.KeyResultCollection.FirstOrDefault(r => r.Id == u.KeyResultId);
                if (resultSet == null)
                    throw new ProcessException($"{u.AlignName}未设置检测结果配置");
                    throw new ProcessException($"{u.AliasName}未设置检测结果配置");
                u.KeyResultList = new List<string>(resultSet.Results);
            });
@@ -511,7 +511,7 @@
                 var excludeKeys = keys.Where(u => u.ImageSeq > count).ToList();
                 if (excludeKeys.Count > 0)
                 {
                     LogAsync(DateTime.Now, $"{string.Join(" ", excludeKeys.Select(u => u.AlignName))}未在图片获取序列中", "");
                     LogAsync(DateTime.Now, $"{string.Join(" ", excludeKeys.Select(u => u.AliasName))}未在图片获取序列中", "");
                     keyBindCollection.Where(k => excludeKeys.Any(u => u.Key == k.Key)).ToList().ForEach(k =>
                          {
                              k.FillKeyValues(null);
@@ -528,24 +528,24 @@
                             var keyBindList = keyBindCollection.Where(u => u.Key == k.Key).ToList();
                             string keyToolKey = k.AlignName + "|" + k.KeyAlgorithemPath;
                             string keyToolKey = k.AliasName + "|" + k.KeyAlgorithemPath;
                             if (!_halconToolDict.ContainsKey(keyToolKey))
                             {
                                 LogAsync(DateTime.Now, $"{k.AlignName}检测算法未初始化", "");
                                 LogAsync(DateTime.Now, $"{k.AliasName}检测算法未初始化", "");
                             }
                             else
                             {
                                 _halconToolDict[keyToolKey].InputImageDic["INPUT_Image"] = image;
                                 if (!_halconToolDict[keyToolKey].RunProcedure(out string error))
                                 {
                                     LogAsync(DateTime.Now, $"{k.AlignName}检测算法异常,{error}", "");
                                     LogAsync(DateTime.Now, $"{k.AliasName}检测算法异常,{error}", "");
                                 }
                                 else
                                 {
                                     var results = _halconToolDict[keyToolKey].GetResultTuple("OUTPUT_Results").HTupleToDouble();
                                     if (results.Count == 0 || results.Any(u => u < 0))
                                     {
                                         LogAsync(DateTime.Now, $"{k.AlignName}检测结果异常", "");
                                         LogAsync(DateTime.Now, $"{k.AliasName}检测结果异常", "");
                                     }
                                     else
                                     {
src/Bro.M071.Process/M071Process_MotionCard.cs
@@ -125,7 +125,7 @@
        private void MotionCardSettingCheck()
        {
            IDevice device = DeviceCollection.FirstOrDefault(u => u is IMotionCard);
            if (device.InitialConfig is MotionCardInitialConfigBase iConfig)
            if (device?.InitialConfig is MotionCardInitialConfigBase iConfig)
            {
                outputCtrlCard = device as MotionCardBase;
src/Bro.M071.Process/UI/KeyIndicator.cs
@@ -30,20 +30,6 @@
        [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("标签显示区域")]
@@ -68,6 +54,11 @@
            {
                DisplayRect = this.DisplayRect,
            };
        }
        protected override void SetSelectedPen()
        {
            Pen = new Pen(Color.Red, 6);
        }
        public override void Draw(Graphics g)
@@ -108,7 +99,12 @@
        public override bool IsMouseInSide(Point p)
        {
            return false;
            return p.X >= DisplayRect.X && p.X <= DisplayRect.X + DisplayRect.Width && p.Y >= DisplayRect.Y && p.Y <= DisplayRect.Y + DisplayRect.Height;
        }
        public override bool IsMouseCanMoveElement(Point p)
        {
            return IsMouseInSide(p);
        }
        public override void OnKeyDown(object sender, KeyEventArgs e)
@@ -133,6 +129,52 @@
        public override void Translate(int x, int y)
        {
            DisplayRect = new Rectangle(DisplayRect.X + x, DisplayRect.Y + y, DisplayRect.Width, DisplayRect.Height);
        }
        public override void Relocate(Point point)
        {
            DisplayRect = new Rectangle(point.X - DisplayRect.Width / 2, point.Y - DisplayRect.Height / 2, DisplayRect.Width, DisplayRect.Height);
        }
        public override bool IsMouseCanStretchBottom(Point p)
        {
            return Math.Abs(p.X - (DisplayRect.X + DisplayRect.Width / 2)) < 10 && Math.Abs(p.Y - DisplayRect.Y - DisplayRect.Height) < 10;
        }
        public override bool IsMouseCanStretchRight(Point p)
        {
            return Math.Abs(p.X - (DisplayRect.X + DisplayRect.Width)) < 10 && Math.Abs(p.Y - (DisplayRect.Y + DisplayRect.Height / 2)) < 10;
        }
        public override bool IsMouseCanStretchRightLowerCorner(Point p)
        {
            return Math.Abs(p.X - (DisplayRect.X + DisplayRect.Width)) < 10 && Math.Abs(p.Y - (DisplayRect.Y + DisplayRect.Height)) < 10;
        }
        int x, y = 0;
        public override void StretchBottom(Point p)
        {
            if (p.Y > DisplayRect.Y)
            {
                DisplayRect = new Rectangle(DisplayRect.X, DisplayRect.Y, DisplayRect.Width, p.Y - DisplayRect.Y);
            }
        }
        public override void StretchRight(Point p)
        {
            if (p.X > DisplayRect.X)
            {
                DisplayRect = new Rectangle(DisplayRect.X, DisplayRect.Y, p.X - DisplayRect.X, DisplayRect.Height);
            }
        }
        public override void StretchRightLowerCorner(Point p)
        {
            if (p.X > DisplayRect.X && p.Y > DisplayRect.Y)
            {
                DisplayRect = new Rectangle(DisplayRect.X, DisplayRect.Y, p.X - DisplayRect.X, p.Y - DisplayRect.Y);
            }
        }
        protected override void DrawResult(Graphics g)
src/Bro.M071.Process/UI/M071_MainForm.Designer.cs
@@ -240,6 +240,7 @@
            this.lvMeasures.UseCompatibleStateImageBehavior = false;
            this.lvMeasures.View = System.Windows.Forms.View.List;
            this.lvMeasures.SelectedIndexChanged += new System.EventHandler(this.lvMeasures_SelectedIndexChanged);
            this.lvMeasures.DoubleClick += new System.EventHandler(this.lvMeasures_DoubleClick);
            // 
            // propGridKeyIndicator
            // 
src/Bro.M071.Process/UI/M071_MainForm.cs
@@ -70,7 +70,8 @@
                lvMeasures.Items.Add(item);
            });
            txtBarcode.ReadOnly = Config.IsBarcodeManulInputBlocked;
            if (txtBarcode.IsHandleCreated)
                txtBarcode.BeginInvoke(new Action(() => txtBarcode.ReadOnly = Config.IsBarcodeManulInputBlocked));
            Process_M071.OnClearBarcode -= M071_MainForm_OnClearBarcode;
            Process_M071.OnClearBarcode += M071_MainForm_OnClearBarcode;
@@ -150,6 +151,19 @@
            MessageBox.Show("标签修改完成");
        }
        private void lvMeasures_DoubleClick(object sender, EventArgs e)
        {
            if (lvMeasures.SelectedItems.Count <= 0)
                return;
            var ele = cvImage.Elements.FirstOrDefault(u => u.ID == lvMeasures.SelectedItems[0].Tag.ToString());
            if (ele != null)
            {
                ele.State = ElementState.Selected;
                cvImage.Invalidate();
            }
        }
        #endregion
        #region 上方状态区
@@ -169,6 +183,11 @@
                txtBarcode.Text = _barcode;
                _barcode = "";
            }
            if (e.KeyValue == 27)
            {
                cvImage.Elements.ToList().ForEach(ele => ele.State = ElementState.Normal);
            }
        }
        private void txtBarcode_TextChanged(object sender, EventArgs e)
src/Bro.Process/Bro.Process.csproj
@@ -168,4 +168,9 @@
    <Error Condition="!Exists('..\..\packages\PostSharp.6.2.7\build\PostSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\PostSharp.6.2.7\build\PostSharp.targets'))" />
  </Target>
  <Import Project="..\..\packages\PostSharp.6.2.7\build\PostSharp.targets" Condition="Exists('..\..\packages\PostSharp.6.2.7\build\PostSharp.targets')" />
  <ProjectExtensions>
    <VisualStudio>
      <UserProperties setting_1json__JsonSchema="https://batect.dev/configSchema.json" />
    </VisualStudio>
  </ProjectExtensions>
</Project>
src/Bro.UI.Device.Winform/CtrlCameraRunBase.Designer.cs
@@ -27,8 +27,14 @@
            this.tsmiShowOpBar = new System.Windows.Forms.ToolStripMenuItem();
            this.tsmiShowElements = new System.Windows.Forms.ToolStripMenuItem();
            this.tsmiShowStatusBar = new System.Windows.Forms.ToolStripMenuItem();
            this.tsmiBtnExecuteOpConfig = new System.Windows.Forms.ToolStripButton();
            this.tscOpConfig = new System.Windows.Forms.ToolStripContainer();
            this.tsmiShowOpConfig = new System.Windows.Forms.ToolStripMenuItem();
            this.propGridOpConfig = new System.Windows.Forms.PropertyGrid();
            this.toolStripOperation.SuspendLayout();
            this.ctmsVisibleControl.SuspendLayout();
            this.tscOpConfig.ContentPanel.SuspendLayout();
            this.tscOpConfig.SuspendLayout();
            this.SuspendLayout();
            // 
            // toolStripOperation
@@ -41,7 +47,8 @@
            this.toolStripOperation.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.tssBtnCameraOp,
            this.tsTxtExposure,
            this.tsBtnModifyExposure});
            this.tsBtnModifyExposure,
            this.tsmiBtnExecuteOpConfig});
            this.toolStripOperation.Location = new System.Drawing.Point(38, 2);
            this.toolStripOperation.Name = "toolStripOperation";
            this.toolStripOperation.Size = new System.Drawing.Size(440, 28);
@@ -76,7 +83,7 @@
            // 
            this.tsTxtExposure.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F);
            this.tsTxtExposure.Name = "tsTxtExposure";
            this.tsTxtExposure.Size = new System.Drawing.Size(100, 25);
            this.tsTxtExposure.Size = new System.Drawing.Size(100, 28);
            // 
            // tsBtnModifyExposure
            // 
@@ -84,7 +91,7 @@
            this.tsBtnModifyExposure.Image = ((System.Drawing.Image)(resources.GetObject("tsBtnModifyExposure.Image")));
            this.tsBtnModifyExposure.ImageTransparentColor = System.Drawing.Color.Magenta;
            this.tsBtnModifyExposure.Name = "tsBtnModifyExposure";
            this.tsBtnModifyExposure.Size = new System.Drawing.Size(60, 22);
            this.tsBtnModifyExposure.Size = new System.Drawing.Size(60, 25);
            this.tsBtnModifyExposure.Text = "修改曝光";
            this.tsBtnModifyExposure.Click += new System.EventHandler(this.tsBtnModifyExposure_Click);
            // 
@@ -94,9 +101,10 @@
            this.tsmiShowToolBar,
            this.tsmiShowOpBar,
            this.tsmiShowElements,
            this.tsmiShowStatusBar});
            this.tsmiShowStatusBar,
            this.tsmiShowOpConfig});
            this.ctmsVisibleControl.Name = "ctmsVisibleControl";
            this.ctmsVisibleControl.Size = new System.Drawing.Size(149, 92);
            this.ctmsVisibleControl.Size = new System.Drawing.Size(149, 114);
            // 
            // tsmiShowToolBar
            // 
@@ -130,11 +138,54 @@
            this.tsmiShowStatusBar.Text = "显示状态栏";
            this.tsmiShowStatusBar.CheckedChanged += new System.EventHandler(this.tsmiShowStatusBar_CheckedChanged);
            // 
            // tsmiBtnExecuteOpConfig
            //
            this.tsmiBtnExecuteOpConfig.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
            this.tsmiBtnExecuteOpConfig.Image = ((System.Drawing.Image)(resources.GetObject("tsmiBtnExecuteOpConfig.Image")));
            this.tsmiBtnExecuteOpConfig.ImageTransparentColor = System.Drawing.Color.Magenta;
            this.tsmiBtnExecuteOpConfig.Name = "tsmiBtnExecuteOpConfig";
            this.tsmiBtnExecuteOpConfig.Size = new System.Drawing.Size(84, 25);
            this.tsmiBtnExecuteOpConfig.Text = "执行操作配置";
            this.tsmiBtnExecuteOpConfig.Click += new System.EventHandler(this.tsmiBtnExecuteOpConfig_Click);
            //
            // tscOpConfig
            //
            //
            // tscOpConfig.ContentPanel
            //
            this.tscOpConfig.ContentPanel.Controls.Add(this.propGridOpConfig);
            this.tscOpConfig.ContentPanel.Size = new System.Drawing.Size(478, 175);
            this.tscOpConfig.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.tscOpConfig.Location = new System.Drawing.Point(0, 265);
            this.tscOpConfig.Name = "tscOpConfig";
            this.tscOpConfig.Size = new System.Drawing.Size(478, 175);
            this.tscOpConfig.TabIndex = 1;
            this.tscOpConfig.Text = "toolStripContainer1";
            this.tscOpConfig.Visible = false;
            //
            // tsmiShowOpConfig
            //
            this.tsmiShowOpConfig.CheckOnClick = true;
            this.tsmiShowOpConfig.Name = "tsmiShowOpConfig";
            this.tsmiShowOpConfig.Size = new System.Drawing.Size(148, 22);
            this.tsmiShowOpConfig.Text = "显示操作配置";
            this.tsmiShowOpConfig.CheckedChanged += new System.EventHandler(this.tsmiShowOpConfig_CheckedChanged);
            //
            // propGridOpConfig
            //
            this.propGridOpConfig.Dock = System.Windows.Forms.DockStyle.Fill;
            this.propGridOpConfig.Location = new System.Drawing.Point(0, 0);
            this.propGridOpConfig.Name = "propGridOpConfig";
            this.propGridOpConfig.Size = new System.Drawing.Size(478, 175);
            this.propGridOpConfig.TabIndex = 0;
            this.propGridOpConfig.ToolbarVisible = false;
            //
            // CtrlCameraRunBase
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ContextMenuStrip = this.ctmsVisibleControl;
            this.Controls.Add(this.tscOpConfig);
            this.Controls.Add(this.toolStripOperation);
            this.Name = "CtrlCameraRunBase";
            this.Size = new System.Drawing.Size(478, 440);
@@ -142,6 +193,9 @@
            this.toolStripOperation.ResumeLayout(false);
            this.toolStripOperation.PerformLayout();
            this.ctmsVisibleControl.ResumeLayout(false);
            this.tscOpConfig.ContentPanel.ResumeLayout(false);
            this.tscOpConfig.ResumeLayout(false);
            this.tscOpConfig.PerformLayout();
            this.ResumeLayout(false);
        }
@@ -158,5 +212,9 @@
        private System.Windows.Forms.ToolStripMenuItem tsmiShowOpBar;
        private System.Windows.Forms.ToolStripMenuItem tsmiShowElements;
        private System.Windows.Forms.ToolStripMenuItem tsmiShowStatusBar;
        private System.Windows.Forms.ToolStripButton tsmiBtnExecuteOpConfig;
        private System.Windows.Forms.ToolStripMenuItem tsmiShowOpConfig;
        private System.Windows.Forms.ToolStripContainer tscOpConfig;
        private System.Windows.Forms.PropertyGrid propGridOpConfig;
    }
}
src/Bro.UI.Device.Winform/CtrlCameraRunBase.cs
@@ -1,8 +1,11 @@
using Bro.Common.Interface;
using Bro.Common.Factory;
using Bro.Common.Helper;
using Bro.Common.Interface;
using Bro.UI.Model.Winform;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
namespace Bro.Common.Base.UI
@@ -46,6 +49,17 @@
            Camera.OnCameraOpModeChanged += Camera_OnCameraOpModeChanged;
            InitialToolBarVisible();
            string typeCode = Camera.GetType().GetCustomAttribute<DeviceAttribute>()?.TypeCode;
            if (string.IsNullOrWhiteSpace(typeCode))
            {
                propGridOpConfig.SelectedObject = OpConfig = new CameraOprerationConfigBase();
            }
            else
            {
                propGridOpConfig.SelectedObject = OpConfig = ConfigFactory.GetOperationConfig(typeCode);
            }
        }
        private readonly Dictionary<string, List<IShapeElement>> _eleBufferDict = new Dictionary<string, List<IShapeElement>>();
@@ -248,8 +262,13 @@
        {
            IsShowStatusBar = tsmiShowStatusBar.Checked;
        }
        private void tsmiShowOpConfig_CheckedChanged(object sender, EventArgs e)
        {
            tscOpConfig.Visible = tsmiShowOpConfig.Checked;
        }
        #endregion
        public IOperationConfig OpConfig { get; set; }
        public void UploadOperationConfig(IOperationConfig opConfig)
@@ -261,5 +280,10 @@
        {
            throw new NotImplementedException();
        }
        private void tsmiBtnExecuteOpConfig_Click(object sender, EventArgs e)
        {
            Camera.Snapshot(OpConfig);
        }
    }
}
src/Bro.UI.Device.Winform/CtrlCameraRunBase.resx
@@ -151,6 +151,21 @@
        TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
  </data>
  <data name="tsmiBtnExecuteOpConfig.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
    <value>
        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
        TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
  </data>
  <metadata name="ctmsVisibleControl.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <value>127, 17</value>
  </metadata>
src/Bro.UI.Model.Winform/ElementBase.cs
@@ -243,16 +243,20 @@
            if (State == ElementState.MeasureDoneNG || State == ElementState.MeasureDoneOK)
                return;
            if (State == ElementState.MouseInSide)
            //if (State == ElementState.MouseInSide)
            //{
            //    State = ElementState.Selected;
            //}
            //else if (State == ElementState.Selected || State == ElementState.Moving)
            //{
            //    if (IsMouseInSide(p))
            //    {
            //        State = ElementState.MouseInSide;
            //    }
            //}
            if (IsMouseInSide(p))
            {
                State = ElementState.Selected;
            }
            else if (State == ElementState.Selected || State == ElementState.Moving)
            {
                if (IsMouseInSide(p))
                {
                    State = ElementState.MouseInSide;
                }
            }
        }
@@ -262,22 +266,59 @@
        public virtual void OnMouseDown(Point p)
        {
            switch (State)
            //switch (State)
            //{
            //    case ElementState.New:
            //        OnMouseDownWhenNew(p);
            //        break;
            //    case ElementState.MouseHover:
            //        break;
            //    case ElementState.MouseInSide:
            //        State = ElementState.Selected;
            //        break;
            //    case ElementState.Selected:
            //        _startPoint = p;
            //        State = ElementState.Moving;
            //        break;
            //    case ElementState.Normal:
            //        break;
            //}
            if (IsMouseCanMoveElement(p) && State == ElementState.Selected)
            {
                case ElementState.New:
                    OnMouseDownWhenNew(p);
                    break;
                case ElementState.MouseHover:
                    break;
                case ElementState.MouseInSide:
                    State = ElementState.Selected;
                    break;
                case ElementState.Selected:
                    _startPoint = p;
                    State = ElementState.Moving;
                    break;
                case ElementState.Normal:
                    break;
                State = ElementState.Moving;
            }
            else if (IsMouseCanStretchBottom(p) && State == ElementState.CanStretchBottom)
            {
                State = ElementState.StretchingBottom;
            }
            else if (IsMouseCanStretchTop(p) && State == ElementState.CanStretchTop)
            {
                State = ElementState.StretchingTop;
            }
            else if (IsMouseCanStretchLeft(p) && State == ElementState.CanStretchLeft)
            {
                State = ElementState.StretchingLeft;
            }
            else if (IsMouseCanStretchRight(p) && State == ElementState.CanStretchRight)
            {
                State = ElementState.StretchingRight;
            }
            else if (IsMouseCanStretchLeftLowerCorner(p) && State == ElementState.CanStretchLeftLowerCorner)
            {
                State = ElementState.StretchingLeftLowerCorner;
            }
            else if (IsMouseCanStretchLeftUpperCorner(p) && State == ElementState.CanStretchLeftUpperCorner)
            {
                State = ElementState.StretchingLeftUpperCorner;
            }
            else if (IsMouseCanStretchRightLowerCorner(p) && State == ElementState.CanStretchRightLowerCorner)
            {
                State = ElementState.StretchingRightLowerCorner;
            }
            else if (IsMouseCanStretchRightUpperCorner(p) && State == ElementState.CanStretchRightUpperCorner)
            {
                State = ElementState.StretchingRightUpperCorner;
            }
        }
@@ -289,27 +330,133 @@
                    OnMouseMoveWhenNew(p);
                    break;
                case ElementState.Selected:
                    if (IsMouseCanStretchLeft(p))
                    {
                        State = ElementState.CanStretchLeft;
                    }
                    else if (IsMouseCanStretchRight(p))
                    {
                        State = ElementState.CanStretchRight;
                    }
                    else if (IsMouseCanStretchTop(p))
                    {
                        State = ElementState.CanStretchTop;
                    }
                    else if (IsMouseCanStretchBottom(p))
                    {
                        State = ElementState.CanStretchBottom;
                    }
                    else if (IsMouseCanStretchLeftLowerCorner(p))
                    {
                        State = ElementState.CanStretchLeftLowerCorner;
                    }
                    else if (IsMouseCanStretchLeftUpperCorner(p))
                    {
                        State = ElementState.CanStretchLeftUpperCorner;
                    }
                    else if (IsMouseCanStretchRightLowerCorner(p))
                    {
                        State = ElementState.CanStretchRightLowerCorner;
                    }
                    else if (IsMouseCanStretchRightUpperCorner(p))
                    {
                        State = ElementState.CanStretchRightUpperCorner;
                    }
                    break;
                case ElementState.Moving:
                    _currentPoint = p;
                    Translate(_currentPoint.X - _startPoint.X, _currentPoint.Y - _startPoint.Y);
                    _startPoint = _currentPoint;
                    //Translate(_currentPoint.X - _startPoint.X, _currentPoint.Y - _startPoint.Y);
                    //_startPoint = _currentPoint;
                    Relocate(p);
                    break;
                case ElementState.MouseHover:
                case ElementState.MouseInSide:
                case ElementState.Normal:
                    if (IsMouseInSide(p))
                    //if (IsMouseInSide(p))
                    //{
                    //    State = ElementState.MouseInSide;
                    //}
                    //else if (IsMouseHover(p))
                    //{
                    //    State = ElementState.MouseHover;
                    //}
                    //else
                    //{
                    //    State = ElementState.Normal;
                    //}
                    break;
                case ElementState.CanStretchBottom:
                    if (!IsMouseCanStretchBottom(p))
                    {
                        State = ElementState.MouseInSide;
                        State = ElementState.Selected;
                    }
                    else if (IsMouseHover(p))
                    break;
                case ElementState.CanStretchTop:
                    if (!IsMouseCanStretchTop(p))
                    {
                        State = ElementState.MouseHover;
                        State = ElementState.Selected;
                    }
                    else
                    break;
                case ElementState.CanStretchLeft:
                    if (!IsMouseCanStretchLeft(p))
                    {
                        State = ElementState.Normal;
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchRight:
                    if (!IsMouseCanStretchRight(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchLeftUpperCorner:
                    if (!IsMouseCanStretchLeftUpperCorner(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchLeftLowerCorner:
                    if (!IsMouseCanStretchLeftLowerCorner(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchRightLowerCorner:
                    if (!IsMouseCanStretchRightLowerCorner(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchRightUpperCorner:
                    if (!IsMouseCanStretchRightUpperCorner(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.StretchingTop:
                    StretchTop(p);
                    break;
                case ElementState.StretchingBottom:
                    StretchBottom(p);
                    break;
                case ElementState.StretchingLeft:
                    StretchLeft(p);
                    break;
                case ElementState.StretchingRight:
                    StretchRight(p);
                    break;
                case ElementState.StretchingLeftLowerCorner:
                    StretchLeftLowerCorner(p);
                    break;
                case ElementState.StretchingLeftUpperCorner:
                    StretchLeftUpperCorner(p);
                    break;
                case ElementState.StretchingRightLowerCorner:
                    StretchRightLowerCorner(p);
                    break;
                case ElementState.StretchingRightUpperCorner:
                    StretchRightUpperCorner(p);
                    break;
            }
        }
@@ -319,15 +466,48 @@
            switch (State)
            {
                case ElementState.Moving:
                    //Calculate(null);
                    State = ElementState.Selected;
                    break;
                case ElementState.Selected:
                    //Calculate(null);
                    if (!IsMouseInSide(p))
                    {
                        State = ElementState.Normal;
                    }
                    break;
                case ElementState.StretchingBottom:
                    State = ElementState.CanStretchBottom;
                    break;
                case ElementState.StretchingLeft:
                    State = ElementState.CanStretchLeft;
                    break;
                case ElementState.StretchingRight:
                    State = ElementState.CanStretchRight;
                    break;
                case ElementState.StretchingTop:
                    State = ElementState.CanStretchTop;
                    break;
                case ElementState.StretchingLeftLowerCorner:
                    State = ElementState.CanStretchLeftLowerCorner;
                    break;
                case ElementState.StretchingLeftUpperCorner:
                    State = ElementState.CanStretchLeftUpperCorner;
                    break;
                case ElementState.StretchingRightUpperCorner:
                    State = ElementState.CanStretchRightUpperCorner;
                    break;
                case ElementState.StretchingRightLowerCorner:
                    State = ElementState.CanStretchRightLowerCorner;
                    break;
                default:
                    State = ElementState.Normal;
                    break;
            }
            AfterTranformOp();
        }
        public virtual void AfterTranformOp()
        {
        }
        #region 当基元状态为新建或可编辑时的鼠标操作动作
@@ -366,32 +546,84 @@
        public abstract bool IsIntersect(Rectangle rect);
        #region Move & Stretch & Move Anchor
        public virtual bool IsMouseCanMoveElement()
        public virtual bool IsMouseCanMoveElement(Point p)
        {
            return false;
        }
        public virtual bool IsMouseCanStretchLeft()
        public virtual bool IsMouseCanStretchLeft(Point p)
        {
            return false;
        }
        public virtual bool IsMouseCanStretchRight()
        public virtual bool IsMouseCanStretchRight(Point p)
        {
            return false;
        }
        public virtual bool IsMouseCanStretchTop()
        public virtual bool IsMouseCanStretchTop(Point p)
        {
            return false;
        }
        public virtual bool IsMouseCanStretchBottom()
        public virtual bool IsMouseCanStretchBottom(Point p)
        {
            return false;
        }
        public virtual bool IsMouseCanMoveAnchor()
        public virtual void StretchLeft(Point p)
        {
        }
        public virtual void StretchRight(Point p)
        {
        }
        public virtual void StretchTop(Point p)
        {
        }
        public virtual void StretchBottom(Point p)
        {
        }
        public virtual bool IsMouseCanStretchLeftUpperCorner(Point p)
        {
            return false;
        }
        public virtual bool IsMouseCanStretchRightUpperCorner(Point p)
        {
            return false;
        }
        public virtual bool IsMouseCanStretchLeftLowerCorner(Point p)
        {
            return false;
        }
        public virtual bool IsMouseCanStretchRightLowerCorner(Point p)
        {
            return false;
        }
        public virtual void StretchLeftUpperCorner(Point p)
        {
        }
        public virtual void StretchRightUpperCorner(Point p)
        {
        }
        public virtual void StretchLeftLowerCorner(Point p)
        {
        }
        public virtual void StretchRightLowerCorner(Point p)
        {
        }
        public virtual bool IsMouseCanMoveAnchor(Point p)
        {
            return false;
        }
@@ -402,6 +634,8 @@
        #region 变形操作
        public abstract void Translate(int x, int y);
        public virtual void Relocate(Point point) { }
        //public abstract void RotateAt(int x, int y, float degree);
        #endregion
src/Bro.UI.Model.Winform/UI/Canvas.cs
@@ -77,7 +77,7 @@
            set => stsStatus.Visible = value;
        }
        private async void OnMouseLocationUpdated(Point screenPoint, Point imagePoint, string colorDesc)
        private void OnMouseLocationUpdated(Point screenPoint, Point imagePoint, string colorDesc)
        {
            //await Task.Run(() => tsslLocation.Text = $"屏幕坐标X:{screenPoint.X},Y:{screenPoint.Y}    图片坐标X:{imagePoint.X},Y:{imagePoint.Y}   颜色:{colorDesc}");
            this.Invoke(new Action(() =>
@@ -381,17 +381,17 @@
        private void tsmiUnselectElements_Click(object sender, EventArgs e)
        {
            if (MouseState == MouseState.SelectedElement)
            {
                MouseState = MouseState.Normal;
            //if (MouseState == MouseState.SelectedElement)
            //{
            //    MouseState = MouseState.Normal;
                //Elements.ForEach(ele =>
                foreach (IShapeElement ele in Elements)
                {
                    ele.State = ElementState.Normal;
                }
                //);
            }
            //    //Elements.ForEach(ele =>
            //    foreach (IShapeElement ele in Elements)
            //    {
            //        ele.State = ElementState.Normal;
            //    }
            //    //);
            //}
        }
        #endregion
src/Bro.UI.Model.Winform/UI/CanvasImage.cs
@@ -30,6 +30,8 @@
            MouseDown += Canvas_MouseDown;
            MouseMove += Canvas_MouseMove;
            MouseUp += Canvas_MouseUp;
            EventRouter.ChangeElementsMouseState = OnElementChangeMouseState;
        }
        #region Event
@@ -261,10 +263,12 @@
                        MouseState = MouseState.New;
                        break;
                    case ElementState.Selected:
                        MouseState = MouseState.SelectedElement;
                        CurrentElementId = ele.ID;
                        Cursor = Cursors.Default;
                        break;
                    case ElementState.Moving:
                        MouseState = MouseState.MoveElement;
                        Cursor = Cursors.NoMove2D;
                        break;
                    case ElementState.MouseInSide:
                        MouseState = MouseState.InSideElement;
@@ -272,14 +276,67 @@
                    case ElementState.MouseHover:
                        MouseState = MouseState.HoverElement;
                        break;
                    case ElementState.CanStretchLeft:
                        Cursor = Cursors.SizeWE;
                        break;
                    case ElementState.StretchingLeft:
                        MouseState = MouseState.StretchingLeft;
                        Cursor = Cursors.SizeWE;
                        break;
                    case ElementState.CanStretchBottom:
                        Cursor = Cursors.SizeNS;
                        break;
                    case ElementState.StretchingBottom:
                        MouseState = MouseState.StretchingBottom;
                        Cursor = Cursors.SizeNS;
                        break;
                    case ElementState.CanStretchRight:
                        Cursor = Cursors.SizeWE;
                        break;
                    case ElementState.StretchingRight:
                        MouseState = MouseState.StretchingRight;
                        Cursor = Cursors.SizeWE;
                        break;
                    case ElementState.CanStretchTop:
                        Cursor = Cursors.SizeNS;
                        break;
                    case ElementState.StretchingTop:
                        MouseState = MouseState.StretchingTop;
                        Cursor = Cursors.SizeNS;
                        break;
                    case ElementState.CanStretchLeftLowerCorner:
                        Cursor = Cursors.SizeNESW;
                        break;
                    case ElementState.StretchingLeftLowerCorner:
                        MouseState = MouseState.StretchingLeftLowerCorner;
                        Cursor = Cursors.SizeNESW;
                        break;
                    case ElementState.CanStretchLeftUpperCorner:
                        Cursor = Cursors.SizeNWSE;
                        break;
                    case ElementState.StretchingLeftUpperCorner:
                        MouseState = MouseState.StretchingLeftUpperCorner;
                        Cursor = Cursors.SizeNWSE;
                        break;
                    case ElementState.CanStretchRightLowerCorner:
                        Cursor = Cursors.SizeNWSE;
                        break;
                    case ElementState.StretchingRightLowerCorner:
                        MouseState = MouseState.StretchingRightLowerCorner;
                        Cursor = Cursors.SizeNWSE;
                        break;
                    case ElementState.CanStretchRightUpperCorner:
                        Cursor = Cursors.SizeNESW;
                        break;
                    case ElementState.StretchingRightUpperCorner:
                        MouseState = MouseState.StretchingRightUpperCorner;
                        Cursor = Cursors.SizeNESW;
                        break;
                    default:
                        MouseState = MouseState.Normal;
                        break;
                }
                if (MouseState == MouseState.SelectedElement)
                {
                    CurrentElementId = ele.ID;
                }
            }
            else
@@ -328,6 +385,7 @@
        }
        Point startPoint, currentPoint;
        bool _isMouseBtnPressing = false;
        private void Canvas_MouseDown(object sender, MouseEventArgs e)
        {
@@ -335,49 +393,22 @@
            if (e.Button == MouseButtons.Left)
            {
                _isMouseBtnPressing = true;
                switch (MouseState)
                {
                    case MouseState.Normal:
                        //if (DrawTemplate == null && string.IsNullOrWhiteSpace(CurrentElementId))
                        //{
                        //    this.Cursor = Cursors.Hand;
                        //    startPoint = e.Location;
                        //}
                        //else
                        //{
                        //    MouseState = MouseState.New;
                        //}
                        MouseState = MouseState.MovingAll;
                        startPoint = e.Location;
                        //Elements.ForEach(ele =>
                        foreach (IShapeElement ele in Elements)
                        {
                            ele.State = ElementState.Normal;
                            ele.OnMouseDown(p);
                        }
                        //);
                        break;
                    case MouseState.StretchingLeft:
                        break;
                    case MouseState.StretchingRight:
                        break;
                    case MouseState.StretchingUp:
                    case MouseState.StretchingTop:
                        break;
                    case MouseState.StretchingDown:
                    case MouseState.StretchingBottom:
                        break;
                    case MouseState.MoveElement:
                        break;
                    case MouseState.SelectedElement:
                        //MouseState = MouseState.MoveElement;
                        startPoint = e.Location;
                        //Elements.ForEach(ele =>
                        foreach (IShapeElement ele in Elements)
                        {
                            ele.OnMouseDown(p);
                        }
                        //);
                        break;
                    case MouseState.HoverElement:
                    case MouseState.InSideElement:
@@ -392,26 +423,16 @@
                        break;
                }
                //if (DrawTemplate == null)
                //{
                //    this.Cursor = Cursors.Hand;
                //    startPoint = e.Location;
                //}
                //Point p = ToMapPoint(e.Location);
                //Elements.ForEach(ele =>
                //{
                //    ele.State = ElementState.Normal;
                //    ele.OnMouseDown(p);
                //});
                //DrawTemplate?.OnMouseDown(p);
                foreach (IShapeElement ele in Elements)
                {
                    ele.OnMouseDown(p);
                }
            }
        }
        private void Canvas_MouseUp(object sender, MouseEventArgs e)
        {
            _isMouseBtnPressing = false;
            switch (MouseState)
            {
                case MouseState.Normal:
@@ -424,9 +445,9 @@
                    break;
                case MouseState.StretchingRight:
                    break;
                case MouseState.StretchingUp:
                case MouseState.StretchingTop:
                    break;
                case MouseState.StretchingDown:
                case MouseState.StretchingBottom:
                    break;
                case MouseState.MoveElement:
                    //MouseState = MouseState.SelectedElement;
@@ -443,7 +464,6 @@
                case MouseState.SelectionZoneDoing:
                    MouseState = MouseState.SelectionZone;
                    //Elements.ForEach(ele =>
                    foreach (IShapeElement ele in Elements)
                    {
                        if (ele.IsIntersect(_selectionRect))
@@ -451,7 +471,6 @@
                            ele.State = ElementState.Selected;
                        }
                    }
                    //);
                    break;
            }
@@ -460,12 +479,10 @@
            Point p = ToMapPoint(e.Location);
            DrawTemplate?.OnMouseUp(p);
            //Elements.ForEach(ele =>
            foreach (IShapeElement ele in Elements)
            {
                ele.OnMouseUp(p);
            }
            //);
        }
        private void Canvas_MouseMove(object sender, MouseEventArgs e)
@@ -475,26 +492,26 @@
            switch (MouseState)
            {
                case MouseState.Normal:
                    //Elements.ForEach(u =>
                    //{
                    //    u.OnMouseMove(p);
                    //});
                    {
                        if (_isMouseBtnPressing)
                        {
                            currentPoint = e.Location;
                            Point p1 = ToMapPoint(startPoint);
                            Point p2 = ToMapPoint(currentPoint);
                            Matrix.Translate(p2.X - p1.X, p2.Y - p1.Y);
                            startPoint = e.Location;
                        }
                    }
                    break;
                case MouseState.StretchingLeft:
                    break;
                case MouseState.StretchingRight:
                    break;
                case MouseState.StretchingUp:
                case MouseState.StretchingTop:
                    break;
                case MouseState.StretchingDown:
                case MouseState.StretchingBottom:
                    break;
                case MouseState.MoveElement:
                    //Elements.ForEach(ele =>
                    foreach (IShapeElement ele in Elements)
                    {
                        ele.OnMouseMove(p);
                    }
                    //);
                    break;
                case MouseState.HoverElement:
                case MouseState.InSideElement:
@@ -504,13 +521,6 @@
                case MouseState.Editing:
                    break;
                case MouseState.MovingAll:
                    {
                        currentPoint = e.Location;
                        Point p1 = ToMapPoint(startPoint);
                        Point p2 = ToMapPoint(currentPoint);
                        Matrix.Translate(p2.X - p1.X, p2.Y - p1.Y);
                        startPoint = e.Location;
                    }
                    break;
                case MouseState.SelectionZoneDoing:
                    {
@@ -529,17 +539,6 @@
                    break;
            }
            //if (this.Cursor == Cursors.Hand)
            //{
            //    currentPoint = e.Location;
            //    Point p1 = ToMapPoint(startPoint);
            //    Point p2 = ToMapPoint(currentPoint);
            //    Matrix.Translate(p2.X - p1.X, p2.Y - p1.Y);
            //    startPoint = e.Location;
            //}
            //DisplayMouseLocation(e.Location);
            Point mapPoint = ToMapPoint(e.Location);
            Color color = Color.Transparent;
            if (MAP != null && mapPoint.X > 0 && mapPoint.X < MAP.Width && mapPoint.Y > 0 && mapPoint.Y < MAP.Height)
@@ -550,12 +549,10 @@
            if (MouseState != MouseState.SelectionZoneDoing)
            {
                //Elements.ForEach(u =>
                foreach (IShapeElement ele in Elements)
                {
                    ele.OnMouseMove(p);
                }
                //);
            }
            Invalidate();
@@ -569,7 +566,7 @@
            {
                switch (MouseState)
                {
                    case MouseState.SelectedElement:
                    //case MouseState.SelectedElement:
                    case MouseState.HoverElement:
                    case MouseState.InSideElement:
                    case MouseState.MoveElement:
@@ -587,7 +584,7 @@
            }
            else
            {
                if (MouseState == MouseState.SelectedElement)
                //if (MouseState == MouseState.SelectedElement)
                {
                    MouseState = MouseState.Normal;
@@ -702,22 +699,22 @@
        #region 按键操作
        public void OnCanvasKeyPressed(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 27)  //Esc
            {
                if (MouseState == MouseState.SelectedElement)
                {
                    MouseState = MouseState.Normal;
            //if (e.KeyChar == 27)  //Esc
            //{
            //    //if (MouseState == MouseState.SelectedElement)
            //    {
            //        MouseState = MouseState.Normal;
                    //Elements.ForEach(ele =>
                    foreach (IShapeElement ele in Elements)
                    {
                        ele.State = ElementState.Normal;
                    }
                    //);
                }
            }
            //        //Elements.ForEach(ele =>
            //        foreach (IShapeElement ele in Elements)
            //        {
            //            ele.State = ElementState.Normal;
            //        }
            //        //);
            //    }
            //}
            Invalidate();
            //Invalidate();
        }
        public void OnCanvasKeyDown(object sender, KeyEventArgs e)
@@ -741,7 +738,7 @@
                    Elements.Remove(Elements.FirstOrDefault(u => u.ID == CurrentElementId));
                    break;
                case Keys.Escape:
                    if (MouseState == MouseState.SelectedElement)
                    //if (MouseState == MouseState.SelectedElement)
                    {
                        MouseState = MouseState.Normal;
src/Bro.UI.Model.Winform/UI/DockContent/MenuFrmBase.cs
@@ -2,6 +2,7 @@
using Bro.Common.Interface;
using System;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
@@ -23,11 +24,14 @@
                //if (process != value)
                {
                    process = value;
                    _constructionDoneHandle.Wait();
                    OnProcessUpdated();
                }
            }
        }
        ManualResetEventSlim _constructionDoneHandle = new ManualResetEventSlim(false);
        public MenuFrmBase()
        {
            InitializeComponent();
@@ -37,6 +41,8 @@
            {
                FormClosing += MenuFrmBase_FormClosing;
            }
            _constructionDoneHandle.Set();
        }
        protected virtual void MenuFrmBase_FormClosing(object sender, FormClosingEventArgs e)