From d85cbf0ccd61d95b96695756e0c90db8b7679545 Mon Sep 17 00:00:00 2001
From: C3204 <C3204@BC3204>
Date: 星期四, 18 十二月 2025 10:35:22 +0800
Subject: [PATCH] 添加项目文件。

---
 LB_SmartVisionCameraSDK/PHM6000/Pilot2D.cs                                                      |  529 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.Designer.cs           | 1849 +
 LB_VisionProcesses/LB_VisionProcesses.csproj                                                    |   67 
 LB_VisionFlowNode/FlowPanel.cs                                                                  | 1463 
 LB_SmartVision/Forms/Pages/MESPage/MESEditPage.resx                                             |  120 
 LB_VisionControl/UserHSmartWindowControl.resx                                                   |  126 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jinzhi.png                                             |    0 
 LB_VisionControl/Forms/RenameForm.Designer.cs                                                   |  262 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.resx        |  132 
 LB_VisionProcesses/Forms/GlobalVarForm.resx                                                     |  144 
 LB_VisionProcesses/PluginManager.cs                                                             |  432 
 LB_VisionProcesses/Forms/GlobalVarForm.cs                                                       |  160 
 LB_SmartVision/LB_SqlCommand.cs                                                                 |  573 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shezhi.png                                             |    0 
 LB_VisionProcesses/Forms/GlobalVarControl.resx                                                  |  120 
 LB_VisionProcesses/MainForm.cs                                                                  |   34 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.resx                                         |  120 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-qiehuan.png                                            |    0 
 LB_SmartVisionCommon/DiskInfoHelper.cs                                                          |   49 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.resx                            |  120 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.cs                                           |  404 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-weiguanlian.png                                        |    0 
 LB_VisionFlowNode/LB_VisionFlowNode.csproj                                                      |   28 
 LB_VisionProcesses/ref/PHM6000API.dll                                                           |    0 
 LB_VisionProcesses/ProcessEditForm.cs                                                           |  159 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-APPjianpan.png                                         |    0 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.cs                    | 1249 
 LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestTool.cs                                |  160 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-gengduo.png                                            |    0 
 LB_SmartVisionCameraDevice/ref/PointCloud3D.dll                                                 |    0 
 LB_VisionProcesses/ref/MVSDK_Net.XML                                                            | 2589 +
 LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.Designer.cs                  |  251 
 LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-xinzengxinzeng.png                                   |    0 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanbi.png                                             |    0 
 LB_SmartVisionCommon/DynamicPropertyDescriptor.cs                                               |   70 
 LB_VisionControl/ScriptEditControl/ClassFileList.cs                                             |   59 
 LB_SmartVision/Forms/Pages/MESPage/MESEditPage.Designer.cs                                      |  152 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-chexiao.png                                            |    0 
 LB_SmartVision/Tool/ObservableConcurrentDictionary.cs                                           |  186 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shipinpeizhi.png                                       |    0 
 LB_SmartVisionCameraDevice/SensorManager.cs                                                     |  145 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shousuo.png                                            |    0 
 LB_VisionControl/ref/halcondotnet.dll                                                           |    0 
 LB_SmartVisionCameraDevice/ref/PHM6000API.lib                                                   |    0 
 LB_VisionProcesses/ref/halcondotnet.dll                                                         |    0 
 LB_VisionFlowNode/MainForm.cs                                                                   |   10 
 LB_SmartVision/Forms/Pages/MyPage.resx                                                          |  120 
 LB_VisionControl/Properties/Resources.resx                                                      |  120 
 LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-zhuangtailoudou.png                                  |    0 
 LB_VisionFlowNode/FlowConnection.cs                                                             |   49 
 LB_SmartVision/VisionForm.resx                                                                  | 1080 
 LB_SmartVision/Forms/Pages/SettingPage/CsvPage.Designer.cs                                      |  250 
 LB_VisionFlowNode/FlowSerializer.cs                                                             |   73 
 LB_VisionControl/ScriptEditControl/ClassFileList.resx                                           |  129 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.cs                              |  445 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.cs                                 |  135 
 LB_SmartVisionCameraDevice/DeviceType.cs                                                        |   27 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pizhu.png                                              |    0 
 LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.cs                         |   30 
 LB_VisionProcesses/Communicators/TCom/TCPClient.cs                                              |  155 
 LB_SmartVision/Form1.Designer.cs                                                                |   90 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhiding.png                                            |    0 
 LB_VisionControl/ScriptEditControl/ComplieUI.resx                                               |  150 
 LB_SmartVisionCameraSDK/PclEntry.cs                                                             |  356 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.resx                             |  286 
 LB_SmartVisionCommon/PermissionAttribute.cs                                                     |   38 
 LB_VisionControl/Form1.cs                                                                       |   10 
 LB_VisionProcesses/Processes/DelayTime.cs                                                       |   41 
 LB_VisionProcesses/Forms/GlobalVarForm.Designer.cs                                              |  203 
 LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.resx                                     |  144 
 LB_SmartVisionLoginUI/lanbao.jpg                                                                |    0 
 LB_SmartVision/Form1.resx                                                                       |  120 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.resx             |  120 
 LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.resx                         |  120 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.cs                  |  325 
 LB_SmartVisionCommon/UserData.cs                                                                |   81 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pizhuxinxi.png                                         |    0 
 LB_VisionControl/Properties/Resources.Designer.cs                                               |   63 
 LB_VisionControl/ScriptEditControl/KeysWordCMDAuto.cs                                           |   32 
 LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.cs                            |  211 
 LB_VisionProcesses/Communicators/UserCommunicator/T306Command/T306CommandTool.cs                |  145 
 LB_SmartVision/Forms/Pages/MESPage/MESEditPage.cs                                               |   30 
 LB_VisionFlowNode/RenameForm.resx                                                               |  139 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/TextSource.cs                               |  329 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/LinesAccessor.cs                            |  100 
 LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.resx                                     |  120 
 LB_VisionProcesses/ref/PointCloud3D.dll                                                         |    0 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuangjiantouyou.png                                   |    0 
 LB_VisionProcesses/Alogrithms/Halcon/HDevelopExport.cs                                          | 8637 +++++
 LB_SmartVisionLoginUI/images/07.png                                                             |    0 
 LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.cs                                 |  189 
 LB_VisionControl/Form1.resx                                                                     |  120 
 LB_VisionProcesses/ProcessCollections.cs                                                        |  324 
 LB_SmartVisionCameraDevice/PHM6000/PHM6000SensorConfig.cs                                       | 1055 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/Export.cs                                   |  225 
 LB_VisionProcesses/Cameras/2DCameraForm.resx                                                    |  144 
 LB_VisionProcesses/ProcessInfo.cs                                                               |   21 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanzhu.png                                            |    0 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/AutocompleteItem.cs                         |  234 
 LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.cs                                  |  275 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiemi.png                                              |    0 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouzuo-1.png                                       |    0 
 LB_SmartVisionCommon/PermissionPropertyDescriptor.cs                                            |   70 
 LB_SmartVision/Forms/CreateProductForm.Designer.cs                                              |  185 
 LB_VisionControl/ScriptEditControl/CommandRun.cs                                                |   91 
 LB_VisionProcesses/ref/PHM6000.dll                                                              |    0 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelTool.cs                        |  921 
 LB_SmartVision/Forms/Pages/CameraPage/CameraForm.Designer.cs                                    |  509 
 LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.cs                            |  317 
 LB_SmartVisionCameraDevice/PHM6000/PHM6000Sensor.cs                                             | 1230 
 LB_VisionProcesses/Program.cs                                                                   |   22 
 LB_SmartVisionCommon/LogHelper.cs                                                               |  115 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.Designer.cs                        |  215 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.resx                  |  129 
 LB_SmartVisionLoginUI/images/favicon.ico                                                        |    0 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-sousuo.png                                             |    0 
 LB_VisionProcesses/Cameras/BaseCamera.cs                                                        |  299 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/Char.cs                                     |   56 
 LB_SmartVisionCameraSDK/LB_SmartVisionCameraSDK.csproj                                          |   16 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-caogaoxiang.png                                        |    0 
 LB_SmartVisionCameraDevice/CameraUserRole.cs                                                    |   27 
 LB_SmartVisionLoginUI/images/02.png                                                             |    0 
 LB_VisionProcesses/ref/Pilot2D.dll                                                              |    0 
 LB_SmartVisionCommon/DynamicPermissionObject.cs                                                 |  197 
 LB_SmartVisionLoginUI/images/lanbao.jpg                                                         |    0 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuangjiantouzuo.png                                   |    0 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.Designer.cs                     | 1026 
 LB_VisionControl/ScriptEditControl/ConsoleTextBox.resx                                          |  120 
 LB_SmartVisionCameraSDK/PHM6000/PHM6000Profiler.cs                                              |  951 
 LB_VisionControl/ScriptEditControl/ScriptEditForm.cs                                            |  510 
 LB_SmartVisionCameraSDK/ref/PHM6000API.lib                                                      |    0 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HCalibTool/BaseCalib.cs                                 |  272 
 LB_VisionControl/UserItem.Designer.cs                                                           |   58 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.resx                            |  129 
 LB_VisionControl/ScriptEditControl/csharp.ico                                                   |    0 
 LB_SmartVision/Forms/Pages/SettingPage/CsvPage.resx                                             |  120 
 LB_SmartVision/LB_SmartVision.sln                                                               |   67 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.cs                    | 1459 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/CommandManager.cs                           |  236 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.resx                            |  120 
 LB_SmartVisionCameraSDK/PHM6000/Point.cs                                                        |  265 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineTool.cs                          |  817 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-duihao.png                                             |    0 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobTool.cs                                  |  361 
 LB_SmartVisionLoginUI/images/logo_h.png                                                         |    0 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jian.png                                               |    0 
 LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.cs                                      |  105 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pinglun.png                                            |    0 
 LB_SmartVision/Forms/Pages/SettingPage/ControlStateManager.cs                                   |  118 
 LB_SmartVisionLoginUI/logo.ico                                                                  |    0 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dTool.cs                      |  329 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shouzhe.png                                            |    0 
 LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.Designer.cs                        |  239 
 LB_SmartVisionCommon/NetworkMonitor.cs                                                          |   34 
 LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouyoufangxiangyou.png                           |    0 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.resx                               |  144 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/SyntaxHighlighter.cs                        |  710 
 LB_VisionProcesses/PluginLoadContext.cs                                                         |   46 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-ziyuanpeizhi.png                                       |    0 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelTool.cs                        |  705 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouzuo.png                                         |    0 
 LB_VisionProcesses/Communicators/TCom/TCPServer.cs                                              |  231 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HCalibTool/HCaltab.cs                                   |  555 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.resx                |  126 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jia.png                                                |    0 
 LB_VisionControl/ScriptEditControl/ScriptEditForm.Designer.cs                                   |  463 
 LB_VisionProcesses/Properties/Resources.resx                                                    |  120 
 LB_VisionProcesses/ProcessEditForm.Designer.cs                                                  |  109 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.resx                                      |  123 
 LB_VisionControl/UserItem.resx                                                                  |  123 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.Designer.cs                     |  129 
 LB_VisionControl/UserPictureBox.cs                                                              |  481 
 LB_SmartVision/ProcessRun/ProcessRunBll.cs                                                      |  958 
 LB_VisionFlowNode/FlowNodeEditor.resx                                                           |  160 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.Designer.cs                     |  245 
 LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.Designer.cs                               |  322 
 LB_SmartVisionLoginUI/ICommonData_Loading.cs                                                    |   16 
 LB_VisionControl/Forms/RenameForm.resx                                                          |  139 
 LB_VisionProcesses/ref/CLIDelegate.dll                                                          |    0 
 LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.resx                                |  120 
 LB_SmartVisionLoginUI/MainWindow.xaml                                                           |   79 
 LB_SmartVisionLoginUI/App.xaml                                                                  |    9 
 LB_VisionProcesses/Communicators/CommunicatorForm.resx                                          |  144 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/VisualMarker.cs.cs                          |  107 
 LB_VisionFlowNode/MainForm.Designer.cs                                                          |  101 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shangchuan.png                                         |    0 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.Designer.cs                      |  110 
 LB_SmartVisionCameraDevice/LB_SmartVisionCameraDevice.csproj                                    |   25 
 LB_VisionProcesses/Communicators/TCom/UARTPort.cs                                               |  245 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuisong.png                                            |    0 
 LB_SmartVision/Forms/Pages/SettingPage/CsvPage.cs                                               |  105 
 LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.Designer.cs                |  152 
 LB_VisionProcesses/IProcess.cs                                                                  |  268 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-qidongyujing.png                                       |    0 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelTool.cs              |  453 
 LB_VisionControl/UserHSmartWindowControl.Designer.cs                                            |  151 
 LB_SmartVisionCameraDevice/ref/Pilot2D.dll                                                      |    0 
 LB_SmartVisionCommon/LB_SmartVisionCommon.csproj                                                |   20 
 LB_SmartVisionCameraSDK/ref/PHM6000.dll                                                         |    0 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.Designer.cs         |  674 
 LB_VisionProcesses/Cameras/ICamera.cs                                                           |  312 
 LB_VisionProcesses/Forms/GlobalVarControl.Designer.cs                                           |   99 
 LB_VisionProcesses/Processes/ScriptTool/ScriptTool.cs                                           |  478 
 LB_VisionProcesses/Processes/BaseProcess.cs                                                     |  336 
 LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.cs                                            |  134 
 LB_VisionControl/ScriptEditControl/ScriptEditControl.Designer.cs                                |  234 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.resx                               |  144 
 LB_VisionFlowNode/IFlowContext.cs                                                               |  680 
 LB_VisionControl/ScriptEditControl/ContextMenuStripEx.cs                                        |   26 
 LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.cs                                       |  510 
 LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.resx                          |  120 
 LB_VisionFlowNode/MainForm.resx                                                                 |  286 
 LB_SmartVisionCameraDevice/ref/PHM6000API.dll                                                   |    0 
 LB_SmartVision/LB_Collections.cs                                                                |  223 
 LB_SmartVisionCameraSDK/ref/Pilot2D.dll                                                         |    0 
 LB_VisionProcesses/Processes/RecordTool/RecordTool.cs                                           |   62 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-mima.png                                               |    0 
 LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithm.cs                                       | 5656 +++
 LB_SmartVisionCameraDevice/ref/PHM6000.dll                                                      |    0 
 LB_SmartVisionCommon/Fun.cs                                                                     |   59 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.Designer.cs                                  |  149 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/PlatformType.cs                             |   76 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.cs                              |  349 
 LB_VisionProcesses/ProcessAttribute.cs                                                          |   40 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/Place.cs                                    |   83 
 LB_VisionProcesses/ProcessEditForm.resx                                                         |  144 
 LB_SmartVision/logo.ico                                                                         |    0 
 LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouzuofangxiangzuo.png                           |    0 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhongqi.png                                            |    0 
 LB_VisionControl/ScriptEditControl/ConsoleTextBox.cs                                            |  120 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuisongjilu.png                                        |    0 
 LB_SmartVision/Program.cs                                                                       |   17 
 LB_SmartVisionLoginUI/images/键盘.ico                                                             |    0 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.cs                              |   44 
 LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.Designer.cs                            |  122 
 LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.cs                           |   30 
 LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.Designer.cs                              |  372 
 LB_SmartVision/README.md                                                                        |    1 
 LB_VisionControl/ScriptEditControl/CommConfig.cs                                                |   40 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineTool.cs                          |  267 
 LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.resx                                 |  120 
 LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.resx                                      |  120 
 LB_VisionProcesses/MainForm.Designer.cs                                                         |   72 
 LB_SmartVisionLoginUI/images/04.png                                                             |    0 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-bangzhuzhongxin.png                                    |    0 
 LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.Designer.cs                  |  152 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/FileTextSource.cs                           |  411 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouxia.png                                         |    0 
 LB_VisionProcesses/Communicators/CommunicatorForm.Designer.cs                                   |  392 
 LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.Designer.cs                              |  196 
 LB_SmartVisionLoginUI/App.xaml.cs                                                               |   17 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.cs          |  506 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.Designer.cs                     | 1419 
 LB_SmartVisionCommon/AESHelper.cs                                                               |   62 
 LB_VisionFlowNode/FlowNodeEditor.Designer.cs                                                    |  133 
 LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.cs                                        |  180 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/Range.cs                                    | 1330 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-fangkongquanpeizhi.png                                 |    0 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.cs                              |  169 
 LB_SmartVision/ref/halcondotnet.dll                                                             |    0 
 LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.resx                       |  120 
 LB_SmartVisionCameraDevice/Data/StateIcon.cs                                                    |   31 
 LB_SmartVisionCameraSDK/ref/PHM6000API.dll                                                      |    0 
 LB_SmartVision/LB_SmartVision.csproj                                                            |   57 
 LB_VisionProcesses/Communicators/CommunicatorForm.cs                                            |  353 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouyou.png                                         |    0 
 LB_VisionProcesses/Properties/Resources.Designer.cs                                             |   63 
 LB_SmartVisionCommon/PropertySorter.cs                                                          |  134 
 LB_SmartVisionCameraSDK/ref/PointCloud3D.dll                                                    |    0 
 LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.resx                                          |  120 
 LB_SmartVisionLoginUI/images/03.png                                                             |    0 
 LB_SmartVision/Tool/OperateIniHelper.cs                                                         |  161 
 LB_SmartVisionCommon/NetworkTester.cs                                                           |   46 
 LB_VisionControl/Forms/RenameForm.cs                                                            |   69 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantoushang.png                                       |    0 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.cs                       | 5473 +++
 LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.resx                          |  129 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guankongpeizhi.png                                     |    0 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.cs                              |  102 
 LB_SmartVisionCameraSDK/PHM6000/ProfilerData.cs                                                 |  771 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-xiazai.png                                             |    0 
 LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.Designer.cs                   |  154 
 LB_VisionProcesses/Cameras/2DCameraForm.Designer.cs                                             |  861 
 LB_SmartVision/GlobalVar.cs                                                                     |  124 
 LB_VisionFlowNode/Program.cs                                                                    |   17 
 LB_VisionFlowNode/FlowEnum.cs                                                                   |   40 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-fuzhi.png                                              |    0 
 LB_VisionProcesses/Cameras/CameraConfig.cs                                                      |  315 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.Designer.cs             |  860 
 LB_SmartVision/VisionForm.Designer.cs                                                           |  369 
 LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.Designer.cs                              |  330 
 LB_VisionProcesses/Cameras/2DCameraForm.cs                                                      |  660 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.Designer.cs                     |  132 
 LB_SmartVision/Forms/Pages/CameraPage/CameraForm.resx                                           |  144 
 LB_VisionControl/ROI.cs                                                                         |  580 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.cs                      |  424 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.resx                  |  129 
 LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.cs                                   |  278 
 LB_VisionProcesses/ref/PHM6000API.lib                                                           |    0 
 LB_VisionProcesses/Communicators/CommunicatorConfig.cs                                          |  243 
 LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.resx                                   |  120 
 LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantoushangfangxiangshang.png                       |    0 
 LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.Designer.cs                               |  153 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.Designer.cs |  713 
 LB_SmartVisionCameraSDK/PHM6000/SysCalibration.cs                                               |  761 
 LB_VisionProcesses/Communicators/TCom/LocalMonitor.cs                                           |  162 
 LB_SmartVision/Properties/Resources.Designer.cs                                                 |   63 
 LB_SmartVision/LOGO/logo.ico                                                                    |    0 
 LB_VisionProcesses/ref/ThridLibray.dll                                                          |    0 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.cs                      |  424 
 LB_SmartVision/Form1.cs                                                                         |   20 
 LB_VisionControl/ScriptEditControl/ComplieUI.Designer.cs                                        |  217 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/Line.cs                                     |  356 
 LB_SmartVisionCameraDevice/PHM6000/CaliOutLine.cs                                               |   23 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.cs                               |   96 
 LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.Designer.cs                         |  172 
 LB_SmartVision/Forms/CreateProductForm.cs                                                       |   93 
 LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.resx                                    |  120 
 LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.cs                                       |  121 
 LB_VisionProcesses/Forms/GlobalVarControl.cs                                                    |  164 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/SyntaxDescriptor.cs                         |   53 
 LB_SmartVision/Tool/Tool.cs                                                                     | 1134 
 LB_VisionControl/ScriptEditControl/EditHeightLight.cs                                           |   51 
 LB_SmartVisionLoginUI/images/01.JPG                                                             |    0 
 LB_VisionProcesses/logo.ico                                                                     |    0 
 LB_VisionProcesses/MainForm.resx                                                                |  120 
 LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.cs                           |  223 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.Designer.cs                               |  164 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.resx                     |  120 
 LB_VisionFlowNode/FlowNode.cs                                                                   |  239 
 LB_VisionControl/ScriptEditControl/ComplieBuilder.cs                                            |  144 
 LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.resx                                     |  148 
 LB_VisionControl/ScriptEditControl/ComplieType.cs                                               |   14 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.resx                            |  144 
 LB_VisionProcesses/Communicators/ICommunicator.cs                                               |   69 
 LB_VisionProcesses/ref/MVSDK_Net.dll                                                            |    0 
 LB_SmartVision/Forms/Pages/MyPage.cs                                                            |   32 
 LB_SmartVisionCommon/UserManager.cs                                                             |  311 
 LB_VisionControl/UserHSmartWindowControl.cs                                                     | 1174 
 LB_SmartVisionLoginUI/images/logo.ico                                                           |    0 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.cs               |  149 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.Designer.cs              |   68 
 LB_VisionProcesses/Communicators/CommunicatorCollections.cs                                     |  224 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/AutocompleteMenu.cs                         |  597 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/TypeDescriptor.cs                           |   99 
 LB_SmartVisionCommon/AsyncLogHelper.cs                                                          |  177 
 LB_SmartVisionLoginUI/LB_SmartVisionLoginUI.csproj                                              |   15 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/LimitedStack.cs                             |  109 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.Designer.cs      |  196 
 LB_SmartVisionCommon/CommonVar.cs                                                               |   18 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/Style.cs                                    |  410 
 LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.cs                                        |  220 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.resx                    |  126 
 LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.cs                                     |  257 
 LB_SmartVisionCommon/NetworkDiagnostics.cs                                                      |  117 
 LB_VisionControl/LB_VisionControl.csproj                                                        |   54 
 LB_SmartVisionLoginUI/favicon.ico                                                               |    0 
 LB_SmartVisionLoginUI/images/06.png                                                             |    0 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.Designer.cs                        |  151 
 LB_VisionControl/Form1.Designer.cs                                                              |   39 
 LB_VisionControl/ScriptEditControl/ScriptEditControl.resx                                       |  135 
 LB_VisionProcesses/Communicators/BaseCommunicator.cs                                            |  180 
 LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.cs                                       |  142 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.Designer.cs           | 1807 +
 LB_SmartVision/Forms/CreateProductForm.resx                                                     |  144 
 LB_VisionProcesses/PluginInfo.cs                                                                |   45 
 LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.resx                               |  120 
 LB_VisionControl/ScriptEditControl/ClassFileList.Designer.cs                                    |   86 
 LB_SmartVision/ProcessRun/ExpressionTreeMappingEngine.cs                                        |  362 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-chakanxiangqing.png                                    |    0 
 LB_VisionFlowNode/RenameForm.cs                                                                 |   62 
 LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.cs                                        |  334 
 LB_SmartVision/ProcessRun/ProcessContext.cs                                                     |  698 
 LB_VisionFlowNode/RenameForm.Designer.cs                                                        |  261 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhankai.png                                            |    0 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuozhuaizhongxin.png                                   |    0 
 LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.Designer.cs                   |  515 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuaxin.png                                            |    0 
 LB_VisionFlowNode/FlowNodeEditor.cs                                                             |   71 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouyou-1.png                                       |    0 
 LB_VisionControl/ScriptEditControl/KeyWordsAuto.cs                                              |  229 
 LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.Designer.cs                          |   48 
 LB_SmartVisionCommon/ConfigManager.cs                                                           |   44 
 LB_SmartVisionLoginUI/logo_h.png                                                                |    0 
 LB_VisionControl/Program.cs                                                                     |   18 
 LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouxiafangxiangxia.png                           |    0 
 LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.resx                         |  120 
 LB_SmartVisionLoginUI/App.config                                                                |    6 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanlian.png                                           |    0 
 LB_VisionControl/ScriptEditControl/ScriptEditForm.resx                                          | 1657 
 LB_SmartVision/VisionForm.cs                                                                    |  997 
 LB_SmartVisionCameraDevice/PHM6000/CaliModel.cs                                                 |   73 
 LB_SmartVisionLoginUI/MainWindow.xaml.cs                                                        |  197 
 LB_SmartVisionLoginUI/images/05.png                                                             |    0 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/Commands.cs                                 |  724 
 LB_VisionControl/ScriptEditControl/ComplieUI.cs                                                 |  126 
 LB_SmartVisionLoginUI/AssemblyInfo.cs                                                           |   10 
 LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.cs                                 |   29 
 LB_VisionControl/ScriptEditControl/CompliReslut.cs                                              |   15 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shaixuan.png                                           |    0 
 LB_VisionControl/UserItem.cs                                                                    |  135 
 LB_VisionProcesses/ProcessParams.cs                                                             |  208 
 LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.Designer.cs                                   |  341 
 LB_SmartVision/Forms/Pages/CameraPage/CameraForm.cs                                             |  272 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shanchu.png                                            |    0 
 LB_VisionControl/ScriptEditControl/ScriptEditControl.cs                                         |  366 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.resx                    |  126 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.resx                            |  129 
 LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.resx                                      |  120 
 LB_SmartVision/Properties/Resources.resx                                                        |  120 
 LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.Designer.cs             |  860 
 LB_SmartVision/.cr/personal/FavoritesList/List.xml                                              |    6 
 LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.Designer.cs                             |   56 
 LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jieshu.png                                             |    0 
 LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobTool.cs                                  |  408 
 415 files changed, 102,382 insertions(+), 0 deletions(-)

diff --git a/LB_SmartVision/.cr/personal/FavoritesList/List.xml b/LB_SmartVision/.cr/personal/FavoritesList/List.xml
new file mode 100644
index 0000000..a60e5ed
--- /dev/null
+++ b/LB_SmartVision/.cr/personal/FavoritesList/List.xml
@@ -0,0 +1,6 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<Root Type="DevExpress.CodeRush.Foundation.CodePlaces.Options.FavoritesListContainer">
+  <Options Language="Neutral">
+    <Groups />
+  </Options>
+</Root>
\ No newline at end of file
diff --git a/LB_SmartVision/Form1.Designer.cs b/LB_SmartVision/Form1.Designer.cs
new file mode 100644
index 0000000..b288884
--- /dev/null
+++ b/LB_SmartVision/Form1.Designer.cs
@@ -0,0 +1,90 @@
+锘縩amespace LB_SmartVision
+{
+    partial class Form1
+    {
+        /// <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()
+        {
+            materialTabControl1 = new MaterialSkin.Controls.MaterialTabControl();
+            tabPage1 = new TabPage();
+            tabPage2 = new TabPage();
+            materialTabControl1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // materialTabControl1
+            // 
+            materialTabControl1.Controls.Add(tabPage1);
+            materialTabControl1.Controls.Add(tabPage2);
+            materialTabControl1.Depth = 0;
+            materialTabControl1.Dock = DockStyle.Fill;
+            materialTabControl1.Font = new Font("Microsoft YaHei UI", 12F);
+            materialTabControl1.Location = new Point(0, 0);
+            materialTabControl1.MouseState = MaterialSkin.MouseState.HOVER;
+            materialTabControl1.Name = "materialTabControl1";
+            materialTabControl1.SelectedIndex = 0;
+            materialTabControl1.Size = new Size(800, 450);
+            materialTabControl1.TabIndex = 0;
+            // 
+            // tabPage1
+            // 
+            tabPage1.Font = new Font("Microsoft YaHei UI", 9F, FontStyle.Regular, GraphicsUnit.Pixel);
+            tabPage1.Location = new Point(4, 30);
+            tabPage1.Name = "tabPage1";
+            tabPage1.Padding = new Padding(3);
+            tabPage1.Size = new Size(792, 416);
+            tabPage1.TabIndex = 0;
+            tabPage1.Text = "tabPage1";
+            tabPage1.UseVisualStyleBackColor = true;
+            // 
+            // tabPage2
+            // 
+            tabPage2.Location = new Point(4, 30);
+            tabPage2.Name = "tabPage2";
+            tabPage2.Padding = new Padding(3);
+            tabPage2.Size = new Size(792, 416);
+            tabPage2.TabIndex = 1;
+            tabPage2.Text = "tabPage2";
+            tabPage2.UseVisualStyleBackColor = true;
+            // 
+            // Form1
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(800, 450);
+            Controls.Add(materialTabControl1);
+            Name = "Form1";
+            Text = "Form1";
+            materialTabControl1.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private MaterialSkin.Controls.MaterialTabControl materialTabControl1;
+        private TabPage tabPage1;
+        private TabPage tabPage2;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Form1.cs b/LB_SmartVision/Form1.cs
new file mode 100644
index 0000000..15fc698
--- /dev/null
+++ b/LB_SmartVision/Form1.cs
@@ -0,0 +1,20 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVision
+{
+    public partial class Form1 : Form
+    {
+        public Form1()
+        {
+            InitializeComponent();
+        }
+    }
+}
diff --git a/LB_SmartVision/Form1.resx b/LB_SmartVision/Form1.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Form1.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/LB_SmartVision/Forms/CreateProductForm.Designer.cs b/LB_SmartVision/Forms/CreateProductForm.Designer.cs
new file mode 100644
index 0000000..d7f9829
--- /dev/null
+++ b/LB_SmartVision/Forms/CreateProductForm.Designer.cs
@@ -0,0 +1,185 @@
+锘縰sing ReaLTaiizor.Controls;
+
+namespace LB_SmartVision.Forms
+{
+    partial class CreateProductForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CreateProductForm));
+            uiLabel1 = new Label();
+            uiLabel2 = new Label();
+            uiButtonCancel = new AirButton();
+            uiButtonCreate = new AirButton();
+            uiButtonTest = new AirButton();
+            uiTextBoxProductName = new TextBox();
+            uiComboBoxProducts = new ComboBox();
+            themeForm1 = new ReaLTaiizor.Forms.ThemeForm();
+            SuspendLayout();
+            // 
+            // uiLabel1
+            // 
+            uiLabel1.Font = new Font("瀹嬩綋", 12F);
+            uiLabel1.ForeColor = SystemColors.Control;
+            uiLabel1.Location = new Point(120, 97);
+            uiLabel1.Name = "uiLabel1";
+            uiLabel1.Size = new Size(100, 23);
+            uiLabel1.TabIndex = 1;
+            uiLabel1.Text = "澶嶅埗婧�";
+            // 
+            // uiLabel2
+            // 
+            uiLabel2.Font = new Font("瀹嬩綋", 12F);
+            uiLabel2.ForeColor = SystemColors.Control;
+            uiLabel2.Location = new Point(120, 163);
+            uiLabel2.Name = "uiLabel2";
+            uiLabel2.Size = new Size(100, 23);
+            uiLabel2.TabIndex = 2;
+            uiLabel2.Text = "浜у搧鍚�";
+            // 
+            // uiButtonCancel
+            // 
+            uiButtonCancel.Customization = "7e3t//Ly8v/r6+v/5ubm/+vr6//f39//p6en/zw8PP8UFBT/gICA/w==";
+            uiButtonCancel.Font = new Font("瀹嬩綋", 12F);
+            uiButtonCancel.Image = null;
+            uiButtonCancel.Location = new Point(343, 234);
+            uiButtonCancel.MinimumSize = new Size(1, 1);
+            uiButtonCancel.Name = "uiButtonCancel";
+            uiButtonCancel.NoRounding = false;
+            uiButtonCancel.Size = new Size(100, 35);
+            uiButtonCancel.TabIndex = 4;
+            uiButtonCancel.Text = "鍙栨秷";
+            uiButtonCancel.Transparent = false;
+            uiButtonCancel.Click += uiButtonCancel_Click;
+            // 
+            // uiButtonCreate
+            // 
+            uiButtonCreate.Customization = "7e3t//Ly8v/r6+v/5ubm/+vr6//f39//p6en/zw8PP8UFBT/gICA/w==";
+            uiButtonCreate.Enabled = false;
+            uiButtonCreate.Font = new Font("瀹嬩綋", 12F);
+            uiButtonCreate.Image = null;
+            uiButtonCreate.Location = new Point(187, 234);
+            uiButtonCreate.MinimumSize = new Size(1, 1);
+            uiButtonCreate.Name = "uiButtonCreate";
+            uiButtonCreate.NoRounding = false;
+            uiButtonCreate.Size = new Size(100, 35);
+            uiButtonCreate.TabIndex = 9;
+            uiButtonCreate.Text = "鍒涘缓";
+            uiButtonCreate.Transparent = false;
+            uiButtonCreate.Click += uiButtonCreate_Click;
+            // 
+            // uiButtonTest
+            // 
+            uiButtonTest.Customization = "7e3t//Ly8v/r6+v/5ubm/+vr6//f39//p6en/zw8PP8UFBT/gICA/w==";
+            uiButtonTest.Font = new Font("瀹嬩綋", 12F);
+            uiButtonTest.Image = null;
+            uiButtonTest.Location = new Point(31, 234);
+            uiButtonTest.MinimumSize = new Size(1, 1);
+            uiButtonTest.Name = "uiButtonTest";
+            uiButtonTest.NoRounding = false;
+            uiButtonTest.Size = new Size(100, 35);
+            uiButtonTest.TabIndex = 10;
+            uiButtonTest.Text = "娴嬭瘯";
+            uiButtonTest.Transparent = false;
+            uiButtonTest.Click += uiButtonTest_Click;
+            // 
+            // uiTextBoxProductName
+            // 
+            uiTextBoxProductName.Font = new Font("瀹嬩綋", 12F);
+            uiTextBoxProductName.ForeColor = Color.Black;
+            uiTextBoxProductName.Location = new Point(227, 157);
+            uiTextBoxProductName.Margin = new Padding(4, 5, 4, 5);
+            uiTextBoxProductName.MinimumSize = new Size(1, 16);
+            uiTextBoxProductName.Name = "uiTextBoxProductName";
+            uiTextBoxProductName.Size = new Size(150, 26);
+            uiTextBoxProductName.TabIndex = 12;
+            uiTextBoxProductName.Text = "鏂颁骇鍝�";
+            uiTextBoxProductName.TextChanged += uiTextBoxProductName_TextChanged;
+            // 
+            // uiComboBoxProducts
+            // 
+            uiComboBoxProducts.FormattingEnabled = true;
+            uiComboBoxProducts.Location = new Point(226, 95);
+            uiComboBoxProducts.Name = "uiComboBoxProducts";
+            uiComboBoxProducts.Size = new Size(151, 25);
+            uiComboBoxProducts.TabIndex = 13;
+            uiComboBoxProducts.MouseClick += uiComboBoxProducts_MouseClick;
+            // 
+            // themeForm1
+            // 
+            themeForm1.BackColor = Color.FromArgb(32, 41, 50);
+            themeForm1.Dock = DockStyle.Fill;
+            themeForm1.Font = new Font("Microsoft Sans Serif", 9F);
+            themeForm1.Image = (Image)resources.GetObject("themeForm1.Image");
+            themeForm1.Location = new Point(0, 0);
+            themeForm1.Name = "themeForm1";
+            themeForm1.Padding = new Padding(10, 70, 10, 9);
+            themeForm1.RoundCorners = true;
+            themeForm1.Sizable = true;
+            themeForm1.Size = new Size(507, 309);
+            themeForm1.SmartBounds = true;
+            themeForm1.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            themeForm1.TabIndex = 14;
+            themeForm1.Text = "鍒涘缓浜у搧";
+            // 
+            // CreateProductForm
+            // 
+            AutoScaleMode = AutoScaleMode.None;
+            BackColor = Color.FromArgb(32, 41, 50);
+            ClientSize = new Size(507, 309);
+            ControlBox = false;
+            Controls.Add(uiComboBoxProducts);
+            Controls.Add(uiTextBoxProductName);
+            Controls.Add(uiButtonTest);
+            Controls.Add(uiButtonCreate);
+            Controls.Add(uiButtonCancel);
+            Controls.Add(uiLabel2);
+            Controls.Add(uiLabel1);
+            Controls.Add(themeForm1);
+            ForeColor = SystemColors.Control;
+            FormBorderStyle = FormBorderStyle.None;
+            MaximizeBox = false;
+            MinimizeBox = false;
+            MinimumSize = new Size(261, 61);
+            Name = "CreateProductForm";
+            Text = "鍒涘缓浜у搧";
+            TransparencyKey = Color.Fuchsia;
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+        private Label uiLabel1;
+        private Label uiLabel2;
+        private ReaLTaiizor.Controls.AirButton uiButtonCancel;
+        private ReaLTaiizor.Controls.AirButton uiButtonCreate;
+        private ReaLTaiizor.Controls.AirButton uiButtonTest;
+        private TextBox uiTextBoxProductName;
+        private ComboBox uiComboBoxProducts;
+        private ReaLTaiizor.Forms.ThemeForm themeForm1;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/CreateProductForm.cs b/LB_SmartVision/Forms/CreateProductForm.cs
new file mode 100644
index 0000000..8ea53ef
--- /dev/null
+++ b/LB_SmartVision/Forms/CreateProductForm.cs
@@ -0,0 +1,93 @@
+锘�
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using ReaLTaiizor.Forms;
+using RJCP.IO.Ports;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Data.SqlClient;
+using System.Drawing;
+using System.IO.Ports;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
+
+
+namespace LB_SmartVision.Forms
+{
+    public partial class CreateProductForm : Form
+    {
+        public List<string> listDatabaseName { get; set; }
+        public bool bCreate = false;
+
+        public CreateProductForm(List<string> listDatabaseNam = null)
+        {
+            InitializeComponent();
+            // 绂佹淇敼绐楀彛澶у皬
+            //this.FormBorderStyle = FormBorderStyle.FixedDialog;
+
+            uiButtonCreate.Enabled = false;
+            if (listDatabaseNam == null)
+                listDatabaseNam = LB_SqlCommand.GetUserDatabases();
+
+            this.listDatabaseName = listDatabaseNam;
+        }
+
+
+        private void uiButtonTest_Click(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+
+            LB_SmartVision.Tool.Tool.ReadStringConfig("浜у搧鍒楄〃", out string Products);
+            List<string> lstProduct = (Products.Split(',')).ToList();
+            if (lstProduct.Contains(uiTextBoxProductName.Text))
+                MessageBox.Show($"浜у搧[{uiTextBoxProductName.Text}]宸插瓨鍦�!", "寮傚父");
+            else
+                uiButtonCreate.Enabled = true;
+        }
+
+        private void uiButtonCreate_Click(object sender, EventArgs e)
+        {
+            if (LB_SmartVision.Tool.Tool.CopyDirectory(Path.Combine(GlobalVar.strApplicationPath + "鎵�鏈変骇鍝乗\", GlobalVar.strProductName)
+                , Path.Combine(GlobalVar.strApplicationPath + "鎵�鏈変骇鍝乗\", uiTextBoxProductName.Text)))
+            {
+                LB_SmartVision.Tool.Tool.ReadStringConfig("浜у搧鍒楄〃", out string Products);
+                List<string> lstProduct = (Products.Split(',')).ToList();
+                lstProduct.Add(uiTextBoxProductName.Text);
+                LB_SmartVision.Tool.Tool.WriteConfig("浜у搧鍒楄〃", string.Join(",", lstProduct));
+                MessageBox.Show($"鍒涘缓浜у搧[{uiTextBoxProductName.Text}]鎴愬姛!");
+                this.Close();
+            }
+        }
+
+        private void uiButtonCancel_Click(object sender, EventArgs e)
+        {
+            bCreate = false;
+            this.Close();
+        }
+
+        private void uiComboBoxProducts_MouseClick(object sender, MouseEventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+
+            uiComboBoxProducts.Items.Clear();
+            uiComboBoxProducts.Items.Add("鏃�");
+
+            LB_SmartVision.Tool.Tool.ReadStringConfig("浜у搧鍒楄〃", out string Products);
+            List<string> lstProduct = (Products.Split(',')).ToList();
+            foreach (string DatabaseName in lstProduct)
+                uiComboBoxProducts.Items.Add(DatabaseName);
+        }
+
+        private void uiTextBoxProductName_TextChanged(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/CreateProductForm.resx b/LB_SmartVision/Forms/CreateProductForm.resx
new file mode 100644
index 0000000..9ca1331
--- /dev/null
+++ b/LB_SmartVision/Forms/CreateProductForm.resx
@@ -0,0 +1,144 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="themeForm1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        wgAADsIBFShKgAAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
+        BkVBUPCBCEG8BXNQ48GLeImCehIJxMsqhsSZruod46K4HtSIGjU+4iOr0c1I9fSsM3/PLNtCPO0H36m/
+        evz/X11VnreKVRTAHPOZumkY6lFwqURws3BwZ8ywTQnuiCP/+iTCzY1qaUPzdm/Atf3PaHre6XPsjyQM
+        2xLGV4XwIyX4QRj+UMK/lPFvJTyhBMeV8IgQvmRJuH4Ko+l5p9UjGBbCJ5RxTgj+VMZmXxKcSAjekHE/
+        NNs5DgaTKLinEQYVO4Trf1mkV81wixLUslPmA3bzF2XcKeP+hWY/u3n0fCXcrQwLyjAvjNsb1dI6N05P
+        mFAIHlHG73sEypPgGwnhfpn0zzH7jzddcK4Q7kqfKNMI4a9K+MwBDgbdeF04MBWsFYYdQvhbLlBvfhKT
+        f+vMtLfG7C0JJXxKGY67WnvCmPAFGRs7z42boul5AzHBfdK6TjdQtzPGk8oos5F/5Y7sfVvPhg+lp+1h
+        0yIsxARPmtaN78WEl8eEX+SNclxUhne0glUrNrN9zfMGlPAuZTzaQ99FYfwuDv3ruoLvq5bWaQSvZCfL
+        GXUYLwrj240Qxtu2lkSN4FpdWfKZH9jb9RQ1Cq62f9sVOlxUxn3KQXnJ0PO8QxU/jBm1h74v7ZniEG9K
+        Hdg/quzvXO709k0Y3u08ucGqWgheX862H4XgxbR47SqU8D1X0EXC2VmGizqDz0xPr0kYH9eO360gNe0b
+        jWppozB+1kOQEb5MCLa0C64NoeGrhOGrvH6lhK81GiIvnggmrDLzgvTkvwvDA+5wsU4nhG/m9AUoBD/F
+        HFzWN4H0XQn2vF8eXN8Z3FAPYasl59oUYjuB+sTImDB+nhfgYQ39STf4fmu1DHtz+oIUgiM1KkWtwcFw
+        sOujVT3hrnaL7UQc+hcL5W+sKIXhw0OVjaW0iwnBc47gqIQ45QY32PKRzv8eTguRYM9SS5YouEEZjv37
+        EffbzbjBDdZyxZYQ12EB2qS0bWrJqRVazPDWkojwZbuZrsgZtDJ0iY1g12khEtTicMTvclwn2CKE32YJ
+        7G5PORfZ1HtMCH7MOV4BrQ3XCe92+4onk5Nn2PolDAvWXnuOzAwzo6Nnx4Q3SrojwqfKeMxWMpsXWVs+
+        2WrfKRdbW1W6Hf0shM/33Y7my4PrleFZIfhAaWjU/e5ivlw+y3S2FySMtynjvcrwsFiLJv/RhPBB2ws1
+        hK2WcBLBFf1qawlplwvxaQlxe786OOU4PBWsjSO85mBlQ8n99r/BisSdAas4FfgHpdEUZpwUX7sAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/CameraPage/CameraForm.Designer.cs b/LB_SmartVision/Forms/Pages/CameraPage/CameraForm.Designer.cs
new file mode 100644
index 0000000..0cd3475
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CameraPage/CameraForm.Designer.cs
@@ -0,0 +1,509 @@
+锘縩amespace LB_SmartVision.Forms.Pages.CameraPage
+{
+    partial class CameraForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CameraForm));
+            uiComboBoxBrand = new ComboBox();
+            uiRadioButtonSoftTrigger = new RadioButton();
+            uiRadioButtonHardTrigger = new RadioButton();
+            uiGroupBoxImage = new GroupBox();
+            uiGroupBoxCameraParams = new GroupBox();
+            btnSetting = new Button();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            tableLayoutPanel3 = new TableLayoutPanel();
+            uiMarkLabel1 = new Label();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            uiButtonGrabOnce = new Button();
+            uiButtonStartSoftGrab = new Button();
+            uiButtonCloseSoftGrab = new Button();
+            uiButtonStartHardGrab = new Button();
+            tableLayoutPanel4 = new TableLayoutPanel();
+            uiMarkLabel2 = new Label();
+            uiTextBoxExp = new TextBox();
+            tableLayoutPanel5 = new TableLayoutPanel();
+            uiMarkLabel3 = new Label();
+            uiTextBoxGain = new TextBox();
+            tableLayoutPanel6 = new TableLayoutPanel();
+            uiMarkLabel4 = new Label();
+            uiTextBoxGrabTime = new TextBox();
+            uiSplitContainer1 = new SplitContainer();
+            themeForm1 = new ReaLTaiizor.Forms.ThemeForm();
+            controlBox1 = new ReaLTaiizor.Controls.ControlBox();
+            uiGroupBoxCameraParams.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tableLayoutPanel3.SuspendLayout();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel4.SuspendLayout();
+            tableLayoutPanel5.SuspendLayout();
+            tableLayoutPanel6.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)uiSplitContainer1).BeginInit();
+            uiSplitContainer1.Panel1.SuspendLayout();
+            uiSplitContainer1.Panel2.SuspendLayout();
+            uiSplitContainer1.SuspendLayout();
+            themeForm1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // uiComboBoxBrand
+            // 
+            uiComboBoxBrand.Dock = DockStyle.Fill;
+            uiComboBoxBrand.Enabled = false;
+            uiComboBoxBrand.Font = new Font("瀹嬩綋", 12F);
+            uiComboBoxBrand.Location = new Point(104, 5);
+            uiComboBoxBrand.Margin = new Padding(4, 5, 4, 5);
+            uiComboBoxBrand.MinimumSize = new Size(63, 0);
+            uiComboBoxBrand.Name = "uiComboBoxBrand";
+            uiComboBoxBrand.Size = new Size(260, 24);
+            uiComboBoxBrand.TabIndex = 24;
+            uiComboBoxBrand.SelectedIndexChanged += cob_Brand_SelectedIndexChanged;
+            // 
+            // uiRadioButtonSoftTrigger
+            // 
+            uiRadioButtonSoftTrigger.Dock = DockStyle.Fill;
+            uiRadioButtonSoftTrigger.Font = new Font("瀹嬩綋", 12F);
+            uiRadioButtonSoftTrigger.Location = new Point(3, 55);
+            uiRadioButtonSoftTrigger.MinimumSize = new Size(1, 1);
+            uiRadioButtonSoftTrigger.Name = "uiRadioButtonSoftTrigger";
+            uiRadioButtonSoftTrigger.Size = new Size(368, 46);
+            uiRadioButtonSoftTrigger.TabIndex = 25;
+            uiRadioButtonSoftTrigger.Text = "杞Е鍙�";
+            uiRadioButtonSoftTrigger.CheckedChanged += uiRadioButtonSoftTrigger_CheckedChanged;
+            // 
+            // uiRadioButtonHardTrigger
+            // 
+            uiRadioButtonHardTrigger.Dock = DockStyle.Fill;
+            uiRadioButtonHardTrigger.Font = new Font("瀹嬩綋", 12F);
+            uiRadioButtonHardTrigger.Location = new Point(3, 159);
+            uiRadioButtonHardTrigger.MinimumSize = new Size(1, 1);
+            uiRadioButtonHardTrigger.Name = "uiRadioButtonHardTrigger";
+            uiRadioButtonHardTrigger.Size = new Size(368, 46);
+            uiRadioButtonHardTrigger.TabIndex = 26;
+            uiRadioButtonHardTrigger.Text = "纭Е鍙�";
+            // 
+            // uiGroupBoxImage
+            // 
+            uiGroupBoxImage.Dock = DockStyle.Fill;
+            uiGroupBoxImage.Font = new Font("瀹嬩綋", 12F);
+            uiGroupBoxImage.ForeColor = SystemColors.Control;
+            uiGroupBoxImage.Location = new Point(0, 0);
+            uiGroupBoxImage.Margin = new Padding(4, 5, 4, 5);
+            uiGroupBoxImage.MinimumSize = new Size(1, 1);
+            uiGroupBoxImage.Name = "uiGroupBoxImage";
+            uiGroupBoxImage.Padding = new Padding(0, 32, 0, 0);
+            uiGroupBoxImage.Size = new Size(495, 521);
+            uiGroupBoxImage.TabIndex = 17;
+            uiGroupBoxImage.TabStop = false;
+            uiGroupBoxImage.Text = "瀹炴椂閲囬泦";
+            // 
+            // uiGroupBoxCameraParams
+            // 
+            uiGroupBoxCameraParams.Controls.Add(btnSetting);
+            uiGroupBoxCameraParams.Controls.Add(tableLayoutPanel2);
+            uiGroupBoxCameraParams.Dock = DockStyle.Fill;
+            uiGroupBoxCameraParams.Font = new Font("瀹嬩綋", 12F);
+            uiGroupBoxCameraParams.ForeColor = SystemColors.Control;
+            uiGroupBoxCameraParams.Location = new Point(0, 0);
+            uiGroupBoxCameraParams.Margin = new Padding(4, 5, 4, 5);
+            uiGroupBoxCameraParams.MinimumSize = new Size(1, 1);
+            uiGroupBoxCameraParams.Name = "uiGroupBoxCameraParams";
+            uiGroupBoxCameraParams.Padding = new Padding(0, 32, 0, 0);
+            uiGroupBoxCameraParams.Size = new Size(374, 521);
+            uiGroupBoxCameraParams.TabIndex = 18;
+            uiGroupBoxCameraParams.TabStop = false;
+            uiGroupBoxCameraParams.Text = "鐩告満鍙傛暟";
+            // 
+            // btnSetting
+            // 
+            btnSetting.Location = new Point(3, 18);
+            btnSetting.Name = "btnSetting";
+            btnSetting.Size = new Size(97, 29);
+            btnSetting.TabIndex = 18;
+            btnSetting.Text = "鍙傛暟璁剧疆";
+            btnSetting.UseVisualStyleBackColor = true;
+            btnSetting.Visible = false;
+            btnSetting.Click += btn_Setting_Click;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 1;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel2.Controls.Add(uiRadioButtonHardTrigger, 0, 3);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel3, 0, 0);
+            tableLayoutPanel2.Controls.Add(uiRadioButtonSoftTrigger, 0, 1);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel1, 0, 2);
+            tableLayoutPanel2.Controls.Add(uiButtonStartHardGrab, 0, 4);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel4, 0, 5);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel5, 0, 6);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel6, 0, 7);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(0, 51);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 9;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutPanel2.Size = new Size(374, 470);
+            tableLayoutPanel2.TabIndex = 17;
+            // 
+            // tableLayoutPanel3
+            // 
+            tableLayoutPanel3.ColumnCount = 2;
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Controls.Add(uiComboBoxBrand, 1, 0);
+            tableLayoutPanel3.Controls.Add(uiMarkLabel1, 0, 0);
+            tableLayoutPanel3.Dock = DockStyle.Fill;
+            tableLayoutPanel3.Location = new Point(3, 3);
+            tableLayoutPanel3.Name = "tableLayoutPanel3";
+            tableLayoutPanel3.RowCount = 1;
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Size = new Size(368, 46);
+            tableLayoutPanel3.TabIndex = 0;
+            // 
+            // uiMarkLabel1
+            // 
+            uiMarkLabel1.Dock = DockStyle.Fill;
+            uiMarkLabel1.Font = new Font("瀹嬩綋", 12F);
+            uiMarkLabel1.ForeColor = SystemColors.Control;
+            uiMarkLabel1.Location = new Point(3, 0);
+            uiMarkLabel1.Name = "uiMarkLabel1";
+            uiMarkLabel1.Padding = new Padding(5, 0, 0, 0);
+            uiMarkLabel1.Size = new Size(94, 46);
+            uiMarkLabel1.TabIndex = 25;
+            uiMarkLabel1.Text = "鍝佺墝";
+            uiMarkLabel1.TextAlign = ContentAlignment.MiddleLeft;
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 3;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
+            tableLayoutPanel1.Controls.Add(uiButtonGrabOnce, 0, 0);
+            tableLayoutPanel1.Controls.Add(uiButtonStartSoftGrab, 1, 0);
+            tableLayoutPanel1.Controls.Add(uiButtonCloseSoftGrab, 2, 0);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(3, 107);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 1;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Size = new Size(368, 46);
+            tableLayoutPanel1.TabIndex = 30;
+            // 
+            // uiButtonGrabOnce
+            // 
+            uiButtonGrabOnce.Dock = DockStyle.Fill;
+            uiButtonGrabOnce.Font = new Font("瀹嬩綋", 12F);
+            uiButtonGrabOnce.Location = new Point(3, 3);
+            uiButtonGrabOnce.MinimumSize = new Size(1, 1);
+            uiButtonGrabOnce.Name = "uiButtonGrabOnce";
+            uiButtonGrabOnce.Size = new Size(116, 40);
+            uiButtonGrabOnce.TabIndex = 31;
+            uiButtonGrabOnce.Text = "鍗曞紶閲囬泦";
+            uiButtonGrabOnce.Click += uiButtonGrabOnce_Click;
+            // 
+            // uiButtonStartSoftGrab
+            // 
+            uiButtonStartSoftGrab.Dock = DockStyle.Fill;
+            uiButtonStartSoftGrab.Font = new Font("瀹嬩綋", 12F);
+            uiButtonStartSoftGrab.Location = new Point(125, 3);
+            uiButtonStartSoftGrab.MinimumSize = new Size(1, 1);
+            uiButtonStartSoftGrab.Name = "uiButtonStartSoftGrab";
+            uiButtonStartSoftGrab.Size = new Size(116, 40);
+            uiButtonStartSoftGrab.TabIndex = 31;
+            uiButtonStartSoftGrab.Text = "杩炵画閲囬泦";
+            uiButtonStartSoftGrab.Click += uiButtonStartSoftGrab_Click;
+            // 
+            // uiButtonCloseSoftGrab
+            // 
+            uiButtonCloseSoftGrab.Dock = DockStyle.Fill;
+            uiButtonCloseSoftGrab.Font = new Font("瀹嬩綋", 12F);
+            uiButtonCloseSoftGrab.Location = new Point(247, 3);
+            uiButtonCloseSoftGrab.MinimumSize = new Size(1, 1);
+            uiButtonCloseSoftGrab.Name = "uiButtonCloseSoftGrab";
+            uiButtonCloseSoftGrab.Size = new Size(118, 40);
+            uiButtonCloseSoftGrab.TabIndex = 31;
+            uiButtonCloseSoftGrab.Text = "鍏抽棴閲囬泦";
+            uiButtonCloseSoftGrab.Click += uiButtonCloseSoftGrab_Click;
+            // 
+            // uiButtonStartHardGrab
+            // 
+            uiButtonStartHardGrab.Dock = DockStyle.Fill;
+            uiButtonStartHardGrab.Font = new Font("瀹嬩綋", 12F);
+            uiButtonStartHardGrab.Location = new Point(3, 211);
+            uiButtonStartHardGrab.MinimumSize = new Size(1, 1);
+            uiButtonStartHardGrab.Name = "uiButtonStartHardGrab";
+            uiButtonStartHardGrab.Size = new Size(368, 46);
+            uiButtonStartHardGrab.TabIndex = 27;
+            uiButtonStartHardGrab.Text = "绛夊緟纭欢瑙﹀彂";
+            uiButtonStartHardGrab.Click += uiButtonStartHardGrab_Click;
+            // 
+            // tableLayoutPanel4
+            // 
+            tableLayoutPanel4.ColumnCount = 2;
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel4.Controls.Add(uiMarkLabel2, 0, 0);
+            tableLayoutPanel4.Controls.Add(uiTextBoxExp, 1, 0);
+            tableLayoutPanel4.Dock = DockStyle.Fill;
+            tableLayoutPanel4.Location = new Point(3, 263);
+            tableLayoutPanel4.Name = "tableLayoutPanel4";
+            tableLayoutPanel4.RowCount = 1;
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel4.Size = new Size(368, 46);
+            tableLayoutPanel4.TabIndex = 28;
+            // 
+            // uiMarkLabel2
+            // 
+            uiMarkLabel2.Dock = DockStyle.Fill;
+            uiMarkLabel2.Font = new Font("瀹嬩綋", 12F);
+            uiMarkLabel2.ForeColor = SystemColors.Control;
+            uiMarkLabel2.Location = new Point(3, 0);
+            uiMarkLabel2.Name = "uiMarkLabel2";
+            uiMarkLabel2.Padding = new Padding(5, 0, 0, 0);
+            uiMarkLabel2.Size = new Size(94, 46);
+            uiMarkLabel2.TabIndex = 31;
+            uiMarkLabel2.Text = "鏇濆厜(us)";
+            uiMarkLabel2.TextAlign = ContentAlignment.MiddleLeft;
+            // 
+            // uiTextBoxExp
+            // 
+            uiTextBoxExp.Dock = DockStyle.Fill;
+            uiTextBoxExp.Font = new Font("瀹嬩綋", 12F);
+            uiTextBoxExp.Location = new Point(104, 5);
+            uiTextBoxExp.Margin = new Padding(4, 5, 4, 5);
+            uiTextBoxExp.MinimumSize = new Size(1, 16);
+            uiTextBoxExp.Name = "uiTextBoxExp";
+            uiTextBoxExp.Size = new Size(260, 26);
+            uiTextBoxExp.TabIndex = 31;
+            uiTextBoxExp.Text = "1000";
+            uiTextBoxExp.TextChanged += uiTextBoxExp_TextChanged;
+            // 
+            // tableLayoutPanel5
+            // 
+            tableLayoutPanel5.ColumnCount = 2;
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel5.Controls.Add(uiMarkLabel3, 0, 0);
+            tableLayoutPanel5.Controls.Add(uiTextBoxGain, 1, 0);
+            tableLayoutPanel5.Dock = DockStyle.Fill;
+            tableLayoutPanel5.Location = new Point(3, 315);
+            tableLayoutPanel5.Name = "tableLayoutPanel5";
+            tableLayoutPanel5.RowCount = 1;
+            tableLayoutPanel5.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel5.Size = new Size(368, 46);
+            tableLayoutPanel5.TabIndex = 29;
+            // 
+            // uiMarkLabel3
+            // 
+            uiMarkLabel3.Dock = DockStyle.Fill;
+            uiMarkLabel3.Font = new Font("瀹嬩綋", 12F);
+            uiMarkLabel3.ForeColor = SystemColors.Control;
+            uiMarkLabel3.Location = new Point(3, 0);
+            uiMarkLabel3.Name = "uiMarkLabel3";
+            uiMarkLabel3.Padding = new Padding(5, 0, 0, 0);
+            uiMarkLabel3.Size = new Size(94, 46);
+            uiMarkLabel3.TabIndex = 31;
+            uiMarkLabel3.Text = "澧炵泭";
+            uiMarkLabel3.TextAlign = ContentAlignment.MiddleLeft;
+            // 
+            // uiTextBoxGain
+            // 
+            uiTextBoxGain.Dock = DockStyle.Fill;
+            uiTextBoxGain.Font = new Font("瀹嬩綋", 12F);
+            uiTextBoxGain.Location = new Point(104, 5);
+            uiTextBoxGain.Margin = new Padding(4, 5, 4, 5);
+            uiTextBoxGain.MinimumSize = new Size(1, 16);
+            uiTextBoxGain.Name = "uiTextBoxGain";
+            uiTextBoxGain.Size = new Size(260, 26);
+            uiTextBoxGain.TabIndex = 32;
+            uiTextBoxGain.Text = "1";
+            uiTextBoxGain.TextChanged += uiTextBoxGain_TextChanged;
+            // 
+            // tableLayoutPanel6
+            // 
+            tableLayoutPanel6.ColumnCount = 2;
+            tableLayoutPanel6.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutPanel6.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel6.Controls.Add(uiMarkLabel4, 0, 0);
+            tableLayoutPanel6.Controls.Add(uiTextBoxGrabTime, 1, 0);
+            tableLayoutPanel6.Dock = DockStyle.Fill;
+            tableLayoutPanel6.Location = new Point(3, 367);
+            tableLayoutPanel6.Name = "tableLayoutPanel6";
+            tableLayoutPanel6.RowCount = 1;
+            tableLayoutPanel6.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel6.Size = new Size(368, 46);
+            tableLayoutPanel6.TabIndex = 31;
+            // 
+            // uiMarkLabel4
+            // 
+            uiMarkLabel4.Dock = DockStyle.Fill;
+            uiMarkLabel4.Font = new Font("瀹嬩綋", 12F);
+            uiMarkLabel4.ForeColor = SystemColors.Control;
+            uiMarkLabel4.Location = new Point(3, 0);
+            uiMarkLabel4.Name = "uiMarkLabel4";
+            uiMarkLabel4.Padding = new Padding(5, 0, 0, 0);
+            uiMarkLabel4.Size = new Size(94, 46);
+            uiMarkLabel4.TabIndex = 31;
+            uiMarkLabel4.Text = "鑰楁椂(ms)";
+            uiMarkLabel4.TextAlign = ContentAlignment.MiddleLeft;
+            // 
+            // uiTextBoxGrabTime
+            // 
+            uiTextBoxGrabTime.Dock = DockStyle.Fill;
+            uiTextBoxGrabTime.Enabled = false;
+            uiTextBoxGrabTime.Font = new Font("瀹嬩綋", 12F);
+            uiTextBoxGrabTime.Location = new Point(104, 5);
+            uiTextBoxGrabTime.Margin = new Padding(4, 5, 4, 5);
+            uiTextBoxGrabTime.MinimumSize = new Size(1, 16);
+            uiTextBoxGrabTime.Name = "uiTextBoxGrabTime";
+            uiTextBoxGrabTime.Size = new Size(260, 26);
+            uiTextBoxGrabTime.TabIndex = 31;
+            // 
+            // uiSplitContainer1
+            // 
+            uiSplitContainer1.Dock = DockStyle.Fill;
+            uiSplitContainer1.ForeColor = SystemColors.Control;
+            uiSplitContainer1.Location = new Point(10, 70);
+            uiSplitContainer1.MinimumSize = new Size(20, 20);
+            uiSplitContainer1.Name = "uiSplitContainer1";
+            // 
+            // uiSplitContainer1.Panel1
+            // 
+            uiSplitContainer1.Panel1.Controls.Add(uiGroupBoxCameraParams);
+            // 
+            // uiSplitContainer1.Panel2
+            // 
+            uiSplitContainer1.Panel2.Controls.Add(uiGroupBoxImage);
+            uiSplitContainer1.Size = new Size(880, 521);
+            uiSplitContainer1.SplitterDistance = 374;
+            uiSplitContainer1.SplitterWidth = 11;
+            uiSplitContainer1.TabIndex = 20;
+            // 
+            // themeForm1
+            // 
+            themeForm1.BackColor = Color.FromArgb(32, 41, 50);
+            themeForm1.Controls.Add(controlBox1);
+            themeForm1.Controls.Add(uiSplitContainer1);
+            themeForm1.Dock = DockStyle.Fill;
+            themeForm1.Font = new Font("Microsoft YaHei UI", 9F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            themeForm1.Image = (Image)resources.GetObject("themeForm1.Image");
+            themeForm1.Location = new Point(0, 0);
+            themeForm1.Name = "themeForm1";
+            themeForm1.Padding = new Padding(10, 70, 10, 9);
+            themeForm1.RoundCorners = true;
+            themeForm1.Sizable = true;
+            themeForm1.Size = new Size(900, 600);
+            themeForm1.SmartBounds = true;
+            themeForm1.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            themeForm1.TabIndex = 21;
+            themeForm1.Text = "鐩告満璁剧疆";
+            // 
+            // controlBox1
+            // 
+            controlBox1.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            controlBox1.BackColor = Color.FromArgb(32, 34, 37);
+            controlBox1.CloseHoverColor = Color.FromArgb(230, 17, 35);
+            controlBox1.DefaultLocation = true;
+            controlBox1.EnableHoverHighlight = true;
+            controlBox1.EnableMaximizeButton = true;
+            controlBox1.EnableMinimizeButton = true;
+            controlBox1.ForeColor = Color.FromArgb(155, 155, 155);
+            controlBox1.Location = new Point(800, 18);
+            controlBox1.MaximizeHoverColor = Color.FromArgb(74, 74, 74);
+            controlBox1.MinimizeHoverColor = Color.FromArgb(63, 63, 65);
+            controlBox1.Name = "controlBox1";
+            controlBox1.Size = new Size(90, 25);
+            controlBox1.TabIndex = 21;
+            controlBox1.Text = "controlBox1";
+            // 
+            // CameraForm
+            // 
+            AutoScaleMode = AutoScaleMode.None;
+            ClientSize = new Size(900, 600);
+            Controls.Add(themeForm1);
+            FormBorderStyle = FormBorderStyle.None;
+            MinimumSize = new Size(261, 61);
+            Name = "CameraForm";
+            Text = "鐩告満璁剧疆";
+            TransparencyKey = Color.Fuchsia;
+            FormClosing += CameraForm_FormClosing;
+            uiGroupBoxCameraParams.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel3.ResumeLayout(false);
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel4.ResumeLayout(false);
+            tableLayoutPanel4.PerformLayout();
+            tableLayoutPanel5.ResumeLayout(false);
+            tableLayoutPanel5.PerformLayout();
+            tableLayoutPanel6.ResumeLayout(false);
+            tableLayoutPanel6.PerformLayout();
+            uiSplitContainer1.Panel1.ResumeLayout(false);
+            uiSplitContainer1.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)uiSplitContainer1).EndInit();
+            uiSplitContainer1.ResumeLayout(false);
+            themeForm1.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+        private RadioButton uiRadioButtonHardTrigger;
+        private RadioButton uiRadioButtonSoftTrigger;
+        private ComboBox uiComboBoxBrand;
+        private GroupBox uiGroupBoxImage;
+        private GroupBox uiGroupBoxCameraParams;
+        private SplitContainer uiSplitContainer1;
+        private Button uiButtonStartHardGrab;
+        private TableLayoutPanel tableLayoutPanel2;
+        private TableLayoutPanel tableLayoutPanel5;
+        private TableLayoutPanel tableLayoutPanel3;
+        private TableLayoutPanel tableLayoutPanel4;
+        private Label uiMarkLabel1;
+        private TableLayoutPanel tableLayoutPanel1;
+        private Button uiButtonGrabOnce;
+        private Button uiButtonStartSoftGrab;
+        private Button uiButtonCloseSoftGrab;
+        private Label uiMarkLabel2;
+        private TextBox uiTextBoxExp;
+        private Label uiMarkLabel3;
+        private TextBox uiTextBoxGain;
+        private TableLayoutPanel tableLayoutPanel6;
+        private Label uiMarkLabel4;
+        private TextBox uiTextBoxGrabTime;
+        private Button btnSetting;
+        private ReaLTaiizor.Forms.ThemeForm themeForm1;
+        private ReaLTaiizor.Controls.ControlBox controlBox1;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/CameraPage/CameraForm.cs b/LB_SmartVision/Forms/Pages/CameraPage/CameraForm.cs
new file mode 100644
index 0000000..24c3194
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CameraPage/CameraForm.cs
@@ -0,0 +1,272 @@
+锘縰sing LB_VisionControl;
+using LB_VisionProcesses.Cameras;
+using ReaLTaiizor.Forms;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Xml.Linq;
+using static System.Net.Mime.MediaTypeNames;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
+
+namespace LB_SmartVision.Forms.Pages.CameraPage
+{
+    public partial class CameraForm : Form
+    {
+        BaseCamera camera { get; set; }
+        UserPictureBox onlinePictureBox { get; set; }
+
+        public CameraForm()
+        {
+            InitializeComponent();
+        }
+
+        public CameraForm(BaseCamera camera)
+        {
+            InitializeComponent();
+
+            // 浣跨敤 LINQ 鑾峰彇鎵�鏈夋灇涓惧�煎苟鎵撳嵃
+            var brands = Enum.GetValues(typeof(CameraBrand)).Cast<CameraBrand>();
+            foreach (var brand in brands)
+                uiComboBoxBrand.Items.Add(brand.ToString());
+
+            if (camera == null)
+                return;
+
+            this.camera = camera;
+            this.Text = camera.SN;
+
+            //璁剧疆鍝佺墝
+
+
+            onlinePictureBox = new UserPictureBox(uiGroupBoxImage);
+            this.uiGroupBoxImage.Controls.Clear();
+            this.uiGroupBoxImage.Controls.Add(onlinePictureBox);
+            onlinePictureBox.Dock = DockStyle.Fill;
+
+            //璁剧疆瑙﹀彂
+            camera.GetTriggerMode(out TriggerMode triggerMode, out TriggerSource triggerSource);
+            if (triggerSource == TriggerSource.Software)
+                uiRadioButtonSoftTrigger.Checked = true;
+            else
+                uiRadioButtonHardTrigger.Checked = true;
+
+            uiButtonGrabOnce.Enabled = uiRadioButtonSoftTrigger.Checked;
+            uiButtonStartSoftGrab.Enabled = uiRadioButtonSoftTrigger.Checked;
+            uiButtonCloseSoftGrab.Enabled = uiRadioButtonSoftTrigger.Checked;
+            uiButtonStartHardGrab.Enabled = !uiRadioButtonSoftTrigger.Checked;
+
+            //璁剧疆鏇濆厜鍜屽鐩�
+            camera.GetExpouseTime(out double exp);
+            uiTextBoxExp.Text = exp.ToString();
+
+            camera.GetGain(out double gain);
+            uiTextBoxGain.Text = gain.ToString();
+
+            //鍔犺浇鍥炶皟鍑芥暟
+            Subscribe();
+        }
+
+        private void CameraForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            if (camera == null)
+                return;
+
+            camera.StopGrabbing();
+
+            if (uiRadioButtonSoftTrigger.Checked)
+                camera.SetTriggerMode(TriggerMode.On, TriggerSource.Software);
+            else
+                camera.SetTriggerMode(TriggerMode.On, TriggerSource.Line0);
+
+            camera.StartGrabbing();
+
+            Unsubscribe();
+        }
+
+        public void Unsubscribe()
+        {
+            try
+            {
+                if (camera == null)
+                    return;
+                //鍙栨秷鍥炶皟鍑芥暟
+                camera.ImageGrabbed -= GetImageBllComplete;
+            }
+            catch (Exception ex)
+            {
+                // 璁板綍閿欒淇℃伅
+                Debug.WriteLine($"閿欒: {ex.Message}");
+            }
+
+        }
+
+        public void Subscribe()
+        {
+            try
+            {
+                if (camera == null)
+                    return;
+
+                //鍙栨秷鍥炶皟鍑芥暟
+                camera.ImageGrabbed -= GetImageBllComplete;
+                //鍔犺浇鍥炶皟鍑芥暟
+                camera.ImageGrabbed += GetImageBllComplete;
+            }
+            catch (Exception ex)
+            {
+                // 璁板綍閿欒淇℃伅
+                Debug.WriteLine($"閿欒: {ex.Message}");
+            }
+        }
+
+        private void uiRadioButtonSoftTrigger_CheckedChanged(object sender, EventArgs e)
+        {
+            uiButtonGrabOnce.Enabled = uiRadioButtonSoftTrigger.Checked;
+            uiButtonStartSoftGrab.Enabled = uiRadioButtonSoftTrigger.Checked;
+            uiButtonCloseSoftGrab.Enabled = uiRadioButtonSoftTrigger.Checked;
+            uiButtonStartHardGrab.Enabled = !uiRadioButtonSoftTrigger.Checked;
+
+            if (camera == null)
+                return;
+
+            if (uiRadioButtonSoftTrigger.Checked)
+                camera.SetTriggerMode(TriggerMode.On, TriggerSource.Software);
+            else
+                camera.SetTriggerMode(TriggerMode.On, TriggerSource.Line0);
+        }
+
+        private void uiButtonGrabOnce_Click(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+
+            Task.Factory.StartNew(() =>
+            {
+                DateTime startTime = DateTime.Now; // 褰撳墠鏃堕棿
+                camera.GetImageWithSoftTrigger(out Bitmap bitmap);
+
+                this.BeginInvoke(new Action(() =>
+                {
+                    if (bitmap != null)
+                        this.uiTextBoxGrabTime.Text = (DateTime.Now - startTime).TotalMilliseconds.ToString();
+                    else
+                        this.uiTextBoxGrabTime.Text = "-1ms";
+                }));
+            });
+        }
+
+        private void uiButtonStartSoftGrab_Click(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+
+            Task.Factory.StartNew(() =>
+            {
+                camera.StopGrabbing();
+                camera.StartWith_SoftTriggerModel();
+            });
+        }
+
+        private void uiButtonCloseSoftGrab_Click(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+
+            Task.Factory.StartNew(() =>
+            {
+                camera.StopGrabbing();
+                camera.SetTriggerMode(TriggerMode.On, TriggerSource.Software);
+                camera.StartGrabbing();
+            });
+        }
+
+        private void uiButtonStartHardGrab_Click(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+
+            Task.Factory.StartNew(() =>
+            {
+                camera.StopGrabbing();
+                camera.StartWith_HardTriggerModel();
+            });
+        }
+
+        /// <summary>
+        /// 鐩告満鍥炶皟杩愯
+        /// </summary>
+        /// <param name="CCDName"></param>
+        /// <param name="image"></param>
+        private void GetImageBllComplete(object sender, CameraEventArgs e)
+        {
+            if (e.Bitmap == null)
+                return;
+
+            lock (e.Bitmap)
+            {
+                if (this.InvokeRequired) // 妫�鏌ユ槸鍚﹂渶瑕佸湪UI绾跨▼涓婅皟鐢�
+                {
+                    this.Invoke(new Action(() =>
+                    {
+                        onlinePictureBox.Image = e.Bitmap;
+                    })); // 閫掑綊璋冪敤鑷韩锛屼絾杩欐鍦║I绾跨▼涓�
+                }
+                else
+                {
+                    onlinePictureBox.Image = e.Bitmap;
+                }
+            }
+        }
+
+        private ulong ImageWidth;
+        private ulong ImageHeight;
+        private Pen pen = new Pen(Color.Blue, 3f);
+
+        private System.Drawing.Point[] stPointList = new System.Drawing.Point[4];
+
+        private void pictureBox_Paint(object sender, PaintEventArgs e)
+        {
+
+        }
+
+        private void uiTextBoxExp_TextChanged(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+
+            double exp = 1000;
+            if (double.TryParse(uiTextBoxExp.Text.ToString(), out exp))
+                camera.SetExpouseTime(exp);
+        }
+
+        private void uiTextBoxGain_TextChanged(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+
+            double gain = 10;
+            if (double.TryParse(uiTextBoxGain.Text.ToString(), out gain))
+                camera.SetGain(gain);
+        }
+
+        private void cob_Brand_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if (uiComboBoxBrand.Text == "MindCamera")
+                btnSetting.Visible = true;
+            else
+                btnSetting.Visible = false;
+        }
+
+        private void btn_Setting_Click(object sender, EventArgs e)
+        {
+
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/CameraPage/CameraForm.resx b/LB_SmartVision/Forms/Pages/CameraPage/CameraForm.resx
new file mode 100644
index 0000000..922b5eb
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CameraPage/CameraForm.resx
@@ -0,0 +1,144 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="themeForm1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        vgAADr4B6kKxwAAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
+        BkVBUPCBCEG8BXNQ48GLeImCehIJxMsqhsSZruod46K4HtSIGjU+4iOr0c1I9fSsM3/PLNtCPO0H36m/
+        evz/X11VnreKVRTAHPOZumkY6lFwqURws3BwZ8ywTQnuiCP/+iTCzY1qaUPzdm/Atf3PaHre6XPsjyQM
+        2xLGV4XwIyX4QRj+UMK/lPFvJTyhBMeV8IgQvmRJuH4Ko+l5p9UjGBbCJ5RxTgj+VMZmXxKcSAjekHE/
+        NNs5DgaTKLinEQYVO4Trf1mkV81wixLUslPmA3bzF2XcKeP+hWY/u3n0fCXcrQwLyjAvjNsb1dI6N05P
+        mFAIHlHG73sEypPgGwnhfpn0zzH7jzddcK4Q7kqfKNMI4a9K+MwBDgbdeF04MBWsFYYdQvhbLlBvfhKT
+        f+vMtLfG7C0JJXxKGY67WnvCmPAFGRs7z42boul5AzHBfdK6TjdQtzPGk8oos5F/5Y7sfVvPhg+lp+1h
+        0yIsxARPmtaN78WEl8eEX+SNclxUhne0glUrNrN9zfMGlPAuZTzaQ99FYfwuDv3ruoLvq5bWaQSvZCfL
+        GXUYLwrj240Qxtu2lkSN4FpdWfKZH9jb9RQ1Cq62f9sVOlxUxn3KQXnJ0PO8QxU/jBm1h74v7ZniEG9K
+        Hdg/quzvXO709k0Y3u08ucGqWgheX862H4XgxbR47SqU8D1X0EXC2VmGizqDz0xPr0kYH9eO360gNe0b
+        jWppozB+1kOQEb5MCLa0C64NoeGrhOGrvH6lhK81GiIvnggmrDLzgvTkvwvDA+5wsU4nhG/m9AUoBD/F
+        HFzWN4H0XQn2vF8eXN8Z3FAPYasl59oUYjuB+sTImDB+nhfgYQ39STf4fmu1DHtz+oIUgiM1KkWtwcFw
+        sOujVT3hrnaL7UQc+hcL5W+sKIXhw0OVjaW0iwnBc47gqIQ45QY32PKRzv8eTguRYM9SS5YouEEZjv37
+        EffbzbjBDdZyxZYQ12EB2qS0bWrJqRVazPDWkojwZbuZrsgZtDJ0iY1g12khEtTicMTvclwn2CKE32YJ
+        7G5PORfZ1HtMCH7MOV4BrQ3XCe92+4onk5Nn2PolDAvWXnuOzAwzo6Nnx4Q3SrojwqfKeMxWMpsXWVs+
+        2WrfKRdbW1W6Hf0shM/33Y7my4PrleFZIfhAaWjU/e5ivlw+y3S2FySMtynjvcrwsFiLJv/RhPBB2ws1
+        hK2WcBLBFf1qawlplwvxaQlxe786OOU4PBWsjSO85mBlQ8n99r/BisSdAas4FfgHpdEUZpwUX7sAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.Designer.cs b/LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.Designer.cs
new file mode 100644
index 0000000..cfbcc7f
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.Designer.cs
@@ -0,0 +1,153 @@
+锘�
+using ReaLTaiizor.Controls;
+
+namespace LB_SmartVision.Forms.Pages.CameraPage
+{
+    partial class CamerasEditPage
+    {
+        /// <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()
+        {
+            uiButton1 = new HopeButton();
+            uiButton2 = new LostButton();
+            uiFlowLayoutPanel1 = new FlowLayoutPanel();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            SuspendLayout();
+            // 
+            // uiButton1
+            // 
+            uiButton1.BorderColor = Color.FromArgb(220, 223, 230);
+            uiButton1.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            uiButton1.Cursor = Cursors.Hand;
+            uiButton1.DangerColor = Color.FromArgb(245, 108, 108);
+            uiButton1.DefaultColor = Color.FromArgb(255, 255, 255);
+            uiButton1.Dock = DockStyle.Fill;
+            uiButton1.Font = new Font("瀹嬩綋", 12F);
+            uiButton1.HoverTextColor = Color.FromArgb(48, 49, 51);
+            uiButton1.InfoColor = Color.FromArgb(144, 147, 153);
+            uiButton1.Location = new Point(503, 3);
+            uiButton1.MinimumSize = new Size(1, 1);
+            uiButton1.Name = "uiButton1";
+            uiButton1.PrimaryColor = Color.FromArgb(64, 158, 255);
+            uiButton1.Size = new Size(95, 38);
+            uiButton1.SuccessColor = Color.FromArgb(103, 194, 58);
+            uiButton1.TabIndex = 11;
+            uiButton1.Text = "澧炲姞";
+            uiButton1.TextColor = Color.White;
+            uiButton1.WarningColor = Color.FromArgb(230, 162, 60);
+            uiButton1.Click += uiButton1_Click;
+            // 
+            // uiButton2
+            // 
+            uiButton2.BackColor = Color.FromArgb(39, 41, 60);
+            uiButton2.Cursor = Cursors.Hand;
+            uiButton2.Dock = DockStyle.Fill;
+            uiButton2.Font = new Font("瀹嬩綋", 12F);
+            uiButton2.ForeColor = Color.White;
+            uiButton2.HoverColor = Color.DodgerBlue;
+            uiButton2.Image = null;
+            uiButton2.Location = new Point(403, 3);
+            uiButton2.MinimumSize = new Size(1, 1);
+            uiButton2.Name = "uiButton2";
+            uiButton2.Size = new Size(94, 38);
+            uiButton2.TabIndex = 12;
+            uiButton2.Text = "娓呴櫎";
+            uiButton2.Click += uiButton2_Click;
+            // 
+            // uiFlowLayoutPanel1
+            // 
+            uiFlowLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            uiFlowLayoutPanel1.Dock = DockStyle.Fill;
+            uiFlowLayoutPanel1.Font = new Font("瀹嬩綋", 12F);
+            uiFlowLayoutPanel1.ForeColor = SystemColors.Control;
+            uiFlowLayoutPanel1.Location = new Point(4, 5);
+            uiFlowLayoutPanel1.Margin = new Padding(4, 5, 4, 5);
+            uiFlowLayoutPanel1.MinimumSize = new Size(1, 1);
+            uiFlowLayoutPanel1.Name = "uiFlowLayoutPanel1";
+            uiFlowLayoutPanel1.Padding = new Padding(2);
+            uiFlowLayoutPanel1.Size = new Size(599, 293);
+            uiFlowLayoutPanel1.TabIndex = 10;
+            uiFlowLayoutPanel1.Text = "`";
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.Controls.Add(uiFlowLayoutPanel1, 0, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 1);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 2;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.Size = new Size(607, 353);
+            tableLayoutPanel1.TabIndex = 13;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 6;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.Controls.Add(uiButton1, 5, 0);
+            tableLayoutPanel2.Controls.Add(uiButton2, 4, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 306);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 1;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(601, 44);
+            tableLayoutPanel2.TabIndex = 11;
+            // 
+            // CamerasEditPage
+            // 
+            BackColor = Color.FromArgb(32, 41, 50);
+            Controls.Add(tableLayoutPanel1);
+            Name = "CamerasEditPage";
+            Size = new Size(607, 353);
+            Paint += CamerasEditPage_Paint;
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ReaLTaiizor.Controls.HopeButton uiButton1;
+        private ReaLTaiizor.Controls.LostButton uiButton2;
+        private FlowLayoutPanel uiFlowLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel2;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.cs b/LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.cs
new file mode 100644
index 0000000..1d9acea
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.cs
@@ -0,0 +1,180 @@
+锘�
+using LB_VisionControl;
+using LB_VisionProcesses.Cameras;
+using OpenCvSharp.Flann;
+using System;
+using System.Collections.Concurrent;
+using System.Windows.Forms;
+using System.Xml.Linq;
+
+namespace LB_SmartVision.Forms.Pages.CameraPage
+{
+    public partial class CamerasEditPage : UserControl
+    {
+        public Action<string, LogInfoType> LogInfo;
+
+
+        public CamerasEditPage()
+        {
+            InitializeComponent();
+
+            Name = "CamerasEditPage";
+            Text = "鐩告満璁剧疆";
+            //this.Font = new Font("Microsoft YaHei UI", 16F, FontStyle.Regular, GraphicsUnit.Point, 0);
+        }
+
+        private void CamerasEditPage_Paint(object sender, PaintEventArgs e)
+        {
+            uiFlowLayoutPanel1.Controls.Clear();
+
+            if (GlobalVar.dicCameras.Count <= 0)
+                return;
+
+            foreach (var item in GlobalVar.dicCameras)
+            {
+                string CameraSN = item.Key;
+                string CameraBrand = item.Value.Brand.ToString();
+
+                if (string.IsNullOrEmpty(CameraSN) || string.IsNullOrEmpty(CameraBrand))
+                    return;
+
+                UserItem flow = new UserItem(new string[] { "娴嬭瘯", "鍒锋柊", "绉婚櫎" });
+                flow.Name = CameraSN;
+                flow.Text = $"[{CameraBrand}]";
+                if (item.Value.isGrabbing)
+                    flow.state = State.Pass;
+                else
+                    flow.state |= State.Error;
+                LoadFlowEvent(flow);
+
+                uiFlowLayoutPanel1.Controls.Add(flow);
+            }
+        }
+
+
+        private void uiButton1_Click(object sender, System.EventArgs e)
+        {
+            CreateCameraForm createCameraForm = new CreateCameraForm();
+            createCameraForm.ShowDialog();
+
+            if (createCameraForm.bCreate)
+            {
+                BaseCamera camera = createCameraForm.camera;
+                if (GlobalVar.dicCameras.ContainsKey(camera.SN))
+                {
+                    MessageBox.Show($"鐩告満[{camera.SN}]宸插瓨鍦�!", "寮傚父");
+                    return;
+                }
+
+                string CameraSN = camera.SN;//"127.0.0.1"
+                string CameraBrand = camera.Brand.ToString();//"1111"
+
+                if (string.IsNullOrEmpty(CameraSN) || string.IsNullOrEmpty(CameraBrand))
+                    return;
+
+                GlobalVar.dicCameras.TryAdd(CameraSN, camera);
+                LogInfo?.Invoke(string.Format("娣诲姞鐩告満[{0}][{1}]鎴愬姛", CameraBrand, CameraSN), LogInfoType.PASS);
+            }
+            this.Invalidate();
+        }
+
+        private void uiButton2_Click(object sender, System.EventArgs e)
+        {
+            //娓呴櫎鐢–lear鏂规硶
+            uiFlowLayoutPanel1.Controls.Clear();
+            foreach (var camera in GlobalVar.dicCameras.Values)
+            {
+                camera.CloseDevice();
+            }
+            GlobalVar.dicCameras.Clear();
+        }
+
+        private void LoadFlowEvent(UserItem flow)
+        {
+            //鎸夐敭1涓烘祴璇�
+            flow.MenuItem1ClickedEvent += TestEvent;
+            //鎸夐敭2涓哄埛鏂�
+            flow.MenuItem2ClickedEvent += ReconnectEvent;
+            //鎸夐敭3涓虹Щ闄�
+            flow.MenuItem3ClickedEvent += DeleteEvent;
+        }
+
+        private void RemoveFlowEvent(UserItem flow)
+        {
+            //鎸夐敭1涓烘祴璇�
+            flow.MenuItem1ClickedEvent -= TestEvent;
+            //鎸夐敭2涓哄埛鏂�
+            flow.MenuItem2ClickedEvent -= ReconnectEvent;
+            //鎸夐敭3涓虹Щ闄�
+            flow.MenuItem3ClickedEvent += DeleteEvent;
+        }
+
+        // 娴嬭瘯鐩告満
+        private void TestEvent(string Name, string Text)
+        {
+            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+            {
+                UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                string name = flow.Name;
+                if (name != Name)
+                    continue;
+
+                if (GlobalVar.dicCameras.ContainsKey(name))
+                {
+                    CameraForm cameraForm = new CameraForm(GlobalVar.dicCameras[name]);
+                    cameraForm.Show();
+                }
+            }
+        }
+
+        // 绉婚櫎鐩告満
+        private void DeleteEvent(string Name, string Text)
+        {
+            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+            {
+                UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                string name = flow.Name;
+                if (name != Name)
+                    continue;
+
+                RemoveFlowEvent(flow);
+                uiFlowLayoutPanel1.Controls.Remove(uiFlowLayoutPanel1.Controls[i]);
+                if (GlobalVar.dicCameras.TryRemove(name, out BaseCamera BaseCamera))
+                {
+                    BaseCamera.Dispose();
+                    LogInfo?.Invoke(string.Format("绉婚櫎鐩告満[{0}]", name), LogInfoType.INFO);
+                }
+                else
+                    LogInfo?.Invoke(string.Format("绉婚櫎鐩告満[{0}]澶辫触", name), LogInfoType.ERROR);
+
+            }
+        }
+
+        // 閲嶈繛鐩告満
+        private void ReconnectEvent(string Name, string Text)
+        {
+            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+            {
+                UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                string name = flow.Name;
+                if (name != Name)
+                    continue;
+
+                GlobalVar.dicCameras[name].CloseDevice();
+                Thread.Sleep(50);
+                GlobalVar.dicCameras[name].InitDevice(name, this.Handle);
+                if (GlobalVar.dicCameras[name].isGrabbing)
+                {
+                    flow.state = State.Pass;
+                    LogInfo?.Invoke(string.Format("閲嶈繛鐩告満[{0}]鎴愬姛", name), LogInfoType.PASS);
+                }
+                else
+                {
+                    flow.state = State.Error;
+                    LogInfo?.Invoke(string.Format("閲嶈繛鐩告満[{0}]澶辫触", name), LogInfoType.ERROR);
+                }
+                flow.Refresh();
+            }
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.resx b/LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CameraPage/CamerasEditPage.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/LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.Designer.cs b/LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.Designer.cs
new file mode 100644
index 0000000..1d51f43
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.Designer.cs
@@ -0,0 +1,196 @@
+锘縩amespace LB_SmartVision.Forms.Pages.CameraPage
+{
+    partial class CreateCameraForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CreateCameraForm));
+            uiLabel1 = new Label();
+            uiLabel2 = new Label();
+            uiButtonCancel = new Button();
+            uiButtonCreate = new Button();
+            uiButtonTest = new Button();
+            uiComboBoxBrand = new ComboBox();
+            uiComboBoxSN = new ComboBox();
+            themeForm1 = new ReaLTaiizor.Forms.ThemeForm();
+            controlBox1 = new ReaLTaiizor.Controls.ControlBox();
+            themeForm1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // uiLabel1
+            // 
+            uiLabel1.Font = new Font("瀹嬩綋", 12F);
+            uiLabel1.ForeColor = SystemColors.Control;
+            uiLabel1.Location = new Point(120, 97);
+            uiLabel1.Name = "uiLabel1";
+            uiLabel1.Size = new Size(100, 23);
+            uiLabel1.TabIndex = 1;
+            uiLabel1.Text = "鍝佺墝";
+            // 
+            // uiLabel2
+            // 
+            uiLabel2.Font = new Font("瀹嬩綋", 12F);
+            uiLabel2.ForeColor = SystemColors.Control;
+            uiLabel2.Location = new Point(120, 163);
+            uiLabel2.Name = "uiLabel2";
+            uiLabel2.Size = new Size(100, 23);
+            uiLabel2.TabIndex = 2;
+            uiLabel2.Text = "鐩告満SN";
+            // 
+            // uiButtonCancel
+            // 
+            uiButtonCancel.Font = new Font("瀹嬩綋", 12F);
+            uiButtonCancel.ForeColor = SystemColors.Control;
+            uiButtonCancel.Location = new Point(343, 234);
+            uiButtonCancel.MinimumSize = new Size(1, 1);
+            uiButtonCancel.Name = "uiButtonCancel";
+            uiButtonCancel.Size = new Size(100, 35);
+            uiButtonCancel.TabIndex = 4;
+            uiButtonCancel.Text = "鍙栨秷";
+            uiButtonCancel.Click += uiButtonCancel_Click;
+            // 
+            // uiButtonCreate
+            // 
+            uiButtonCreate.Enabled = false;
+            uiButtonCreate.Font = new Font("瀹嬩綋", 12F);
+            uiButtonCreate.ForeColor = SystemColors.Control;
+            uiButtonCreate.Location = new Point(187, 234);
+            uiButtonCreate.MinimumSize = new Size(1, 1);
+            uiButtonCreate.Name = "uiButtonCreate";
+            uiButtonCreate.Size = new Size(100, 35);
+            uiButtonCreate.TabIndex = 9;
+            uiButtonCreate.Text = "鍒涘缓";
+            uiButtonCreate.Click += uiButtonCreate_Click;
+            // 
+            // uiButtonTest
+            // 
+            uiButtonTest.Font = new Font("瀹嬩綋", 12F);
+            uiButtonTest.ForeColor = SystemColors.Control;
+            uiButtonTest.Location = new Point(31, 234);
+            uiButtonTest.MinimumSize = new Size(1, 1);
+            uiButtonTest.Name = "uiButtonTest";
+            uiButtonTest.Size = new Size(100, 35);
+            uiButtonTest.TabIndex = 10;
+            uiButtonTest.Text = "娴嬭瘯";
+            uiButtonTest.Click += uiButtonTest_Click;
+            // 
+            // uiComboBoxBrand
+            // 
+            uiComboBoxBrand.Font = new Font("瀹嬩綋", 12F);
+            uiComboBoxBrand.Location = new Point(227, 94);
+            uiComboBoxBrand.Margin = new Padding(4, 5, 4, 5);
+            uiComboBoxBrand.MinimumSize = new Size(63, 0);
+            uiComboBoxBrand.Name = "uiComboBoxBrand";
+            uiComboBoxBrand.Size = new Size(150, 24);
+            uiComboBoxBrand.TabIndex = 11;
+            uiComboBoxBrand.SelectedIndexChanged += uiComboBoxBrand_SelectedIndexChanged;
+            uiComboBoxBrand.MouseClick += uiComboBoxBrand_MouseClick;
+            // 
+            // uiComboBoxSN
+            // 
+            uiComboBoxSN.Font = new Font("瀹嬩綋", 12F);
+            uiComboBoxSN.Location = new Point(227, 157);
+            uiComboBoxSN.Margin = new Padding(4, 5, 4, 5);
+            uiComboBoxSN.MinimumSize = new Size(63, 0);
+            uiComboBoxSN.Name = "uiComboBoxSN";
+            uiComboBoxSN.Size = new Size(150, 24);
+            uiComboBoxSN.TabIndex = 12;
+            uiComboBoxSN.MouseClick += uiComboBoxSN_MouseClick;
+            // 
+            // themeForm1
+            // 
+            themeForm1.BackColor = Color.FromArgb(32, 41, 50);
+            themeForm1.Controls.Add(controlBox1);
+            themeForm1.Dock = DockStyle.Fill;
+            themeForm1.Font = new Font("Microsoft Sans Serif", 9F);
+            themeForm1.ForeColor = SystemColors.Control;
+            themeForm1.Image = (Image)resources.GetObject("themeForm1.Image");
+            themeForm1.Location = new Point(0, 0);
+            themeForm1.Name = "themeForm1";
+            themeForm1.Padding = new Padding(10, 70, 10, 9);
+            themeForm1.RoundCorners = true;
+            themeForm1.Sizable = true;
+            themeForm1.Size = new Size(507, 309);
+            themeForm1.SmartBounds = true;
+            themeForm1.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            themeForm1.TabIndex = 13;
+            themeForm1.Text = "鍒涘缓鐩告満";
+            // 
+            // controlBox1
+            // 
+            controlBox1.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            controlBox1.BackColor = Color.FromArgb(32, 34, 37);
+            controlBox1.CloseHoverColor = Color.FromArgb(230, 17, 35);
+            controlBox1.DefaultLocation = true;
+            controlBox1.EnableHoverHighlight = true;
+            controlBox1.EnableMaximizeButton = true;
+            controlBox1.EnableMinimizeButton = true;
+            controlBox1.ForeColor = Color.FromArgb(155, 155, 155);
+            controlBox1.Location = new Point(405, 12);
+            controlBox1.MaximizeHoverColor = Color.FromArgb(74, 74, 74);
+            controlBox1.MinimizeHoverColor = Color.FromArgb(63, 63, 65);
+            controlBox1.Name = "controlBox1";
+            controlBox1.Size = new Size(90, 25);
+            controlBox1.TabIndex = 0;
+            controlBox1.Text = "controlBox1";
+            // 
+            // CreateCameraForm
+            // 
+            AutoScaleMode = AutoScaleMode.None;
+            ClientSize = new Size(507, 309);
+            ControlBox = false;
+            Controls.Add(uiComboBoxSN);
+            Controls.Add(uiComboBoxBrand);
+            Controls.Add(uiButtonTest);
+            Controls.Add(uiButtonCreate);
+            Controls.Add(uiButtonCancel);
+            Controls.Add(uiLabel2);
+            Controls.Add(uiLabel1);
+            Controls.Add(themeForm1);
+            FormBorderStyle = FormBorderStyle.None;
+            MaximizeBox = false;
+            MinimizeBox = false;
+            MinimumSize = new Size(261, 61);
+            Name = "CreateCameraForm";
+            Text = "鍒涘缓鐩告満";
+            TransparencyKey = Color.Fuchsia;
+            themeForm1.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+        private Label uiLabel1;
+        private Label uiLabel2;
+        private Button uiButtonCancel;
+        private Button uiButtonCreate;
+        private Button uiButtonTest;
+        private ComboBox uiComboBoxBrand;
+        private ComboBox uiComboBoxSN;
+        private ReaLTaiizor.Forms.ThemeForm themeForm1;
+        private ReaLTaiizor.Controls.ControlBox controlBox1;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.cs b/LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.cs
new file mode 100644
index 0000000..1a9d3a5
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.cs
@@ -0,0 +1,121 @@
+锘縰sing LB_VisionProcesses.Cameras;
+using RJCP.IO.Ports;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO.Ports;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
+
+
+namespace LB_SmartVision.Forms.Pages.CameraPage
+{
+    public partial class CreateCameraForm : Form
+    {
+        public BaseCamera camera { get; set; }
+        public bool bCreate = false;
+
+        public CreateCameraForm(ICamera camera = null)
+        {
+            InitializeComponent();
+            // 绂佹淇敼绐楀彛澶у皬
+            this.FormBorderStyle = FormBorderStyle.FixedDialog;
+            if (camera == null)
+                //camera = new HRCamera();
+
+            uiButtonCreate.Enabled = false;
+        }
+
+        private void uiButtonTest_Click(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+
+            if (string.IsNullOrEmpty(uiComboBoxSN.Text))
+                MessageBox.Show($"鍒濆鍖栫浉鏈篬{uiComboBoxSN.Text}]涓虹┖!", "寮傚父");
+
+            if (camera == null)
+            {
+                MessageBox.Show("璇峰厛閫夋嫨鐩告満鍝佺墝!", "寮傚父");
+                return;
+            }
+
+            camera.CloseDevice();
+            if (camera.InitDevice(uiComboBoxSN.Text, this.Handle))
+            {
+                uiButtonCreate.Enabled = true;
+                camera.CloseDevice();
+            }
+            else
+                MessageBox.Show($"鍒濆鍖栫浉鏈篬{uiComboBoxSN.Text}]澶辫触!", "寮傚父");
+        }
+
+        private void uiButtonCreate_Click(object sender, EventArgs e)
+        {
+            if (camera.InitDevice(uiComboBoxSN.Text, this.Handle))
+            {
+                bCreate = true;
+                this.Close();
+            }
+            else
+                MessageBox.Show($"鍒濆鍖栫浉鏈篬{uiComboBoxSN.Text}]澶辫触!", "寮傚父");
+        }
+
+        private void uiButtonCancel_Click(object sender, EventArgs e)
+        {
+            if (camera != null)
+                camera.CloseDevice();
+            bCreate = false;
+            this.Close();
+        }
+
+        private void uiComboBoxBrand_MouseClick(object sender, MouseEventArgs e)
+        {
+            uiComboBoxBrand.Items.Clear();
+            foreach (CameraBrand brand in Enum.GetValues(typeof(CameraBrand)))
+            {
+                if (brand != CameraBrand.UNSUPPORTED)
+                    uiComboBoxBrand.Items.Add(brand.ToString());
+            }
+        }
+
+        private void uiComboBoxBrand_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+            uiComboBoxSN.Text = string.Empty;
+
+            if (camera != null)
+                camera.CloseDevice();
+
+            Enum.TryParse<CameraBrand>(uiComboBoxBrand.Text, out CameraBrand brand);
+            switch (brand)
+            {
+                case CameraBrand.HRCamera:
+                    //camera = new HRCamera();
+                    break;
+                case CameraBrand.LBCamera:
+                    //camera = new LBCamera();
+                    break;
+                default:
+                    return;
+            }
+        }
+
+        private void uiComboBoxSN_MouseClick(object sender, MouseEventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+            uiComboBoxSN.Text = string.Empty;
+
+            uiComboBoxSN.Items.Clear();
+            var list = camera.GetListEnum();
+
+            foreach (string sn in list)
+                uiComboBoxSN.Items.Add(sn);
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.resx b/LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.resx
new file mode 100644
index 0000000..3384e6d
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CameraPage/CreateCameraForm.resx
@@ -0,0 +1,144 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="themeForm1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAPiSURBVFhH7VZLiBxlEG7d+IjBKKtktqt6d8kybLqqZyfi
+        +lgUXcGooKIXxYBKLgZFQVDwgQhBvAVzUOPBi3iJgnoSCcTLKobEma7qHeOiuB7UiBo1PuIjq9HNSPX0
+        rDN/zyzbQjztB9+pv3r8/19dVZ63ilUUwBzzmbppGOpRcKlEcLNwcGfMsE0J7ogj//okws2NamlD83Zv
+        wLX9z2h63ulz7I8kDNsSxleF8CMl+EEY/lDCv5TxbyU8oQTHlfCIEL5kSbh+CqPpeafVIxgWwieUcU4I
+        /lTGZl8SnEgI3pBxPzTbOQ4Gkyi4pxEGFTuE639ZpFfNcIsS1LJT5gN28xdl3Cnj/oVmP7t59Hwl3K0M
+        C8owL4zbG9XSOjdOT5hQCB5Rxu97BMqT4BsJ4X6Z9M8x+483XXCuEO5KnyjTCOGvSvjMAQ4G3XhdODAV
+        rBWGHUL4Wy5Qb34Sk3/rzLS3xuwtCSV8ShmOu1p7wpjwBRkbO8+Nm6LpeQMxwX3Suk43ULczxpPKKLOR
+        f+WO7H1bz4YPpaftYdMiLMQET5rWje/FhJfHhF/kjXJcVIZ3tIJVKzazfc3zBpTwLmU82kPfRWH8Lg79
+        67qC76uW1mkEr2Qnyxl1GC8K49uNEMbbtpZEjeBaXVnymR/Y2/UUNQqutn/bFTpcVMZ9ykF5ydDzvEMV
+        P4wZtYe+L+2Z4hBvSh3YP6rs71zu9PZNGN7tPLnBqloIXl/Oth+F4MW0eO0qlPA9V9BFwtlZhos6g89M
+        T69JGB/Xjt+tIDXtG41qaaMwftZDkBG+TAi2tAuuDaHhq4Thq7x+pYSvNRoiL54IJqwy84L05L8LwwPu
+        cLFOJ4Rv5vQFKAQ/xRxc1jeB9F0J9rxfHlzfGdxQD2GrJefaFGI7gfrEyJgwfp4X4GEN/Uk3+H5rtQx7
+        c/qCFIIjNSpFrcHBcLDro1U94a52i+1EHPoXC+VvrCiF4cNDlY2ltIsJwXOO4KiEOOUGN9jykc7/Hk4L
+        kWDPUkuWKLhBGY79+xH32824wQ3WcsWWENdhAdqktG1qyakVWszw1pKI8GW7ma7IGbQydImNYNdpIRLU
+        4nDE73JcJ9gihN9mCexuTzkX2dR7TAh+zDleAa0N1wnvdvuKJ5OTZ9j6JQwL1l57jswMM6OjZ8eEN0q6
+        I8KnynjMVjKbF1lbPtlq3ykXW1tVuh39LITP992O5suD65XhWSH4QGlo1P3uYr5cPst0thckjLcp473K
+        8LBYiyb/0YTwQdsLNYStlnASwRX9amsJaZcL8WkJcXu/OjjlODwVrI0jvOZgZUPJ/fa/wYrEnQGrOBX4
+        B6XRFGacFF+7AAAAAElFTkSuQmCC
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.Designer.cs b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.Designer.cs
new file mode 100644
index 0000000..3eb06b4
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.Designer.cs
@@ -0,0 +1,239 @@
+锘縩amespace LB_SmartVision.Forms.Pages.CommunicatorPage
+{
+    partial class CommunicatorForm
+    {
+        /// <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()
+        {
+            label3 = new Label();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            grpReceive = new GroupBox();
+            txtReceiveMsg = new TextBox();
+            txtSendMsg = new TextBox();
+            grpSetting = new GroupBox();
+            txtIP = new TextBox();
+            txtPort = new TextBox();
+            lblPort = new Label();
+            cmbIP = new ComboBox();
+            lblIP = new Label();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            btnRuleSend = new Button();
+            btnSend = new Button();
+            tableLayoutPanel1.SuspendLayout();
+            grpReceive.SuspendLayout();
+            grpSetting.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            SuspendLayout();
+            // 
+            // label3
+            // 
+            label3.AutoSize = true;
+            label3.Dock = DockStyle.Fill;
+            label3.Location = new Point(3, 100);
+            label3.Name = "label3";
+            label3.Size = new Size(669, 20);
+            label3.TabIndex = 18;
+            label3.Text = "鍙戦�佷俊鎭�";
+            label3.TextAlign = ContentAlignment.BottomLeft;
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(grpReceive, 0, 4);
+            tableLayoutPanel1.Controls.Add(txtSendMsg, 0, 2);
+            tableLayoutPanel1.Controls.Add(grpSetting, 0, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 3);
+            tableLayoutPanel1.Controls.Add(label3, 0, 1);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(3, 64);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 5;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Size = new Size(675, 334);
+            tableLayoutPanel1.TabIndex = 26;
+            // 
+            // grpReceive
+            // 
+            grpReceive.Controls.Add(txtReceiveMsg);
+            grpReceive.Dock = DockStyle.Fill;
+            grpReceive.Location = new Point(3, 193);
+            grpReceive.Name = "grpReceive";
+            grpReceive.Size = new Size(669, 138);
+            grpReceive.TabIndex = 30;
+            grpReceive.TabStop = false;
+            grpReceive.Text = "閫氳璁板綍";
+            // 
+            // txtReceiveMsg
+            // 
+            txtReceiveMsg.Dock = DockStyle.Fill;
+            txtReceiveMsg.Location = new Point(3, 19);
+            txtReceiveMsg.Multiline = true;
+            txtReceiveMsg.Name = "txtReceiveMsg";
+            txtReceiveMsg.ReadOnly = true;
+            txtReceiveMsg.ScrollBars = ScrollBars.Both;
+            txtReceiveMsg.Size = new Size(663, 116);
+            txtReceiveMsg.TabIndex = 0;
+            // 
+            // txtSendMsg
+            // 
+            txtSendMsg.Dock = DockStyle.Fill;
+            txtSendMsg.Location = new Point(3, 123);
+            txtSendMsg.Name = "txtSendMsg";
+            txtSendMsg.Size = new Size(669, 23);
+            txtSendMsg.TabIndex = 29;
+            // 
+            // grpSetting
+            // 
+            grpSetting.Controls.Add(txtIP);
+            grpSetting.Controls.Add(txtPort);
+            grpSetting.Controls.Add(lblPort);
+            grpSetting.Controls.Add(cmbIP);
+            grpSetting.Controls.Add(lblIP);
+            grpSetting.Dock = DockStyle.Fill;
+            grpSetting.Location = new Point(3, 3);
+            grpSetting.Name = "grpSetting";
+            grpSetting.Size = new Size(669, 94);
+            grpSetting.TabIndex = 28;
+            grpSetting.TabStop = false;
+            grpSetting.Text = "閫氳閰嶇疆";
+            // 
+            // txtIP
+            // 
+            txtIP.Location = new Point(79, 22);
+            txtIP.Name = "txtIP";
+            txtIP.Size = new Size(100, 23);
+            txtIP.TabIndex = 7;
+            // 
+            // txtPort
+            // 
+            txtPort.Location = new Point(79, 60);
+            txtPort.Name = "txtPort";
+            txtPort.Size = new Size(100, 23);
+            txtPort.TabIndex = 6;
+            // 
+            // lblPort
+            // 
+            lblPort.AutoSize = true;
+            lblPort.Location = new Point(13, 63);
+            lblPort.Name = "lblPort";
+            lblPort.Size = new Size(32, 17);
+            lblPort.TabIndex = 4;
+            lblPort.Text = "绔彛";
+            // 
+            // cmbIP
+            // 
+            cmbIP.FormattingEnabled = true;
+            cmbIP.Location = new Point(79, 21);
+            cmbIP.Name = "cmbIP";
+            cmbIP.Size = new Size(100, 25);
+            cmbIP.TabIndex = 1;
+            // 
+            // lblIP
+            // 
+            lblIP.AutoSize = true;
+            lblIP.Location = new Point(13, 26);
+            lblIP.Name = "lblIP";
+            lblIP.Size = new Size(32, 17);
+            lblIP.TabIndex = 0;
+            lblIP.Text = "鍦板潃";
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 3;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 80F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 80F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(btnRuleSend, 1, 0);
+            tableLayoutPanel2.Controls.Add(btnSend, 0, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 153);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 1;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(669, 34);
+            tableLayoutPanel2.TabIndex = 27;
+            // 
+            // btnRuleSend
+            // 
+            btnRuleSend.Dock = DockStyle.Fill;
+            btnRuleSend.Location = new Point(83, 3);
+            btnRuleSend.Name = "btnRuleSend";
+            btnRuleSend.Size = new Size(74, 28);
+            btnRuleSend.TabIndex = 14;
+            btnRuleSend.Text = "鏍¢獙鍙戦��";
+            btnRuleSend.UseVisualStyleBackColor = true;
+            btnRuleSend.Click += btnRuleSend_Click;
+            // 
+            // btnSend
+            // 
+            btnSend.Dock = DockStyle.Fill;
+            btnSend.Location = new Point(3, 3);
+            btnSend.Name = "btnSend";
+            btnSend.Size = new Size(74, 28);
+            btnSend.TabIndex = 12;
+            btnSend.Text = "鍙戦��";
+            btnSend.UseVisualStyleBackColor = true;
+            btnSend.Click += btnSend_Click;
+            // 
+            // CommunicatorForm
+            // 
+            AutoScaleMode = AutoScaleMode.None;
+            ClientSize = new Size(681, 401);
+            Controls.Add(tableLayoutPanel1);
+            Name = "CommunicatorForm";
+            FormClosing += CommunicatorForm_FormClosing;
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel1.PerformLayout();
+            grpReceive.ResumeLayout(false);
+            grpReceive.PerformLayout();
+            grpSetting.ResumeLayout(false);
+            grpSetting.PerformLayout();
+            tableLayoutPanel2.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+        private Label label3;
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel2;
+        private GroupBox grpSetting;
+        private TextBox txtIP;
+        private TextBox txtPort;
+        private Label lblPort;
+        private ComboBox cmbIP;
+        private Label lblIP;
+        private TextBox txtSendMsg;
+        private GroupBox grpReceive;
+        private TextBox txtReceiveMsg;
+        private Button btnSend;
+        private Button btnRuleSend;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.cs b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.cs
new file mode 100644
index 0000000..c582b42
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.cs
@@ -0,0 +1,189 @@
+锘縰sing LB_VisionProcesses.Communicators;
+using LB_VisionProcesses.Communicators.TCom;
+using ReaLTaiizor.Forms;
+using RJCP.IO.Ports;
+using System.Diagnostics;
+
+namespace LB_SmartVision.Forms.Pages.CommunicatorPage
+{
+    public partial class CommunicatorForm : MaterialForm
+    {
+        BaseCommunicator communicator { get; set; }
+
+        public CommunicatorForm()
+        {
+            InitializeComponent();
+        }
+
+        public CommunicatorForm(BaseCommunicator communicator, string name)
+        {
+            InitializeComponent();
+            if (communicator == null)
+                return;
+
+            cmbIP.Enabled = false;
+            txtIP.Enabled = false;
+            txtPort.Enabled = false;
+            this.Text = name;
+
+            if (communicator is UARTPort)
+            {
+                //缁熻鍙敤绔彛
+                SerialPortStream temp = new SerialPortStream();
+                string[] ArryPort = temp.GetPortNames();
+                for (int i = 0; i < ArryPort.Length; i++)
+                    cmbIP.Items.Add(ArryPort[i]);
+
+                cmbIP.Text = communicator.CommunicatorConnections["鍦板潃"]?.ToString();
+                txtPort.Text = communicator.CommunicatorConnections["绔彛"]?.ToString();
+                txtIP.Visible = false;
+                cmbIP.Visible = true;
+
+                lblIP.Text = "COM鍙�";
+                lblPort.Text = "娉㈢壒鐜�";
+            }
+            else if (communicator is TCPClient || communicator is TCPServer)
+            {
+                txtIP.Text = communicator.CommunicatorConnections["鍦板潃"]?.ToString();
+                txtPort.Text = communicator.CommunicatorConnections["绔彛"]?.ToString();
+                txtIP.Visible = true;
+                cmbIP.Visible = false;
+
+                lblIP.Text = "鍦板潃";
+                lblPort.Text = "绔彛";
+            }
+            else if (communicator is LocalMonitor)
+            {
+                txtIP.Text = communicator.CommunicatorConnections["鍦板潃"]?.ToString();
+                txtPort.Text = communicator.CommunicatorConnections["绔彛"]?.ToString();
+                txtIP.Visible = true;
+                cmbIP.Visible = false;
+
+                lblIP.Text = "鐩戞帶鏂囦欢";
+                lblPort.Text = "鍐欏叆鏂囦欢";
+            }
+
+            this.communicator = communicator;
+            //鍔犺浇鍥炶皟鍑芥暟
+            Subscribe();
+        }
+
+        private void CommunicatorForm_FormClosing(object sender, FormClosingEventArgs e) => Unsubscribe();
+
+        public void Unsubscribe()
+        {
+            try
+            {
+                if (communicator == null)
+                    return;
+                //鍙栨秷鍥炶皟鍑芥暟
+                communicator.MessageReceived -= ShowReceiveMsg;
+            }
+            catch (Exception ex)
+            {
+                // 璁板綍閿欒淇℃伅
+                Debug.WriteLine($"閿欒: {ex.Message}");
+            }
+
+        }
+
+        public void Subscribe()
+        {
+            try
+            {
+                if (communicator == null)
+                    return;
+
+                //鍙栨秷鍥炶皟鍑芥暟
+                communicator.MessageReceived -= ShowReceiveMsg;
+                //鍔犺浇鍥炶皟鍑芥暟
+                communicator.MessageReceived += ShowReceiveMsg;
+            }
+            catch (Exception ex)
+            {
+                // 璁板綍閿欒淇℃伅
+                Debug.WriteLine($"閿欒: {ex.Message}");
+            }
+        }
+
+        /// <summary>
+        /// 閫氳鍥炶皟杩愯
+        /// </summary>
+        /// <param name="CCDName"></param>
+        /// <param name="image"></param>
+        private void ShowReceiveMsg(string strReceiveMsg)
+        {
+            // 濡傛灉褰撳墠涓嶆槸 UI 绾跨▼锛屽垯閫氳繃 Invoke 灏嗘搷浣滆皟搴﹀埌 UI 绾跨▼
+            if (this.InvokeRequired)
+            {
+                this.Invoke(new Action<string>((msg) =>
+                {
+                    // 鏇存柊 UI 鎺т欢锛屾瘮濡傛樉绀烘帴鏀跺埌鐨勬秷鎭�
+                    this.txtReceiveMsg.AppendText(("[鎺ユ敹]" + DateTime.Now.ToString() + "锛�" + msg));
+                    this.txtReceiveMsg.AppendText("\r\n");
+                    this.txtReceiveMsg.SelectionStart = this.txtReceiveMsg.Text.Length;
+                    this.txtReceiveMsg.ScrollToCaret();
+                }), strReceiveMsg);
+            }
+            else
+            {
+                // 濡傛灉宸茬粡鍦� UI 绾跨▼涓婏紝鐩存帴鏇存柊 UI
+                this.txtReceiveMsg.AppendText(("[鎺ユ敹]" + DateTime.Now.ToString() + "锛�" + strReceiveMsg));
+                this.txtReceiveMsg.AppendText("\r\n");
+                this.txtReceiveMsg.SelectionStart = this.txtReceiveMsg.Text.Length;
+                this.txtReceiveMsg.ScrollToCaret();
+            }
+        }
+
+        private void ShowSendMsg(string strSendMsg)
+        {
+            // 濡傛灉褰撳墠涓嶆槸 UI 绾跨▼锛屽垯閫氳繃 Invoke 灏嗘搷浣滆皟搴﹀埌 UI 绾跨▼
+            if (this.InvokeRequired)
+            {
+                this.Invoke(new Action<string>((msg) =>
+                {
+                    // 鏇存柊 UI 鎺т欢锛屾瘮濡傛樉绀烘帴鏀跺埌鐨勬秷鎭�
+                    this.txtReceiveMsg.AppendText(("[鍙戦�乚" + DateTime.Now.ToString() + "锛�" + msg));
+                    this.txtReceiveMsg.AppendText("\r\n");
+                    this.txtReceiveMsg.SelectionStart = this.txtReceiveMsg.Text.Length;
+                    this.txtReceiveMsg.ScrollToCaret();
+                }), strSendMsg);
+            }
+            else
+            {
+                // 濡傛灉宸茬粡鍦� UI 绾跨▼涓婏紝鐩存帴鏇存柊 UI
+                this.txtReceiveMsg.AppendText(("[鍙戦�乚" + DateTime.Now.ToString() + "锛�" + strSendMsg));
+                this.txtReceiveMsg.AppendText("\r\n");
+                this.txtReceiveMsg.SelectionStart = this.txtReceiveMsg.Text.Length;
+                this.txtReceiveMsg.ScrollToCaret();
+            }
+        }
+
+        private void btnSend_Click(object sender, EventArgs e)
+        {
+            if (communicator == null)
+                return;
+
+            if (communicator.SendMessage(txtSendMsg.Text))
+                ShowSendMsg(txtSendMsg.Text);
+        }
+
+        private void btnRuleSend_Click(object sender, EventArgs e)
+        {
+            if (communicator == null)
+                return;
+
+            string SendMsg = txtSendMsg.Text;
+
+            byte[] HexByte = BaseCommunicator.strToHexByte(SendMsg);
+            ushort crcHexByte = BaseCommunicator.CRC16Calculate(HexByte, HexByte.Length);
+
+            string crcString = crcHexByte.ToString("X4");
+            //HexByte = strToHexByte(strSendMsg + crcString);
+            SendMsg = SendMsg + crcString;
+
+            if (communicator.SendMessage(SendMsg))
+                ShowSendMsg(SendMsg);
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.resx b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.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/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.Designer.cs b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.Designer.cs
new file mode 100644
index 0000000..d7f3f39
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.Designer.cs
@@ -0,0 +1,154 @@
+锘�
+using ReaLTaiizor.Controls;
+
+namespace LB_SmartVision.Forms.Pages.CommunicatorPage
+{
+    partial class CommunicatorsEditPage
+    {
+        /// <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()
+        {
+            uiButton1 = new HopeButton();
+            uiButton2 = new LostButton();
+            uiFlowLayoutPanel1 = new FlowLayoutPanel();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            SuspendLayout();
+            // 
+            // uiButton1
+            // 
+            uiButton1.BorderColor = Color.FromArgb(220, 223, 230);
+            uiButton1.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            uiButton1.Cursor = Cursors.Hand;
+            uiButton1.DangerColor = Color.FromArgb(245, 108, 108);
+            uiButton1.DefaultColor = Color.FromArgb(255, 255, 255);
+            uiButton1.Dock = DockStyle.Fill;
+            uiButton1.Font = new Font("瀹嬩綋", 12F);
+            uiButton1.HoverTextColor = Color.FromArgb(48, 49, 51);
+            uiButton1.InfoColor = Color.FromArgb(144, 147, 153);
+            uiButton1.Location = new Point(503, 3);
+            uiButton1.MinimumSize = new Size(1, 1);
+            uiButton1.Name = "uiButton1";
+            uiButton1.PrimaryColor = Color.FromArgb(64, 158, 255);
+            uiButton1.Size = new Size(95, 38);
+            uiButton1.SuccessColor = Color.FromArgb(103, 194, 58);
+            uiButton1.TabIndex = 11;
+            uiButton1.Text = "澧炲姞";
+            uiButton1.TextColor = Color.White;
+            uiButton1.WarningColor = Color.FromArgb(230, 162, 60);
+            uiButton1.Click += uiButton1_Click;
+            // 
+            // uiButton2
+            // 
+            uiButton2.BackColor = Color.FromArgb(45, 45, 48);
+            uiButton2.Cursor = Cursors.Hand;
+            uiButton2.Dock = DockStyle.Fill;
+            uiButton2.Font = new Font("瀹嬩綋", 12F);
+            uiButton2.ForeColor = Color.White;
+            uiButton2.HoverColor = Color.DodgerBlue;
+            uiButton2.Image = null;
+            uiButton2.Location = new Point(403, 3);
+            uiButton2.MinimumSize = new Size(1, 1);
+            uiButton2.Name = "uiButton2";
+            uiButton2.Size = new Size(94, 38);
+            uiButton2.TabIndex = 12;
+            uiButton2.Text = "娓呴櫎";
+            uiButton2.Click += uiButton2_Click;
+            // 
+            // uiFlowLayoutPanel1
+            // 
+            uiFlowLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            uiFlowLayoutPanel1.Dock = DockStyle.Fill;
+            uiFlowLayoutPanel1.Font = new Font("瀹嬩綋", 12F);
+            uiFlowLayoutPanel1.ForeColor = SystemColors.Control;
+            uiFlowLayoutPanel1.Location = new Point(4, 5);
+            uiFlowLayoutPanel1.Margin = new Padding(4, 5, 4, 5);
+            uiFlowLayoutPanel1.MinimumSize = new Size(1, 1);
+            uiFlowLayoutPanel1.Name = "uiFlowLayoutPanel1";
+            uiFlowLayoutPanel1.Padding = new Padding(2);
+            uiFlowLayoutPanel1.Size = new Size(599, 293);
+            uiFlowLayoutPanel1.TabIndex = 10;
+            uiFlowLayoutPanel1.Text = "`";
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.Controls.Add(uiFlowLayoutPanel1, 0, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 1);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 2;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.Size = new Size(607, 353);
+            tableLayoutPanel1.TabIndex = 13;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 6;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.Controls.Add(uiButton1, 5, 0);
+            tableLayoutPanel2.Controls.Add(uiButton2, 4, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 306);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 1;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(601, 44);
+            tableLayoutPanel2.TabIndex = 11;
+            // 
+            // CommunicatorsEditPage
+            // 
+            BackColor = Color.FromArgb(32, 41, 50);
+            Controls.Add(tableLayoutPanel1);
+            ForeColor = SystemColors.Control;
+            Name = "CommunicatorsEditPage";
+            Size = new Size(607, 353);
+            Paint += CommunicatorsEditPage_Paint;
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ReaLTaiizor.Controls.HopeButton uiButton1;
+        private ReaLTaiizor.Controls.LostButton uiButton2;
+        private FlowLayoutPanel uiFlowLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel2;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.cs b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.cs
new file mode 100644
index 0000000..30de3e4
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.cs
@@ -0,0 +1,211 @@
+锘�
+using LB_VisionControl;
+using LB_VisionProcesses.Communicators;
+using VisionControl.Forms;
+
+namespace LB_SmartVision.Forms.Pages.CommunicatorPage
+{
+    public partial class CommunicatorsEditPage : UserControl
+    {
+        public Action<string, LogInfoType> LogInfo;
+
+        public CommunicatorsEditPage()
+        {
+            InitializeComponent();
+
+            Name = "CommunicatorsPage";
+            Text = "閫氳璁剧疆";
+            //this.Font = new Font("Microsoft YaHei UI", 16F, FontStyle.Regular, GraphicsUnit.Point, 0);
+        }
+
+        private void CommunicatorsEditPage_Paint(object sender, PaintEventArgs e)
+        {
+            uiFlowLayoutPanel1.Controls.Clear();
+
+            if (GlobalVar.dicCommunicators.Count <= 0)
+                return;
+
+            foreach (var item in GlobalVar.dicCommunicators)
+            {
+                string ClassName = item.Value.GetType().Name;// "TCP"
+                string IP = item.Value.CommunicatorConnections["鍦板潃"].ToString();//"127.0.0.1"
+                string PORT = item.Value.CommunicatorConnections["绔彛"].ToString();//"1111"
+
+                if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT))
+                    return;
+
+                string CommunicatorConnectionString = $"({ClassName}){IP}:{PORT}";
+
+                UserItem flow = new UserItem(new string[] { "娴嬭瘯", "鍒锋柊", "绉婚櫎", "閲嶅懡鍚�" });
+                //flow.SetDPIScale();
+                flow.Name = item.Key;
+                flow.Text = CommunicatorConnectionString;
+                if (item.Value.bConnected)
+                    flow.state = State.Pass;
+                else
+                    flow.state = State.Error;
+                LoadFlowEvent(flow);
+
+                uiFlowLayoutPanel1.Controls.Add(flow);
+            }
+        }
+
+        private void uiButton1_Click(object sender, System.EventArgs e)
+        {
+            CreateCommunicatorForm createCommunicatorForm = new CreateCommunicatorForm();
+            createCommunicatorForm.ShowDialog();
+
+            if (createCommunicatorForm.bCreate)
+            {
+                BaseCommunicator communicator = createCommunicatorForm.communicator;
+                string Name = "閫氳鍙�" + GlobalVar.dicCommunicators.Count;
+                if (GlobalVar.dicCommunicators.ContainsKey(Name))
+                    Name += "鍓湰";
+
+                string ClassName = communicator.GetType().Name;// "TCP"
+                string IP = communicator.CommunicatorConnections["鍦板潃"].ToString();//"127.0.0.1"
+                string PORT = communicator.CommunicatorConnections["绔彛"].ToString();//"1111"
+
+                if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT))
+                    return;
+
+                string CommunicatorConnectionString = $"({ClassName}){IP}:{PORT}";
+
+                GlobalVar.dicCommunicators.TryAdd(Name, communicator);
+                communicator.CommunicatorName = Name;
+                LogInfo?.Invoke(string.Format("娣诲姞閫氳鍙{0}]鎴愬姛", Name), LogInfoType.PASS);
+            }
+            this.Invalidate();
+        }
+
+        private void uiButton2_Click(object sender, System.EventArgs e)
+        {
+            //娓呴櫎鐢–lear鏂规硶
+            uiFlowLayoutPanel1.Controls.Clear();
+            foreach (var communicator in GlobalVar.dicCommunicators.Values)
+            {
+                communicator.Disconnect();
+            }
+            GlobalVar.dicCommunicators.Clear();
+            this.Refresh();
+        }
+
+        private void LoadFlowEvent(UserItem flow)
+        {
+            //鎸夐敭1涓烘祴璇�
+            flow.MenuItem1ClickedEvent += TestEvent;
+            //鎸夐敭2涓哄埛鏂�
+            flow.MenuItem2ClickedEvent += ReconnectEvent;
+            //鎸夐敭3涓虹Щ闄�
+            flow.MenuItem3ClickedEvent += DeleteEvent;
+            //鎸夐敭4涓洪噸鍛藉悕
+            flow.MenuItem4ClickedEvent += RenameEvent;
+        }
+
+        private void RemoveFlowEvent(UserItem flow)
+        {
+            //鎸夐敭1涓烘祴璇�
+            flow.MenuItem1ClickedEvent -= TestEvent;
+            //鎸夐敭2涓哄埛鏂�
+            flow.MenuItem2ClickedEvent -= ReconnectEvent;
+            //鎸夐敭3涓虹Щ闄�
+            flow.MenuItem3ClickedEvent -= DeleteEvent;
+            //鎸夐敭4涓洪噸鍛藉悕
+            flow.MenuItem4ClickedEvent -= RenameEvent;
+        }
+
+        // 娴嬭瘯閫氳鍙�
+        private void TestEvent(string Name, string Text)
+        {
+            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+            {
+                UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                string name = flow.Name;
+                if (name != Name)
+                    continue;
+
+                if (GlobalVar.dicCommunicators.ContainsKey(name))
+                {
+                    CommunicatorForm cameraForm = new CommunicatorForm(GlobalVar.dicCommunicators[name], name);
+                    cameraForm.Show();
+                }
+            }
+        }
+
+        // 绉婚櫎閫氳鍙�
+        private void DeleteEvent(string Name, string Text)
+        {
+            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+            {
+                UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                string name = flow.Name;
+                if (name != Name)
+                    continue;
+
+                RemoveFlowEvent(flow);
+                uiFlowLayoutPanel1.Controls.Remove(uiFlowLayoutPanel1.Controls[i]);
+                GlobalVar.dicCommunicators.TryRemove(name, out BaseCommunicator BaseCommunicator);
+                if (BaseCommunicator != null)
+                    LogInfo?.Invoke(string.Format("绉婚櫎閫氳鍙{0}]", name), LogInfoType.INFO);
+            }
+        }
+
+        private void RenameEvent(string Name, string Text)
+        {
+            RenameForm renameForm = new RenameForm(Name);
+            // 璁㈤槄浜嬩欢
+            renameForm.ShowDialog();
+            if (!renameForm.bRename)
+                return;
+
+            if (GlobalVar.dicCommunicators.ContainsKey(renameForm.strNewName))
+            {
+                MessageBox.Show("鍛藉悕閲嶅!", "寮傚父");
+                return;
+            }
+
+            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+            {
+                UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                string name = flow.Name;
+                if (name != Name)
+                    continue;
+                flow.Name = renameForm.strNewName;
+                string oldName = name;
+                string newName = renameForm.strNewName;
+
+                if (GlobalVar.dicCommunicators.ContainsKey(oldName))
+                    GlobalVar.dicCommunicators.TryRename(oldName, newName);
+
+                flow.Refresh();
+            }
+        }
+
+        // 閲嶈繛娴佺▼
+        private void ReconnectEvent(string Name, string Text)
+        {
+            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+            {
+                UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                string name = flow.Name;
+                if (name != Name)
+                    continue;
+
+                GlobalVar.dicCommunicators[name].Disconnect();
+                Thread.Sleep(50);
+                GlobalVar.dicCommunicators[name].Connect();
+                if (GlobalVar.dicCommunicators[name].bConnected)
+                {
+                    flow.state = State.Pass;
+                    LogInfo?.Invoke(string.Format("閲嶈繛閫氳鍙{0}]鎴愬姛", name), LogInfoType.PASS);
+                }
+                else
+                {
+                    flow.state = State.Error;
+                    LogInfo?.Invoke(string.Format("閲嶈繛閫氳鍙{0}]澶辫触", name), LogInfoType.ERROR);
+                }
+                flow.Refresh();
+            }
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.resx b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.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/LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.Designer.cs b/LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.Designer.cs
new file mode 100644
index 0000000..5eb648d
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.Designer.cs
@@ -0,0 +1,251 @@
+锘縩amespace LB_SmartVision.Forms.Pages.CommunicatorPage
+{
+    partial class CreateCommunicatorForm
+    {
+        /// <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()
+        {
+            uiLabelIP = new Label();
+            uiLabelPort = new Label();
+            uiButtonCancel = new Button();
+            uiTextBoxPort = new TextBox();
+            rButtonUART = new RadioButton();
+            rButtonTCPServer = new RadioButton();
+            rButtonTCPClient = new RadioButton();
+            uiButtonCreate = new Button();
+            uiButtonTest = new Button();
+            uiComboBoxPort = new ComboBox();
+            uiIPTextBox = new TextBox();
+            uiTextBoxPath = new TextBox();
+            rButtonMonitor = new RadioButton();
+            SuspendLayout();
+            // 
+            // uiLabelIP
+            // 
+            uiLabelIP.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            uiLabelIP.ForeColor = Color.FromArgb(48, 48, 48);
+            uiLabelIP.Location = new Point(84, 111);
+            uiLabelIP.Name = "uiLabelIP";
+            uiLabelIP.Size = new Size(100, 23);
+            uiLabelIP.TabIndex = 1;
+            uiLabelIP.Text = "鍦板潃";
+            // 
+            // uiLabelPort
+            // 
+            uiLabelPort.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            uiLabelPort.ForeColor = Color.FromArgb(48, 48, 48);
+            uiLabelPort.Location = new Point(84, 177);
+            uiLabelPort.Name = "uiLabelPort";
+            uiLabelPort.Size = new Size(100, 23);
+            uiLabelPort.TabIndex = 2;
+            uiLabelPort.Text = "绔彛";
+            // 
+            // uiButtonCancel
+            // 
+            uiButtonCancel.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            uiButtonCancel.Location = new Point(343, 234);
+            uiButtonCancel.MinimumSize = new Size(1, 1);
+            uiButtonCancel.Name = "uiButtonCancel";
+            uiButtonCancel.Size = new Size(100, 35);
+            uiButtonCancel.TabIndex = 4;
+            uiButtonCancel.Text = "鍙栨秷";
+            uiButtonCancel.Click += uiButtonCancel_Click;
+            // 
+            // uiTextBoxPort
+            // 
+            uiTextBoxPort.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            uiTextBoxPort.Location = new Point(191, 175);
+            uiTextBoxPort.Margin = new Padding(4, 5, 4, 5);
+            uiTextBoxPort.MinimumSize = new Size(1, 16);
+            uiTextBoxPort.Name = "uiTextBoxPort";
+            uiTextBoxPort.Padding = new Padding(5);
+            //uiTextBoxPort.ShowText = false;
+            uiTextBoxPort.Size = new Size(205, 29);
+            uiTextBoxPort.TabIndex = 5;
+            //uiTextBoxPort.TextAlignment = ContentAlignment.MiddleLeft;
+            //uiTextBoxPort.Watermark = "";
+            uiTextBoxPort.TextChanged += uiTextBoxPort_TextChanged;
+            // 
+            // rButtonUART
+            // 
+            rButtonUART.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            rButtonUART.Location = new Point(51, 12);
+            rButtonUART.MinimumSize = new Size(1, 1);
+            rButtonUART.Name = "rButtonUART";
+            rButtonUART.Size = new Size(150, 29);
+            rButtonUART.TabIndex = 6;
+            rButtonUART.Text = "涓插彛閫氳";
+            rButtonUART.CheckedChanged += rButtonUART_CheckedChanged;
+            // 
+            // rButtonTCPServer
+            // 
+            rButtonTCPServer.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            rButtonTCPServer.Location = new Point(51, 47);
+            rButtonTCPServer.MinimumSize = new Size(1, 1);
+            rButtonTCPServer.Name = "rButtonTCPServer";
+            rButtonTCPServer.Size = new Size(150, 29);
+            rButtonTCPServer.TabIndex = 7;
+            rButtonTCPServer.Text = "TCP鏈嶅姟鍣�";
+            rButtonTCPServer.CheckedChanged += rButtonTCPServer_CheckedChanged;
+            // 
+            // rButtonTCPClient
+            // 
+            rButtonTCPClient.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            rButtonTCPClient.Location = new Point(293, 47);
+            rButtonTCPClient.MinimumSize = new Size(1, 1);
+            rButtonTCPClient.Name = "rButtonTCPClient";
+            rButtonTCPClient.Size = new Size(150, 29);
+            rButtonTCPClient.TabIndex = 8;
+            rButtonTCPClient.Text = "TCP瀹㈡埛绔�";
+            rButtonTCPClient.CheckedChanged += rButtonTCPClient_CheckedChanged;
+            // 
+            // uiButtonCreate
+            // 
+            uiButtonCreate.Enabled = false;
+            uiButtonCreate.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            uiButtonCreate.Location = new Point(191, 234);
+            uiButtonCreate.MinimumSize = new Size(1, 1);
+            uiButtonCreate.Name = "uiButtonCreate";
+            uiButtonCreate.Size = new Size(100, 35);
+            uiButtonCreate.TabIndex = 9;
+            uiButtonCreate.Text = "鍒涘缓";
+            uiButtonCreate.Click += uiButtonCreate_Click;
+            // 
+            // uiButtonTest
+            // 
+            uiButtonTest.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            uiButtonTest.Location = new Point(31, 234);
+            uiButtonTest.MinimumSize = new Size(1, 1);
+            uiButtonTest.Name = "uiButtonTest";
+            uiButtonTest.Size = new Size(100, 35);
+            uiButtonTest.TabIndex = 10;
+            uiButtonTest.Text = "娴嬭瘯";
+            uiButtonTest.Click += uiButtonTest_Click;
+            // 
+            // uiComboBoxPort
+            // 
+            uiComboBoxPort.DataSource = null;
+            //uiComboBoxPort.FillColor = Color.White;
+            uiComboBoxPort.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            //uiComboBoxPort.ItemHoverColor = Color.FromArgb(155, 200, 255);
+            //uiComboBoxPort.ItemSelectForeColor = Color.FromArgb(235, 243, 255);
+            uiComboBoxPort.Location = new Point(191, 108);
+            uiComboBoxPort.Margin = new Padding(4, 5, 4, 5);
+            uiComboBoxPort.MinimumSize = new Size(63, 0);
+            uiComboBoxPort.Name = "uiComboBoxPort";
+            uiComboBoxPort.Padding = new Padding(0, 0, 30, 2);
+            uiComboBoxPort.Size = new Size(205, 29);
+            //uiComboBoxPort.SymbolSize = 24;
+            uiComboBoxPort.TabIndex = 11;
+            //uiComboBoxPort.TextAlignment = ContentAlignment.MiddleLeft;
+            //uiComboBoxPort.Watermark = "";
+            uiComboBoxPort.MouseClick += uiComboBoxPort_MouseClick;
+            // 
+            // uiIPTextBox
+            // 
+            //uiIPTextBox.FillColor2 = Color.FromArgb(235, 243, 255);
+            uiIPTextBox.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            uiIPTextBox.Location = new Point(191, 108);
+            uiIPTextBox.Margin = new Padding(4, 5, 4, 5);
+            uiIPTextBox.MinimumSize = new Size(1, 1);
+            uiIPTextBox.Name = "uiIPTextBox";
+            uiIPTextBox.Padding = new Padding(1);
+            //uiIPTextBox.ShowText = false;
+            uiIPTextBox.Size = new Size(205, 29);
+            uiIPTextBox.TabIndex = 12;
+            //uiIPTextBox.TextAlignment = ContentAlignment.MiddleCenter;
+            uiIPTextBox.MouseClick += uiIPTextBox_MouseClick;
+            // 
+            // uiTextBoxPath
+            // 
+            uiTextBoxPath.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            uiTextBoxPath.Location = new Point(191, 108);
+            uiTextBoxPath.Margin = new Padding(4, 5, 4, 5);
+            uiTextBoxPath.MinimumSize = new Size(1, 16);
+            uiTextBoxPath.Name = "uiTextBoxPath";
+            uiTextBoxPath.Padding = new Padding(5);
+            //uiTextBoxPath.ShowText = false;
+            uiTextBoxPath.Size = new Size(205, 29);
+            uiTextBoxPath.TabIndex = 13;
+            //uiTextBoxPath.TextAlignment = ContentAlignment.MiddleLeft;
+            //uiTextBoxPath.Watermark = "";
+            // 
+            // rButtonMonitor
+            // 
+            rButtonMonitor.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point);
+            rButtonMonitor.Location = new Point(293, 12);
+            rButtonMonitor.MinimumSize = new Size(1, 1);
+            rButtonMonitor.Name = "rButtonMonitor";
+            rButtonMonitor.Size = new Size(150, 29);
+            rButtonMonitor.TabIndex = 14;
+            rButtonMonitor.Text = "鏈湴鐩戞帶";
+            rButtonMonitor.CheckedChanged += rButtonMonitor_CheckedChanged;
+            // 
+            // CreateCommunicatorForm
+            // 
+            //AllowShowTitle = false;
+            AutoScaleMode = AutoScaleMode.None;
+            ClientSize = new Size(484, 285);
+            ControlBox = false;
+            Controls.Add(rButtonMonitor);
+            Controls.Add(uiTextBoxPath);
+            Controls.Add(uiIPTextBox);
+            Controls.Add(uiComboBoxPort);
+            Controls.Add(uiTextBoxPort);
+            Controls.Add(uiButtonTest);
+            Controls.Add(uiButtonCreate);
+            Controls.Add(rButtonTCPClient);
+            Controls.Add(rButtonTCPServer);
+            Controls.Add(rButtonUART);
+            Controls.Add(uiButtonCancel);
+            Controls.Add(uiLabelPort);
+            Controls.Add(uiLabelIP);
+            MaximizeBox = false;
+            MinimizeBox = false;
+            Name = "CreateCommunicatorForm";
+            Padding = new Padding(0);
+            //ShowTitle = false;
+            Text = "鍒涘缓閫氳";
+            //ZoomScaleRect = new Rectangle(15, 15, 800, 450);
+            ResumeLayout(false);
+        }
+
+        #endregion
+        private Label uiLabelIP;
+        private Label uiLabelPort;
+        private Button uiButtonCancel;
+        private TextBox uiTextBoxPort;
+        private RadioButton rButtonUART;
+        private RadioButton rButtonTCPServer;
+        private RadioButton rButtonTCPClient;
+        private Button uiButtonCreate;
+        private Button uiButtonTest;
+        private ComboBox uiComboBoxPort;
+        private TextBox uiIPTextBox;
+        private TextBox uiTextBoxPath;
+        private RadioButton rButtonMonitor;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.cs b/LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.cs
new file mode 100644
index 0000000..0865a23
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.cs
@@ -0,0 +1,223 @@
+锘縰sing LB_VisionProcesses.Communicators;
+using LB_VisionProcesses.Communicators.TCom;
+using RJCP.IO.Ports;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO.Ports;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.CommunicatorPage
+{
+    public partial class CreateCommunicatorForm : Form
+    {
+        public BaseCommunicator communicator { get; set; }
+
+        public bool bCreate = false;
+
+        public CreateCommunicatorForm(BaseCommunicator communicator = null)
+        {
+            InitializeComponent();
+            // 绂佹淇敼绐楀彛澶у皬
+            this.FormBorderStyle = FormBorderStyle.FixedDialog;
+            if (communicator == null)
+                communicator = new UARTPort();
+
+            rButtonUART.Checked = true;
+            uiButtonCreate.Enabled = false;
+        }
+
+        private void uiButtonTest_Click(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+
+            rButtonUART.Enabled = false;
+            rButtonTCPServer.Enabled = false;
+            rButtonTCPClient.Enabled = false;
+            rButtonMonitor.Enabled = false;
+
+            if (communicator != null)
+                communicator.Disconnect();
+
+            if (rButtonUART.Checked)
+            {
+                communicator = new UARTPort();
+
+                IP = uiComboBoxPort.Text;
+                PORT = uiTextBoxPort.Text;
+            }
+            else if (rButtonTCPServer.Checked)
+            {
+                communicator = new TCPServer();
+
+                IP = uiIPTextBox.Text;
+                PORT = uiTextBoxPort.Text;
+            }
+            else if (rButtonTCPClient.Checked)
+            {
+                communicator = new TCPClient();
+
+                IP = uiIPTextBox.Text;
+                PORT = uiTextBoxPort.Text;
+            }
+            else if (rButtonMonitor.Checked)
+            {
+                communicator = new LocalMonitor();
+
+                IP = uiTextBoxPath.Text;
+                PORT = uiTextBoxPort.Text;
+            }
+            else
+            {
+                MessageBox.Show("鏈�夋嫨閫氳绫诲瀷!", "寮傚父");
+                return;
+            }
+
+            communicator.CommunicatorConnections.Add("鍦板潃", IP);
+            communicator.CommunicatorConnections.Add("绔彛", PORT);
+            if (communicator.Connect())
+            {
+                uiButtonCreate.Enabled = true;
+                communicator.Disconnect();
+            }
+            else
+                MessageBox.Show($"鍒濆鍖栭�氳鍙eけ璐�,鍘熷洜鏄�:{communicator.Msg}", "寮傚父");
+        }
+
+        public string IP = string.Empty;
+        public string PORT = string.Empty;
+
+        private void uiButtonCreate_Click(object sender, EventArgs e)
+        {
+            if (communicator.Connect())
+            {
+                bCreate = true;
+                this.Close();
+            }
+            else
+                MessageBox.Show($"鍒濆鍖栭�氳鍙eけ璐�,鍘熷洜鏄�:{communicator.Msg}", "寮傚父");
+        }
+
+        private void uiButtonCancel_Click(object sender, EventArgs e)
+        {
+            if (communicator != null)
+                communicator.Disconnect();
+
+            bCreate = false;
+            this.Close();
+        }
+
+        private void rButtonUART_CheckedChanged(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+            if (communicator != null)
+                communicator.Disconnect();
+
+            if (rButtonUART.Checked)
+            {
+                uiLabelIP.Visible = true;
+                uiLabelIP.Text = "COM鍙�";
+                uiIPTextBox.Visible = false;
+                uiComboBoxPort.Visible = true;
+                uiTextBoxPath.Visible = false;
+
+                uiLabelPort.Visible = true;
+                uiLabelPort.Text = "娉㈢壒鐜�";
+                uiTextBoxPort.Visible = true;
+
+                uiButtonCreate.Enabled = false;
+            }
+        }
+
+        private void rButtonTCPServer_CheckedChanged(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+            if (communicator != null)
+                communicator.Disconnect();
+
+            if (rButtonTCPServer.Checked)
+            {
+                uiLabelIP.Visible = true;
+                uiLabelIP.Text = "鍦板潃";
+                uiIPTextBox.Visible = true;
+                uiComboBoxPort.Visible = false;
+                uiTextBoxPath.Visible = false;
+
+                uiLabelPort.Visible = true;
+                uiLabelPort.Text = "绔彛";
+                uiTextBoxPort.Visible = true;
+
+                uiButtonCreate.Enabled = false;
+            }
+        }
+
+        private void rButtonTCPClient_CheckedChanged(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+            if (communicator != null)
+                communicator.Disconnect();
+
+            if (rButtonTCPClient.Checked)
+            {
+                uiLabelIP.Visible = true;
+                uiLabelIP.Text = "鍦板潃";
+                uiIPTextBox.Visible = true;
+                uiComboBoxPort.Visible = false;
+                uiTextBoxPath.Visible = false;
+
+                uiLabelPort.Visible = true;
+                uiLabelPort.Text = "绔彛";
+                uiTextBoxPort.Visible = true;
+            }
+        }
+
+        private void rButtonMonitor_CheckedChanged(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+            if (communicator != null)
+                communicator.Disconnect();
+
+            if (rButtonMonitor.Checked)
+            {
+                uiLabelIP.Visible = true;
+                uiLabelIP.Text = "鐩戞帶鏂囦欢";
+                uiIPTextBox.Visible = false;
+                uiComboBoxPort.Visible = false;
+                uiTextBoxPath.Visible = true;
+
+                uiLabelPort.Visible = true;
+                uiLabelPort.Text = "鍐欏叆鏂囦欢";
+                uiTextBoxPort.Visible = true;
+            }
+        }
+
+        private void uiComboBoxPort_MouseClick(object sender, MouseEventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+            uiComboBoxPort.Text = string.Empty;
+
+            uiComboBoxPort.Items.Clear();
+            //缁熻鍙敤绔彛
+            SerialPortStream temp = new SerialPortStream();
+            string[] ArryPort = temp.GetPortNames();
+            for (int i = 0; i < ArryPort.Length; i++)
+                uiComboBoxPort.Items.Add(ArryPort[i]);
+        }
+
+        private void uiTextBoxPort_TextChanged(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+        }
+
+        private void uiIPTextBox_MouseClick(object sender, MouseEventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.resx b/LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CreateCommunicatorForm.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/LB_SmartVision/Forms/Pages/MESPage/MESEditPage.Designer.cs b/LB_SmartVision/Forms/Pages/MESPage/MESEditPage.Designer.cs
new file mode 100644
index 0000000..f61ac14
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/MESPage/MESEditPage.Designer.cs
@@ -0,0 +1,152 @@
+锘�
+using ReaLTaiizor.Controls;
+
+namespace LB_SmartVision.Forms.Pages.MESPage
+{
+    partial class MESEditPage
+    {
+        /// <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()
+        {
+            uiButton1 = new HopeButton();
+            uiButton2 = new LostButton();
+            uiFlowLayoutPanel1 = new FlowLayoutPanel();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            SuspendLayout();
+            // 
+            // uiButton1
+            // 
+            uiButton1.BorderColor = Color.FromArgb(220, 223, 230);
+            uiButton1.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            uiButton1.Cursor = Cursors.Hand;
+            uiButton1.DangerColor = Color.FromArgb(245, 108, 108);
+            uiButton1.DefaultColor = Color.FromArgb(255, 255, 255);
+            uiButton1.Dock = DockStyle.Fill;
+            uiButton1.Font = new Font("瀹嬩綋", 12F);
+            uiButton1.HoverTextColor = Color.FromArgb(48, 49, 51);
+            uiButton1.InfoColor = Color.FromArgb(144, 147, 153);
+            uiButton1.Location = new Point(503, 3);
+            uiButton1.MinimumSize = new Size(1, 1);
+            uiButton1.Name = "uiButton1";
+            uiButton1.PrimaryColor = Color.FromArgb(64, 158, 255);
+            uiButton1.Size = new Size(95, 38);
+            uiButton1.SuccessColor = Color.FromArgb(103, 194, 58);
+            uiButton1.TabIndex = 11;
+            uiButton1.Text = "澧炲姞";
+            uiButton1.TextColor = Color.White;
+            uiButton1.WarningColor = Color.FromArgb(230, 162, 60);
+            // 
+            // uiButton2
+            // 
+            uiButton2.BackColor = Color.FromArgb(45, 45, 48);
+            uiButton2.Cursor = Cursors.Hand;
+            uiButton2.Dock = DockStyle.Fill;
+            uiButton2.Font = new Font("瀹嬩綋", 12F);
+            uiButton2.ForeColor = Color.White;
+            uiButton2.HoverColor = Color.DodgerBlue;
+            uiButton2.Image = null;
+            uiButton2.Location = new Point(403, 3);
+            uiButton2.MinimumSize = new Size(1, 1);
+            uiButton2.Name = "uiButton2";
+            uiButton2.Size = new Size(94, 38);
+            uiButton2.TabIndex = 12;
+            uiButton2.Text = "娓呴櫎";
+            // 
+            // uiFlowLayoutPanel1
+            // 
+            uiFlowLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            uiFlowLayoutPanel1.Dock = DockStyle.Fill;
+            uiFlowLayoutPanel1.Font = new Font("瀹嬩綋", 12F);
+            uiFlowLayoutPanel1.ForeColor = SystemColors.Control;
+            uiFlowLayoutPanel1.Location = new Point(4, 5);
+            uiFlowLayoutPanel1.Margin = new Padding(4, 5, 4, 5);
+            uiFlowLayoutPanel1.MinimumSize = new Size(1, 1);
+            uiFlowLayoutPanel1.Name = "uiFlowLayoutPanel1";
+            uiFlowLayoutPanel1.Padding = new Padding(2);
+            uiFlowLayoutPanel1.Size = new Size(599, 293);
+            uiFlowLayoutPanel1.TabIndex = 10;
+            uiFlowLayoutPanel1.Text = "`";
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.Controls.Add(uiFlowLayoutPanel1, 0, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 1);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 2;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.Size = new Size(607, 353);
+            tableLayoutPanel1.TabIndex = 13;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 6;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.Controls.Add(uiButton1, 5, 0);
+            tableLayoutPanel2.Controls.Add(uiButton2, 4, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.ForeColor = SystemColors.Control;
+            tableLayoutPanel2.Location = new Point(3, 306);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 1;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(601, 44);
+            tableLayoutPanel2.TabIndex = 11;
+            // 
+            // MESEditPage
+            // 
+            BackColor = Color.FromArgb(32, 41, 50);
+            Controls.Add(tableLayoutPanel1);
+            Name = "MESEditPage";
+            Size = new Size(607, 353);
+            Paint += MESEditPage_Paint;
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ReaLTaiizor.Controls.HopeButton uiButton1;
+        private ReaLTaiizor.Controls.LostButton uiButton2;
+        private FlowLayoutPanel uiFlowLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel2;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/MESPage/MESEditPage.cs b/LB_SmartVision/Forms/Pages/MESPage/MESEditPage.cs
new file mode 100644
index 0000000..cd8f822
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/MESPage/MESEditPage.cs
@@ -0,0 +1,30 @@
+锘縰sing LB_VisionControl;
+using OpenCvSharp.Flann;
+using System;
+using System.Collections.Concurrent;
+using System.Windows.Forms;
+using System.Xml.Linq;
+
+namespace LB_SmartVision.Forms.Pages.MESPage
+{
+    public partial class MESEditPage : UserControl
+    {
+        public Action<string, LogInfoType> LogInfo;
+
+
+        public MESEditPage()
+        {
+            InitializeComponent();
+
+            Name = "MESEditPage";
+            Text = "MES璁剧疆";
+        }
+
+        private void MESEditPage_Paint(object sender, PaintEventArgs e)
+        {
+            uiFlowLayoutPanel1.Controls.Clear();
+        }
+
+
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/MESPage/MESEditPage.resx b/LB_SmartVision/Forms/Pages/MESPage/MESEditPage.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/MESPage/MESEditPage.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/LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.Designer.cs b/LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.Designer.cs
new file mode 100644
index 0000000..b13a7da
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.Designer.cs
@@ -0,0 +1,152 @@
+锘�
+using ReaLTaiizor.Controls;
+
+namespace LB_SmartVision.Forms.Pages.MotionControlPage
+{
+    partial class MotionControlEditPage
+    {
+        /// <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()
+        {
+            uiButton1 = new HopeButton();
+            uiButton2 = new LostButton();
+            uiFlowLayoutPanel1 = new FlowLayoutPanel();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            SuspendLayout();
+            // 
+            // uiButton1
+            // 
+            uiButton1.BorderColor = Color.FromArgb(220, 223, 230);
+            uiButton1.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            uiButton1.Cursor = Cursors.Hand;
+            uiButton1.DangerColor = Color.FromArgb(245, 108, 108);
+            uiButton1.DefaultColor = Color.FromArgb(255, 255, 255);
+            uiButton1.Dock = DockStyle.Fill;
+            uiButton1.Font = new Font("瀹嬩綋", 12F);
+            uiButton1.HoverTextColor = Color.FromArgb(48, 49, 51);
+            uiButton1.InfoColor = Color.FromArgb(144, 147, 153);
+            uiButton1.Location = new Point(503, 3);
+            uiButton1.MinimumSize = new Size(1, 1);
+            uiButton1.Name = "uiButton1";
+            uiButton1.PrimaryColor = Color.FromArgb(64, 158, 255);
+            uiButton1.Size = new Size(95, 38);
+            uiButton1.SuccessColor = Color.FromArgb(103, 194, 58);
+            uiButton1.TabIndex = 11;
+            uiButton1.Text = "澧炲姞";
+            uiButton1.TextColor = Color.White;
+            uiButton1.WarningColor = Color.FromArgb(230, 162, 60);
+            // 
+            // uiButton2
+            // 
+            uiButton2.BackColor = Color.FromArgb(45, 45, 48);
+            uiButton2.Cursor = Cursors.Hand;
+            uiButton2.Dock = DockStyle.Fill;
+            uiButton2.Font = new Font("瀹嬩綋", 12F);
+            uiButton2.ForeColor = Color.White;
+            uiButton2.HoverColor = Color.DodgerBlue;
+            uiButton2.Image = null;
+            uiButton2.Location = new Point(403, 3);
+            uiButton2.MinimumSize = new Size(1, 1);
+            uiButton2.Name = "uiButton2";
+            uiButton2.Size = new Size(94, 38);
+            uiButton2.TabIndex = 12;
+            uiButton2.Text = "娓呴櫎";
+            // 
+            // uiFlowLayoutPanel1
+            // 
+            uiFlowLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            uiFlowLayoutPanel1.Dock = DockStyle.Fill;
+            uiFlowLayoutPanel1.Font = new Font("瀹嬩綋", 12F);
+            uiFlowLayoutPanel1.ForeColor = SystemColors.Control;
+            uiFlowLayoutPanel1.Location = new Point(4, 5);
+            uiFlowLayoutPanel1.Margin = new Padding(4, 5, 4, 5);
+            uiFlowLayoutPanel1.MinimumSize = new Size(1, 1);
+            uiFlowLayoutPanel1.Name = "uiFlowLayoutPanel1";
+            uiFlowLayoutPanel1.Padding = new Padding(2);
+            uiFlowLayoutPanel1.Size = new Size(599, 293);
+            uiFlowLayoutPanel1.TabIndex = 10;
+            uiFlowLayoutPanel1.Text = "`";
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.Controls.Add(uiFlowLayoutPanel1, 0, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 1);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 2;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.Size = new Size(607, 353);
+            tableLayoutPanel1.TabIndex = 13;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 6;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.Controls.Add(uiButton1, 5, 0);
+            tableLayoutPanel2.Controls.Add(uiButton2, 4, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 306);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 1;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(601, 44);
+            tableLayoutPanel2.TabIndex = 11;
+            // 
+            // MotionControlEditPage
+            // 
+            BackColor = Color.FromArgb(32, 41, 50);
+            Controls.Add(tableLayoutPanel1);
+            ForeColor = SystemColors.Control;
+            Name = "MotionControlEditPage";
+            Size = new Size(607, 353);
+            Paint += MESEditPage_Paint;
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ReaLTaiizor.Controls.HopeButton uiButton1;
+        private ReaLTaiizor.Controls.LostButton uiButton2;
+        private FlowLayoutPanel uiFlowLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel2;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.cs b/LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.cs
new file mode 100644
index 0000000..6ef3551
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.cs
@@ -0,0 +1,30 @@
+锘縰sing LB_VisionControl;
+using OpenCvSharp.Flann;
+using System;
+using System.Collections.Concurrent;
+using System.Windows.Forms;
+using System.Xml.Linq;
+
+namespace LB_SmartVision.Forms.Pages.MotionControlPage
+{
+    public partial class MotionControlEditPage : UserControl
+    {
+        public Action<string, LogInfoType> LogInfo;
+
+
+        public MotionControlEditPage()
+        {
+            InitializeComponent();
+
+            Name = "MotionControlEditPage";
+            Text = "杩愬姩鎺у埗璁剧疆";
+        }
+
+        private void MESEditPage_Paint(object sender, PaintEventArgs e)
+        {
+            uiFlowLayoutPanel1.Controls.Clear();
+        }
+
+
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.resx b/LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlEditPage.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/LB_SmartVision/Forms/Pages/MyPage.cs b/LB_SmartVision/Forms/Pages/MyPage.cs
new file mode 100644
index 0000000..9e5398c
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/MyPage.cs
@@ -0,0 +1,32 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages
+{
+    public class MyPage : TabPage
+    {
+        public UserControl UserControl;
+
+        public MyPage()
+        {
+            UserControl = new UserControl();
+            UserControl.Dock = DockStyle.Fill;
+            Name = "UserControl";
+            Text = "鐢ㄦ埛鎺т欢";
+            this.Controls.Add(UserControl);
+        }
+
+        public MyPage(UserControl _userControl)
+        {
+            this.UserControl = _userControl;
+            this.UserControl.Dock = DockStyle.Fill;
+            Name = _userControl.Name;
+            Text = _userControl.Text;
+            this.Controls.Add(this.UserControl);
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/MyPage.resx b/LB_SmartVision/Forms/Pages/MyPage.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/MyPage.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/LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.Designer.cs b/LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.Designer.cs
new file mode 100644
index 0000000..8545ca1
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.Designer.cs
@@ -0,0 +1,56 @@
+锘縩amespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    partial class AllProcessesPage
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            controlsPanel = new Panel();
+            SuspendLayout();
+            // 
+            // controlsPanel
+            // 
+            controlsPanel.Dock = DockStyle.Fill;
+            controlsPanel.Location = new Point(0, 0);
+            controlsPanel.Name = "controlsPanel";
+            controlsPanel.Size = new Size(803, 478);
+            controlsPanel.TabIndex = 0;
+            // 
+            // AllProcessesPage
+            // 
+            //AutoScaleDimensions = new SizeF(7F, 17F);
+            //AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(controlsPanel);
+            Name = "AllProcessesPage";
+            Size = new Size(803, 478);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        public Panel controlsPanel;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.cs b/LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.cs
new file mode 100644
index 0000000..01ab907
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.cs
@@ -0,0 +1,105 @@
+锘縰sing HalconDotNet;
+using LB_SmartVision.Tool;
+using System.Data;
+using System.Runtime.InteropServices;
+using System.Xml.Linq;
+
+namespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    public partial class AllProcessesPage : TabPage
+    {
+        public ObservableConcurrentDictionary<string, ProcessControl> dicProcessControls = new ObservableConcurrentDictionary<string, ProcessControl>();
+
+        /// <summary>
+        /// 瀹炰緥鍖栨祦绋嬬晫闈�
+        /// </summary>
+        /// <param name="dicProcesses"></param>
+        public AllProcessesPage()
+        {
+            InitializeComponent();
+
+            Name = "AllProcessesPage";
+            Text = "涓荤晫闈�";
+            //this.Font = new Font("Microsoft YaHei UI", 16F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            this.BackColor = Color.FromArgb(32, 41, 50);
+
+            InitVisionUI();
+            this.Invalidated += AllProcessesPage_Invalidated;
+        }
+
+        private void AllProcessesPage_Invalidated(object? sender, InvalidateEventArgs e) => InitVisionUI();
+
+        public void InitVisionUI()
+        {
+            List<string> keys = dicProcessControls.Keys.ToList();
+
+            foreach (var title in keys)
+            {
+                bool isExist = false;
+                foreach (var layout in GlobalVar.dicLayout.Values)
+                {
+                    if (layout.Title == title)
+                    {
+                        isExist = true;
+                        break;
+                    }
+                }
+
+                if (!isExist)
+                {
+                    if (dicProcessControls.ContainsKey(title))
+                    {
+                        this.controlsPanel.Controls.Remove(dicProcessControls[title]);
+                        dicProcessControls.TryRemove(title, out _);
+                    }
+                }
+            }
+
+            int enableLayout = 0;
+            foreach (var layout in GlobalVar.dicLayout.Values)
+            {
+                if (GlobalVar.dicProcesses.ContainsKey(layout.ProcessName))
+                    enableLayout++;
+            }
+
+            int index = 0;
+            for (int i = 0; i < GlobalVar.dicLayout.Count; i++)
+            {
+                string name = GlobalVar.dicLayout[i].ProcessName;
+                string title = GlobalVar.dicLayout[i].Title;
+                if (GlobalVar.dicProcesses.ContainsKey(name))
+                {
+                    if (dicProcessControls.ContainsKey(title))
+                    {
+                        ProcessControl processControl = dicProcessControls[title];
+                        processControl.Size
+                            = new Size(this.controlsPanel.Size.Width / enableLayout
+                            , this.controlsPanel.Size.Height);
+                        processControl.Location
+                            = new Point(processControl.Size.Width * index, 0);
+
+                        if (GlobalVar.dicProcesses[name].GetImage(GlobalVar.dicLayout[i], out _, out HObject RecordImage))
+                            dicProcessControls[title].ShowHoImage(RecordImage);
+                    }
+                    else
+                    {
+                        ProcessControl processControl = new ProcessControl(GlobalVar.dicLayout[i]);
+                        processControl.Size
+                            = new Size(this.controlsPanel.Size.Width / enableLayout
+                            , this.controlsPanel.Size.Height);
+                        processControl.Location
+                            = new Point(processControl.Size.Width * index, 0);
+                        processControl.SetTitle(title);
+
+                        dicProcessControls.TryAdd(title, processControl);
+                        this.controlsPanel.Controls.Add(processControl);
+
+                        if (GlobalVar.dicProcesses[name].GetImage(GlobalVar.dicLayout[i], out _, out HObject RecordImage))
+                            dicProcessControls[title].ShowHoImage(RecordImage);
+                    }
+                    index++;
+                }
+            }
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.resx b/LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.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/LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.Designer.cs b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.Designer.cs
new file mode 100644
index 0000000..b43b520
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.Designer.cs
@@ -0,0 +1,164 @@
+锘縩amespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    partial class ProcessControl
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            toolStrip1 = new ToolStrip();
+            lblTitle = new ToolStripLabel();
+            btnRun = new ToolStripButton();
+            btnCircleRun = new ToolStripButton();
+            panel1 = new Panel();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            label1 = new Label();
+            toolStrip1.SuspendLayout();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            SuspendLayout();
+            // 
+            // toolStrip1
+            // 
+            toolStrip1.BackColor = Color.FromArgb(32, 41, 50);
+            toolStrip1.Items.AddRange(new ToolStripItem[] { lblTitle, btnRun, btnCircleRun });
+            toolStrip1.Location = new Point(0, 0);
+            toolStrip1.Name = "toolStrip1";
+            toolStrip1.Size = new Size(360, 25);
+            toolStrip1.TabIndex = 0;
+            toolStrip1.Text = "toolStrip1";
+            // 
+            // lblTitle
+            // 
+            lblTitle.BackColor = SystemColors.ActiveCaptionText;
+            lblTitle.Name = "lblTitle";
+            lblTitle.Size = new Size(56, 22);
+            lblTitle.Text = "娴佺▼鍚嶇О";
+            // 
+            // btnRun
+            // 
+            btnRun.ImageTransparentColor = Color.Magenta;
+            btnRun.Name = "btnRun";
+            btnRun.Size = new Size(60, 22);
+            btnRun.Text = "鍗曟杩愯";
+            btnRun.ToolTipText = "鍗曟杩愯";
+            btnRun.Click += btnRun_Click;
+            // 
+            // btnCircleRun
+            // 
+            btnCircleRun.ImageTransparentColor = Color.Magenta;
+            btnCircleRun.Name = "btnCircleRun";
+            btnCircleRun.Size = new Size(60, 22);
+            btnCircleRun.Text = "杩炵画杩愯";
+            btnCircleRun.ToolTipText = "杩炵画";
+            btnCircleRun.Click += btnCircleRun_Click;
+            // 
+            // panel1
+            // 
+            panel1.BackColor = Color.FromArgb(32, 41, 50);
+            panel1.Dock = DockStyle.Fill;
+            panel1.Location = new Point(3, 3);
+            panel1.Name = "panel1";
+            panel1.Size = new Size(354, 187);
+            panel1.TabIndex = 1;
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(panel1, 0, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 1);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 25);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 2;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 22F));
+            tableLayoutPanel1.Size = new Size(360, 215);
+            tableLayoutPanel1.TabIndex = 2;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.BackColor = Color.FromArgb(32, 41, 50);
+            tableLayoutPanel2.ColumnCount = 3;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
+            tableLayoutPanel2.Controls.Add(label1, 0, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 196);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 1;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(354, 16);
+            tableLayoutPanel2.TabIndex = 2;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.BackColor = Color.FromArgb(32, 41, 50);
+            label1.Dock = DockStyle.Fill;
+            label1.Location = new Point(3, 0);
+            label1.Name = "label1";
+            label1.Size = new Size(112, 16);
+            label1.TabIndex = 0;
+            label1.Text = "鎬绘暟锛�0";
+            label1.DoubleClick += lblCount_DoubleClick;
+            label1.MouseHover += lblCount_MouseHover;
+            // 
+            // ProcessControl
+            // 
+            AutoScaleDimensions = new SizeF(96F, 96F);
+            AutoScaleMode = AutoScaleMode.Dpi;
+            BackColor = SystemColors.Control;
+            Controls.Add(tableLayoutPanel1);
+            Controls.Add(toolStrip1);
+            ForeColor = SystemColors.Control;
+            Name = "ProcessControl";
+            Size = new Size(360, 240);
+            Load += ProcessControl_Load;
+            toolStrip1.ResumeLayout(false);
+            toolStrip1.PerformLayout();
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel2.PerformLayout();
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private ToolStrip toolStrip1;
+        private ToolStripButton btnRun;
+        private ToolStripLabel lblTitle;
+        private Panel panel1;
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel2;
+        private Label label1;
+        private ToolStripButton btnCircleRun;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.cs b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.cs
new file mode 100644
index 0000000..43158ae
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.cs
@@ -0,0 +1,220 @@
+锘縰sing HalconDotNet;
+using LB_SmartVision.ProcessRun;
+using LB_VisionControl;
+using Layout = LB_SmartVision.Forms.Pages.SettingPage.Layout;
+
+namespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    public partial class ProcessControl : UserControl
+    {
+        UserHSmartWindowControl UserHSmartWindowControl = new UserHSmartWindowControl();
+
+        ProcessRunBll ProcessRunBll
+        {
+            get
+            {
+                if (GlobalVar.dicProcesses.ContainsKey(_Layout.ProcessName))
+                    return GlobalVar.dicProcesses[_Layout.ProcessName];
+                else
+                    return null;
+            }
+        }
+
+        Layout _Layout { get; set; } = new Layout();
+
+        public ProcessControl()
+        {
+            InitializeComponent();
+        }
+
+        public ProcessControl(Layout layout)
+        {
+            InitializeComponent();
+            _Layout = layout;
+        }
+
+        private void ProcessControl_Load(object sender, EventArgs e)
+        {
+            this.panel1.Controls.Add(this.UserHSmartWindowControl);
+            this.UserHSmartWindowControl.Dock = DockStyle.Fill;
+
+            SetTitle(_Layout.ProcessName);
+
+            if (ProcessRunBll != null)
+                this.label1.Text = $"鎬绘暟锛歿ProcessRunBll.total}";
+        }
+
+        public void SetTitle(string title)
+        {
+            // 濡傛灉褰撳墠涓嶆槸 UI 绾跨▼锛屽垯閫氳繃 Invoke 灏嗘搷浣滆皟搴﹀埌 UI 绾跨▼
+            if (this.InvokeRequired)
+            {
+                this.BeginInvoke(new Action<string>((title) =>
+                {
+                    this.lblTitle.Text = title;
+                }), title);
+            }
+            else
+            {
+                // 濡傛灉宸茬粡鍦� UI 绾跨▼涓婏紝鐩存帴鏇存柊 
+                this.lblTitle.Text = title;
+            }
+        }
+
+        public void ClearObj()
+        {
+            if (this.InvokeRequired)
+            {
+                this.BeginInvoke(new Action(() =>
+                {
+                    UserHSmartWindowControl.ClearObj();
+                }));
+            }
+            else
+                UserHSmartWindowControl.ClearObj();
+        }
+
+        /// <summary>
+        /// 寮傛鏄剧ず鍥剧墖
+        /// </summary>
+        /// <param name="ho_image"></param>
+        public void ShowHoImage(HObject ho_image)
+        {
+            UserHSmartWindowControl.hImage = ho_image;
+
+            if (this.InvokeRequired)
+            {
+                this.BeginInvoke(new Action(() =>
+                {
+                    this.label1.Text = $"鎬绘暟锛歿ProcessRunBll.total}";
+                }));
+            }
+            else
+                this.label1.Text = $"鎬绘暟锛歿ProcessRunBll.total}";
+        }
+
+        public bool Run(out string msg)
+        {
+            if (ProcessRunBll == null)
+            {
+                msg = $"娴佺▼{_Layout.ProcessName}涓嶅瓨鍦�";
+                return false;
+            }
+
+            if (isCircleRuning || ProcessRunBll.bPruning)
+                ProcessRunBll.LogInfo($"{ProcessRunBll.Name}姝e湪杩愯", LogInfoType.ERROR);
+
+            ProcessRunBll.Run();
+
+            msg = ProcessRunBll.Msg;
+            return ProcessRunBll.Result;
+        }
+
+        private void btnRun_Click(object sender, EventArgs e)
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                string msg = string.Empty;
+                bool result = false;
+                try
+                {
+                    if (ProcessRunBll == null)
+                        return;
+
+                    ProcessRunBll.LogInfo(string.Format("娴佺▼[{0}]寮�濮嬭繍琛�", this.ProcessRunBll.Name), LogInfoType.INFO);
+
+                    ClearObj();
+                    result = Run(out msg);
+
+                    if (ProcessRunBll.GetImage(_Layout, out _, out HObject RecordImage))
+                        ShowHoImage(RecordImage);
+                }
+                catch { msg = "杩愯鍑虹幇浜嗗紓甯�"; }
+
+                ProcessRunBll.LogInfo(string.Format("娴佺▼[{0}]杩愯瀹屾垚,缁撴灉:{1}", this.ProcessRunBll.Name, msg)
+                , result ? LogInfoType.PASS : LogInfoType.ERROR);
+            }));
+        }
+
+
+        CancellationTokenSource ctsTask = new CancellationTokenSource();
+        bool isCircleRuning = false;
+        private void btnCircleRun_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                isCircleRuning = !isCircleRuning;
+                btnRun.Enabled = !isCircleRuning;
+
+                if (isCircleRuning)
+                {
+                    threadCircleRun = new Thread(ThreadCircleRun);
+                    threadCircleRun.IsBackground = true;
+                    threadCircleRun.Start();
+                }
+                else
+                {
+                    isCircleRuning = false;
+                    threadCircleRun.Abort();
+                }
+            }
+            catch { }
+        }
+
+        Thread threadCircleRun = null;
+
+        void ThreadCircleRun()
+        {
+            if (!isCircleRuning)
+            {
+                ProcessRunBll.LogInfo($"{ProcessRunBll.Name}鍏抽棴杩炵画杩愯", LogInfoType.PASS);
+                return;
+            }
+
+            ProcessRunBll.LogInfo($"{ProcessRunBll.Name}寮�鍚繛缁繍琛�", LogInfoType.WARN);
+
+            while (isCircleRuning)
+            {
+                //this.BeginInvoke(new Action(() =>
+                //{
+                try
+                {
+                    ProcessRunBll.LogInfo($"{ProcessRunBll.Name}寮�濮嬭繍琛�", LogInfoType.WARN);
+                    ClearObj();
+                    bool result = ProcessRunBll.Run();
+                    string msg = result ? "杩愯鎴愬姛" : ProcessRunBll.Msg;
+
+                    ProcessRunBll.LogInfo($"{ProcessRunBll.Name}杩愯缁撴潫,缁撴灉涓�:{msg}"
+                        , result ? LogInfoType.PASS : LogInfoType.ERROR);
+
+                    if (ProcessRunBll.GetImage(_Layout, out _, out HObject RecordImage))
+                        ShowHoImage(RecordImage);
+                }
+                catch { }
+                //}));
+
+                Thread.Sleep(100);
+            }
+        }
+
+        System.Windows.Forms.ToolTip TotalToolTip = new System.Windows.Forms.ToolTip();
+
+        private void lblCount_DoubleClick(object sender, EventArgs e)
+        {
+            this.BeginInvoke(() =>
+            {
+                ProcessRunBll.ClearTotal();
+                this.label1.Text = $"鎬绘暟锛歿ProcessRunBll.total}";
+            });
+        }
+
+        private void lblCount_MouseHover(object sender, EventArgs e)
+        {
+            // 鏄剧ずToolTip锛堢浉瀵逛簬鎺т欢鐨勪綅缃級
+            TotalToolTip.Show($"鐩撮�氱巼:{ProcessRunBll.Rate_OK.ToString("F3")}", (Control)sender,
+                               ((Control)sender).Width / 2, // x鍋忕Щ
+                               -20,                      // y鍋忕Щ锛堣礋鍊艰〃绀轰笂鏂癸級
+                               2000);                    // 鏄剧ず鏃堕棿(ms)
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.resx b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.resx
new file mode 100644
index 0000000..ea0dea7
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessControl.resx
@@ -0,0 +1,123 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.Designer.cs b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.Designer.cs
new file mode 100644
index 0000000..c282ed3
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.Designer.cs
@@ -0,0 +1,129 @@
+锘縩amespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    partial class ProcessInputsEditControl
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tableLayoutPanel1 = new TableLayoutPanel();
+            lblInput = new Label();
+            lbl = new Label();
+            lblOutput = new Label();
+            uiButtonEdit = new Button();
+            tableLayoutPanel1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            tableLayoutPanel1.ColumnCount = 4;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.33333F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333359F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333359F));
+            tableLayoutPanel1.Controls.Add(lblInput, 0, 0);
+            tableLayoutPanel1.Controls.Add(lbl, 1, 0);
+            tableLayoutPanel1.Controls.Add(lblOutput, 2, 0);
+            tableLayoutPanel1.Controls.Add(uiButtonEdit, 3, 0);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.ForeColor = SystemColors.Control;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 1;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Size = new Size(500, 50);
+            tableLayoutPanel1.TabIndex = 0;
+            // 
+            // lblInput
+            // 
+            lblInput.AutoSize = true;
+            lblInput.Dock = DockStyle.Fill;
+            lblInput.Font = new Font("Microsoft YaHei UI", 12F);
+            lblInput.Location = new Point(3, 0);
+            lblInput.Name = "lblInput";
+            lblInput.Size = new Size(153, 50);
+            lblInput.TabIndex = 1;
+            lblInput.Text = "X.Inputs.X";
+            lblInput.TextAlign = ContentAlignment.MiddleRight;
+            // 
+            // lbl
+            // 
+            lbl.AutoSize = true;
+            lbl.Dock = DockStyle.Fill;
+            lbl.Font = new Font("Microsoft YaHei UI", 12F);
+            lbl.Location = new Point(162, 0);
+            lbl.Name = "lbl";
+            lbl.Size = new Size(14, 50);
+            lbl.TabIndex = 2;
+            lbl.Text = "-";
+            lbl.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // lblOutput
+            // 
+            lblOutput.AutoSize = true;
+            lblOutput.Dock = DockStyle.Fill;
+            lblOutput.Font = new Font("Microsoft YaHei UI", 12F);
+            lblOutput.Location = new Point(182, 0);
+            lblOutput.Name = "lblOutput";
+            lblOutput.Size = new Size(154, 50);
+            lblOutput.TabIndex = 3;
+            lblOutput.Text = "X.Outputs.X";
+            lblOutput.TextAlign = ContentAlignment.MiddleLeft;
+            // 
+            // uiButtonEdit
+            // 
+            uiButtonEdit.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiButtonEdit.Location = new Point(342, 3);
+            uiButtonEdit.MinimumSize = new Size(1, 1);
+            uiButtonEdit.Name = "uiButtonEdit";
+            uiButtonEdit.Size = new Size(75, 44);
+            uiButtonEdit.TabIndex = 0;
+            uiButtonEdit.Text = "缂栬緫";
+            uiButtonEdit.Click += uiButtonEdit_Click;
+            // 
+            // ProcessInputsEditControl
+            // 
+            AutoScaleDimensions = new SizeF(96F, 96F);
+            AutoScaleMode = AutoScaleMode.Dpi;
+            Controls.Add(tableLayoutPanel1);
+            MaximumSize = new Size(1920, 50);
+            MinimumSize = new Size(0, 50);
+            Name = "ProcessInputsEditControl";
+            Size = new Size(500, 50);
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel1.PerformLayout();
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private TableLayoutPanel tableLayoutPanel1;
+        private Button uiButtonEdit;
+        public Label lblInput;
+        private Label lbl;
+        public Label lblOutput;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.cs b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.cs
new file mode 100644
index 0000000..729e7cf
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.cs
@@ -0,0 +1,44 @@
+锘縰sing System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    public partial class ProcessInputsEditControl : UserControl
+    {
+        public ProcessInputsEditControl()
+        {
+            InitializeComponent();
+        }
+
+        public ConcurrentDictionary<string, List<Tuple<string, string>>> dicInputsMapping { get; set; }
+
+        public ConcurrentDictionary<string, List<string>> dicOutputsMapping { get; set; }
+
+
+        public ProcessInputsEditControl(string strInput, string strOutput
+            , ConcurrentDictionary<string, List<Tuple<string, string>>> dicInputsMapping, ConcurrentDictionary<string, List<string>> dicOutputsMapping)
+        {
+            InitializeComponent();
+            this.lblInput.Text = strInput;
+            this.lblOutput.Text = strOutput;
+            this.dicInputsMapping = dicInputsMapping;
+            this.dicOutputsMapping = dicOutputsMapping;
+        }
+
+        private void uiButtonEdit_Click(object sender, EventArgs e)
+        {
+            string[] inputs = this.lblInput.Text.Split('.');
+            ProcessOutputsSelectForm processOutputsSelectForm = new ProcessOutputsSelectForm(dicInputsMapping, dicOutputsMapping, inputs[0]);
+            processOutputsSelectForm.ShowDialog();
+            this.lblOutput.Text = processOutputsSelectForm.SelectedOutput;
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.resx b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsEditControl.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/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.Designer.cs b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.Designer.cs
new file mode 100644
index 0000000..12bcc83
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.Designer.cs
@@ -0,0 +1,110 @@
+锘縩amespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    partial class ProcessInputsSelectForm
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProcessInputsSelectForm));
+            themeForm1 = new ReaLTaiizor.Forms.ThemeForm();
+            panel = new ReaLTaiizor.Controls.Panel();
+            controlBox1 = new ReaLTaiizor.Controls.ControlBox();
+            themeForm1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // themeForm1
+            // 
+            themeForm1.BackColor = Color.FromArgb(32, 41, 50);
+            themeForm1.Controls.Add(controlBox1);
+            themeForm1.Controls.Add(panel);
+            themeForm1.Dock = DockStyle.Fill;
+            themeForm1.Font = new Font("Microsoft Sans Serif", 9F);
+            themeForm1.Image = (Image)resources.GetObject("themeForm1.Image");
+            themeForm1.Location = new Point(0, 0);
+            themeForm1.Name = "themeForm1";
+            themeForm1.Padding = new Padding(10, 70, 10, 9);
+            themeForm1.RoundCorners = true;
+            themeForm1.Sizable = true;
+            themeForm1.Size = new Size(907, 484);
+            themeForm1.SmartBounds = true;
+            themeForm1.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            themeForm1.TabIndex = 2;
+            themeForm1.Text = "themeForm1";
+            // 
+            // panel
+            // 
+            panel.BackColor = Color.FromArgb(39, 51, 63);
+            panel.Dock = DockStyle.Fill;
+            panel.EdgeColor = Color.FromArgb(32, 41, 50);
+            panel.Location = new Point(10, 70);
+            panel.Name = "panel";
+            panel.Padding = new Padding(5);
+            panel.Size = new Size(887, 405);
+            panel.SmoothingType = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
+            panel.TabIndex = 0;
+            panel.Text = "panel1";
+            // 
+            // controlBox1
+            // 
+            controlBox1.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            controlBox1.BackColor = Color.FromArgb(32, 34, 37);
+            controlBox1.CloseHoverColor = Color.FromArgb(230, 17, 35);
+            controlBox1.DefaultLocation = true;
+            controlBox1.EnableHoverHighlight = true;
+            controlBox1.EnableMaximizeButton = true;
+            controlBox1.EnableMinimizeButton = true;
+            controlBox1.ForeColor = Color.FromArgb(155, 155, 155);
+            controlBox1.Location = new Point(804, 12);
+            controlBox1.MaximizeHoverColor = Color.FromArgb(74, 74, 74);
+            controlBox1.MinimizeHoverColor = Color.FromArgb(63, 63, 65);
+            controlBox1.Name = "controlBox1";
+            controlBox1.Size = new Size(90, 25);
+            controlBox1.TabIndex = 1;
+            controlBox1.Text = "controlBox1";
+            // 
+            // ProcessInputsSelectForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(907, 484);
+            Controls.Add(themeForm1);
+            FormBorderStyle = FormBorderStyle.None;
+            MinimumSize = new Size(261, 61);
+            Name = "ProcessInputsSelectForm";
+            Text = "themeForm1";
+            TransparencyKey = Color.Fuchsia;
+            FormClosing += ProcessInputsSelectForm_FormClosing;
+            themeForm1.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+        private Button uiButtonOK;
+        private ReaLTaiizor.Forms.ThemeForm themeForm1;
+        private ReaLTaiizor.Controls.Panel panel;
+        private ReaLTaiizor.Controls.ControlBox controlBox1;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.cs b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.cs
new file mode 100644
index 0000000..f9496c3
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.cs
@@ -0,0 +1,96 @@
+锘縰sing LB_SmartVision.ProcessRun;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    public partial class ProcessInputsSelectForm : Form
+    {
+        List<ProcessInputsEditControl> listProcessInputsEditControl = new List<ProcessInputsEditControl>();
+
+        ProcessRunBll ProcessRunBll { get; set; }
+
+        public ProcessInputsSelectForm()
+        {
+            InitializeComponent();
+        }
+
+
+        public ProcessInputsSelectForm(string ProcessName, ProcessRunBll RunBll)
+        {
+            InitializeComponent();
+            if (!RunBll.dicInputsMapping.ContainsKey(ProcessName))
+                return;
+
+            ProcessRunBll = RunBll;
+
+            int index = 0;
+            foreach (Tuple<string, string> tupleInputAndOutput in RunBll.dicInputsMapping[ProcessName])
+            {
+                string Input = tupleInputAndOutput.Item1;
+                string Output = tupleInputAndOutput.Item2;
+
+                ProcessInputsEditControl processInputsEditControl = new ProcessInputsEditControl(Input, Output, RunBll.dicInputsMapping, RunBll.dicOutputsMapping);
+                listProcessInputsEditControl.Add(processInputsEditControl);
+                this.panel.Controls.Add(processInputsEditControl);
+                processInputsEditControl.Size = new System.Drawing.Size(panel.Width, 50);
+                processInputsEditControl.Location = new System.Drawing.Point(0, processInputsEditControl.Size.Height * index);
+                index++;
+            }
+        }
+
+        private void panel_SizeChanged(object sender, EventArgs e)
+        {
+            int index = 0;
+            foreach (var item in listProcessInputsEditControl)
+            {
+                item.Size = new System.Drawing.Size(panel.Width, 50);
+                item.Location = new System.Drawing.Point(0, item.Size.Height * index);
+                index++;
+            }
+        }
+
+        private void ProcessInputsSelectForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            if (ProcessRunBll == null)
+            {
+                e.Cancel = false;  //纭鍏抽棴绐椾綋
+                return;
+            }
+
+            DialogResult res = MessageBox.Show("鏄惁淇濆瓨锛�", "鎻愮ず", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);  //淇濆瓨缁撴灉淇℃伅
+            /// 鍙傛暟1锛氭樉绀烘枃鏈紝鍙傛暟2锛氭爣棰橈紝鍙傛暟3锛氭寜閿被鍨嬶紝鍙傛暟4锛氭樉绀哄浘鏍�
+            if (res != DialogResult.Yes && res != DialogResult.No)  //鍙栨秷
+            {
+                e.Cancel = true;  //鍙栨秷鍏抽棴绐椾綋
+                return;
+            }
+
+            if (res == DialogResult.Yes)  //淇濆瓨
+            {
+                string ProcessName = this.Text;
+                List<Tuple<string, string>> tupleInputAndOutput = new List<Tuple<string, string>>();
+                foreach (var control in listProcessInputsEditControl)
+                {
+                    string strInput = control.lblInput.Text;
+                    string strOutput = control.lblOutput.Text;
+                    Tuple<string, string> tuple = Tuple.Create(strInput, strOutput);
+                    tupleInputAndOutput.Add(tuple);
+                }
+
+                ProcessRunBll.dicInputsMapping.TryRemove(ProcessName, out _);
+                ProcessRunBll.dicInputsMapping.TryAdd(ProcessName, tupleInputAndOutput);
+                e.Cancel = false;  //纭鍏抽棴绐椾綋
+                return;
+            }
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.resx b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.resx
new file mode 100644
index 0000000..ae566c4
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessInputsSelectForm.resx
@@ -0,0 +1,286 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="themeForm1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAIAAAB7GkOtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAACVUSURBVHhe7dXLDnD/OYbhb1RnQP1L5yZodRe7gUTsK6k2StJo42Boi3AE9gRnRChBgqGx4gCu
+        +e/NnTwr12jNVlbe+/nw8z/8vWlf+dxHab/1kz+Y9tUvfCLNL2r58mc/SvvGT38y7Yuf+njaB5PaYlJb
+        POkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkW
+        k9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9ri
+        F7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY
+        1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT
+        2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJS
+        WzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYA
+        xzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzp
+        FpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa
+        4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1
+        mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQW
+        k9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9pi
+        Uls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2
+        AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc8
+        6RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT
+        2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIX
+        tZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjU
+        FpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPa
+        YlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJb
+        NgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDH
+        POkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbPnznz7+V
+        9rWf+ME0T6LlF3/k+9K+/lOfTPuVT308zYto+c+//aO0DcAxk9piUltMaotJbfEiWkxqywbgmEltMakt
+        JrXFpLZ4ES0mtWUDcMyktpjUFpPaYlJbvIgWk9qyAThmUltMaotJbTGpLV5Ei0lt2QAcM6ktJrXFpLaY
+        1BYvosWktmwAjpnUFpPaYlJbTGqLF9FiUls2AMdMaotJbTGpLSa1xYtoMaktG4BjJrXFpLaY1BaT2uJF
+        tJjUlg3AMZPaYlJbTGqLSW3xIlpMassG4JhJbTGpLSa1xaS2eBEtJrVlA3DMpLaY1BaT2mJSW7yIFpPa
+        sgE4ZlJbTGqLSW0xqS1eRItJbdkAHDOpLSa1xaS2mNQWL6LFpLZsAI6Z1BaT2mJSW0xqixfRYlJbNgDH
+        TGqLSW0xqS0mtcWLaDGpLRuAYya1xaS2mNQWk9riRbSY1JYNwDGT2mJSW0xqi0lt8SJaTGrLBuCYSW0x
+        qS0mtcWktngRLSa1ZQNwzKS2mNQWk9piUlu8iBaT2rIBOGZSW0xqi0ltMaktXkSLSW3ZABwzqS0mtcWk
+        tpjUFi+ixaS2bACOmdQWk9piUltMaosX0WJSWzYAx0xqi0ltMaktJrXFi2gxqS0bgGMmtcWktpjUFpPa
+        4kW0mNSWDcAxk9piUltMaotJbfEiWkxqywbgmEltMaktJrXFpLZ4ES0mtWUDcMyktpjUFpPaYlJbvIgW
+        k9qyAThmUltMaotJbTGpLV5Ei0lt2QAcM6ktJrXFpLaY1BYvosWktmwAjpnUFpPaYlJbTGqLF9FiUls2
+        AMdMaotJbTGpLSa1xYtoMaktG4BjJrXFpLaY1BaT2uJFtJjUlg3AMZPaYlJbTGqLSW3xIlpMassG4JhJ
+        bTGpLSa1xaS2eBEtJrVlA3DMpLaY1BaT2mJSW7yIFpPasgE4ZlJbTGqLSW0xqS1eRItJbdkAHDOpLSa1
+        xaS2mNQWL6LFpLZsAI6Z1BaT2mJSW0xqixfRYlJbNgDHTGqLSW0xqS0mtcWLaDGpLRuAYya1xaS2mNQW
+        k9riRbSY1JYNwDGT2mJSW0xqi0lt8SJaTGrLBuCYSW0xqS0mtcWktngRLSa1ZQNwzKS2mNQWk9piUlu8
+        iBaT2rIBOGZSW0xqi0ltMaktXkSLSW3ZABwzqS0mtcWktpjUFi+ixaS2bACOmdQWk9piUltMaosX0WJS
+        WzYAx0xqi0ltMaktJrXFi2gxqS0bgGMmtcWktpjUFpPa4kW0mNSWDcAxk9piUltMaotJbfEiWkxqywbg
+        mEltMaktJrXFpLZ4ES0mtWUDcMyktpjUFpPaYlJbvIgWk9qyAThmUltMaotJbTGpLV5Ei0lt2QAcM6kt
+        JrXFpLaY1BYvosWktmwAjpnUFpPaYlJbTGqLF9FiUls2AMdMaotJbTGpLSa1xYtoMaktG4BjJrXFpLaY
+        1BaT2uJFtJjUlg3AMZPaYlJbTGqLSW3xIlpMassG4JhJbTGpLSa1xaS2eBEtJrVlA3DMpLaY1BaT2mJS
+        W7yIFpPasgE4ZlJbTGqLSW0xqS1eRItJbdkAHDOpLSa1xaS2mNQWL6LFpLZsAI6Z1BaT2mJSW0xqixfR
+        YlJbNgDHTGqLSW0xqS0mtcWLaDGpLR9+88d/IO1Ln/n+NE+ixUlo8aTnpV///CfSfuMLbRuAYya1xaS2
+        mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qy
+        AThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYlk9piUls2AMdMaotJbTFJ
+        85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNw
+        zKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYl
+        k9piUls2AMdMaotJbTFJ85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJ
+        bTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1
+        xaS2bACOmdQWk9pikuYlk9piUls2AMdMaotJbTFJ85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9pi
+        UltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJ
+        bdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYlk9piUls2AMdMaotJbTFJ85JJbTGpLRuAYya1xaS2
+        mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qy
+        AThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYlk9piUls2AMdMaotJbTFJ
+        85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNw
+        zKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYl
+        k9piUls2AMdMaotJbTFJ85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJ
+        bTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1
+        xaS2bACOmdQWk9pikuYlk9piUls2AMdMaotJbTFJ85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9pi
+        UltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJ
+        bdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYlk9piUls+/Otf/X7a/8WfH/rYx9L8Iy1//8e/k/aj
+        3/M9af/73e+m/eff/mHaBuD4Makt/pEWk9piUltMaotJbdkAHD8mtcU/0mJSW0xqi0ltMaktG4Djx6S2
+        +EdaTGqLSW0xqS0mtWUDcPyY1Bb/SItJbTGpLSa1xaS2bACOH5Pa4h9pMaktJrXFpLaY1JYNwPFjUlv8
+        Iy0mtcWktpjUFpPasgE4fkxqi3+kxaS2mNQWk9piUls2AMePSW3xj7SY1BaT2mJSW0xqywbg+DGpLf6R
+        FpPaYlJbTGqLSW3ZABw/JrXFP9JiUltMaotJbTGpLRuA48ektvhHWkxqi0ltMaktJrVlA3D8mNQW/0iL
+        SW0xqS0mtcWktmwAjh+T2uIfaTGpLSa1xaS2mNSWDcDxY1Jb/CMtJrXFpLaY1BaT2rIBOH5Maot/pMWk
+        tpjUFpPaYlJbNgDHj0lt8Y+0mNQWk9piUltMassG4PgxqS3+kRaT2mJSW0xqi0lt2QAcPya1xT/SYlJb
+        TGqLSW0xqS0bgOPHpLb4R1pMaotJbTGpLSa1ZQNw/JjUFv9Ii0ltMaktJrXFpLZsAI4fk9riH2kxqS0m
+        tcWktpjUlg3A8WNSW/wjLSa1xaS2mNQWk9qyATh+TGqLf6TFpLaY1BaT2mJSWzYAx49JbfGPtJjUFpPa
+        YlJbTGrLBuD4Makt/pEWk9piUltMaotJbdkAHD8mtcU/0mJSW0xqi0ltMaktG4Djx6S2+EdaTGqLSW0x
+        qS0mtWUDcPyY1Bb/SItJbTGpLSa1xaS2bACOH5Pa4h9pMaktJrXFpLaY1JYNwPFjUlv8Iy0mtcWktpjU
+        FpPasgE4fkxqi3+kxaS2mNQWk9piUls2AMePSW3xj7SY1BaT2mJSW0xqywbg+DGpLf6RFpPaYlJbTGqL
+        SW3ZABw/JrXFP9JiUltMaotJbTGpLRuA48ektvhHWkxqi0ltMaktJrVlA3D8mNQW/0iLSW0xqS0mtcWk
+        tmwAjh+T2uIfaTGpLSa1xaS2mNSWDcDxY1Jb/CMtJrXFpLaY1BaT2rIBOH5Maot/pMWktpjUFpPaYlJb
+        NgDHj0lt8Y+0mNQWk9piUltMassG4PgxqS3+kRaT2mJSW0xqi0lt2QAcPya1xT/SYlJbTGqLSW0xqS0b
+        gOPHpLb4R1pMaotJbTGpLSa1ZQNw/JjUFv9Ii0ltMaktJrXFpLZsAI4fk9riH2kxqS0mtcWktpjUlg3A
+        8WNSW/wjLSa1xaS2mNQWk9qyATh+TGqLf6TFpLaY1BaT2mJSWzYAx49JbfGPtJjUFpPaYlJbTGrLBuD4
+        Makt/pEWk9piUltMaotJbdkAHD8mtcU/0mJSW0xqi0ltMaktG4Djx6S2+EdaTGqLSW0xqS0mtWUDcPyY
+        1Bb/SItJbTGpLSa1xaS2bACOH5Pa4h9pMaktJrXFpLaY1JYNwPFjUlv8Iy0mtcWktpjUFpPasgE4fkxq
+        i3+kxaS2mNQWk9piUls2AMePSW3xj7SY1BaT2mJSW0xqywbg+DGpLf6RFpPaYlJbTGqLSW3ZABw/JrXF
+        P9JiUltMaotJbTGpLRuA48ektvhHWkxqi0ltMaktJrVlA3D8mNQW/0iLSW0xqS0mtcWktmwAjh+T2uIf
+        aTGpLSa1xaS2mNSWDcDxY1Jb/CMtJrXFpLaY1BaT2rIBOH5Maot/pMWktpjUFpPaYlJbPviq5d/+9Jtp
+        //Rn30r7r7/7o7R//+s/SPuXv/h22n/95e+l/cOf/G7aBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqL
+        SW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWk
+        tpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJb
+        TGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0b
+        gGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnU
+        FpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqL
+        SW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWk
+        tpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJb
+        TGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0b
+        gGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnU
+        FpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqL
+        SW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWk
+        tpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJb
+        TGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0b
+        gGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnU
+        FpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqL
+        SW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWk
+        tpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJb
+        TGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0b
+        gGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnU
+        FpPaYlJbTGqLSW0xqS0ffv3zn0j7xz/7Ztp3/vxbab/8qY+nfTHun//i22n/8Td/mPaVz32UtgE4ZlJb
+        TGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0m
+        tcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPa
+        YlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0x
+        qS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwA
+        jpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJb
+        TGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0m
+        tcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPa
+        YlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0x
+        qS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwA
+        jpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJb
+        TGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0m
+        tcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPa
+        YlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0x
+        qS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwA
+        jpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJb
+        TGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0m
+        tcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPa
+        YlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0x
+        qS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwA
+        jpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLhy995vvT/KSWL3+27bv/899z6Euf+SjN
+        i2j51U9/PG0DcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUD
+        cMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmk
+        tngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNw
+        zKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2
+        eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DM
+        pLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4
+        ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyk
+        tpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngR
+        LSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2
+        mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEt
+        JrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaY
+        pHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0m
+        tWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpik
+        ecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1
+        ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5
+        yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVl
+        A3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJ
+        pLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mteXD
+        N37hx9J++5c+k/a1n/1U2lc+94m0X/vsR2lf/7lPp331Z354Dm0AjpnUFpPaYlJbTGqLSZqXNgDHTGqL
+        SW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpik
+        eWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0xqS0maV7aABwzqS0mtcWktpjUFpM0L20AjpnUFpPa
+        YlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPS
+        BuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0xqS0maV7aABwzqS0mtcWk
+        tpjUFpM0L20AjpnUFpPaYlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3A
+        MZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0x
+        qS0maV7aABwzqS0mtcWktpjUFpM0L20AjpnUFpPaYlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMm
+        tcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJb
+        TNK8tAE4ZlJbTGqLSW0xqS0maV7aABwzqS0mtcWktpjUFpM0L20AjpnUFpPaYlJbTGqLSZqXNgDHTGqL
+        SW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpik
+        eWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0xqS0maV7aABwzqS0mtcWktpjUFpM0L20AjpnUFpPa
+        YlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPS
+        BuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0xqS0maV7aABwzqS0mtcWk
+        tpjUFpM0L20AjpnUFpPaYlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3A
+        MZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0x
+        qS0maV7aABwzqS0mtcWktpjUFpM0L20AjpnUFpPaYlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMm
+        tcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJb
+        TNK8tAE4ZlJbTGqLSW0xqS0maV76fzfth9drmQBzAAAAAElFTkSuQmCC
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.Designer.cs b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.Designer.cs
new file mode 100644
index 0000000..672e91a
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.Designer.cs
@@ -0,0 +1,132 @@
+锘縩amespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    partial class ProcessOutputsSelectForm
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tableLayoutPanel1 = new TableLayoutPanel();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            uiButtonOK = new Button();
+            uiButtonCancel = new Button();
+            treeViewOutputs = new TreeView();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 1);
+            tableLayoutPanel1.Controls.Add(treeViewOutputs, 0, 0);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 2;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.Size = new Size(679, 496);
+            tableLayoutPanel1.TabIndex = 0;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 6;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666718F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666679F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666679F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666679F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666679F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666679F));
+            tableLayoutPanel2.Controls.Add(uiButtonOK, 4, 0);
+            tableLayoutPanel2.Controls.Add(uiButtonCancel, 5, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 449);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 1;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(673, 44);
+            tableLayoutPanel2.TabIndex = 0;
+            // 
+            // uiButtonOK
+            // 
+            uiButtonOK.Dock = DockStyle.Fill;
+            uiButtonOK.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiButtonOK.ForeColor = SystemColors.Control;
+            uiButtonOK.Location = new Point(451, 3);
+            uiButtonOK.MinimumSize = new Size(1, 1);
+            uiButtonOK.Name = "uiButtonOK";
+            uiButtonOK.Size = new Size(106, 38);
+            uiButtonOK.TabIndex = 0;
+            uiButtonOK.Text = "纭畾";
+            uiButtonOK.Click += uiButtonOK_Click;
+            // 
+            // uiButtonCancel
+            // 
+            uiButtonCancel.Dock = DockStyle.Fill;
+            uiButtonCancel.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiButtonCancel.ForeColor = SystemColors.Control;
+            uiButtonCancel.Location = new Point(563, 3);
+            uiButtonCancel.MinimumSize = new Size(1, 1);
+            uiButtonCancel.Name = "uiButtonCancel";
+            uiButtonCancel.Size = new Size(107, 38);
+            uiButtonCancel.TabIndex = 1;
+            uiButtonCancel.Text = "鍙栨秷";
+            uiButtonCancel.Click += uiButtonCancel_Click;
+            // 
+            // treeViewOutputs
+            // 
+            treeViewOutputs.BackColor = Color.FromArgb(39, 51, 63);
+            treeViewOutputs.Dock = DockStyle.Fill;
+            treeViewOutputs.ForeColor = SystemColors.Control;
+            treeViewOutputs.Location = new Point(3, 3);
+            treeViewOutputs.Name = "treeViewOutputs";
+            treeViewOutputs.Size = new Size(673, 440);
+            treeViewOutputs.TabIndex = 1;
+            // 
+            // ProcessOutputsSelectForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            BackColor = Color.FromArgb(39, 51, 63);
+            ClientSize = new Size(679, 496);
+            Controls.Add(tableLayoutPanel1);
+            FormBorderStyle = FormBorderStyle.None;
+            Name = "ProcessOutputsSelectForm";
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel2;
+        private TreeView treeViewOutputs;
+        private Button uiButtonOK;
+        private Button uiButtonCancel;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.cs b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.cs
new file mode 100644
index 0000000..3c23041
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.cs
@@ -0,0 +1,102 @@
+锘縰sing LB_VisionProcesses;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
+
+namespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    public partial class ProcessOutputsSelectForm : Form
+    {
+        public string SelectedOutput = string.Empty;
+
+        public ProcessOutputsSelectForm()
+        {
+            InitializeComponent();
+        }
+
+
+        public ProcessOutputsSelectForm(ConcurrentDictionary<string, List<Tuple<string, string>>> dicInputsMapping, ConcurrentDictionary<string, List<string>> dicOutputsMapping, string ProcessName = "")
+        {
+            InitializeComponent();
+            treeViewOutputs.Nodes.Clear();
+            // 鍒涘缓鐖惰妭鐐�
+            TreeNode nullNode = new TreeNode("鏃�");
+            treeViewOutputs.Nodes.Add(nullNode);
+
+            // 鍒涘缓鐖惰妭鐐�
+            TreeNode globalNode = new TreeNode("鍏ㄥ眬鍙橀噺");
+            foreach (var name in IProcess.dicGlobalVars.Keys)
+            {
+                // 鍒涘缓瀛愯妭鐐�
+                TreeNode childNode1 = new TreeNode(name);
+                globalNode.Nodes.Add(childNode1);
+            }
+            treeViewOutputs.Nodes.Add(globalNode);
+
+            foreach (var item in dicOutputsMapping)
+            {
+                if (ProcessName != item.Key)
+                {
+                    // 鍒涘缓鐖惰妭鐐�
+                    TreeNode parentNode = new TreeNode(item.Key);
+
+                    // 娣诲姞杈撳叆鑺傜偣
+                    TreeNode InputsNode = new TreeNode("Inputs");
+                    List<Tuple<string, string>> listInputs = dicInputsMapping[item.Key];
+                    foreach (var inputs in listInputs)
+                    {
+                        // 鍒涘缓瀛愯妭鐐�
+                        TreeNode childNode1 = new TreeNode(inputs.Item1);
+                        InputsNode.Nodes.Add(childNode1);
+                    }
+
+                    // 娣诲姞杈撳嚭鑺傜偣
+                    TreeNode OutputsNode = new TreeNode("Outputs");
+                    List<string> listOutputs = item.Value;
+                    foreach (var output in listOutputs)
+                    {
+                        // 鍒涘缓瀛愯妭鐐�
+                        TreeNode childNode1 = new TreeNode(output);
+                        OutputsNode.Nodes.Add(childNode1);
+                    }
+
+                    // 灏嗙埗鑺傜偣娣诲姞鍒� TreeView
+                    parentNode.Nodes.Add(InputsNode);
+                    parentNode.Nodes.Add(OutputsNode);
+                    treeViewOutputs.Nodes.Add(parentNode);
+                }
+            }
+        }
+
+        private void uiButtonOK_Click(object sender, EventArgs e)
+        {
+            if (this.treeViewOutputs.SelectedNode == null)
+                return;
+            if (this.treeViewOutputs.SelectedNode.Text == "鏃�")
+            {
+                SelectedOutput = string.Empty;
+                this.Close();
+            }
+
+            if (this.treeViewOutputs.SelectedNode.Parent != null)
+            {
+                SelectedOutput = this.treeViewOutputs.SelectedNode.Text;
+                this.Close();
+            }
+        }
+
+        private void uiButtonCancel_Click(object sender, EventArgs e)
+        {
+            SelectedOutput = string.Empty;
+            this.Close();
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.resx b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessOutputsSelectForm.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/LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.Designer.cs b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.Designer.cs
new file mode 100644
index 0000000..2cbb2f5
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.Designer.cs
@@ -0,0 +1,149 @@
+锘縰sing ReaLTaiizor.Controls;
+
+namespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    partial class ProcessPage
+    {
+        /// <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()
+        {
+            btn_Run = new HopeButton();
+            tableLayoutPanel3 = new TableLayoutPanel();
+            tableLayoutPanel4 = new TableLayoutPanel();
+            panel1 = new System.Windows.Forms.Panel();
+            splitContainer1 = new SplitContainer();
+            tableLayoutPanel3.SuspendLayout();
+            tableLayoutPanel4.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
+            splitContainer1.Panel2.SuspendLayout();
+            splitContainer1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // btn_Run
+            // 
+            btn_Run.BorderColor = Color.FromArgb(220, 223, 230);
+            btn_Run.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            btn_Run.DangerColor = Color.FromArgb(245, 108, 108);
+            btn_Run.DefaultColor = Color.FromArgb(255, 255, 255);
+            btn_Run.Dock = DockStyle.Fill;
+            btn_Run.Font = new Font("瀹嬩綋", 12F);
+            btn_Run.HoverTextColor = Color.FromArgb(48, 49, 51);
+            btn_Run.InfoColor = Color.FromArgb(144, 147, 153);
+            btn_Run.Location = new Point(419, 3);
+            btn_Run.MinimumSize = new Size(1, 1);
+            btn_Run.Name = "btn_Run";
+            btn_Run.PrimaryColor = Color.FromArgb(64, 158, 255);
+            btn_Run.Size = new Size(102, 38);
+            btn_Run.SuccessColor = Color.FromArgb(103, 194, 58);
+            btn_Run.TabIndex = 1;
+            btn_Run.Text = "杩愯";
+            btn_Run.TextColor = Color.White;
+            btn_Run.WarningColor = Color.FromArgb(230, 162, 60);
+            btn_Run.Click += btn_Run_Click;
+            // 
+            // tableLayoutPanel3
+            // 
+            tableLayoutPanel3.ColumnCount = 1;
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Controls.Add(tableLayoutPanel4, 0, 1);
+            tableLayoutPanel3.Controls.Add(panel1, 0, 0);
+            tableLayoutPanel3.Dock = DockStyle.Fill;
+            tableLayoutPanel3.Location = new Point(0, 0);
+            tableLayoutPanel3.Name = "tableLayoutPanel3";
+            tableLayoutPanel3.RowCount = 2;
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel3.Size = new Size(530, 371);
+            tableLayoutPanel3.TabIndex = 10;
+            // 
+            // tableLayoutPanel4
+            // 
+            tableLayoutPanel4.ColumnCount = 5;
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
+            tableLayoutPanel4.Controls.Add(btn_Run, 4, 0);
+            tableLayoutPanel4.Dock = DockStyle.Fill;
+            tableLayoutPanel4.Location = new Point(3, 324);
+            tableLayoutPanel4.Name = "tableLayoutPanel4";
+            tableLayoutPanel4.RowCount = 1;
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel4.Size = new Size(524, 44);
+            tableLayoutPanel4.TabIndex = 0;
+            // 
+            // panel1
+            // 
+            panel1.AutoScroll = true;
+            panel1.Dock = DockStyle.Fill;
+            panel1.ForeColor = SystemColors.Control;
+            panel1.Location = new Point(3, 3);
+            panel1.Name = "panel1";
+            panel1.Size = new Size(524, 315);
+            panel1.TabIndex = 1;
+            // 
+            // splitContainer1
+            // 
+            splitContainer1.Dock = DockStyle.Fill;
+            splitContainer1.Location = new Point(0, 0);
+            splitContainer1.Name = "splitContainer1";
+            // 
+            // splitContainer1.Panel1
+            // 
+            splitContainer1.Panel1.ForeColor = SystemColors.Control;
+            // 
+            // splitContainer1.Panel2
+            // 
+            splitContainer1.Panel2.Controls.Add(tableLayoutPanel3);
+            splitContainer1.Size = new Size(801, 371);
+            splitContainer1.SplitterDistance = 267;
+            splitContainer1.TabIndex = 11;
+            // 
+            // ProcessPage
+            // 
+            BackColor = Color.FromArgb(32, 41, 50);
+            Controls.Add(splitContainer1);
+            Name = "ProcessPage";
+            Size = new Size(801, 371);
+            Paint += ProcessPage_Paint;
+            tableLayoutPanel3.ResumeLayout(false);
+            tableLayoutPanel4.ResumeLayout(false);
+            splitContainer1.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit();
+            splitContainer1.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+        private ReaLTaiizor.Controls.HopeButton btn_Run;
+        //private Light uiLight1;
+        private TableLayoutPanel tableLayoutPanel3;
+        private TableLayoutPanel tableLayoutPanel4;
+        private SplitContainer splitContainer1;
+        private System.Windows.Forms.Panel panel1;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.cs b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.cs
new file mode 100644
index 0000000..dd1a063
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.cs
@@ -0,0 +1,404 @@
+锘縰sing HalconDotNet;
+using OpenCvSharp;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Collections.Concurrent;
+using LB_VisionControl;
+using LB_SmartVision.ProcessRun;
+using LB_VisionProcesses;
+using LB_VisionProcesses.Cameras;
+using LB_VisionProcesses.Communicators;
+
+namespace LB_SmartVision.Forms.Pages.ProcessPage
+{
+    public partial class ProcessPage : UserControl
+    {
+        /// <summary>
+        /// 杩愯姝ラ(object涓篒Proces鎴栬�卭bject涓篒Camera)
+        /// </summary>
+        public ProcessRunBll ProcessRunBll { get; set; }
+
+        public Action<string, LogInfoType> LogInfo;
+
+        private UserHSmartWindowControl UserHSmartWindowControl = new UserHSmartWindowControl();
+
+        public ProcessPage()
+        {
+            InitializeComponent();
+        }
+
+        public ProcessPage(string Name, ProcessRunBll ProcessRunBll)
+        {
+            InitializeComponent();
+            this.Text = "ProcessPage";
+            this.Name = Name;
+
+            this.ProcessRunBll = ProcessRunBll;
+
+            Name = ProcessRunBll.Name;
+            Text = ProcessRunBll.Name;
+
+            this.splitContainer1.Panel1.Controls.Add(UserHSmartWindowControl);
+            UserHSmartWindowControl.Dock = DockStyle.Fill;
+
+            this.panel1.Controls.Add(ProcessRunBll.nodesControl);
+
+            ProcessRunBll.nodesControl.Location = new System.Drawing.Point(0, 0);
+            ProcessRunBll.nodesControl.Size = new System.Drawing.Size(5000, 5000);
+
+            RemoveAllHandler();
+
+            ProcessRunBll.nodesControl.AddNodeAction += AddProcess;
+            ProcessRunBll.nodesControl.RenameNodeAction += RenameProcess;
+            ProcessRunBll.nodesControl.InAndOutNodeAction += InAndOutProcess;
+            ProcessRunBll.nodesControl.DeleteNodeAction += DeleteProcess;
+            ProcessRunBll.nodesControl.EditNodeAction += EditProcess;
+            ProcessRunBll.nodesControl.AddBranchAction += AddBranch;
+            ProcessRunBll.nodesControl.DeleteBranchAction += DeleteBranch;
+        }
+
+        private void ProcessPage_Paint(object sender, PaintEventArgs e)
+        {
+            if (ProcessRunBll.Result)
+                btn_Run.ButtonType = ReaLTaiizor.Util.HopeButtonType.Success;
+            else
+                btn_Run.ButtonType = ReaLTaiizor.Util.HopeButtonType.Danger;
+
+            if (ProcessRunBll.GetImage(out _, out HObject RecordImage))
+                UserHSmartWindowControl.ShowHoImage(RecordImage);
+        }
+
+        public void RemoveAllHandler()
+        {
+            ProcessRunBll.nodesControl.AddNodeAction -= AddProcess;
+            ProcessRunBll.nodesControl.RenameNodeAction -= RenameProcess;
+            ProcessRunBll.nodesControl.InAndOutNodeAction -= InAndOutProcess;
+            ProcessRunBll.nodesControl.DeleteNodeAction -= DeleteProcess;
+            ProcessRunBll.nodesControl.EditNodeAction -= EditProcess;
+            ProcessRunBll.nodesControl.AddBranchAction -= AddBranch;
+            ProcessRunBll.nodesControl.DeleteBranchAction -= DeleteBranch;
+        }
+
+        private void btn_Run_Click(object sender, EventArgs e)
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                UserHSmartWindowControl.ClearObj();
+
+                LogInfo?.Invoke(string.Format("娴佺▼[{0}]寮�濮嬭繍琛�", this.ProcessRunBll.Name), LogInfoType.INFO);
+
+                bool result = this.ProcessRunBll.Run();
+                string msg = ProcessRunBll.Msg;
+
+                LogInfo?.Invoke(string.Format("娴佺▼[{0}]杩愯瀹屾垚,缁撴灉:{1}", this.ProcessRunBll.Name, msg)
+                    , result ? LogInfoType.PASS : LogInfoType.ERROR);
+
+                if (ProcessRunBll.GetImage(out _, out HObject RecordImage))
+                    UserHSmartWindowControl.ShowHoImage(RecordImage);
+
+                if (result)
+                    btn_Run.ButtonType = ReaLTaiizor.Util.HopeButtonType.Success;
+                else
+                    btn_Run.ButtonType = ReaLTaiizor.Util.HopeButtonType.Danger;
+            }));
+        }
+
+        public void AddProcess(string ProcessName, string Descript)
+        {
+            string ClassName = ProcessRunBll.Node2ToolClassName(Descript);
+            string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json";
+            if (ProcessRunBll.AddStep(ProcessRunBll.Name, ProcessName, ClassName, ProcessPath))
+            {
+                ProcessRunBll.SaveInputs();
+                ProcessRunBll.SaveOutputs();
+                ProcessRunBll.CompileMappings();
+            }
+            else
+                LogInfo?.Invoke(string.Format("娴佺▼[{0}]娣诲姞姝ラ\"{1}\"澶辫触", this.Text, ProcessName), LogInfoType.ERROR);
+        }
+
+        private void InAndOutProcess(string ProcessName)
+        {
+            var dicSteps = ProcessRunBll.GetSteps();
+            if (!dicSteps.ContainsKey(ProcessName))
+                return;
+
+            ProcessInputsSelectForm inputsSelectForm = new ProcessInputsSelectForm(ProcessName, ProcessRunBll);
+            inputsSelectForm.Text = ProcessName;
+            inputsSelectForm.ShowDialog();
+
+            ProcessRunBll.SaveInputs();
+            ProcessRunBll.SaveOutputs();
+            ProcessRunBll.CompileMappings();
+            //string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json";
+            //((IProcess)dicSteps[ProcessName]).Load(ProcessPath);
+        }
+
+        public void DeleteProcess(string ProcessName)
+        {
+            try
+            {
+                var dicSteps = ProcessRunBll.GetSteps();
+                if (!dicSteps.ContainsKey(ProcessName))
+                    return;
+
+                string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json";
+
+                if (string.IsNullOrEmpty(ProcessName) || string.IsNullOrEmpty(ProcessPath))
+                    return;
+
+                // 鑾峰彇鎵�鏈夋枃浠讹紙涓嶇鍚庣紑鍚嶆槸浠�涔堬級骞惰繘琛岄亶鍘�
+                string directoryPath = Path.GetDirectoryName(ProcessPath);
+
+                string[] files = Directory.GetFiles(directoryPath, ProcessName + ".*");  // 鍖归厤鎵�鏈夊悕绉颁负aa鐨勬枃浠讹紝鍚庣紑涓嶉檺
+
+                foreach (var file in files)
+                {
+                    try
+                    {
+                        if (File.Exists(file))
+                            File.Delete(file);
+                    }
+                    catch (Exception ex)
+                    {
+                        Debug.WriteLine($"鍒犻櫎鏂囦欢 {file} 鏃跺嚭閿�: {ex.Message}");
+                        LogInfo?.Invoke(string.Format("娴佺▼[{0}]绉婚櫎姝ラ\"{1}\"澶辫触,鍘熷洜鏄瘂2}", this.Text, ProcessName, ex.Message), LogInfoType.ERROR);
+                        return;
+                    }
+                }
+
+                if (Directory.Exists(directoryPath + "\\" + ProcessName))
+                    Directory.Delete(directoryPath + "\\" + ProcessName, true);
+
+                if (!ProcessRunBll.Remove(ProcessName))
+                    LogInfo?.Invoke(string.Format("娴佺▼[{0}]绉婚櫎姝ラ\"{1}\"澶辫触", this.Text, ProcessName), LogInfoType.ERROR);
+            }
+            catch (Exception ex) { Debug.WriteLine(ex.Message); }
+        }
+
+        private void RenameProcess(string ProcessName, string newProcessName)
+        {
+            ConcurrentDictionary<string, IProcess> dicSteps = ProcessRunBll.GetSteps();
+            if (!dicSteps.ContainsKey(ProcessName))
+                return;
+
+            ProcessRenameEvent(ProcessName, newProcessName);
+        }
+
+        private void ProcessRenameEvent(string oriName, string newName)
+        {
+            ConcurrentDictionary<string, IProcess> dicSteps = ProcessRunBll.GetSteps();
+
+            //鏇存柊鍚庣殑姝ラ鍚嶄粛鐒堕渶瑕佹槸鍞竴
+            if (dicSteps.ContainsKey(newName))
+            {
+                MessageBox.Show(string.Format("閲嶅懡鍚嶅け璐�,姝ラ鍚嶇О[{0}]宸插瓨鍦�!", newName), "寮傚父");
+                return;
+            }
+
+            if (dicSteps.ContainsKey(oriName))
+            {
+                string oriPath = GlobalVar.allProcessPath + this.Text + "\\" + oriName + ".json";
+                string newPath = GlobalVar.allProcessPath + this.Text + "\\" + newName + ".json";
+
+                string directoryPath = Path.GetDirectoryName(oriPath);
+                string[] files = new string[] { };
+
+                // 閲嶅懡鍚嶅綋鍓嶆枃浠跺す
+                files = Directory.GetFiles(directoryPath, oriName + ".*");  // 鍖归厤鎵�鏈夊悕绉颁负oriName鐨勬枃浠讹紝鍚庣紑涓嶉檺
+                foreach (var file in files)
+                {
+                    try
+                    {
+                        // 鑾峰彇鏂囦欢鐨勬墿灞曞悕
+                        string extension = Path.GetExtension(file);
+
+                        // 鏋勯�犳柊鏂囦欢鍚�
+                        string newFileName = Path.Combine(directoryPath, newName + extension);
+
+                        if (!File.Exists(newFileName))
+                        {
+                            // 閲嶅懡鍚嶆枃浠�
+                            File.Move(file, newFileName);
+                            Debug.WriteLine($"鏂囦欢宸查噸鍛藉悕: {file} -> {newFileName}");
+                        }
+                        else
+                        {
+                            LogInfo?.Invoke(string.Format("娴佺▼[{0}]閲嶅懡鍚嶆楠"{1}\"涓篭"{2}\"澶辫触,鍘熷洜鏄瘂3}", this.Text, oriName, newName, "鍛藉悕閲嶅"), LogInfoType.ERROR);
+                            return;
+                        }
+
+                    }
+                    catch (Exception ex)
+                    {
+                        Debug.WriteLine($"閲嶅懡鍚嶆枃浠� {file} 鏃跺嚭閿�: {ex.Message}");
+                        LogInfo?.Invoke(string.Format("娴佺▼[{0}]閲嶅懡鍚嶆楠"{1}\"涓篭"{2}\"澶辫触,鍘熷洜鏄瘂3}", this.Text, oriName, newName, ex.Message), LogInfoType.ERROR);
+                        return;
+                    }
+                }
+
+
+                // 閲嶅懡鍚嶅綋鍓嶆枃浠跺す
+                if (Directory.Exists(directoryPath + "\\" + oriName))
+                {
+                    Directory.Move(directoryPath + "\\" + oriName, directoryPath + "\\" + newName);
+                    // 閲嶅懡鍚嶅瓙鏂囦欢澶�
+                    string newParentDirectory = Path.GetDirectoryName(GlobalVar.allProcessPath + this.Text + "\\" + newName + "\\" + oriName + ".json");
+                    files = Directory.GetFiles(newParentDirectory, oriName + ".*");  // 鍖归厤瀛愭枃浠跺す鍐呮墍鏈夊悕绉颁负oriName鐨勬枃浠讹紝鍚庣紑涓嶉檺锛堜竴鑸彧鏈変竴涓級
+                    foreach (var file in files)
+                    {
+                        try
+                        {
+                            // 鑾峰彇鏂囦欢鐨勬墿灞曞悕
+                            string extension = Path.GetExtension(file);
+                            // 鏋勯�犳柊鏂囦欢鍚�
+                            string newFileName = Path.Combine(newParentDirectory, newName + extension);
+
+                            if (!File.Exists(newFileName))
+                            {
+                                if (!Directory.Exists(newParentDirectory))
+                                    Directory.CreateDirectory(newParentDirectory);
+
+                                // 閲嶅懡鍚嶆枃浠�
+                                File.Move(file, newFileName);
+                                Debug.WriteLine($"鏂囦欢宸查噸鍛藉悕: {file} -> {newFileName}");
+                            }
+                            else
+                            {
+                                LogInfo?.Invoke(string.Format("娴佺▼[{0}]閲嶅懡鍚嶆楠"{1}\"涓篭"{2}\"澶辫触,鍘熷洜鏄瘂3}", this.Text, oriName, newName, "鍛藉悕閲嶅"), LogInfoType.ERROR);
+                                return;
+                            }
+
+                        }
+                        catch (Exception ex)
+                        {
+                            Debug.WriteLine($"閲嶅懡鍚嶆枃浠� {file} 鏃跺嚭閿�: {ex.Message}");
+                            LogInfo?.Invoke(string.Format("娴佺▼[{0}]閲嶅懡鍚嶆楠"{1}\"涓篭"{2}\"澶辫触,鍘熷洜鏄瘂3}", this.Text, oriName, newName, ex.Message), LogInfoType.ERROR);
+                            return;
+                        }
+                    }
+                }
+
+                ProcessRunBll.Rename(oriName, newName);
+                LogInfo?.Invoke(string.Format("娴佺▼[{0}]閲嶅懡鍚嶆楠"{1}\"涓篭"{2}\"鎴愬姛", this.Text, oriName, newName), LogInfoType.PASS);
+
+                //if (dicSteps[newName] is VisionProTool && Tool.ContainsChinese(newName))
+                //    MessageBox.Show($"VisionPro宸ュ叿涓嶆敮鎸佸懡鍚嶄负涓枃:{newName}", "寮傚父");
+            }
+        }
+
+        private void EditProcess(string ProcessName)
+        {
+            try
+            {
+                ConcurrentDictionary<string, IProcess> dicSteps = ProcessRunBll.GetSteps();
+
+                if (!dicSteps.ContainsKey(ProcessName))
+                    return;
+
+                string ClassName = dicSteps[ProcessName].GetType().ToString();
+                string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json";
+
+                if (string.IsNullOrEmpty(ProcessName) || string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(ProcessPath))
+                    return;
+
+                //鍒╃敤鍙嶅皠鍒涘缓瀹炰緥
+                Type type = IProcess.GetExecutingAssembly().GetType(ClassName);
+                if (type == null)
+                {
+                    LogInfo?.Invoke(string.Format("娴佺▼[{0}]姝ラ\"{1}\"鎵撳紑澶辫触浜�,绫籟{2}]涓嶅瓨鍦�", this.Text, ProcessName, ClassName), LogInfoType.ERROR);
+                    return;
+                }
+
+                IProcess process = ((IProcess)dicSteps[ProcessName]).Clone() as IProcess;
+
+                Object InputImage = new Object();
+                if (process.InputImage != null)
+                {
+                    if (process.InputImage is HObject ho_image && ho_image.IsInitialized())
+                        InputImage = ho_image.CopyObj(1, -1);
+                    else if (process.InputImage is Mat mat && !mat.Empty())
+                        InputImage = mat.Clone();
+                    else if (process.InputImage is Bitmap bitmap)
+                        InputImage = bitmap.Clone();
+                }
+
+                if (ClassName.Contains("CameraConfig") && process is CameraConfig)
+                {
+                    LB_VisionProcesses.Cameras.CameraForm cameraForm
+                        = new LB_VisionProcesses.Cameras.CameraForm(GlobalVar.dicCameras.Items, (CameraConfig)process, ProcessPath);
+                    cameraForm.ShowDialog();
+
+                    if (!(process.Load(ProcessPath)))
+                        LogInfo?.Invoke(string.Format("娴佺▼[{0}]姝ラ\"{1}\"鍔犺浇澶辫触浜�", this.Text, ProcessName), LogInfoType.ERROR);
+                    process.strProcessName = ProcessName;
+                }
+                else if (ClassName.Contains("CommunicatorConfig") && process is CommunicatorConfig)
+                {
+                    LB_VisionProcesses.Communicators.CommunicatorForm communicatorForm
+                        = new LB_VisionProcesses.Communicators.CommunicatorForm(GlobalVar.dicCommunicators.Items, (CommunicatorConfig)process, ProcessPath);
+                    communicatorForm.ShowDialog();
+
+                    if (!(process.Load(ProcessPath)))
+                        LogInfo?.Invoke(string.Format("娴佺▼[{0}]姝ラ\"{1}\"鍔犺浇澶辫触浜�", this.Text, ProcessName), LogInfoType.ERROR);
+                    process.strProcessName = ProcessName;
+                }
+                else
+                {
+                    ProcessEditForm processEditForm = new ProcessEditForm(process, ProcessPath);
+                    processEditForm.ShowDialog();
+
+                    //閲嶆柊鍔犺浇鏇存柊鍚庣殑姝ラ
+                    if (processEditForm.hasChanged)
+                        LogInfo?.Invoke(string.Format("娴佺▼[{0}]姝ラ\"{1}\"鏇存柊浜�", this.Text, ProcessName), LogInfoType.WARN);
+
+                    if (!(process.Load(ProcessPath)))
+                        LogInfo?.Invoke(string.Format("娴佺▼[{0}]姝ラ\"{1}\"鍔犺浇澶辫触浜�", this.Text, ProcessName), LogInfoType.ERROR);
+                    process.strProcessName = ProcessName;
+                }
+
+                if (InputImage != null)
+                {
+                    if (InputImage is HObject ho_image && ho_image.IsInitialized())
+                        process.InputImage = ho_image.CopyObj(1, -1);
+                    else if (InputImage is Mat mat && !mat.Empty())
+                        process.InputImage = mat.Clone();
+                    else if (InputImage is Bitmap bitmap)
+                        process.InputImage = bitmap.Clone();
+                }
+                dicSteps[ProcessName] = process;
+
+                ProcessRunBll.UpdataInputsAndOutputs(ProcessName, process);
+            }
+            catch (Exception ex) { Debug.WriteLine(ex.Message); }
+        }
+
+        private void AddBranch(string ProcessName)
+        {
+            var dicSteps = ProcessRunBll.GetSteps();
+            if (!dicSteps.ContainsKey(ProcessName))
+                return;
+
+            // 澶氬垎鏀殑鏈川涓鸿剼鏈伐鍏�,鏍规嵁branchIndex鏉ヨ蛋瀵瑰簲鐨勫垎鏀�
+            if (dicSteps[ProcessName] is LB_VisionProcesses.Processes.ScriptTool.ScriptTool ScriptTool)
+            {
+                ScriptTool.Params.Outputs.Add($"Branch{ScriptTool.Params.Outputs.Count}", false);
+                Debug.WriteLine($"鑴氭湰宸ュ叿[{ProcessName}]澧炲姞浜咮ranch{ScriptTool.Params.Outputs.Count - 1}");
+            }
+        }
+
+        private void DeleteBranch(string ProcessName)
+        {
+            var dicSteps = ProcessRunBll.GetSteps();
+            if (!dicSteps.ContainsKey(ProcessName))
+                return;
+
+            // 澶氬垎鏀殑鏈川涓鸿剼鏈伐鍏�,鏍规嵁branchIndex鏉ヨ蛋瀵瑰簲鐨勫垎鏀�
+            if (dicSteps[ProcessName] is LB_VisionProcesses.Processes.ScriptTool.ScriptTool ScriptTool
+                && ScriptTool.Params.Outputs.Remove($"Branch{ScriptTool.Params.Outputs.Count}"))
+            {
+                Debug.WriteLine($"鑴氭湰宸ュ叿[{ProcessName}]绉婚櫎浜咮ranch{ScriptTool.Params.Outputs.Count + 1}");
+            }
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.resx b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/ProcessPage/ProcessPage.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/LB_SmartVision/Forms/Pages/SettingPage/ControlStateManager.cs b/LB_SmartVision/Forms/Pages/SettingPage/ControlStateManager.cs
new file mode 100644
index 0000000..c894943
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/ControlStateManager.cs
@@ -0,0 +1,118 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    // 鏈�浼樻柟妗堝疄鐜�
+    public class ControlStateManager
+    {
+        private readonly Dictionary<string, Control> _controlMap = new Dictionary<string, Control>();
+        private readonly TableLayoutPanel _tablePanel;
+
+        public ControlStateManager(TableLayoutPanel tablePanel)
+        {
+            _tablePanel = tablePanel;
+            BuildControlMap();
+        }
+
+        // 鍒濆鍖栨椂鏋勫缓鎺т欢瀛楀吀锛堝彧闇�涓�娆★級
+        private void BuildControlMap(Control parent = null)
+        {
+            parent = parent ?? _tablePanel;
+
+            foreach (Control control in parent.Controls)
+            {
+                if (!string.IsNullOrEmpty(control.Name))
+                {
+                    _controlMap[control.Name] = control;
+                }
+
+                if (control.HasChildren)
+                {
+                    BuildControlMap(control);
+                }
+            }
+        }
+
+        // O(1) 蹇�熻闂�
+        public T GetControl<T>(string name) where T : Control
+        {
+            return _controlMap.TryGetValue(name, out Control control) ? control as T : null;
+        }
+
+        // 鑾峰彇TextBox鍊�
+        public string GetTextBoxValue(string name)
+        {
+            return GetControl<TextBox>(name)?.Text;
+        }
+
+        // 鑾峰彇CheckBox鐘舵��
+        public bool? GetCheckBoxState(string name)
+        {
+            return GetControl<CheckBox>(name)?.Checked;
+        }
+
+        /// <summary>
+        /// 鑾峰彇 ComboBox 鐨勯�変腑椤规枃鏈�
+        /// </summary>
+        public string GetComboBoxText(string comboBoxName)
+        {
+            var comboBox = GetControl<ComboBox>(comboBoxName);
+            return comboBox?.SelectedItem?.ToString() ?? string.Empty;
+        }
+
+        /// <summary>
+        /// 鑾峰彇 ComboBox 鐨勯�変腑绱㈠紩
+        /// </summary>
+        public int GetComboBoxSelectedIndex(string comboBoxName)
+        {
+            var comboBox = GetControl<ComboBox>(comboBoxName);
+            return comboBox?.SelectedIndex ?? -1;
+        }
+
+        /// <summary>
+        /// 鑾峰彇 ComboBox 鐨勬墍鏈夐」
+        /// </summary>
+        public List<object> GetComboBoxItems(string comboBoxName)
+        {
+            var comboBox = GetControl<ComboBox>(comboBoxName);
+            return comboBox?.Items.Cast<object>().ToList() ?? new List<object>();
+        }
+
+        /// <summary>
+        /// 鑾峰彇 ComboBox 鐨勫畬鏁寸姸鎬�
+        /// </summary>
+        public ComboBoxState GetComboBoxState(string comboBoxName)
+        {
+            var comboBox = GetControl<ComboBox>(comboBoxName);
+            if (comboBox == null) return null;
+
+            return new ComboBoxState
+            {
+                Items = comboBox.Items.Cast<object>().ToList(),
+                SelectedIndex = comboBox.SelectedIndex,
+                SelectedItem = comboBox.SelectedItem,
+                Text = comboBox.Text
+            };
+        }
+
+        // 鍔ㄦ�佹洿鏂版帶浠舵槧灏勶紙褰撴坊鍔�/鍒犻櫎鎺т欢鏃惰皟鐢級
+        public void RefreshControlMap()
+        {
+            _controlMap.Clear();
+            BuildControlMap();
+        }
+    }
+
+    // ComboBox 鐘舵�佹暟鎹粨鏋�
+    public class ComboBoxState
+    {
+        public List<object> Items { get; set; }
+        public int SelectedIndex { get; set; }
+        public object SelectedItem { get; set; }
+        public string Text { get; set; }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/CsvPage.Designer.cs b/LB_SmartVision/Forms/Pages/SettingPage/CsvPage.Designer.cs
new file mode 100644
index 0000000..74ccd30
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/CsvPage.Designer.cs
@@ -0,0 +1,250 @@
+锘縩amespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    partial class CsvPage
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tableLayoutPanel1 = new TableLayoutPanel();
+            tableLayoutPanel3 = new TableLayoutPanel();
+            btn_Add = new ReaLTaiizor.Controls.ForeverButton();
+            btnDel = new ReaLTaiizor.Controls.AirButton();
+            btn_Save = new ReaLTaiizor.Controls.HopeButton();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            pnlLayout = new Panel();
+            tableLayoutPanel4 = new TableLayoutPanel();
+            label2 = new Label();
+            label1 = new Label();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel3.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tableLayoutPanel4.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel3, 0, 1);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 0);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 2;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.Size = new Size(772, 535);
+            tableLayoutPanel1.TabIndex = 0;
+            // 
+            // tableLayoutPanel3
+            // 
+            tableLayoutPanel3.ColumnCount = 6;
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.Controls.Add(btn_Add, 5, 0);
+            tableLayoutPanel3.Controls.Add(btnDel, 0, 0);
+            tableLayoutPanel3.Controls.Add(btn_Save, 4, 0);
+            tableLayoutPanel3.Dock = DockStyle.Fill;
+            tableLayoutPanel3.Location = new Point(3, 488);
+            tableLayoutPanel3.Name = "tableLayoutPanel3";
+            tableLayoutPanel3.RowCount = 1;
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Size = new Size(766, 44);
+            tableLayoutPanel3.TabIndex = 2;
+            // 
+            // btn_Add
+            // 
+            btn_Add.BackColor = Color.Transparent;
+            btn_Add.BaseColor = Color.FromArgb(35, 168, 109);
+            btn_Add.Dock = DockStyle.Fill;
+            btn_Add.Font = new Font("瀹嬩綋", 12F);
+            btn_Add.Location = new Point(638, 3);
+            btn_Add.MinimumSize = new Size(1, 1);
+            btn_Add.Name = "btn_Add";
+            btn_Add.Rounded = false;
+            btn_Add.Size = new Size(125, 38);
+            btn_Add.TabIndex = 3;
+            btn_Add.Text = "娣诲姞";
+            btn_Add.TextColor = Color.FromArgb(243, 243, 243);
+            btn_Add.Click += btnAdd_Click;
+            // 
+            // btnDel
+            // 
+            btnDel.Customization = "7e3t//Ly8v/r6+v/5ubm/+vr6//f39//p6en/zw8PP8UFBT/gICA/w==";
+            btnDel.Dock = DockStyle.Fill;
+            btnDel.Font = new Font("Segoe UI", 9F);
+            btnDel.Image = null;
+            btnDel.Location = new Point(3, 3);
+            btnDel.Name = "btnDel";
+            btnDel.NoRounding = false;
+            btnDel.Size = new Size(121, 38);
+            btnDel.TabIndex = 5;
+            btnDel.Text = "绉婚櫎";
+            btnDel.Transparent = false;
+            // 
+            // btn_Save
+            // 
+            btn_Save.BorderColor = Color.FromArgb(220, 223, 230);
+            btn_Save.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            btn_Save.DangerColor = Color.FromArgb(245, 108, 108);
+            btn_Save.DefaultColor = Color.FromArgb(255, 255, 255);
+            btn_Save.Dock = DockStyle.Fill;
+            btn_Save.Font = new Font("Segoe UI", 12F);
+            btn_Save.HoverTextColor = Color.FromArgb(48, 49, 51);
+            btn_Save.InfoColor = Color.FromArgb(144, 147, 153);
+            btn_Save.Location = new Point(511, 3);
+            btn_Save.Name = "btn_Save";
+            btn_Save.PrimaryColor = Color.FromArgb(64, 158, 255);
+            btn_Save.Size = new Size(121, 38);
+            btn_Save.SuccessColor = Color.FromArgb(103, 194, 58);
+            btn_Save.TabIndex = 6;
+            btn_Save.Text = "淇濆瓨";
+            btn_Save.TextColor = Color.White;
+            btn_Save.WarningColor = Color.FromArgb(230, 162, 60);
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 1;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(pnlLayout, 0, 1);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel4, 0, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(2, 2);
+            tableLayoutPanel2.Margin = new Padding(2);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 2;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 24F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(768, 481);
+            tableLayoutPanel2.TabIndex = 6;
+            // 
+            // pnlLayout
+            // 
+            pnlLayout.Dock = DockStyle.Fill;
+            pnlLayout.Location = new Point(3, 27);
+            pnlLayout.Name = "pnlLayout";
+            pnlLayout.Size = new Size(762, 451);
+            pnlLayout.TabIndex = 3;
+            // 
+            // tableLayoutPanel4
+            // 
+            tableLayoutPanel4.ColumnCount = 2;
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 147F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel4.Controls.Add(label2, 0, 0);
+            tableLayoutPanel4.Controls.Add(label1, 0, 0);
+            tableLayoutPanel4.Dock = DockStyle.Fill;
+            tableLayoutPanel4.Location = new Point(2, 2);
+            tableLayoutPanel4.Margin = new Padding(2);
+            tableLayoutPanel4.Name = "tableLayoutPanel4";
+            tableLayoutPanel4.RowCount = 1;
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel4.Size = new Size(764, 20);
+            tableLayoutPanel4.TabIndex = 4;
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.Dock = DockStyle.Fill;
+            label2.ForeColor = SystemColors.Control;
+            label2.Location = new Point(149, 0);
+            label2.Margin = new Padding(2, 0, 2, 0);
+            label2.Name = "label2";
+            label2.Size = new Size(613, 20);
+            label2.TabIndex = 10;
+            label2.Text = "鏁版嵁";
+            label2.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Dock = DockStyle.Fill;
+            label1.ForeColor = SystemColors.Control;
+            label1.Location = new Point(2, 0);
+            label1.Margin = new Padding(2, 0, 2, 0);
+            label1.Name = "label1";
+            label1.Size = new Size(143, 20);
+            label1.TabIndex = 8;
+            label1.Text = "鍏宠仈娴佺▼";
+            label1.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // CsvPage
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(tableLayoutPanel1);
+            Name = "CsvPage";
+            Size = new Size(772, 535);
+            SizeChanged += CsvPage_SizeChanged;
+            Paint += CsvPage_Paint;
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel3.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel4.ResumeLayout(false);
+            tableLayoutPanel4.PerformLayout();
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel3;
+        private ReaLTaiizor.Controls.ForeverButton btn_Add;
+        private Panel pnlLayout;
+        private TableLayoutPanel tableLayoutPanel2;
+        private TableLayoutPanel tableLayoutPanel4;
+        private Label label1;
+        private Label label2;
+        private Label label6;
+        private Label label5;
+        private Label label4;
+        private Label label3;
+        private Label label7;
+        private Label label13;
+        private Label label12;
+        private Label label11;
+        private Label label10;
+        private Label label8;
+        private ReaLTaiizor.Controls.AirButton btnDel;
+        private ReaLTaiizor.Controls.HopeButton btn_Save;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/CsvPage.cs b/LB_SmartVision/Forms/Pages/SettingPage/CsvPage.cs
new file mode 100644
index 0000000..41df5b7
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/CsvPage.cs
@@ -0,0 +1,105 @@
+锘縰sing LB_VisionProcesses;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    public partial class CsvPage : UserControl
+    {
+        public CsvPage()
+        {
+            InitializeComponent();
+
+            btn_Save.Click += (sender, e) =>
+            {
+                if (!VisionForm.SaveAllCsv())
+                    MessageBox.Show("!!!淇濆瓨澶辫触!!!", "寮傚父");
+                else
+                    MessageBox.Show("淇濆瓨鎴愬姛!");
+            };
+
+            btnDel.Click += (sender, e) =>
+            {
+                foreach (var control in pnlLayout.Controls)
+                {
+                    if (control is CsvSettingControl csvSettingControl
+                        && csvSettingControl.IsSelected)
+                    {
+                        var item = GlobalVar.dicLayout.FirstOrDefault(x => x.Value.Title == csvSettingControl.Title);
+                        GlobalVar.dicLayout.TryRemove(item.Key, out _);
+                    }
+                }
+                this.Invalidate();
+            };
+        }
+
+        private void CsvPage_Paint(object sender, PaintEventArgs e)
+        {
+            //this.pnlLayout.Controls.Clear();
+
+            //var sortedKeys = GlobalVar.dicCsvSetting.Keys
+            //    .OrderBy(k => k, new NaturalStringComparer())
+            //    .ToList();
+
+            //int index = 0;
+            //foreach (var key in sortedKeys)
+            //{
+            //    string ProcessesName = key;
+
+            //    CsvSettingControl control = new CsvSettingControl(GlobalVar.dicCsvSetting[ProcessesName]);
+            //    control.Size = new Size(this.pnlLayout.Size.Width, control.Size.Height);
+            //    control.Location = new Point(0, control.Size.Height * index);
+            //    this.pnlLayout.Controls.Add(control);
+            //    index++;
+            //}
+        }
+
+        private void CsvPage_SizeChanged(object sender, EventArgs e) => CsvPage_VisibleChanged(sender, e);
+
+        private void CsvPage_VisibleChanged(object sender, EventArgs e)
+        {
+            this.pnlLayout.Controls.Clear();
+
+            var sortedKeys = GlobalVar.dicCsvSetting.Keys
+                .OrderBy(k => k, new NaturalStringComparer())
+                .ToList();
+
+            int index = 0;
+            foreach (var key in sortedKeys)
+            {
+                string ProcessesName = key;
+
+                CsvSettingControl control = new CsvSettingControl(GlobalVar.dicCsvSetting[ProcessesName]);
+                control.Size = new Size(this.pnlLayout.Size.Width, control.Size.Height);
+                control.Location = new Point(0, control.Size.Height * index);
+                this.pnlLayout.Controls.Add(control);
+                index++;
+            }
+        }
+
+        private void btnAdd_Click(object sender, EventArgs e)
+        {
+            GlobalVar.dicCsvSetting.TryAdd($"{GlobalVar.dicCsvSetting.Count}", new CsvSetting());
+
+            CsvPage_VisibleChanged(sender, e);
+        }
+    }
+
+    [Serializable]
+    public class CsvSetting
+    {
+        public string ProcessName { get; set; } = string.Empty;
+
+        public List<string> Others { get; set; } = new List<string>();
+
+        public CsvSetting() { }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/CsvPage.resx b/LB_SmartVision/Forms/Pages/SettingPage/CsvPage.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/CsvPage.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/LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.Designer.cs b/LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.Designer.cs
new file mode 100644
index 0000000..f33ce6a
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.Designer.cs
@@ -0,0 +1,122 @@
+锘縩amespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    partial class CsvSettingControl
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tableLayoutPanel1 = new TableLayoutPanel();
+            btn_DelMsg = new Button();
+            btn_AddMsg = new Button();
+            cmb_Process = new ComboBox();
+            ckb_Selected = new CheckBox();
+            tableLayoutPanel1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            tableLayoutPanel1.ColumnCount = 5;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 150F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(btn_DelMsg, 3, 0);
+            tableLayoutPanel1.Controls.Add(btn_AddMsg, 2, 0);
+            tableLayoutPanel1.Controls.Add(cmb_Process, 1, 0);
+            tableLayoutPanel1.Controls.Add(ckb_Selected, 0, 0);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 1;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Size = new Size(807, 30);
+            tableLayoutPanel1.TabIndex = 0;
+            // 
+            // btn_DelMsg
+            // 
+            btn_DelMsg.Dock = DockStyle.Fill;
+            btn_DelMsg.Location = new Point(223, 3);
+            btn_DelMsg.Name = "btn_DelMsg";
+            btn_DelMsg.Size = new Size(44, 24);
+            btn_DelMsg.TabIndex = 29;
+            btn_DelMsg.Text = "-";
+            btn_DelMsg.UseVisualStyleBackColor = true;
+            btn_DelMsg.Click += btnDelMsg_Click;
+            // 
+            // btn_AddMsg
+            // 
+            btn_AddMsg.Dock = DockStyle.Fill;
+            btn_AddMsg.Location = new Point(173, 3);
+            btn_AddMsg.Name = "btn_AddMsg";
+            btn_AddMsg.Size = new Size(44, 24);
+            btn_AddMsg.TabIndex = 28;
+            btn_AddMsg.Text = "+";
+            btn_AddMsg.UseVisualStyleBackColor = true;
+            btn_AddMsg.Click += btnAddMsg_Click;
+            // 
+            // cmb_Process
+            // 
+            cmb_Process.Dock = DockStyle.Fill;
+            cmb_Process.FormattingEnabled = true;
+            cmb_Process.Location = new Point(23, 3);
+            cmb_Process.Name = "cmb_Process";
+            cmb_Process.Size = new Size(144, 25);
+            cmb_Process.TabIndex = 7;
+            // 
+            // ckb_Selected
+            // 
+            ckb_Selected.AutoSize = true;
+            ckb_Selected.Dock = DockStyle.Fill;
+            ckb_Selected.Location = new Point(3, 3);
+            ckb_Selected.Name = "ckb_Selected";
+            ckb_Selected.Size = new Size(14, 24);
+            ckb_Selected.TabIndex = 30;
+            ckb_Selected.Text = " ";
+            ckb_Selected.UseVisualStyleBackColor = true;
+            // 
+            // CsvSettingControl
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(tableLayoutPanel1);
+            Name = "CsvSettingControl";
+            Size = new Size(807, 30);
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel1.PerformLayout();
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private TableLayoutPanel tableLayoutPanel1;
+        private ComboBox cmb_Process;
+        private Button btn_AddMsg;
+        private Button btn_DelMsg;
+        private CheckBox ckb_Selected;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.cs b/LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.cs
new file mode 100644
index 0000000..177f9d3
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.cs
@@ -0,0 +1,257 @@
+锘縰sing HalconDotNet;
+using LB_SmartVision.ProcessRun;
+using OpenCvSharp.Flann;
+using ReaLTaiizor.Controls;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    public partial class CsvSettingControl : UserControl
+    {
+        ConcurrentDictionary<string, ComboBox> dicComboxs = new ConcurrentDictionary<string, ComboBox>();
+
+        public bool IsSelected { get { return ckb_Selected.Checked; } }
+
+        public string Title { get { return RunBll.Name; } }
+
+        private CsvSetting csv { get; set; } = new CsvSetting();
+
+        private ProcessRunBll RunBll
+        {
+            get
+            {
+                if (GlobalVar.dicProcesses.ContainsKey(cmb_Process.Text))
+                    return GlobalVar.dicProcesses[cmb_Process.Text];
+                else
+                    return null;
+            }
+        }
+
+        public CsvSettingControl(CsvSetting csv = null)
+        {
+            InitializeComponent();
+
+            if (csv == null)
+                csv = new CsvSetting();
+            this.csv = csv;
+
+            cmb_Process.MouseClick += MouseClick;
+            cmb_Process.SelectedIndexChanged += SelectedIndexChanged;
+
+            cmb_Process.Items.Clear();
+            cmb_Process.Items.Add("");
+            cmb_Process.Items.AddRange(GlobalVar.dicProcesses.Keys.ToArray());
+
+            cmb_Process.Text = csv.ProcessName;
+
+            if (csv.Others.Count > 0)
+            {
+                Single perSpace = 100 / csv.Others.Count;
+
+                while (tableLayoutPanel1.ColumnCount - 4 < csv.Others.Count)
+                {
+                    tableLayoutPanel1.ColumnCount++;
+                    tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, perSpace));
+                }
+
+                for (int i = 4; i < tableLayoutPanel1.ColumnCount; i++)
+                {
+                    tableLayoutPanel1.ColumnStyles[i].SizeType = SizeType.Percent;
+                    tableLayoutPanel1.ColumnStyles[i].Width = perSpace;
+                }
+
+                int index = 0;
+                foreach (var value in csv.Others)
+                {
+                    string key = $"cmb{index}";
+                    if (!dicComboxs.ContainsKey(key))
+                    {
+                        ComboBox comboBox = new ComboBox();
+                        comboBox.Name = key;
+                        comboBox.MouseClick += MouseClick;
+                        comboBox.SelectedIndexChanged += SelectedIndexChanged;
+                        comboBox.Text = value;
+                        comboBox.Dock = DockStyle.Fill;
+                        tableLayoutPanel1.Controls.Add(comboBox, index + 4, 0);
+                        dicComboxs.TryAdd(key, comboBox);
+                    }
+                    else
+                        dicComboxs[key].Text = value;
+
+                    index++;
+                }
+            }
+
+            // 鎭㈠甯冨眬锛堝彧瑙﹀彂涓�娆¢噸缁橈級
+            tableLayoutPanel1.ResumeLayout(false);
+            this.ResumeLayout(false);
+        }
+
+        private void MouseClick(object sender, EventArgs e)
+        {
+            switch ((sender as ComboBox).Name)
+            {
+                case "cmbProcess":
+                    cmb_Process.Items.Clear();
+                    cmb_Process.Items.Add("");
+                    cmb_Process.Items.AddRange(GlobalVar.dicProcesses.Keys.ToArray());
+                    break;
+                default:
+                    ComboBox comboBox = sender as ComboBox;
+                    if (comboBox != null && comboBox.Name.StartsWith("cmb"))
+                    {
+                        comboBox.Items.Clear();
+                        comboBox.Items.Add("");
+                        if (RunBll == null)
+                            return;
+                        foreach (var lstOutput in RunBll.dicOutputsMapping)
+                        {
+                            foreach (var output in lstOutput.Value)
+                                comboBox.Items.Add(output);
+                        }
+
+                        foreach (var lstInput in RunBll.dicInputsMapping)
+                        {
+                            foreach (var tuple in lstInput.Value)
+                            {
+                                string inputs = tuple.Item1;
+                                comboBox.Items.Add(inputs);
+                            }
+                        }
+                    }
+                    break;
+            }
+        }
+
+        private void SelectedIndexChanged(object sender, EventArgs e)
+        {
+            switch ((sender as ComboBox).Name)
+            {
+                case "cmbProcess":
+                    csv.ProcessName = cmb_Process.Text;
+                    break;
+                default:
+                    // 鏇存柊瀛楀吀
+                    ComboBox comboBox = sender as ComboBox;
+                    if (comboBox != null && comboBox.Name.StartsWith("cmb"))
+                    {
+                        if (int.TryParse(comboBox.Name.Replace("cmb", ""), out int index))
+                        {
+                            if (index < csv.Others.Count)
+                                csv.Others[index] = comboBox.Text;
+                            else
+                                csv.Others.Add(comboBox.Text);
+                        }
+                    }
+                    break;
+            }
+        }
+
+        private void btnAddMsg_Click(object sender, EventArgs e)
+        {
+            csv.Others.Add("");
+
+            this.BeginInvoke(new Action(() =>
+            {
+                if (csv.Others.Count > 0)
+                {
+                    Single perSpace = 100 / csv.Others.Count;
+
+                    while (tableLayoutPanel1.ColumnCount - 4 < csv.Others.Count)
+                    {
+                        tableLayoutPanel1.ColumnCount++;
+                        tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, perSpace));
+                    }
+
+                    for (int i = 4; i < tableLayoutPanel1.ColumnCount; i++)
+                    {
+                        tableLayoutPanel1.ColumnStyles[i].SizeType = SizeType.Percent;
+                        tableLayoutPanel1.ColumnStyles[i].Width = perSpace;
+                    }
+
+                    int index = 0;
+                    foreach (var value in csv.Others)
+                    {
+                        string key = $"cmb{index}";
+                        if (!dicComboxs.ContainsKey(key))
+                        {
+                            ComboBox comboBox = new ComboBox();
+                            comboBox.Name = key;
+                            comboBox.MouseClick += MouseClick;
+                            comboBox.SelectedIndexChanged += SelectedIndexChanged;
+                            comboBox.Text = value;
+                            comboBox.Dock = DockStyle.Fill;
+                            tableLayoutPanel1.Controls.Add(comboBox, index + 4, 0);
+                            dicComboxs.TryAdd(key, comboBox);
+                        }
+                        else
+                            dicComboxs[key].Text = value;
+
+                        index++;
+                    }
+                }
+            }));
+        }
+
+        private void btnDelMsg_Click(object sender, EventArgs e)
+        {
+            if (csv.Others.Count <= 0)
+                return;
+
+            if (dicComboxs.TryRemove($"cmb{csv.Others.Count - 1}", out ComboBox cmb))
+            {
+                cmb.MouseClick -= MouseClick;
+                cmb.SelectedIndexChanged -= SelectedIndexChanged;
+                tableLayoutPanel1.Controls.Remove(cmb);
+                csv.Others.RemoveAt(csv.Others.Count - 1);
+            }
+
+            this.BeginInvoke(new Action(() =>
+            {
+                if (csv.Others.Count > 0)
+                {
+                    Single perSpace = 100 / csv.Others.Count;
+
+                    tableLayoutPanel1.ColumnCount--;
+                    tableLayoutPanel1.ColumnStyles.RemoveAt(tableLayoutPanel1.ColumnStyles.Count - 1);
+
+                    for (int i = 4; i < tableLayoutPanel1.ColumnCount; i++)
+                    {
+                        tableLayoutPanel1.ColumnStyles[i].SizeType = SizeType.Percent;
+                        tableLayoutPanel1.ColumnStyles[i].Width = perSpace;
+                    }
+
+                    int index = 0;
+                    foreach (var value in csv.Others)
+                    {
+                        string key = $"cmb{index}";
+                        if (!dicComboxs.ContainsKey(key))
+                        {
+                            ComboBox comboBox = new ComboBox();
+                            comboBox.Name = key;
+                            comboBox.MouseClick += MouseClick;
+                            comboBox.SelectedIndexChanged += SelectedIndexChanged;
+                            comboBox.Text = value;
+                            comboBox.Dock = DockStyle.Fill;
+                            tableLayoutPanel1.Controls.Add(comboBox, index + 4, 0);
+                            dicComboxs.TryAdd(key, comboBox);
+                        }
+                        else
+                            dicComboxs[key].Text = value;
+
+                        index++;
+                    }
+                }
+            }));
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.resx b/LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/CsvSettingControl.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/LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.Designer.cs b/LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.Designer.cs
new file mode 100644
index 0000000..8e48839
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.Designer.cs
@@ -0,0 +1,341 @@
+锘縩amespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    partial class LayoutPage
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tableLayoutPanel1 = new TableLayoutPanel();
+            tableLayoutPanel3 = new TableLayoutPanel();
+            btn_Add = new ReaLTaiizor.Controls.ForeverButton();
+            btn_Del = new ReaLTaiizor.Controls.AirButton();
+            btn_Save = new ReaLTaiizor.Controls.HopeButton();
+            btn_Top = new ReaLTaiizor.Controls.AirButton();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            pnlLayout = new Panel();
+            tableLayoutPanel4 = new TableLayoutPanel();
+            label7 = new Label();
+            label6 = new Label();
+            label5 = new Label();
+            label4 = new Label();
+            label3 = new Label();
+            label1 = new Label();
+            label2 = new Label();
+            label8 = new Label();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel3.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tableLayoutPanel4.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel3, 0, 1);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 0);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 2;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.Size = new Size(772, 535);
+            tableLayoutPanel1.TabIndex = 0;
+            // 
+            // tableLayoutPanel3
+            // 
+            tableLayoutPanel3.ColumnCount = 6;
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.Controls.Add(btn_Add, 5, 0);
+            tableLayoutPanel3.Controls.Add(btn_Del, 0, 0);
+            tableLayoutPanel3.Controls.Add(btn_Save, 4, 0);
+            tableLayoutPanel3.Controls.Add(btn_Top, 1, 0);
+            tableLayoutPanel3.Dock = DockStyle.Fill;
+            tableLayoutPanel3.Location = new Point(3, 488);
+            tableLayoutPanel3.Name = "tableLayoutPanel3";
+            tableLayoutPanel3.RowCount = 1;
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Size = new Size(766, 44);
+            tableLayoutPanel3.TabIndex = 2;
+            // 
+            // btn_Add
+            // 
+            btn_Add.BackColor = Color.Transparent;
+            btn_Add.BaseColor = Color.FromArgb(35, 168, 109);
+            btn_Add.Dock = DockStyle.Fill;
+            btn_Add.Font = new Font("瀹嬩綋", 12F);
+            btn_Add.Location = new Point(638, 3);
+            btn_Add.MinimumSize = new Size(1, 1);
+            btn_Add.Name = "btn_Add";
+            btn_Add.Rounded = false;
+            btn_Add.Size = new Size(125, 38);
+            btn_Add.TabIndex = 3;
+            btn_Add.Text = "娣诲姞";
+            btn_Add.TextColor = Color.FromArgb(243, 243, 243);
+            btn_Add.Click += btnAdd_Click;
+            // 
+            // btn_Del
+            // 
+            btn_Del.Customization = "7e3t//Ly8v/r6+v/5ubm/+vr6//f39//p6en/zw8PP8UFBT/gICA/w==";
+            btn_Del.Font = new Font("Segoe UI", 9F);
+            btn_Del.Image = null;
+            btn_Del.Location = new Point(3, 3);
+            btn_Del.Name = "btn_Del";
+            btn_Del.NoRounding = false;
+            btn_Del.Size = new Size(121, 38);
+            btn_Del.TabIndex = 4;
+            btn_Del.Text = "绉婚櫎";
+            btn_Del.Transparent = false;
+            btn_Del.Click += btnDel_Click;
+            // 
+            // btn_Save
+            // 
+            btn_Save.BorderColor = Color.FromArgb(220, 223, 230);
+            btn_Save.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            btn_Save.DangerColor = Color.FromArgb(245, 108, 108);
+            btn_Save.DefaultColor = Color.FromArgb(255, 255, 255);
+            btn_Save.Font = new Font("Segoe UI", 12F);
+            btn_Save.HoverTextColor = Color.FromArgb(48, 49, 51);
+            btn_Save.InfoColor = Color.FromArgb(144, 147, 153);
+            btn_Save.Location = new Point(511, 3);
+            btn_Save.Name = "btn_Save";
+            btn_Save.PrimaryColor = Color.FromArgb(64, 158, 255);
+            btn_Save.Size = new Size(121, 38);
+            btn_Save.SuccessColor = Color.FromArgb(103, 194, 58);
+            btn_Save.TabIndex = 5;
+            btn_Save.Text = "淇濆瓨";
+            btn_Save.TextColor = Color.White;
+            btn_Save.WarningColor = Color.FromArgb(230, 162, 60);
+            // 
+            // btn_Top
+            // 
+            btn_Top.Customization = "7e3t//Ly8v/r6+v/5ubm/+vr6//f39//p6en/zw8PP8UFBT/gICA/w==";
+            btn_Top.Dock = DockStyle.Fill;
+            btn_Top.Font = new Font("Segoe UI", 9F);
+            btn_Top.Image = null;
+            btn_Top.Location = new Point(130, 3);
+            btn_Top.Name = "btn_Top";
+            btn_Top.NoRounding = false;
+            btn_Top.Size = new Size(121, 38);
+            btn_Top.TabIndex = 6;
+            btn_Top.Text = "涓婄Щ";
+            btn_Top.Transparent = false;
+            btn_Top.Click += btnTop_Click;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 1;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(pnlLayout, 0, 1);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel4, 0, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.ForeColor = SystemColors.Control;
+            tableLayoutPanel2.Location = new Point(2, 2);
+            tableLayoutPanel2.Margin = new Padding(2);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 2;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 24F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(768, 481);
+            tableLayoutPanel2.TabIndex = 6;
+            // 
+            // pnlLayout
+            // 
+            pnlLayout.Dock = DockStyle.Fill;
+            pnlLayout.Location = new Point(3, 27);
+            pnlLayout.Name = "pnlLayout";
+            pnlLayout.Size = new Size(762, 451);
+            pnlLayout.TabIndex = 3;
+            // 
+            // tableLayoutPanel4
+            // 
+            tableLayoutPanel4.ColumnCount = 8;
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 147F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2881641F));
+            tableLayoutPanel4.Controls.Add(label7, 6, 0);
+            tableLayoutPanel4.Controls.Add(label6, 5, 0);
+            tableLayoutPanel4.Controls.Add(label5, 4, 0);
+            tableLayoutPanel4.Controls.Add(label4, 3, 0);
+            tableLayoutPanel4.Controls.Add(label3, 2, 0);
+            tableLayoutPanel4.Controls.Add(label1, 0, 0);
+            tableLayoutPanel4.Controls.Add(label2, 1, 0);
+            tableLayoutPanel4.Controls.Add(label8, 7, 0);
+            tableLayoutPanel4.Dock = DockStyle.Fill;
+            tableLayoutPanel4.Location = new Point(2, 2);
+            tableLayoutPanel4.Margin = new Padding(2);
+            tableLayoutPanel4.Name = "tableLayoutPanel4";
+            tableLayoutPanel4.RowCount = 1;
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel4.Size = new Size(764, 20);
+            tableLayoutPanel4.TabIndex = 4;
+            // 
+            // label7
+            // 
+            label7.AutoSize = true;
+            label7.Dock = DockStyle.Fill;
+            label7.Location = new Point(589, 0);
+            label7.Margin = new Padding(2, 0, 2, 0);
+            label7.Name = "label7";
+            label7.Size = new Size(84, 20);
+            label7.TabIndex = 6;
+            label7.Text = "瀛樺浘璺緞";
+            label7.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label6
+            // 
+            label6.AutoSize = true;
+            label6.Dock = DockStyle.Fill;
+            label6.Location = new Point(501, 0);
+            label6.Margin = new Padding(2, 0, 2, 0);
+            label6.Name = "label6";
+            label6.Size = new Size(84, 20);
+            label6.TabIndex = 5;
+            label6.Text = "缁樺埗缁撴灉3";
+            label6.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Dock = DockStyle.Fill;
+            label5.Location = new Point(413, 0);
+            label5.Margin = new Padding(2, 0, 2, 0);
+            label5.Name = "label5";
+            label5.Size = new Size(84, 20);
+            label5.TabIndex = 4;
+            label5.Text = "缁樺埗缁撴灉2";
+            label5.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label4
+            // 
+            label4.AutoSize = true;
+            label4.Dock = DockStyle.Fill;
+            label4.Location = new Point(325, 0);
+            label4.Margin = new Padding(2, 0, 2, 0);
+            label4.Name = "label4";
+            label4.Size = new Size(84, 20);
+            label4.TabIndex = 3;
+            label4.Text = "缁樺埗缁撴灉1";
+            label4.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label3
+            // 
+            label3.AutoSize = true;
+            label3.Dock = DockStyle.Fill;
+            label3.Location = new Point(237, 0);
+            label3.Margin = new Padding(2, 0, 2, 0);
+            label3.Name = "label3";
+            label3.Size = new Size(84, 20);
+            label3.TabIndex = 2;
+            label3.Text = "鏄剧ず鍥剧墖";
+            label3.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Dock = DockStyle.Fill;
+            label1.ForeColor = SystemColors.Control;
+            label1.Location = new Point(2, 0);
+            label1.Margin = new Padding(2, 0, 2, 0);
+            label1.Name = "label1";
+            label1.Size = new Size(143, 20);
+            label1.TabIndex = 0;
+            label1.Text = "鏄剧ず鍚嶇О";
+            label1.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.Dock = DockStyle.Fill;
+            label2.Location = new Point(149, 0);
+            label2.Margin = new Padding(2, 0, 2, 0);
+            label2.Name = "label2";
+            label2.Size = new Size(84, 20);
+            label2.TabIndex = 1;
+            label2.Text = "鍏宠仈娴佺▼";
+            label2.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label8
+            // 
+            label8.AutoSize = true;
+            label8.Dock = DockStyle.Fill;
+            label8.Location = new Point(677, 0);
+            label8.Margin = new Padding(2, 0, 2, 0);
+            label8.Name = "label8";
+            label8.Size = new Size(85, 20);
+            label8.TabIndex = 7;
+            label8.Text = "鍥剧墖鍓嶇紑";
+            label8.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // LayoutPage
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(tableLayoutPanel1);
+            Name = "LayoutPage";
+            Size = new Size(772, 535);
+            Paint += LayoutPage_Paint;
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel3.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel4.ResumeLayout(false);
+            tableLayoutPanel4.PerformLayout();
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel3;
+        private ReaLTaiizor.Controls.ForeverButton btn_Add;
+        private Panel pnlLayout;
+        private ReaLTaiizor.Controls.AirButton btn_Del;
+        private ReaLTaiizor.Controls.HopeButton btn_Save;
+        private TableLayoutPanel tableLayoutPanel2;
+        private TableLayoutPanel tableLayoutPanel4;
+        private Label label1;
+        private Label label2;
+        private Label label6;
+        private Label label5;
+        private Label label4;
+        private Label label3;
+        private Label label7;
+        private Label label8;
+        private ReaLTaiizor.Controls.AirButton btn_Top;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.cs b/LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.cs
new file mode 100644
index 0000000..1679c30
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.cs
@@ -0,0 +1,134 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    public partial class LayoutPage : UserControl
+    {
+        public LayoutPage()
+        {
+            InitializeComponent();
+
+            btn_Save.Click += (sender, e) =>
+            {
+                if (!VisionForm.SaveAllLayout())
+                    MessageBox.Show("!!!淇濆瓨澶辫触!!!", "寮傚父");
+                else
+                    MessageBox.Show("淇濆瓨鎴愬姛!");
+            };
+        }
+
+        private void LayoutPage_Paint(object sender, PaintEventArgs e)
+        {
+            this.pnlLayout.Controls.Clear();
+
+            for (int index = 0; index < GlobalVar.dicLayout.Count; index++)
+            {
+                LayoutSettingControl control = new LayoutSettingControl(GlobalVar.dicLayout[index]);
+                control.Size = new Size(this.pnlLayout.Size.Width, control.Size.Height);
+                control.Location = new Point(0, control.Size.Height * index);
+                this.pnlLayout.Controls.Add(control);
+            }
+        }
+
+        private void btnAdd_Click(object sender, EventArgs e)
+        {
+            Layout layout = new Layout(GlobalVar.strApplicationPath + "\\鐢熶骇鍥剧墖");
+            foreach (var item in GlobalVar.dicLayout.Values)
+            {
+                if (item.Title == layout.Title)
+                    layout.Title += "(鍓湰)";
+            }
+            GlobalVar.dicLayout.TryAdd(GlobalVar.dicLayout.Count, layout);
+            this.Invalidate();
+        }
+
+        private void btnDel_Click(object sender, EventArgs e)
+        {
+            foreach (var control in pnlLayout.Controls)
+            {
+                if (control is LayoutSettingControl layoutSettingControl
+                    && layoutSettingControl.IsSelected)
+                {
+                    var item = GlobalVar.dicLayout.FirstOrDefault(x => x.Value.Title == layoutSettingControl.Title);
+                    GlobalVar.dicLayout.TryRemove(item.Key, out _);
+                }
+            }
+            this.Invalidate();
+        }
+
+        private void btnTop_Click(object sender, EventArgs e)
+        {
+            bool isSelected = false;
+            foreach (var control in pnlLayout.Controls)
+            {
+                if (control is LayoutSettingControl layoutSettingControl
+                    && layoutSettingControl.IsSelected)
+                {
+                    if (isSelected)
+                    {
+                        MessageBox.Show("姣忔鍙兘涓婄Щ涓�涓�!", "寮傚父");
+                        return;
+                    }
+                    isSelected = true;
+                }
+            }
+
+            for (int index = 0; index < GlobalVar.dicLayout.Count; index++)
+            {
+                foreach (var control in pnlLayout.Controls)
+                {
+                    if (control is LayoutSettingControl layoutSettingControl
+                        && layoutSettingControl.IsSelected)
+                    {
+                        var item = GlobalVar.dicLayout.FirstOrDefault(x => x.Value.Title == layoutSettingControl.Title);
+                        int Key = item.Key;
+                        // 宸茬粡鏄涓�涓簡锛屽垯鏃犲彉鍖�
+                        if (Key == 0)
+                            return;
+
+                        var temp = GlobalVar.dicLayout[Key - 1];
+                        GlobalVar.dicLayout[Key - 1] = item.Value;
+                        GlobalVar.dicLayout[Key] = temp;
+                        this.Invalidate();
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    [Serializable]
+    public class Layout
+    {
+        public string Title { get; set; } = "甯冨眬";
+
+        public string ProcessName { get; set; } = string.Empty;
+
+        public string InputImage { get; set; } = string.Empty;
+
+        public string SaveImageDir { get; set; } = string.Empty;
+
+        public string SaveImageHead { get; set; } = string.Empty;
+
+        public string ImageTitle { get; set; } = string.Empty;
+
+        public string RecordImage1 { get; set; } = string.Empty;
+
+        public string RecordImage2 { get; set; } = string.Empty;
+
+        public string RecordImage3 { get; set; } = string.Empty;
+
+        public Layout() { }
+
+        public Layout(string path) { SaveImageDir = path; }
+
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.resx b/LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/LayoutPage.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/LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.Designer.cs b/LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.Designer.cs
new file mode 100644
index 0000000..18f3143
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.Designer.cs
@@ -0,0 +1,172 @@
+锘縩amespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    partial class LayoutSettingControl
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tableLayoutPanel1 = new TableLayoutPanel();
+            lblName = new CheckBox();
+            cmbInputImage = new ComboBox();
+            cmbProcess = new ComboBox();
+            cmbRecord1 = new ComboBox();
+            cmbRecord2 = new ComboBox();
+            cmbRecord3 = new ComboBox();
+            txtSavePath = new TextBox();
+            txtSaveNameHead = new TextBox();
+            tableLayoutPanel1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            tableLayoutPanel1.ColumnCount = 8;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 150F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2853069F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 14.2881641F));
+            tableLayoutPanel1.Controls.Add(lblName, 0, 0);
+            tableLayoutPanel1.Controls.Add(cmbInputImage, 2, 0);
+            tableLayoutPanel1.Controls.Add(cmbProcess, 1, 0);
+            tableLayoutPanel1.Controls.Add(cmbRecord1, 3, 0);
+            tableLayoutPanel1.Controls.Add(cmbRecord2, 4, 0);
+            tableLayoutPanel1.Controls.Add(cmbRecord3, 5, 0);
+            tableLayoutPanel1.Controls.Add(txtSavePath, 6, 0);
+            tableLayoutPanel1.Controls.Add(txtSaveNameHead, 7, 0);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 1;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Size = new Size(807, 30);
+            tableLayoutPanel1.TabIndex = 0;
+            // 
+            // lblName
+            // 
+            lblName.AutoSize = true;
+            lblName.Dock = DockStyle.Fill;
+            lblName.ForeColor = SystemColors.Control;
+            lblName.Location = new Point(3, 3);
+            lblName.Name = "lblName";
+            lblName.Size = new Size(144, 24);
+            lblName.TabIndex = 6;
+            lblName.Text = "鍚嶇О";
+            lblName.TextAlign = ContentAlignment.MiddleRight;
+            lblName.UseVisualStyleBackColor = true;
+            lblName.MouseDown += lblName_MouseDown;
+            // 
+            // cmbInputImage
+            // 
+            cmbInputImage.Dock = DockStyle.Fill;
+            cmbInputImage.FormattingEnabled = true;
+            cmbInputImage.Location = new Point(246, 3);
+            cmbInputImage.Name = "cmbInputImage";
+            cmbInputImage.Size = new Size(87, 25);
+            cmbInputImage.TabIndex = 0;
+            // 
+            // cmbProcess
+            // 
+            cmbProcess.Dock = DockStyle.Fill;
+            cmbProcess.FormattingEnabled = true;
+            cmbProcess.Location = new Point(153, 3);
+            cmbProcess.Name = "cmbProcess";
+            cmbProcess.Size = new Size(87, 25);
+            cmbProcess.TabIndex = 7;
+            // 
+            // cmbRecord1
+            // 
+            cmbRecord1.Dock = DockStyle.Fill;
+            cmbRecord1.FormattingEnabled = true;
+            cmbRecord1.Location = new Point(339, 3);
+            cmbRecord1.Name = "cmbRecord1";
+            cmbRecord1.Size = new Size(87, 25);
+            cmbRecord1.TabIndex = 1;
+            // 
+            // cmbRecord2
+            // 
+            cmbRecord2.Dock = DockStyle.Fill;
+            cmbRecord2.FormattingEnabled = true;
+            cmbRecord2.Location = new Point(432, 3);
+            cmbRecord2.Name = "cmbRecord2";
+            cmbRecord2.Size = new Size(87, 25);
+            cmbRecord2.TabIndex = 2;
+            // 
+            // cmbRecord3
+            // 
+            cmbRecord3.Dock = DockStyle.Fill;
+            cmbRecord3.FormattingEnabled = true;
+            cmbRecord3.Location = new Point(525, 3);
+            cmbRecord3.Name = "cmbRecord3";
+            cmbRecord3.Size = new Size(87, 25);
+            cmbRecord3.TabIndex = 5;
+            // 
+            // txtSavePath
+            // 
+            txtSavePath.Dock = DockStyle.Fill;
+            txtSavePath.Location = new Point(618, 3);
+            txtSavePath.Name = "txtSavePath";
+            txtSavePath.Size = new Size(87, 23);
+            txtSavePath.TabIndex = 4;
+            txtSavePath.MouseDoubleClick += txtSavePath_MouseDoubleClick;
+            // 
+            // txtSaveNameHead
+            // 
+            txtSaveNameHead.Dock = DockStyle.Fill;
+            txtSaveNameHead.Location = new Point(711, 3);
+            txtSaveNameHead.Name = "txtSaveNameHead";
+            txtSaveNameHead.Size = new Size(93, 23);
+            txtSaveNameHead.TabIndex = 8;
+            txtSaveNameHead.MouseDoubleClick += txtSaveNameHead_MouseDoubleClick;
+            // 
+            // LayoutSettingControl
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(tableLayoutPanel1);
+            Name = "LayoutSettingControl";
+            Size = new Size(807, 30);
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel1.PerformLayout();
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private TableLayoutPanel tableLayoutPanel1;
+        private ComboBox cmbInputImage;
+        private ComboBox cmbRecord1;
+        private ComboBox cmbRecord2;
+        private TextBox txtSavePath;
+        private ComboBox cmbRecord3;
+        private CheckBox lblName;
+        private ComboBox cmbProcess;
+        private TextBox txtSaveNameHead;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.cs b/LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.cs
new file mode 100644
index 0000000..4e6e036
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.cs
@@ -0,0 +1,275 @@
+锘縰sing HalconDotNet;
+using LB_SmartVision.Forms.Pages.ProcessPage;
+using LB_SmartVision.ProcessRun;
+using ReaLTaiizor.Controls;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using VisionControl.Forms;
+
+namespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    public partial class LayoutSettingControl : UserControl
+    {
+        private Layout layout { get; set; } = new Layout();
+
+        private ProcessRunBll processRunBll
+        {
+            get
+            {
+                if (GlobalVar.dicProcesses.ContainsKey(cmbProcess.Text))
+                    return GlobalVar.dicProcesses[cmbProcess.Text];
+                else
+                    return null;
+            }
+        }
+
+        public bool IsSelected { get { return lblName.Checked; } }
+
+        public string Title { get { return lblName.Text; } }
+
+        public string ProcessName { get { return cmbProcess.Text; } }
+
+        public string InputImage { get { return cmbInputImage.Text; } }
+
+        public string SaveImageDir { get { return txtSavePath.Text; } }
+
+        public string RecordImage1 { get { return cmbRecord1.Text; } }
+
+        public string RecordImage2 { get { return cmbRecord2.Text; } }
+
+        public string RecordImage3 { get { return cmbRecord3.Text; } }
+
+        public LayoutSettingControl(Layout layout = null)
+        {
+            InitializeComponent();
+
+            this.layout = layout;
+
+            txtSavePath.TextChanged += TextChanged;
+            txtSavePath.MouseHover += MouseHover;
+
+            txtSaveNameHead.TextChanged += TextChanged;
+            txtSaveNameHead.MouseHover += MouseHover;
+
+            cmbProcess.MouseClick += MouseClick;
+            cmbInputImage.MouseClick += MouseClick;
+            cmbRecord1.MouseClick += MouseClick;
+            cmbRecord2.MouseClick += MouseClick;
+            cmbRecord3.MouseClick += MouseClick;
+
+            cmbProcess.SelectedIndexChanged += SelectedIndexChanged;
+            cmbInputImage.SelectedIndexChanged += SelectedIndexChanged;
+            cmbRecord1.SelectedIndexChanged += SelectedIndexChanged;
+            cmbRecord2.SelectedIndexChanged += SelectedIndexChanged;
+            cmbRecord3.SelectedIndexChanged += SelectedIndexChanged;
+
+            cmbProcess.Items.Clear();
+            cmbProcess.Items.Add("");
+            cmbProcess.Items.AddRange(GlobalVar.dicProcesses.Keys.ToArray());
+
+            if (layout != null)
+            {
+                lblName.Text = layout.Title;
+                cmbProcess.Text = layout.ProcessName;
+                cmbInputImage.Text = layout.InputImage;
+                cmbRecord1.Text = layout.RecordImage1;
+                cmbRecord2.Text = layout.RecordImage2;
+                cmbRecord3.Text = layout.RecordImage3;
+
+                txtSavePath.Text = layout.SaveImageDir;
+                txtSaveNameHead.Text = layout.SaveImageHead;
+            }
+        }
+
+        private void MouseClick(object sender, EventArgs e)
+        {
+            switch ((sender as ComboBox).Name)
+            {
+                case "cmbProcess":
+                    cmbProcess.Items.Clear();
+                    cmbProcess.Items.Add("");
+                    cmbProcess.Items.AddRange(GlobalVar.dicProcesses.Keys.ToArray());
+                    break;
+                case "cmbInputImage":
+                    cmbInputImage.Items.Clear();
+                    cmbInputImage.Items.Add("");
+                    if (processRunBll == null)
+                        return;
+                    foreach (var lstOutput in processRunBll.dicOutputsMapping)
+                    {
+                        foreach (var output in lstOutput.Value)
+                        {
+                            if (output.Contains("Image"))
+                                cmbInputImage.Items.Add($"{lstOutput.Key}.Output.Image");
+                        }
+                    }
+                    break;
+                case "cmbRecord1":
+                    cmbRecord1.Items.Clear();
+                    cmbRecord1.Items.Add("");
+                    if (processRunBll == null)
+                        return;
+                    foreach (var lstOutput in processRunBll.dicOutputsMapping)
+                    {
+                        foreach (var output in lstOutput.Value)
+                        {
+                            if (output.Contains("Record"))
+                                cmbRecord1.Items.Add($"{lstOutput.Key}.Output.Record");
+                        }
+                    }
+                    break;
+                case "cmbRecord2":
+                    cmbRecord2.Items.Clear();
+                    cmbRecord2.Items.Add("");
+                    if (processRunBll == null)
+                        return;
+                    foreach (var lstOutput in processRunBll.dicOutputsMapping)
+                    {
+                        foreach (var output in lstOutput.Value)
+                        {
+                            if (output.Contains("Record"))
+                                cmbRecord2.Items.Add($"{lstOutput.Key}.Output.Record");
+                        }
+                    }
+                    break;
+                case "cmbRecord3":
+                    cmbRecord3.Items.Clear();
+                    cmbRecord3.Items.Add("");
+                    if (processRunBll == null)
+                        return;
+                    foreach (var lstOutput in processRunBll.dicOutputsMapping)
+                    {
+                        foreach (var output in lstOutput.Value)
+                        {
+                            if (output.Contains("Record"))
+                                cmbRecord3.Items.Add($"{lstOutput.Key}.Output.Record");
+                        }
+                    }
+                    break;
+            }
+        }
+
+        private void SelectedIndexChanged(object sender, EventArgs e)
+        {
+            switch ((sender as ComboBox).Name)
+            {
+                case "cmbProcess":
+                    layout.ProcessName = cmbProcess.Text;
+                    break;
+                case "cmbInputImage":
+                    layout.InputImage = cmbInputImage.Text;
+                    break;
+                case "cmbRecord1":
+                    layout.RecordImage1 = cmbRecord1.Text;
+                    break;
+                case "cmbRecord2":
+                    layout.RecordImage2 = cmbRecord2.Text;
+                    break;
+                case "cmbRecord3":
+                    layout.RecordImage3 = cmbRecord3.Text;
+                    break;
+            }
+        }
+
+        private void TextChanged(object sender, EventArgs e)
+        {
+            switch ((sender as TextBox).Name)
+            {
+                case "txtSavePath":
+                    layout.SaveImageDir = txtSavePath.Text;
+                    break;
+                case "txtSaveNameHead":
+                    layout.SaveImageHead = txtSaveNameHead.Text;
+                    break;
+            }
+        }
+
+        private void txtSavePath_MouseDoubleClick(object sender, MouseEventArgs e)
+        {
+            // 鍒涘缓鏂囦欢澶归�夋嫨瀵硅瘽妗�
+            using (var folderDialog = new FolderBrowserDialog())
+            {
+                folderDialog.Description = "璇烽�夋嫨鏂囦欢澶�";
+                folderDialog.ShowNewFolderButton = true; // 鍏佽鍒涘缓鏂版枃浠跺す
+                folderDialog.RootFolder = Environment.SpecialFolder.MyComputer; // 璧峰鐩綍
+
+                // 鏄剧ず瀵硅瘽妗�
+                DialogResult result = folderDialog.ShowDialog();
+
+                if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(folderDialog.SelectedPath))
+                {
+                    string selectedFolder = folderDialog.SelectedPath;
+                    txtSavePath.Text = selectedFolder; // 璁剧疆鏂囨湰妗嗙殑鍊间负閫夋嫨鐨勬枃浠跺す璺緞
+                }
+            }
+        }
+
+        private void txtSaveNameHead_MouseDoubleClick(object sender, MouseEventArgs e)
+        {
+            ProcessOutputsSelectForm processOutputsSelectForm
+                       = new ProcessOutputsSelectForm(GlobalVar.dicProcesses[ProcessName].dicInputsMapping, GlobalVar.dicProcesses[ProcessName].dicOutputsMapping);
+            processOutputsSelectForm.ShowDialog();
+
+            if (!string.IsNullOrEmpty(processOutputsSelectForm.SelectedOutput))
+                txtSaveNameHead.Text += $"{{{processOutputsSelectForm.SelectedOutput}}}";
+        }
+
+        private void MouseHover(object sender, EventArgs e)
+        {
+            if (sender is TextBox txt)
+            {
+                new ToolTip()
+                {
+                    ToolTipIcon = ToolTipIcon.Info, // 璁剧疆鎻愮ず鍥炬爣
+                    UseAnimation = true, // 鍚敤鍔ㄧ敾鏁堟灉
+                    UseFading = true // 鍚敤娣″叆娣″嚭鏁堟灉
+                }.Show(txt.Text
+                    , txt
+                    , txt.Width / 2, txt.Height // 鏄剧ず鍦ㄦ帶浠跺簳閮ㄤ腑闂�
+                    , 1000); // 鏄剧ず1绉�
+            }
+        }
+
+        private void lblName_MouseDown(object sender, MouseEventArgs e)
+        {
+            if (e.Button.ToString() == "Right")
+            {
+                RenameForm renameForm = new RenameForm(lblName.Text);
+                renameForm.ShowDialog();
+                if (renameForm.bRename)
+                {
+
+                    string oriName = renameForm.strOriName;
+                    string newName = renameForm.strNewName;
+
+                    foreach (var layout in GlobalVar.dicLayout.Values)
+                    {
+                        if (layout.Title == newName)
+                        {
+                            MessageBox.Show($"鍙橀噺銆恵newName}銆戝凡瀛樺湪锛岃鏇存崲鍚嶇О!", "寮傚父");
+                            return;
+                        }
+                    }
+
+                    foreach (var layout in GlobalVar.dicLayout.Values)
+                    {
+                        if (layout.Title == oriName && lblName.Checked)
+                        {
+                            layout.Title = newName;
+                            lblName.Text = newName;
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.resx b/LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/LayoutSettingControl.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/LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.Designer.cs b/LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.Designer.cs
new file mode 100644
index 0000000..5f4be0f
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.Designer.cs
@@ -0,0 +1,322 @@
+锘縩amespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    partial class RunSettingPage
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tableLayoutPanel = new TableLayoutPanel();
+            txtImagePath = new TextBox();
+            cmbImageType = new ComboBox();
+            lblImagePath = new Label();
+            lblImageType = new Label();
+            ckbSaveResultImage = new CheckBox();
+            ckbSaveRunImage = new CheckBox();
+            txtImageQuality = new TextBox();
+            lblImageQuality = new Label();
+            btnSave = new Button();
+            btnLoad = new Button();
+            txtTestSearch = new TextBox();
+            btnTest = new Button();
+            splitContainer = new SplitContainer();
+            tableLayoutPanelTest = new TableLayoutPanel();
+            lstControls = new ListBox();
+            tableLayoutPanel.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)splitContainer).BeginInit();
+            splitContainer.Panel1.SuspendLayout();
+            splitContainer.Panel2.SuspendLayout();
+            splitContainer.SuspendLayout();
+            tableLayoutPanelTest.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tableLayoutPanel
+            // 
+            tableLayoutPanel.ColumnCount = 5;
+            tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 140F));
+            tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 70F));
+            tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 140F));
+            tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 70F));
+            tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel.Controls.Add(txtImagePath, 1, 0);
+            tableLayoutPanel.Controls.Add(cmbImageType, 1, 1);
+            tableLayoutPanel.Controls.Add(lblImagePath, 0, 0);
+            tableLayoutPanel.Controls.Add(lblImageType, 0, 1);
+            tableLayoutPanel.Controls.Add(ckbSaveResultImage, 0, 4);
+            tableLayoutPanel.Controls.Add(ckbSaveRunImage, 0, 3);
+            tableLayoutPanel.Controls.Add(txtImageQuality, 1, 2);
+            tableLayoutPanel.Controls.Add(lblImageQuality, 0, 2);
+            tableLayoutPanel.Dock = DockStyle.Fill;
+            tableLayoutPanel.Location = new Point(0, 0);
+            tableLayoutPanel.Margin = new Padding(2);
+            tableLayoutPanel.Name = "tableLayoutPanel";
+            tableLayoutPanel.RowCount = 12;
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanel.Size = new Size(441, 355);
+            tableLayoutPanel.TabIndex = 1;
+            // 
+            // txtImagePath
+            // 
+            txtImagePath.Dock = DockStyle.Fill;
+            txtImagePath.Location = new Point(142, 2);
+            txtImagePath.Margin = new Padding(2);
+            txtImagePath.Name = "txtImagePath";
+            txtImagePath.ScrollBars = ScrollBars.Horizontal;
+            txtImagePath.Size = new Size(66, 23);
+            txtImagePath.TabIndex = 0;
+            txtImagePath.WordWrap = false;
+            txtImagePath.MouseDoubleClick += txtImagePath_MouseDoubleClick;
+            txtImagePath.MouseHover += txtImagePath_MouseHover;
+            // 
+            // cmbImageType
+            // 
+            cmbImageType.Dock = DockStyle.Fill;
+            cmbImageType.FormattingEnabled = true;
+            cmbImageType.Items.AddRange(new object[] { "jpg", "bmp" });
+            cmbImageType.Location = new Point(142, 34);
+            cmbImageType.Margin = new Padding(2);
+            cmbImageType.Name = "cmbImageType";
+            cmbImageType.Size = new Size(66, 25);
+            cmbImageType.TabIndex = 1;
+            cmbImageType.Text = "jpg";
+            // 
+            // lblImagePath
+            // 
+            lblImagePath.AutoSize = true;
+            lblImagePath.ForeColor = SystemColors.Control;
+            lblImagePath.Location = new Point(2, 0);
+            lblImagePath.Margin = new Padding(2, 0, 2, 0);
+            lblImagePath.Name = "lblImagePath";
+            lblImagePath.Size = new Size(56, 17);
+            lblImagePath.TabIndex = 3;
+            lblImagePath.Text = "鍥剧墖璺緞";
+            lblImagePath.TextAlign = ContentAlignment.TopRight;
+            // 
+            // lblImageType
+            // 
+            lblImageType.AutoSize = true;
+            lblImageType.ForeColor = SystemColors.Control;
+            lblImageType.Location = new Point(2, 32);
+            lblImageType.Margin = new Padding(2, 0, 2, 0);
+            lblImageType.Name = "lblImageType";
+            lblImageType.Size = new Size(56, 17);
+            lblImageType.TabIndex = 4;
+            lblImageType.Text = "鍥剧墖鏍煎紡";
+            lblImageType.TextAlign = ContentAlignment.TopRight;
+            // 
+            // ckbSaveResultImage
+            // 
+            ckbSaveResultImage.AutoSize = true;
+            ckbSaveResultImage.ForeColor = SystemColors.Control;
+            ckbSaveResultImage.Location = new Point(2, 130);
+            ckbSaveResultImage.Margin = new Padding(2);
+            ckbSaveResultImage.Name = "ckbSaveResultImage";
+            ckbSaveResultImage.Size = new Size(99, 21);
+            ckbSaveResultImage.TabIndex = 5;
+            ckbSaveResultImage.Text = "淇濆瓨缁撴灉鍥剧墖";
+            ckbSaveResultImage.UseVisualStyleBackColor = true;
+            // 
+            // ckbSaveRunImage
+            // 
+            ckbSaveRunImage.AutoSize = true;
+            ckbSaveRunImage.ForeColor = SystemColors.Control;
+            ckbSaveRunImage.Location = new Point(2, 98);
+            ckbSaveRunImage.Margin = new Padding(2);
+            ckbSaveRunImage.Name = "ckbSaveRunImage";
+            ckbSaveRunImage.Size = new Size(99, 21);
+            ckbSaveRunImage.TabIndex = 2;
+            ckbSaveRunImage.Text = "淇濆瓨杩愯鍥剧墖";
+            ckbSaveRunImage.UseVisualStyleBackColor = true;
+            // 
+            // txtImageQuality
+            // 
+            txtImageQuality.Location = new Point(142, 66);
+            txtImageQuality.Margin = new Padding(2);
+            txtImageQuality.Name = "txtImageQuality";
+            txtImageQuality.Size = new Size(66, 23);
+            txtImageQuality.TabIndex = 7;
+            txtImageQuality.Text = "50";
+            txtImageQuality.TextChanged += txtImageQuality_TextChanged;
+            // 
+            // lblImageQuality
+            // 
+            lblImageQuality.AutoSize = true;
+            lblImageQuality.ForeColor = SystemColors.Control;
+            lblImageQuality.Location = new Point(2, 64);
+            lblImageQuality.Margin = new Padding(2, 0, 2, 0);
+            lblImageQuality.Name = "lblImageQuality";
+            lblImageQuality.Size = new Size(56, 17);
+            lblImageQuality.TabIndex = 8;
+            lblImageQuality.Text = "鍥剧墖璐ㄩ噺";
+            lblImageQuality.TextAlign = ContentAlignment.TopRight;
+            // 
+            // btnSave
+            // 
+            btnSave.Location = new Point(2, 66);
+            btnSave.Margin = new Padding(2);
+            btnSave.Name = "btnSave";
+            btnSave.Size = new Size(71, 28);
+            btnSave.TabIndex = 2;
+            btnSave.Text = "淇濆瓨";
+            btnSave.UseVisualStyleBackColor = true;
+            btnSave.Click += btnSave_Click;
+            // 
+            // btnLoad
+            // 
+            btnLoad.Location = new Point(2, 98);
+            btnLoad.Margin = new Padding(2);
+            btnLoad.Name = "btnLoad";
+            btnLoad.Size = new Size(71, 28);
+            btnLoad.TabIndex = 3;
+            btnLoad.Text = "鍔犺浇";
+            btnLoad.UseVisualStyleBackColor = true;
+            btnLoad.Click += btnLoad_Click;
+            // 
+            // txtTestSearch
+            // 
+            txtTestSearch.Dock = DockStyle.Fill;
+            txtTestSearch.Location = new Point(2, 2);
+            txtTestSearch.Margin = new Padding(2);
+            txtTestSearch.Name = "txtTestSearch";
+            txtTestSearch.Size = new Size(216, 23);
+            txtTestSearch.TabIndex = 4;
+            // 
+            // btnTest
+            // 
+            btnTest.Location = new Point(2, 34);
+            btnTest.Margin = new Padding(2);
+            btnTest.Name = "btnTest";
+            btnTest.Size = new Size(71, 28);
+            btnTest.TabIndex = 5;
+            btnTest.Text = "娴嬭瘯鏌ユ壘";
+            btnTest.UseVisualStyleBackColor = true;
+            btnTest.Click += btnTest_Click;
+            // 
+            // splitContainer
+            // 
+            splitContainer.BackColor = Color.FromArgb(32, 41, 50);
+            splitContainer.Dock = DockStyle.Fill;
+            splitContainer.IsSplitterFixed = true;
+            splitContainer.Location = new Point(0, 0);
+            splitContainer.Margin = new Padding(2);
+            splitContainer.Name = "splitContainer";
+            // 
+            // splitContainer.Panel1
+            // 
+            splitContainer.Panel1.Controls.Add(tableLayoutPanelTest);
+            // 
+            // splitContainer.Panel2
+            // 
+            splitContainer.Panel2.Controls.Add(tableLayoutPanel);
+            splitContainer.Size = new Size(664, 355);
+            splitContainer.SplitterDistance = 220;
+            splitContainer.SplitterWidth = 3;
+            splitContainer.TabIndex = 4;
+            // 
+            // tableLayoutPanelTest
+            // 
+            tableLayoutPanelTest.ColumnCount = 1;
+            tableLayoutPanelTest.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanelTest.Controls.Add(txtTestSearch, 0, 0);
+            tableLayoutPanelTest.Controls.Add(btnTest, 0, 1);
+            tableLayoutPanelTest.Controls.Add(btnLoad, 0, 3);
+            tableLayoutPanelTest.Controls.Add(btnSave, 0, 2);
+            tableLayoutPanelTest.Controls.Add(lstControls, 0, 5);
+            tableLayoutPanelTest.Dock = DockStyle.Fill;
+            tableLayoutPanelTest.Location = new Point(0, 0);
+            tableLayoutPanelTest.Margin = new Padding(2);
+            tableLayoutPanelTest.Name = "tableLayoutPanelTest";
+            tableLayoutPanelTest.RowCount = 6;
+            tableLayoutPanelTest.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanelTest.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanelTest.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanelTest.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanelTest.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F));
+            tableLayoutPanelTest.RowStyles.Add(new RowStyle(SizeType.Absolute, 16F));
+            tableLayoutPanelTest.Size = new Size(220, 355);
+            tableLayoutPanelTest.TabIndex = 0;
+            // 
+            // lstControls
+            // 
+            lstControls.Dock = DockStyle.Fill;
+            lstControls.FormattingEnabled = true;
+            lstControls.ItemHeight = 17;
+            lstControls.Location = new Point(2, 162);
+            lstControls.Margin = new Padding(2);
+            lstControls.Name = "lstControls";
+            lstControls.ScrollAlwaysVisible = true;
+            lstControls.Size = new Size(216, 191);
+            lstControls.TabIndex = 6;
+            // 
+            // RunSettingPage
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(splitContainer);
+            Margin = new Padding(2);
+            Name = "RunSettingPage";
+            Size = new Size(664, 355);
+            tableLayoutPanel.ResumeLayout(false);
+            tableLayoutPanel.PerformLayout();
+            splitContainer.Panel1.ResumeLayout(false);
+            splitContainer.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer).EndInit();
+            splitContainer.ResumeLayout(false);
+            tableLayoutPanelTest.ResumeLayout(false);
+            tableLayoutPanelTest.PerformLayout();
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private TableLayoutPanel tableLayoutPanel;
+        private Button btnSave;
+        private Button btnLoad;
+        private TextBox txtImagePath;
+        private ComboBox cmbImageType;
+        private CheckBox ckbSaveRunImage;
+        private Label lblImagePath;
+        private Label lblImageType;
+        private CheckBox ckbSaveResultImage;
+        private TextBox txtTestSearch;
+        private Button btnTest;
+        private SplitContainer splitContainer;
+        private TableLayoutPanel tableLayoutPanelTest;
+        private ListBox lstControls;
+        private TextBox txtImageQuality;
+        private Label lblImageQuality;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.cs b/LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.cs
new file mode 100644
index 0000000..11519aa
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.cs
@@ -0,0 +1,334 @@
+锘縰sing Newtonsoft.Json;
+using System.Data;
+using System.Diagnostics;
+
+namespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    public partial class RunSettingPage : UserControl
+    {
+        ControlStateManager controlStateManager { get; set; }
+
+        public RunSettingPage()
+        {
+            InitializeComponent();
+            controlStateManager = new ControlStateManager(tableLayoutPanel);
+            lstControls.Items.Clear();
+            foreach (Control control in GetAllControls(tableLayoutPanel))
+            {
+                if (control is TextBox || control is CheckBox || control is ComboBox)
+                {
+                    if (!string.IsNullOrEmpty(control.Name))
+                    {
+                        lstControls.Items.Add(control.Name);
+                    }
+                }
+            }
+        }
+
+        // 鑾峰彇鎵�鏈夊瓙鎺т欢锛堥�掑綊锛�
+        private IEnumerable<Control> GetAllControls(Control control)
+        {
+            var controls = control.Controls.Cast<Control>();
+            return controls.SelectMany(ctrl => GetAllControls(ctrl)).Concat(controls);
+        }
+
+        // 淇濆瓨鎵�鏈夋帶浠剁姸鎬侊紙閫掑綊澶勭悊瀹瑰櫒鎺т欢锛�
+        public void SaveControlsState(TableLayoutPanel tablePanel)
+        {
+            GlobalVar.ControlStates.Clear();
+            SaveControlsRecursive(tablePanel);
+        }
+
+        private void SaveControlsRecursive(Control parentControl)
+        {
+            foreach (Control control in parentControl.Controls)
+            {
+                // 閫掑綊澶勭悊瀹瑰櫒鎺т欢
+                if (control.HasChildren && !(control is ComboBox)) // ComboBox鏈塁hildren浣嗕笉鏄鍣ㄦ帶浠�
+                {
+                    SaveControlsRecursive(control);
+                    continue;
+                }
+
+                string key = $"{control.Name}_{control.GetType().Name}";
+
+                switch (control)
+                {
+                    case TextBox textBox:
+                        GlobalVar.ControlStates[key] = textBox.Text;
+                        break;
+
+                    case CheckBox checkBox:
+                        GlobalVar.ControlStates[key] = checkBox.Checked;
+                        break;
+
+                    case ComboBox comboBox:
+                        var comboData = new
+                        {
+                            Items = comboBox.Items.Cast<object>().ToList(),
+                            SelectedIndex = comboBox.SelectedIndex
+                        };
+                        GlobalVar.ControlStates[key] = comboData;
+                        break;
+                }
+            }
+        }
+
+        // 鍔犺浇鎺т欢鐘舵�侊紙閫掑綊澶勭悊瀹瑰櫒鎺т欢锛�
+        public void LoadControlsState(TableLayoutPanel tablePanel)
+        {
+            LoadControlsRecursive(tablePanel);
+        }
+
+        private void LoadControlsRecursive(Control parentControl)
+        {
+            if (this.InvokeRequired)
+            {
+                this.Invoke(new Action(() => LoadControlsRecursive(parentControl)));
+                return;
+            }
+            foreach (Control control in parentControl.Controls)
+            {
+                if (control.HasChildren && !(control is ComboBox))
+                {
+                    LoadControlsRecursive(control);
+                    continue;
+                }
+
+                string key = $"{control.Name}_{control.GetType().Name}";
+
+                if (!GlobalVar.ControlStates.TryGetValue(key, out object value)) continue;
+
+                switch (control)
+                {
+                    case TextBox textBox when value is string text:
+                        textBox.Text = text;
+                        break;
+
+                    case CheckBox checkBox when value is bool isChecked:
+                        checkBox.Checked = isChecked;
+                        break;
+
+                    case ComboBox comboBox when value != null:
+                        try
+                        {
+                            // 鍔ㄦ�佽В鏋怌omboBox鏁版嵁
+                            var json = JsonConvert.SerializeObject(value);
+                            var comboData = JsonConvert.DeserializeAnonymousType(json, new
+                            {
+                                Items = new List<object>(),
+                                SelectedIndex = 0
+                            });
+
+                            comboBox.BeginUpdate();
+                            comboBox.Items.Clear();
+                            comboBox.Items.AddRange(comboData.Items.ToArray());
+
+                            if (comboData.SelectedIndex >= 0 && comboData.SelectedIndex < comboBox.Items.Count)
+                            {
+                                comboBox.SelectedIndex = comboData.SelectedIndex;
+                            }
+                            comboBox.EndUpdate();
+                        }
+                        catch (Exception ex)
+                        {
+                            Debug.WriteLine($"鍔犺浇ComboBox鏁版嵁澶辫触: {ex.Message}");
+                        }
+                        break;
+                }
+            }
+        }
+
+        // 淇濆瓨鍒癑SON鏂囦欢
+        public void SaveToJson(string filePath = "")
+        {
+            try
+            {
+                SaveControlsState(tableLayoutPanel);
+                if (string.IsNullOrEmpty(filePath))
+                    filePath = GlobalVar.allRunSettingStringPath;
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Formatting.Indented,
+                    TypeNameHandling = TypeNameHandling.Auto // 澶勭悊澶氭�佺被鍨�
+                };
+
+                string json = JsonConvert.SerializeObject(GlobalVar.ControlStates, settings);
+                File.WriteAllText(filePath, json);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show($"淇濆瓨澶辫触: {ex.Message}", "寮傚父");
+            }
+        }
+
+        // 浠嶫SON鏂囦欢鍔犺浇
+        public void LoadFromJson(string filePath = "")
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(filePath))
+                    filePath = GlobalVar.allRunSettingStringPath;
+                if (!File.Exists(filePath))
+                {
+                    SaveToJson(filePath);
+                    Debug.WriteLine($"鏂囦欢涓嶅瓨鍦紝宸插垱寤烘柊鏂囦欢: {filePath}");
+                }
+
+                string json = File.ReadAllText(filePath);
+                var settings = new JsonSerializerSettings
+                {
+                    TypeNameHandling = TypeNameHandling.Auto // 澶勭悊澶氭�佺被鍨�
+                };
+
+                GlobalVar.ControlStates = JsonConvert.DeserializeObject<Dictionary<string, object>>(json, settings);
+                LoadControlsState(tableLayoutPanel);
+
+                if (txtImagePath.Text.Trim() == "" || string.IsNullOrEmpty(txtImagePath.Text))
+                {
+                    // 濡傛灉娌℃湁璁剧疆鍥剧墖璺緞锛屽垯浣跨敤榛樿璺緞
+                    txtImagePath.Text = GlobalVar.strApplicationPath;
+                    SaveToJson(filePath);
+                    LoadControlsState(tableLayoutPanel);
+                }
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show($"鍔犺浇澶辫触: {ex.Message}", "寮傚父");
+            }
+        }
+
+        private void btnTest_Click(object sender, EventArgs e)
+        {
+            string searchControlName = txtTestSearch.Text;
+            if (searchControlName.StartsWith("txt"))
+            {
+                // 鍋囪鏄� TextBox
+                TextBox textBox = controlStateManager.GetControl<TextBox>(searchControlName);
+                if (textBox != null)
+                {
+                    MessageBox.Show($"鎵惧埌鎺т欢: {textBox.Name}, 鏂囨湰鍐呭: {textBox.Text}");
+                }
+                else
+                {
+                    MessageBox.Show($"鏈壘鍒版帶浠�: {searchControlName}", "寮傚父");
+                }
+            }
+            else if (searchControlName.StartsWith("ckb"))
+            {
+                // 鍋囪鏄� CheckBox
+                CheckBox checkBox = controlStateManager.GetControl<CheckBox>(searchControlName);
+                if (checkBox != null)
+                {
+                    MessageBox.Show($"鎵惧埌鎺т欢: {checkBox.Name}, 鐘舵��: {checkBox.Checked}");
+                }
+                else
+                {
+                    MessageBox.Show($"鏈壘鍒版帶浠�: {searchControlName}", "寮傚父");
+                }
+            }
+            else if (searchControlName.StartsWith("cmb"))
+            {
+                // 鍋囪鏄� ComboBox
+                ComboBox comboBox = controlStateManager.GetControl<ComboBox>(searchControlName);
+                if (comboBox != null)
+                {
+                    string selectedText = controlStateManager.GetComboBoxText(searchControlName);
+                    MessageBox.Show($"鎵惧埌鎺т欢: {comboBox.Name}, 閫変腑椤�: {selectedText}");
+                }
+                else
+                {
+                    MessageBox.Show($"鏈壘鍒版帶浠�: {searchControlName}", "寮傚父");
+                }
+            }
+            else
+            {
+                MessageBox.Show("璇疯緭鍏ユ湁鏁堢殑鎺т欢鍚嶇О鍓嶇紑锛坱xt銆乧kb銆乧mb锛�", "寮傚父");
+            }
+        }
+
+        private void btnSave_Click(object sender, EventArgs e)
+        {
+            SaveToJson();
+            MessageBox.Show("鎺т欢鐘舵�佸凡淇濆瓨");
+        }
+
+        private void btnLoad_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Ini Files (*.json)|*.json|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    if (File.Exists(selectedFiles[0]))
+                    {
+                        LoadFromJson(selectedFiles[0]);
+                        MessageBox.Show("鎺т欢鐘舵�佸凡鍔犺浇");
+                    }
+                }
+            }
+        }
+
+        private void txtImagePath_MouseDoubleClick(object sender, MouseEventArgs e)
+        {
+            // 鍒涘缓鏂囦欢澶归�夋嫨瀵硅瘽妗�
+            using (var folderDialog = new FolderBrowserDialog())
+            {
+                folderDialog.Description = "璇烽�夋嫨鏂囦欢澶�";
+                folderDialog.ShowNewFolderButton = true; // 鍏佽鍒涘缓鏂版枃浠跺す
+                folderDialog.RootFolder = Environment.SpecialFolder.MyComputer; // 璧峰鐩綍
+
+                // 鏄剧ず瀵硅瘽妗�
+                DialogResult result = folderDialog.ShowDialog();
+
+                if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(folderDialog.SelectedPath))
+                {
+                    string selectedFolder = folderDialog.SelectedPath;
+                    txtImagePath.Text = selectedFolder; // 璁剧疆鏂囨湰妗嗙殑鍊间负閫夋嫨鐨勬枃浠跺す璺緞
+                }
+            }
+        }
+
+        ToolTip pathToolTip = new ToolTip()
+        {
+            ToolTipIcon = ToolTipIcon.Info, // 璁剧疆鎻愮ず鍥炬爣
+            UseAnimation = true, // 鍚敤鍔ㄧ敾鏁堟灉
+            UseFading = true // 鍚敤娣″叆娣″嚭鏁堟灉
+        };
+        private void txtImagePath_MouseHover(object sender, EventArgs e)
+        {
+            pathToolTip.Show(txtImagePath.Text
+                , txtImagePath
+                , txtImagePath.Width / 2, txtImagePath.Height // 鏄剧ず鍦ㄦ帶浠跺簳閮ㄤ腑闂�
+                , 1000); // 鏄剧ず1绉�
+        }
+
+        private void txtImageQuality_TextChanged(object sender, EventArgs e)
+        {
+            if (int.TryParse(txtImageQuality.Text, out int quality))
+            {
+                if (quality < 0 || quality > 100)
+                {
+                    MessageBox.Show("鍥惧儚璐ㄩ噺蹇呴』鍦�0鍒�100涔嬮棿!", "寮傚父");
+                    txtImageQuality.Text = "100"; // 閲嶇疆涓洪粯璁ゅ��
+                }
+            }
+            else
+            {
+                MessageBox.Show("璇疯緭鍏ユ湁鏁堢殑鏁板瓧!", "寮傚父");
+                txtImageQuality.Text = "100"; // 閲嶇疆涓洪粯璁ゅ��
+            }
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.resx b/LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/RunSettingPage.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/LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.Designer.cs b/LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.Designer.cs
new file mode 100644
index 0000000..088824f
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.Designer.cs
@@ -0,0 +1,372 @@
+锘縰sing ReaLTaiizor.Controls;
+
+namespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    partial class SettingEditPage
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            dataGridView = new DataGridView();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            tableLayoutPanel3 = new TableLayoutPanel();
+            btnSaveProcessSetting = new ForeverButton();
+            btnAdd = new HopeButton();
+            grpSetting = new ParrotGroupBox();
+            grpProcess = new ParrotGroupBox();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            uiFlowLayoutPanel1 = new FlowLayoutPanel();
+            tableLayoutPanel5 = new TableLayoutPanel();
+            btn_AddProcess = new HopeButton();
+            splitContainer1 = new SplitContainer();
+            poisonTabControl1 = new PoisonTabControl();
+            pageProcesses = new System.Windows.Forms.TabPage();
+            pageSetting = new System.Windows.Forms.TabPage();
+            pageLayout = new System.Windows.Forms.TabPage();
+            pageCsv = new System.Windows.Forms.TabPage();
+            ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
+            tableLayoutPanel2.SuspendLayout();
+            tableLayoutPanel3.SuspendLayout();
+            grpSetting.SuspendLayout();
+            grpProcess.SuspendLayout();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel5.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
+            splitContainer1.Panel1.SuspendLayout();
+            splitContainer1.Panel2.SuspendLayout();
+            splitContainer1.SuspendLayout();
+            poisonTabControl1.SuspendLayout();
+            pageProcesses.SuspendLayout();
+            SuspendLayout();
+            // 
+            // dataGridView
+            // 
+            dataGridView.BackgroundColor = Color.FromArgb(32, 41, 50);
+            dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            dataGridView.Dock = DockStyle.Fill;
+            dataGridView.GridColor = SystemColors.Info;
+            dataGridView.Location = new Point(3, 3);
+            dataGridView.Name = "dataGridView";
+            dataGridView.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;
+            dataGridView.Size = new Size(840, 184);
+            dataGridView.TabIndex = 0;
+            dataGridView.CellBeginEdit += dataGridView_CellBeginEdit;
+            dataGridView.CellContentClick += dataGridView_CellContentClick;
+            dataGridView.CellEndEdit += dataGridView_CellEndEdit;
+            dataGridView.UserDeletingRow += dataGridView_UserDeletingRow;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 1;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(dataGridView, 0, 0);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel3, 0, 1);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 19);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 2;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel2.Size = new Size(846, 240);
+            tableLayoutPanel2.TabIndex = 2;
+            // 
+            // tableLayoutPanel3
+            // 
+            tableLayoutPanel3.ColumnCount = 6;
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel3.Controls.Add(btnSaveProcessSetting, 5, 0);
+            tableLayoutPanel3.Controls.Add(btnAdd, 4, 0);
+            tableLayoutPanel3.Dock = DockStyle.Fill;
+            tableLayoutPanel3.Location = new Point(3, 193);
+            tableLayoutPanel3.Name = "tableLayoutPanel3";
+            tableLayoutPanel3.RowCount = 1;
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Size = new Size(840, 44);
+            tableLayoutPanel3.TabIndex = 1;
+            // 
+            // btnSaveProcessSetting
+            // 
+            btnSaveProcessSetting.BackColor = Color.Transparent;
+            btnSaveProcessSetting.BaseColor = Color.FromArgb(35, 168, 109);
+            btnSaveProcessSetting.Dock = DockStyle.Fill;
+            btnSaveProcessSetting.Font = new Font("瀹嬩綋", 12F);
+            btnSaveProcessSetting.Location = new Point(703, 3);
+            btnSaveProcessSetting.MinimumSize = new Size(1, 1);
+            btnSaveProcessSetting.Name = "btnSaveProcessSetting";
+            btnSaveProcessSetting.Rounded = false;
+            btnSaveProcessSetting.Size = new Size(134, 38);
+            btnSaveProcessSetting.TabIndex = 3;
+            btnSaveProcessSetting.Text = "淇濆瓨";
+            btnSaveProcessSetting.TextColor = Color.FromArgb(243, 243, 243);
+            btnSaveProcessSetting.Click += btn_SaveProcessSetting_Click;
+            // 
+            // btnAdd
+            // 
+            btnAdd.BorderColor = Color.FromArgb(220, 223, 230);
+            btnAdd.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            btnAdd.DangerColor = Color.FromArgb(245, 108, 108);
+            btnAdd.DefaultColor = Color.FromArgb(255, 255, 255);
+            btnAdd.Dock = DockStyle.Fill;
+            btnAdd.Font = new Font("瀹嬩綋", 12F);
+            btnAdd.HoverTextColor = Color.FromArgb(48, 49, 51);
+            btnAdd.InfoColor = Color.FromArgb(144, 147, 153);
+            btnAdd.Location = new Point(563, 3);
+            btnAdd.MinimumSize = new Size(1, 1);
+            btnAdd.Name = "btnAdd";
+            btnAdd.PrimaryColor = Color.FromArgb(64, 158, 255);
+            btnAdd.Size = new Size(134, 38);
+            btnAdd.SuccessColor = Color.FromArgb(103, 194, 58);
+            btnAdd.TabIndex = 4;
+            btnAdd.Text = "娣诲姞";
+            btnAdd.TextColor = Color.White;
+            btnAdd.WarningColor = Color.FromArgb(230, 162, 60);
+            btnAdd.Click += btn_Add_Click;
+            // 
+            // grpSetting
+            // 
+            grpSetting.BorderColor = Color.DodgerBlue;
+            grpSetting.BorderWidth = 1;
+            grpSetting.Controls.Add(tableLayoutPanel2);
+            grpSetting.Dock = DockStyle.Fill;
+            grpSetting.Location = new Point(0, 0);
+            grpSetting.Name = "grpSetting";
+            grpSetting.ShowText = true;
+            grpSetting.Size = new Size(852, 262);
+            grpSetting.TabIndex = 5;
+            grpSetting.TabStop = false;
+            grpSetting.Text = "閫氳瑙﹀彂娴佺▼璁剧疆";
+            grpSetting.TextColor = Color.DodgerBlue;
+            // 
+            // grpProcess
+            // 
+            grpProcess.BorderColor = Color.DodgerBlue;
+            grpProcess.BorderWidth = 1;
+            grpProcess.Controls.Add(tableLayoutPanel1);
+            grpProcess.Dock = DockStyle.Fill;
+            grpProcess.Location = new Point(0, 0);
+            grpProcess.Name = "grpProcess";
+            grpProcess.ShowText = true;
+            grpProcess.Size = new Size(852, 266);
+            grpProcess.TabIndex = 5;
+            grpProcess.TabStop = false;
+            grpProcess.Text = "娴佺▼璁剧疆";
+            grpProcess.TextColor = Color.DodgerBlue;
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(uiFlowLayoutPanel1, 0, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel5, 0, 1);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(3, 19);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 2;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.Size = new Size(846, 244);
+            tableLayoutPanel1.TabIndex = 3;
+            // 
+            // uiFlowLayoutPanel1
+            // 
+            uiFlowLayoutPanel1.AutoScroll = true;
+            uiFlowLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            uiFlowLayoutPanel1.Dock = DockStyle.Fill;
+            uiFlowLayoutPanel1.Font = new Font("瀹嬩綋", 12F);
+            uiFlowLayoutPanel1.ForeColor = SystemColors.Control;
+            uiFlowLayoutPanel1.Location = new Point(4, 5);
+            uiFlowLayoutPanel1.Margin = new Padding(4, 5, 4, 5);
+            uiFlowLayoutPanel1.MinimumSize = new Size(1, 1);
+            uiFlowLayoutPanel1.Name = "uiFlowLayoutPanel1";
+            uiFlowLayoutPanel1.Padding = new Padding(2);
+            uiFlowLayoutPanel1.Size = new Size(838, 184);
+            uiFlowLayoutPanel1.TabIndex = 11;
+            uiFlowLayoutPanel1.Text = "`";
+            // 
+            // tableLayoutPanel5
+            // 
+            tableLayoutPanel5.ColumnCount = 6;
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel5.Controls.Add(btn_AddProcess, 0, 0);
+            tableLayoutPanel5.Dock = DockStyle.Fill;
+            tableLayoutPanel5.Location = new Point(3, 197);
+            tableLayoutPanel5.Name = "tableLayoutPanel5";
+            tableLayoutPanel5.RowCount = 1;
+            tableLayoutPanel5.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel5.Size = new Size(840, 44);
+            tableLayoutPanel5.TabIndex = 1;
+            // 
+            // btn_AddProcess
+            // 
+            btn_AddProcess.BorderColor = Color.FromArgb(220, 223, 230);
+            btn_AddProcess.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            btn_AddProcess.DangerColor = Color.FromArgb(245, 108, 108);
+            btn_AddProcess.DefaultColor = Color.FromArgb(255, 255, 255);
+            btn_AddProcess.Dock = DockStyle.Fill;
+            btn_AddProcess.Font = new Font("瀹嬩綋", 12F);
+            btn_AddProcess.HoverTextColor = Color.FromArgb(48, 49, 51);
+            btn_AddProcess.InfoColor = Color.FromArgb(144, 147, 153);
+            btn_AddProcess.Location = new Point(3, 3);
+            btn_AddProcess.MinimumSize = new Size(1, 1);
+            btn_AddProcess.Name = "btn_AddProcess";
+            btn_AddProcess.PrimaryColor = Color.FromArgb(64, 158, 255);
+            btn_AddProcess.Size = new Size(134, 38);
+            btn_AddProcess.SuccessColor = Color.FromArgb(103, 194, 58);
+            btn_AddProcess.TabIndex = 4;
+            btn_AddProcess.Text = "鏂板缓娴佺▼";
+            btn_AddProcess.TextColor = Color.White;
+            btn_AddProcess.WarningColor = Color.FromArgb(230, 162, 60);
+            btn_AddProcess.Click += btn_AddProcess_Click;
+            // 
+            // splitContainer1
+            // 
+            splitContainer1.BackColor = Color.FromArgb(32, 41, 50);
+            splitContainer1.Dock = DockStyle.Fill;
+            splitContainer1.Location = new Point(3, 3);
+            splitContainer1.Name = "splitContainer1";
+            splitContainer1.Orientation = Orientation.Horizontal;
+            // 
+            // splitContainer1.Panel1
+            // 
+            splitContainer1.Panel1.Controls.Add(grpProcess);
+            // 
+            // splitContainer1.Panel2
+            // 
+            splitContainer1.Panel2.Controls.Add(grpSetting);
+            splitContainer1.Size = new Size(852, 532);
+            splitContainer1.SplitterDistance = 266;
+            splitContainer1.TabIndex = 6;
+            // 
+            // poisonTabControl1
+            // 
+            poisonTabControl1.Controls.Add(pageProcesses);
+            poisonTabControl1.Controls.Add(pageSetting);
+            poisonTabControl1.Controls.Add(pageLayout);
+            poisonTabControl1.Controls.Add(pageCsv);
+            poisonTabControl1.Dock = DockStyle.Fill;
+            poisonTabControl1.Location = new Point(0, 0);
+            poisonTabControl1.Name = "poisonTabControl1";
+            poisonTabControl1.Padding = new Point(6, 8);
+            poisonTabControl1.SelectedIndex = 0;
+            poisonTabControl1.Size = new Size(866, 580);
+            poisonTabControl1.TabIndex = 7;
+            poisonTabControl1.UseSelectable = true;
+            // 
+            // pageProcesses
+            // 
+            pageProcesses.Controls.Add(splitContainer1);
+            pageProcesses.Location = new Point(4, 38);
+            pageProcesses.Name = "pageProcesses";
+            pageProcesses.Padding = new Padding(3);
+            pageProcesses.Size = new Size(858, 538);
+            pageProcesses.TabIndex = 0;
+            pageProcesses.Text = "娴佺▼璁剧疆";
+            pageProcesses.UseVisualStyleBackColor = true;
+            // 
+            // pageSetting
+            // 
+            pageSetting.BackColor = Color.FromArgb(32, 41, 50);
+            pageSetting.Location = new Point(4, 38);
+            pageSetting.Name = "pageSetting";
+            pageSetting.Padding = new Padding(3);
+            pageSetting.Size = new Size(858, 538);
+            pageSetting.TabIndex = 1;
+            pageSetting.Text = "杩愯璁剧疆";
+            // 
+            // pageLayout
+            // 
+            pageLayout.BackColor = Color.FromArgb(32, 41, 50);
+            pageLayout.Location = new Point(4, 38);
+            pageLayout.Name = "pageLayout";
+            pageLayout.Size = new Size(858, 538);
+            pageLayout.TabIndex = 2;
+            pageLayout.Text = "娴佺▼甯冨眬";
+            // 
+            // pageCsv
+            // 
+            pageCsv.BackColor = Color.FromArgb(32, 41, 50);
+            pageCsv.Location = new Point(4, 38);
+            pageCsv.Name = "pageCsv";
+            pageCsv.Padding = new Padding(3);
+            pageCsv.Size = new Size(858, 538);
+            pageCsv.TabIndex = 3;
+            pageCsv.Text = "娴佺▼琛ㄦ牸";
+            // 
+            // SettingEditPage
+            // 
+            BackColor = Color.FromArgb(32, 41, 50);
+            Controls.Add(poisonTabControl1);
+            Name = "SettingEditPage";
+            Size = new Size(866, 580);
+            Paint += SettingEditPage_Paint;
+            ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel3.ResumeLayout(false);
+            grpSetting.ResumeLayout(false);
+            grpSetting.PerformLayout();
+            grpProcess.ResumeLayout(false);
+            grpProcess.PerformLayout();
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel5.ResumeLayout(false);
+            splitContainer1.Panel1.ResumeLayout(false);
+            splitContainer1.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit();
+            splitContainer1.ResumeLayout(false);
+            poisonTabControl1.ResumeLayout(false);
+            pageProcesses.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+        private TableLayoutPanel tableLayoutPanel2;
+        private TableLayoutPanel tableLayoutPanel3;
+        private ReaLTaiizor.Controls.ForeverButton btnSaveProcessSetting;
+        private ReaLTaiizor.Controls.HopeButton btnAdd;
+        private DataGridView dataGridView;
+        private FlowLayoutPanel uiFlowLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel5;
+        private HopeButton btn_AddProcess;
+        private ParrotGroupBox grpSetting;
+        private ParrotGroupBox grpProcess;
+        private SplitContainer splitContainer1;
+        private PoisonTabControl poisonTabControl1;
+        private System.Windows.Forms.TabPage pageProcesses;
+        private System.Windows.Forms.TabPage pageLayout;
+        private System.Windows.Forms.TabPage pageSetting;
+        private System.Windows.Forms.TabPage pageCsv;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.cs b/LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.cs
new file mode 100644
index 0000000..06521be
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.cs
@@ -0,0 +1,510 @@
+锘縰sing LB_SmartVision.Forms.Pages.ProcessPage;
+using LB_SmartVision.ProcessRun;
+using LB_VisionControl;
+using LB_VisionProcesses;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System.Collections.Concurrent;
+using System.Data;
+using System.Text;
+using VisionControl.Forms;
+
+namespace LB_SmartVision.Forms.Pages.SettingPage
+{
+    public partial class SettingEditPage : UserControl
+    {
+        public Action<string, LogInfoType> LogInfo;
+        RunSettingPage RunSettingPage = new RunSettingPage();
+        LayoutPage LayoutPage = new LayoutPage();
+        CsvPage CsvPage = new CsvPage();
+        public SettingEditPage()
+        {
+            Name = "SettingEditPage";
+            Text = "娴佺▼璁剧疆";
+            //this.Font = new Font("Microsoft YaHei UI", 16F, FontStyle.Regular, GraphicsUnit.Point, 0);
+
+
+            InitializeComponent();
+            dataGridView.DataError += new DataGridViewDataErrorEventHandler(dataGridView_DataError);
+
+            pageSetting.Controls.Add(RunSettingPage);
+            RunSettingPage.Dock = DockStyle.Fill;
+
+            pageLayout.Controls.Add(LayoutPage);
+            LayoutPage.Dock = DockStyle.Fill;
+
+            pageCsv.Controls.Add(CsvPage);
+            CsvPage.Dock = DockStyle.Fill;
+        }
+
+        private void SettingEditPage_Paint(object sender, PaintEventArgs e)
+        {
+            RunSettingPage.LoadFromJson();
+
+            uiFlowLayoutPanel1.Controls.Clear();
+
+            if (GlobalVar.dicProcesses.Count <= 0)
+                return;
+
+            // 浣跨敤鏂瑰紡
+            var sortedKeys = GlobalVar.dicProcesses.Keys
+                .OrderBy(k => k, new NaturalStringComparer())
+                .ToList();
+            foreach (var key in sortedKeys)
+            {
+                string ProcessesName = key;
+                string ProcessesOK = GlobalVar.dicProcesses[ProcessesName].Rate_OK.ToString() + "%";
+
+                if (string.IsNullOrEmpty(ProcessesName) || string.IsNullOrEmpty(ProcessesOK))
+                    return;
+
+                UserItem flow = new UserItem(new string[] { "閲嶅懡鍚�", "绉婚櫎" });
+                flow.Name = ProcessesName;
+                flow.Text = $"[{ProcessesOK}]";
+                if (GlobalVar.dicProcesses[ProcessesName].Result)
+                    flow.state = State.Pass;
+                else
+                    flow.state = State.Error;
+                LoadFlowEvent(flow);
+
+                uiFlowLayoutPanel1.Controls.Add(flow);
+            }
+
+            LoadData();
+        }
+
+        private void btn_AddProcess_Click(object sender, EventArgs e)
+        {
+            string Name = "娴佺▼" + GlobalVar.dicProcesses.Count;
+            while (GlobalVar.dicProcesses.ContainsKey(Name))
+                Name += "鍓湰";
+
+            if (string.IsNullOrEmpty(Name))
+                return;
+
+            int hashCode = GlobalVar.dicProcesses.GetHashCode();
+            GlobalVar.dicProcesses.TryAdd(Name, new ProcessRunBll(Name, GlobalVar.dicCameras, GlobalVar.dicCommunicators));
+            LogInfo?.Invoke(string.Format("娣诲姞娴佺▼[{0}]鎴愬姛", Name), LogInfoType.PASS);
+            this.Invalidate();
+        }
+
+        private void LoadFlowEvent(UserItem flow)
+        {
+            //鎸夐敭1涓洪噸鍛藉悕
+            flow.MenuItem1ClickedEvent += RenameEvent;
+            //鎸夐敭2涓虹Щ闄�
+            flow.MenuItem2ClickedEvent += DeleteEvent;
+        }
+
+        private void RemoveFlowEvent(UserItem flow)
+        {
+            //鎸夐敭1涓洪噸鍛藉悕
+            flow.MenuItem1ClickedEvent -= RenameEvent;
+            //鎸夐敭2涓虹Щ闄�
+            flow.MenuItem2ClickedEvent -= DeleteEvent;
+        }
+
+        /// <summary>
+        /// 閲嶅懡鍚嶆祦绋�
+        /// </summary>
+        /// <param name="Name"></param>
+        /// <param name="Text"></param>
+        private void RenameEvent(string Name, string Text)
+        {
+            RenameForm renameForm = new RenameForm(Name);
+            // 璁㈤槄浜嬩欢
+            renameForm.ShowDialog();
+            if (!renameForm.bRename)
+                return;
+
+            if (GlobalVar.dicProcesses.ContainsKey(renameForm.strNewName))
+            {
+                MessageBox.Show("鍛藉悕閲嶅!", "寮傚父");
+                return;
+            }
+
+            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+            {
+                UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                string name = flow.Name;
+                if (name != Name)
+                    continue;
+                flow.Name = renameForm.strNewName;
+
+                string oldName = name;
+                string newName = renameForm.strNewName;
+
+                // 閲嶅懡鍚嶅墠淇濆瓨娴佺▼
+                if (GlobalVar.dicProcesses.ContainsKey(oldName)
+                    && GlobalVar.dicProcesses[oldName].Save(out _))
+                    GlobalVar.dicProcesses.TryRename(oldName, newName);
+
+                flow.Refresh();
+            }
+        }
+
+        /// <summary>
+        /// 绉婚櫎娴佺▼
+        /// </summary>
+        /// <param name="Name"></param>
+        /// <param name="Text"></param>
+        private void DeleteEvent(string Name, string Text)
+        {
+            if (uiFlowLayoutPanel1.Controls.Count <= 1)
+            {
+                MessageBox.Show("鑷冲皯淇濈暀涓�涓祦绋�");
+                return;
+            }
+            try
+            {
+                this.BeginInvoke(new Action(() =>
+                {
+                    for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+                    {
+                        UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                        string name = flow.Name;
+                        if (name != Name)
+                            continue;
+
+                        // 鎵ц棰濆鐨勯�昏緫锛屽纭鍒犻櫎鎴栬褰曟暟鎹�
+                        DialogResult result = MessageBox.Show($"纭畾瑕佸垹闄{name}]锛熻鎿嶄綔鏄笉鍙仮澶嶇殑", "鍒犻櫎纭", MessageBoxButtons.YesNoCancel);
+
+                        // 濡傛灉鐢ㄦ埛閫夋嫨鈥滃惁鈥濓紝鍒欏彇娑堝垹闄ゆ搷浣�
+                        if (result == DialogResult.Yes)
+                        {
+                            RemoveFlowEvent(flow);
+                            uiFlowLayoutPanel1.Controls.Remove(uiFlowLayoutPanel1.Controls[i]);
+                            GlobalVar.dicProcesses.TryRemove(name, out ProcessRunBll ProcessRunBll);
+
+                            string ProcessPath = GlobalVar.allProcessPath + name;
+                            if (Directory.Exists(ProcessPath))
+                                Directory.Delete(ProcessPath, true);
+                        }
+                    }
+                }));
+            }
+            catch { }
+
+        }
+
+        private void LoadData()
+        {
+            dataGridView.AllowUserToAddRows = false;
+            dataGridView.Columns.Clear();
+            dataGridView.Rows.Clear();
+
+            dataGridView.DataSource = null;
+
+            // 鍒涘缓甯︽湁 ComboBox 鐨勫垪
+            DataGridViewComboBoxColumn comboBoxColumn0 = new DataGridViewComboBoxColumn();
+            comboBoxColumn0.HeaderText = "娴佺▼鍚�";
+            comboBoxColumn0.Name = "TableName";
+            comboBoxColumn0.Items.Add("鏃�");
+            foreach (var ProcessName in GlobalVar.dicProcesses.Keys)
+                comboBoxColumn0.Items.Add(ProcessName);
+            dataGridView.Columns.Add(comboBoxColumn0);
+
+            // 鍒涘缓甯︽湁 ComboBox 鐨勫垪
+            DataGridViewComboBoxColumn comboBoxColumn1 = new DataGridViewComboBoxColumn();
+            comboBoxColumn1.HeaderText = "瑙﹀彂閫氳";
+            comboBoxColumn1.Name = "TriggerComName";
+            comboBoxColumn1.Items.Add("鏃�");
+            foreach (var ComName in GlobalVar.dicCommunicators.Keys)
+                comboBoxColumn1.Items.Add(ComName);
+            dataGridView.Columns.Add(comboBoxColumn1);
+
+            // 鍒涘缓鏅�氭枃鏈垪
+            dataGridView.Columns.Add("TriggerString", "瑙﹀彂瀛楃");
+
+            DataGridViewComboBoxColumn comboBoxColumn2 = new DataGridViewComboBoxColumn();
+            comboBoxColumn2.HeaderText = "鎴愬姛閫氳";
+            comboBoxColumn2.Name = "PassComName";
+            comboBoxColumn2.Items.Add("鏃�");
+            foreach (var ComName in GlobalVar.dicCommunicators.Keys)
+                comboBoxColumn2.Items.Add(ComName);
+            dataGridView.Columns.Add(comboBoxColumn2);
+
+            // 鍒涘缓鏅�氭枃鏈垪
+            dataGridView.Columns.Add("PassString", "鎴愬姛瀛楃");
+
+            DataGridViewComboBoxColumn comboBoxColumn3 = new DataGridViewComboBoxColumn();
+            comboBoxColumn3.HeaderText = "澶辫触閫氳";
+            comboBoxColumn3.Name = "ErrorComName";
+            comboBoxColumn3.Items.Add("鏃�");
+            foreach (var ComName in GlobalVar.dicCommunicators.Keys)
+                comboBoxColumn3.Items.Add(ComName);
+            dataGridView.Columns.Add(comboBoxColumn3);
+            dataGridView.Columns.Add("ErrorString", "澶辫触瀛楃");
+
+            // 鍒涘缓鏅�氭枃鏈垪
+            dataGridView.Columns.Add("RetestTimes", "閲嶆祴娆℃暟");
+            dataGridView.Columns.Add("ConnectProcess", "鍏宠仈娴佺▼");
+
+            // 鍒涘缓甯︽湁 Button 鐨勫垪
+            DataGridViewButtonColumn btnEditResult = new DataGridViewButtonColumn();
+            btnEditResult.HeaderText = "鍏宠仈缁撴灉";
+            btnEditResult.Name = "ConnectResult";
+            btnEditResult.Text = "鏈叧鑱�"; // 鎸夐挳鏄剧ず鐨勬枃鏈�
+            btnEditResult.UseColumnTextForButtonValue = false; // 绂佺敤缁熶竴鏂囨湰
+            dataGridView.Columns.Add(btnEditResult);
+
+            foreach (var item in GlobalVar.dicProcessSetting.OrderBy(kvp => kvp.Key))
+            {
+                string ProcessName = item.Value["娴佺▼鍚�"];
+
+                string TriggerComName = item.Value["瑙﹀彂閫氳"];
+                string TriggerString = item.Value["瑙﹀彂瀛楃"];
+
+                string PassComName = item.Value["鎴愬姛閫氳"];
+                string PassString = item.Value["鎴愬姛瀛楃"];
+
+                string ErrorComName = item.Value["澶辫触閫氳"];
+                string ErrorString = item.Value["澶辫触瀛楃"];
+
+                string RetestTimes = item.Value["閲嶆祴娆℃暟"];
+                string ConnectProcess = item.Value["鍏宠仈娴佺▼"];
+                string ConnectResult = item.Value["鍏宠仈缁撴灉"];
+
+                if (string.IsNullOrEmpty(ConnectResult) || ConnectResult.Trim() == "")
+                    ConnectResult = "鏈叧鑱�";
+
+                if (!GlobalVar.dicCommunicators.ContainsKey(TriggerComName) && GlobalVar.dicCommunicators.Count > 0)
+                {
+                    if (TriggerComName != "鏃�")
+                        TriggerComName = GlobalVar.dicCommunicators.ElementAt(0).Key;
+                    item.Value["瑙﹀彂閫氳"] = TriggerComName;
+                }
+
+                if (!GlobalVar.dicCommunicators.ContainsKey(PassComName) && GlobalVar.dicCommunicators.Count > 0)
+                {
+                    if (PassComName != "鏃�")
+                        PassComName = GlobalVar.dicCommunicators.ElementAt(0).Key;
+                    item.Value["鎴愬姛閫氳"] = PassComName;
+                }
+
+                if (!GlobalVar.dicCommunicators.ContainsKey(ErrorComName) && GlobalVar.dicCommunicators.Count > 0)
+                {
+                    if (ErrorComName != "鏃�")
+                        ErrorComName = GlobalVar.dicCommunicators.ElementAt(0).Key;
+                    item.Value["澶辫触閫氳"] = ErrorComName;
+                }
+
+                // 娣诲姞琛屽苟璁剧疆鎸夐挳鏂囨湰
+                int rowIndex = dataGridView.Rows.Add(
+                    ProcessName,
+                    TriggerComName,
+                    TriggerString,
+                    PassComName,
+                    PassString,
+                    ErrorComName,
+                    ErrorString,
+                    RetestTimes,
+                    ConnectProcess
+                );
+
+                // 鍗曠嫭璁剧疆鎸夐挳鍒楃殑鍊间负ConnectRsult
+                dataGridView.Rows[rowIndex].Cells["ConnectResult"].Value = ConnectResult;
+            }
+            //dataGridView.Columns["DBName"].ReadOnly = true;
+        }
+
+        private void dataGridView_DataError(object sender, DataGridViewDataErrorEventArgs e)
+        {
+            // 璁板綍閿欒浣嗕笉鏄剧ず榛樿瀵硅瘽妗�
+            e.ThrowException = false;
+
+            //// 鍙互鑷畾涔夐敊璇鐞�
+            //MessageBox.Show($"鏁版嵁閿欒: {e.Exception.Message}", "閿欒",
+            //              MessageBoxButtons.OK, MessageBoxIcon.Error);
+
+            //// 鎴栬�呯畝鍗曞湴蹇界暐閿欒
+            //e.Cancel = true;
+        }
+
+        private void dataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
+        {
+            int rowIndex = e.RowIndex;  // 鑾峰彇淇敼鐨勮绱㈠紩
+            int columnIndex = e.ColumnIndex;  // 鑾峰彇淇敼鐨勫垪绱㈠紩
+
+            if (e.ColumnIndex == 0
+                && dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex] != null
+                && dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewComboBoxCell)
+            {
+                DataGridViewComboBoxCell cell =
+                    dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex] as DataGridViewComboBoxCell;
+
+                // 娓呯┖鍘熸湁閫夐」
+                cell.Items.Clear();
+                foreach (var ProcessName in GlobalVar.dicProcesses.Keys)
+                    cell.Items.Add(ProcessName);
+            }
+
+            if ((e.ColumnIndex == 1 || e.ColumnIndex == 3)
+                && dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex] != null
+                && dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewComboBoxCell)
+            {
+                DataGridViewComboBoxCell cell =
+                    dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex] as DataGridViewComboBoxCell;
+
+                // 娓呯┖鍘熸湁閫夐」
+                cell.Items.Clear();
+                cell.Items.Add("鏃�");
+                foreach (var ComName in GlobalVar.dicCommunicators.Keys)
+                    cell.Items.Add(ComName);
+            }
+        }
+
+        private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
+        {
+            int rowIndex = e.RowIndex;  // 鑾峰彇淇敼鐨勮绱㈠紩
+            int columnIndex = e.ColumnIndex;  // 鑾峰彇淇敼鐨勫垪绱㈠紩
+        }
+
+        private void dataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
+        {
+            // 鑾峰彇褰撳墠鍗冲皢琚垹闄ょ殑琛岀殑鏁版嵁
+            DataGridViewRow rowToDelete = e.Row;
+
+            // 鍋囪鎴戜滑瑕佹鏌ョ涓�鍒楃殑鏁版嵁
+            string ProcessName = rowToDelete.Cells[0]?.Value?.ToString();
+
+            // 鎵ц棰濆鐨勯�昏緫锛屽纭鍒犻櫎鎴栬褰曟暟鎹�
+            DialogResult result = MessageBox.Show($"纭畾瑕佸垹闄わ紵璇ユ搷浣滄槸涓嶅彲鎭㈠鐨�", "鍒犻櫎纭", MessageBoxButtons.YesNo);
+
+            // 濡傛灉鐢ㄦ埛閫夋嫨鈥滃惁鈥濓紝鍒欏彇娑堝垹闄ゆ搷浣�
+            if (result == DialogResult.No)
+            {
+                e.Cancel = true;  // 鍙栨秷鍒犻櫎鎿嶄綔
+            }
+            else
+            {
+                LogInfo?.Invoke(string.Format("娴佺▼[{0}]鍒犻櫎瑙﹀彂璁剧疆", ProcessName), LogInfoType.INFO);
+
+                // 濡傛灉闇�瑕侊紝鍙互鍦ㄨ繖閲屾墽琛屽垹闄ゅ墠鐨勯澶栧鐞�
+                GlobalVar.dicProcessSetting.TryRemove(e.Row.Index, out ConcurrentDictionary<string, string> dic);
+            }
+        }
+
+        private void dataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
+        {
+            try
+            {
+                if (e.ColumnIndex == dataGridView.Columns["ConnectResult"].Index && e.RowIndex >= 0)
+                {
+                    // 鑾峰彇褰撳墠琛岀殑鏁版嵁
+                    string ProcessName = dataGridView.Rows[e.RowIndex].Cells["TableName"].Value?.ToString();
+                    if (string.IsNullOrEmpty(ProcessName))
+                        return;
+
+                    ProcessOutputsSelectForm processOutputsSelectForm
+                        = new ProcessOutputsSelectForm(GlobalVar.dicProcesses[ProcessName].dicInputsMapping, GlobalVar.dicProcesses[ProcessName].dicOutputsMapping);
+                    processOutputsSelectForm.ShowDialog();
+
+                    if (string.IsNullOrEmpty(processOutputsSelectForm.SelectedOutput))
+                    {
+                        (GlobalVar.dicProcessSetting[e.RowIndex])["鍏宠仈缁撴灉"] = processOutputsSelectForm.SelectedOutput;
+                        dataGridView.Rows[e.RowIndex].Cells["ConnectResult"].Value = processOutputsSelectForm.SelectedOutput;
+                    }
+                }
+            }
+            catch { }
+        }
+
+        private void btn_SaveProcessSetting_Click(object sender, EventArgs e)
+        {
+            GlobalVar.dicProcessSetting.Clear();
+            foreach (DataGridViewRow row in dataGridView.Rows)
+            {
+                if (!row.IsNewRow && row.Cells.Count >= 3 && row.Cells[0].Value != null)
+                {
+                    ConcurrentDictionary<string, string> keyValuePairs = new ConcurrentDictionary<string, string>();
+
+                    int i = 0;
+
+                    i = 0;
+                    string ProcessName = row.Cells[i].Value == null ? "" : row.Cells[i].Value.ToString();
+
+                    i = 1;
+                    string TriggerComName = row.Cells[i].Value == null ? "" : row.Cells[i].Value.ToString();
+
+                    i = 2;
+                    string TriggerString = row.Cells[i].Value == null ? "" : row.Cells[i].Value.ToString();
+
+                    i = 3;
+                    string PassComName = row.Cells[i].Value == null ? "" : row.Cells[i].Value.ToString();
+
+                    i = 4;
+                    string PassString = row.Cells[i].Value == null ? "" : row.Cells[i].Value.ToString();
+
+                    i = 5;
+                    string ErrorComName = row.Cells[i].Value == null ? "" : row.Cells[i].Value.ToString();
+
+                    i = 6;
+                    string ErrorString = row.Cells[i].Value == null ? "" : row.Cells[i].Value.ToString();
+
+                    i = 7;
+                    string RetestTimes = row.Cells[i].Value == null ? "" : row.Cells[i].Value.ToString();
+
+                    i = 8;
+                    string ConnectProcess = row.Cells[i].Value == null ? "" : row.Cells[i].Value.ToString();
+
+                    i = 9;
+                    string ConnectResult = row.Cells[i].Value == null ? "鏈叧鑱�" : row.Cells[i].Value.ToString();
+
+                    keyValuePairs.TryAdd("娴佺▼鍚�", ProcessName);
+                    keyValuePairs.TryAdd("瑙﹀彂閫氳", TriggerComName);
+                    keyValuePairs.TryAdd("瑙﹀彂瀛楃", TriggerString);
+
+                    keyValuePairs.TryAdd("鎴愬姛閫氳", PassComName);
+                    keyValuePairs.TryAdd("鎴愬姛瀛楃", PassString);
+
+                    keyValuePairs.TryAdd("澶辫触閫氳", ErrorComName);
+                    keyValuePairs.TryAdd("澶辫触瀛楃", ErrorString);
+
+                    keyValuePairs.TryAdd("閲嶆祴娆℃暟", RetestTimes);
+                    keyValuePairs.TryAdd("鍏宠仈娴佺▼", ConnectProcess);
+                    keyValuePairs.TryAdd("鍏宠仈缁撴灉", ConnectResult);
+
+                    GlobalVar.dicProcessSetting.TryAdd(row.Index, keyValuePairs);
+                }
+            }
+
+            if (!VisionForm.SaveAllProcessSetting())
+            {
+                MessageBox.Show("淇濆瓨澶辫触!", "寮傚父");
+                LogInfo?.Invoke(string.Format("淇濆瓨娴佺▼澶辫触"), LogInfoType.ERROR);
+            }
+            else
+                LogInfo?.Invoke(string.Format("淇濆瓨娴佺▼鎴愬姛"), LogInfoType.PASS);
+        }
+
+        private void btn_Add_Click(object sender, EventArgs e)
+        {
+            string ProcessName = string.Empty;
+            if (GlobalVar.dicProcesses.Count > 0)
+                ProcessName = GlobalVar.dicProcesses.Keys.ToList()[0];
+
+            ConcurrentDictionary<string, string> keyValuePairs = new ConcurrentDictionary<string, string>();
+
+            string ComName = string.Empty;
+            if (string.IsNullOrEmpty(ComName) && GlobalVar.dicCommunicators.Count > 0)
+                ComName = GlobalVar.dicCommunicators.ElementAt(0).Key;
+
+            keyValuePairs.TryAdd("娴佺▼鍚�", ProcessName);
+            keyValuePairs.TryAdd("瑙﹀彂閫氳", ComName);
+            keyValuePairs.TryAdd("瑙﹀彂瀛楃", "TEST");
+            keyValuePairs.TryAdd("鎴愬姛閫氳", ComName);
+            keyValuePairs.TryAdd("鎴愬姛瀛楃", "WB_OK");
+            keyValuePairs.TryAdd("澶辫触閫氳", ComName);
+            keyValuePairs.TryAdd("澶辫触瀛楃", "WB_NG");
+            keyValuePairs.TryAdd("閲嶆祴娆℃暟", "0");
+            keyValuePairs.TryAdd("鍏宠仈娴佺▼", "");
+            keyValuePairs.TryAdd("鍏宠仈缁撴灉", "鏈叧鑱�");
+
+            GlobalVar.dicProcessSetting.TryAdd(dataGridView.Rows.Count, keyValuePairs);
+
+            LogInfo?.Invoke(string.Format("娴佺▼[{0}]鏂板缓瑙﹀彂璁剧疆", ProcessName), LogInfoType.INFO);
+            LoadData();
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.resx b/LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/SettingPage/SettingEditPage.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/LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.Designer.cs b/LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.Designer.cs
new file mode 100644
index 0000000..88a489d
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.Designer.cs
@@ -0,0 +1,152 @@
+锘�
+using ReaLTaiizor.Controls;
+
+namespace LB_SmartVision.Forms.Pages.UserManagementPage
+{
+    partial class UserManagementEditPage
+    {
+        /// <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()
+        {
+            btn_Add = new HopeButton();
+            btn_Clear = new LostButton();
+            uiFlowLayoutPanel1 = new FlowLayoutPanel();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            SuspendLayout();
+            // 
+            // btn_Add
+            // 
+            btn_Add.BorderColor = Color.FromArgb(220, 223, 230);
+            btn_Add.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            btn_Add.Cursor = Cursors.Hand;
+            btn_Add.DangerColor = Color.FromArgb(245, 108, 108);
+            btn_Add.DefaultColor = Color.FromArgb(255, 255, 255);
+            btn_Add.Dock = DockStyle.Fill;
+            btn_Add.Font = new Font("瀹嬩綋", 12F);
+            btn_Add.HoverTextColor = Color.FromArgb(48, 49, 51);
+            btn_Add.InfoColor = Color.FromArgb(144, 147, 153);
+            btn_Add.Location = new Point(503, 3);
+            btn_Add.MinimumSize = new Size(1, 1);
+            btn_Add.Name = "btn_Add";
+            btn_Add.PrimaryColor = Color.FromArgb(64, 158, 255);
+            btn_Add.Size = new Size(95, 38);
+            btn_Add.SuccessColor = Color.FromArgb(103, 194, 58);
+            btn_Add.TabIndex = 11;
+            btn_Add.Text = "澧炲姞";
+            btn_Add.TextColor = Color.White;
+            btn_Add.WarningColor = Color.FromArgb(230, 162, 60);
+            // 
+            // btn_Clear
+            // 
+            btn_Clear.BackColor = Color.FromArgb(45, 45, 48);
+            btn_Clear.Cursor = Cursors.Hand;
+            btn_Clear.Dock = DockStyle.Fill;
+            btn_Clear.Font = new Font("瀹嬩綋", 12F);
+            btn_Clear.ForeColor = Color.White;
+            btn_Clear.HoverColor = Color.DodgerBlue;
+            btn_Clear.Image = null;
+            btn_Clear.Location = new Point(403, 3);
+            btn_Clear.MinimumSize = new Size(1, 1);
+            btn_Clear.Name = "btn_Clear";
+            btn_Clear.Size = new Size(94, 38);
+            btn_Clear.TabIndex = 12;
+            btn_Clear.Text = "娓呴櫎";
+            // 
+            // uiFlowLayoutPanel1
+            // 
+            uiFlowLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            uiFlowLayoutPanel1.Dock = DockStyle.Fill;
+            uiFlowLayoutPanel1.Font = new Font("瀹嬩綋", 12F);
+            uiFlowLayoutPanel1.ForeColor = SystemColors.Control;
+            uiFlowLayoutPanel1.Location = new Point(4, 5);
+            uiFlowLayoutPanel1.Margin = new Padding(4, 5, 4, 5);
+            uiFlowLayoutPanel1.MinimumSize = new Size(1, 1);
+            uiFlowLayoutPanel1.Name = "uiFlowLayoutPanel1";
+            uiFlowLayoutPanel1.Padding = new Padding(2);
+            uiFlowLayoutPanel1.Size = new Size(599, 293);
+            uiFlowLayoutPanel1.TabIndex = 10;
+            uiFlowLayoutPanel1.Text = "`";
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.Controls.Add(uiFlowLayoutPanel1, 0, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 1);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 2;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.Size = new Size(607, 353);
+            tableLayoutPanel1.TabIndex = 13;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 6;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.Controls.Add(btn_Add, 5, 0);
+            tableLayoutPanel2.Controls.Add(btn_Clear, 4, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 306);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 1;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(601, 44);
+            tableLayoutPanel2.TabIndex = 11;
+            // 
+            // UserManagementEditPage
+            // 
+            BackColor = Color.FromArgb(32, 41, 50);
+            Controls.Add(tableLayoutPanel1);
+            ForeColor = SystemColors.Control;
+            Name = "UserManagementEditPage";
+            Size = new Size(607, 353);
+            Paint += MESEditPage_Paint;
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ReaLTaiizor.Controls.HopeButton btn_Add;
+        private ReaLTaiizor.Controls.LostButton btn_Clear;
+        private FlowLayoutPanel uiFlowLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel2;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.cs b/LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.cs
new file mode 100644
index 0000000..528daa5
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.cs
@@ -0,0 +1,30 @@
+锘縰sing LB_VisionControl;
+using OpenCvSharp.Flann;
+using System;
+using System.Collections.Concurrent;
+using System.Windows.Forms;
+using System.Xml.Linq;
+
+namespace LB_SmartVision.Forms.Pages.UserManagementPage
+{
+    public partial class UserManagementEditPage : UserControl
+    {
+        public Action<string, LogInfoType> LogInfo;
+
+
+        public UserManagementEditPage()
+        {
+            InitializeComponent();
+
+            Name = "UserManagementEditPage";
+            Text = "鐢ㄦ埛绠$悊璁剧疆";
+        }
+
+        private void MESEditPage_Paint(object sender, PaintEventArgs e)
+        {
+            uiFlowLayoutPanel1.Controls.Clear();
+        }
+
+
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.resx b/LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/UserManagementPage/UserManagementEditPage.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/LB_SmartVision/GlobalVar.cs b/LB_SmartVision/GlobalVar.cs
new file mode 100644
index 0000000..230e920
--- /dev/null
+++ b/LB_SmartVision/GlobalVar.cs
@@ -0,0 +1,124 @@
+锘縰sing LB_SmartVision.Forms.Pages.SettingPage;
+using LB_SmartVision.ProcessRun;
+using LB_SmartVision.Tool;
+using LB_VisionProcesses.Cameras;
+using LB_VisionProcesses.Communicators;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVision
+{
+    public enum LogInfoType { INFO, WARN, PASS, ERROR, NOSHOW }
+
+    public class GlobalVar
+    {
+        static GlobalVar()
+        {
+            strApplicationPath = Application.StartupPath;
+
+            strPathLog = Application.StartupPath + "鐢熶骇鏃ュ織\\" + DateTime.Now.ToString("yyyyMMdd");
+
+            strPathCsv = Application.StartupPath + "鐢熶骇鏁版嵁\\" + DateTime.Now.ToString("yyyyMMdd");
+
+            strStartTime = DateTime.Now.ToString("yyyyMMdd_HHmm");
+        }
+
+        /// <summary>
+        /// 娴佺▼闆嗗悎(Key:娴佺▼鍚嶏紝Value:杩愯姝ラ闆嗗悎)
+        /// </summary>
+        public static ObservableConcurrentDictionary<string, ProcessRunBll> dicProcesses { get; set; } = new ObservableConcurrentDictionary<string, ProcessRunBll>();
+
+        /// <summary>
+        /// 鐩告満闆嗗悎(Key:鐩告満SN锛孷alue:鐩告満鍙ユ焺)
+        /// </summary>
+        public static ObservableConcurrentDictionary<string, BaseCamera> dicCameras { get; set; } = new ObservableConcurrentDictionary<string, BaseCamera>();
+
+        /// <summary>
+        /// 閫氳闆嗗悎(Key:閫氳鍚嶏紝Value:閫氳鍙ユ焺)
+        /// </summary>
+        public static ObservableConcurrentDictionary<string, BaseCommunicator> dicCommunicators { get; set; } = new ObservableConcurrentDictionary<string, BaseCommunicator>();
+
+        /// <summary>
+        /// 瑙﹀彂娴佺▼璁剧疆闆嗗悎
+        /// </summary>
+        public static ConcurrentDictionary<int, ConcurrentDictionary<string, string>> dicProcessSetting { get; set; } = new ConcurrentDictionary<int, ConcurrentDictionary<string, string>>();
+
+        /// <summary>
+        /// 甯冨眬闆嗗悎
+        /// </summary>
+        public static ConcurrentDictionary<int, Layout> dicLayout { get; set; } = new ConcurrentDictionary<int, Layout>();
+
+        /// <summary>
+        /// 琛ㄦ牸闆嗗悎
+        /// </summary>
+        public static ConcurrentDictionary<string, CsvSetting> dicCsvSetting { get; set; } = new ConcurrentDictionary<string, CsvSetting>();
+
+        public static string allProcessConnectionStringPath
+            => GlobalVar.strApplicationPath + "\\鎵�鏈変骇鍝乗\" + GlobalVar.strProductName + "\\A_ProcessConnections.json";
+
+        #region 鐩告満
+        public static ConcurrentDictionary<string, string> allCamerasConnectionString = new ConcurrentDictionary<string, string>();
+        public static string allCamerasConnectionStringPath
+            => GlobalVar.strApplicationPath + "\\鎵�鏈変骇鍝乗\" + GlobalVar.strProductName + "\\A_CameraConnections.json";
+        #endregion
+
+        #region 閫氳鍙�
+        public static ConcurrentDictionary<string, string> allCommunicatorsConnectionString = new ConcurrentDictionary<string, string>();
+        public static string allCommunicatorsConnectionStringPath
+            => GlobalVar.strApplicationPath + "\\鎵�鏈変骇鍝乗\" + GlobalVar.strProductName + "\\A_CommunicatorConnections.json";
+
+        #endregion
+
+        #region 娴佺▼
+        public static Dictionary<string, object> ControlStates { get; set; } = new Dictionary<string, object>();
+
+        public static string allProcessPath
+            => GlobalVar.strApplicationPath + "\\鎵�鏈変骇鍝乗\" + GlobalVar.strProductName + "\\";
+
+        public static string allProcessSettingStringPath
+            => GlobalVar.strApplicationPath + "\\鎵�鏈変骇鍝乗\" + GlobalVar.strProductName + "\\A_ProcessSettings.json";
+
+        public static string allRunSettingStringPath
+            => GlobalVar.strApplicationPath + "\\鎵�鏈変骇鍝乗\" + GlobalVar.strProductName + "\\A_RunSettings.json";
+
+        public static string allProcessVarsPath
+            => GlobalVar.strApplicationPath + "\\鎵�鏈変骇鍝乗\" + GlobalVar.strProductName + "\\A_ProcessVars.json";
+
+        public static string allLayoutPath
+             => GlobalVar.strApplicationPath + "\\鎵�鏈変骇鍝乗\" + GlobalVar.strProductName + "\\A_AllLayout.json";
+
+        public static string allCsvPath
+            => GlobalVar.strApplicationPath + "\\鎵�鏈変骇鍝乗\" + GlobalVar.strProductName + "\\A_AllCsv.json";
+        #endregion
+
+        /// <summary>
+        /// 杞欢璺緞
+        /// </summary>
+        public static string strApplicationPath = Application.StartupPath;
+
+        /// <summary>
+        /// 浜у搧鍚嶇О
+        /// </summary>
+        public static string strProductName = "浜у搧0";
+
+        /// <summary>
+        /// 瀛樺偍鏃ュ織璺緞
+        /// </summary>
+        public static string strPathLog = Application.StartupPath + "鐢熶骇鏃ュ織\\" + DateTime.Now.ToString("yyyyMMdd");
+
+
+        /// <summary>
+        /// 瀛樺偍鏃ュ織璺緞
+        /// </summary>
+        public static string strPathCsv = Application.StartupPath + "鐢熶骇鏁版嵁\\" + DateTime.Now.ToString("yyyyMMdd");
+
+        /// <summary>
+        /// 杞欢寮�鍚棩鏈�
+        /// </summary>
+        public static string strStartTime = string.Empty;
+    }
+}
diff --git a/LB_SmartVision/LB_Collections.cs b/LB_SmartVision/LB_Collections.cs
new file mode 100644
index 0000000..30ee0d7
--- /dev/null
+++ b/LB_SmartVision/LB_Collections.cs
@@ -0,0 +1,223 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVision
+{
+    [Serializable]
+    public class LB_Collections<T> : ICollection<CollectionItem<T>>
+    {
+        private List<CollectionItem<T>> _items = new List<CollectionItem<T>>();
+
+        // 閫氳繃鍚嶇О鏌ユ壘
+        public CollectionItem<T> Get(string name)
+        {
+            var item = _items.FirstOrDefault(item => item.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
+            if (item == null)
+                return default;
+            return item;
+        }
+
+        // 閫氳繃绱㈠紩鏌ユ壘
+        public CollectionItem<T> Get(int index)
+        {
+            var item = _items.FirstOrDefault(item => item.Index == index);
+            if (item == null)
+                return default;
+            return item;
+        }
+
+        // ICollection<NamedItem<T>> 瀹炵幇
+        public int Count => _items.Count;
+
+        public bool IsReadOnly => false;
+
+        void ICollection<CollectionItem<T>>.Add(CollectionItem<T> item)
+        {
+            var existingItem = Get(item.Name);
+
+            if (existingItem != null)
+            {
+                // 濡傛灉宸插瓨鍦紝鏇存柊鐜版湁椤圭殑鍊�
+                existingItem = item;
+            }
+            else
+            {
+                // 濡傛灉涓嶅瓨鍦紝鍒涘缓鏂伴」骞跺垎閰嶇储寮�
+                _items.Add(item);
+            }
+
+            // 鏇存柊鍚庤嚜鍔ㄦ帓搴�
+            SortItems();
+        }
+
+        // 娣诲姞椤规椂涓烘柊椤瑰垎閰嶄竴涓储寮�
+        public void Add(string name, T value)
+        {
+            var existingItem = Get(name);
+
+            if (existingItem != null)
+            {
+                // 濡傛灉宸插瓨鍦紝鏇存柊鐜版湁椤圭殑鍊�
+                existingItem.Value = value;
+            }
+            else
+            {
+                // 濡傛灉涓嶅瓨鍦紝鍒涘缓鏂伴」骞跺垎閰嶇储寮�
+                var newItem = new CollectionItem<T>(name, _items.Count > 0 ? _items.Max(i => i.Index) + 1 : 0, value);
+                _items.Add(newItem);
+            }
+
+            // 鏇存柊鍚庤嚜鍔ㄦ帓搴�
+            SortItems();
+        }
+
+        // 鎸� Index 鎺掑簭闆嗗悎
+        private void SortItems()
+        {
+            _items = _items.OrderBy(item => item.Index).ToList();
+        }
+
+        // 閫氳繃绱㈠紩鍣ㄥ疄鐜板熀浜庡簭鍙风殑璁块棶
+        public T this[int index]
+        {
+            get
+            {
+                if (index < 0 || index >= _items.Count)
+                {
+                    return default;
+                }
+                return _items[index].Value;
+            }
+            set
+            {
+                if (index < 0 || index >= _items.Count)
+                {
+                    return;
+                }
+                _items[index].Value = value;
+            }
+        }
+
+        public T this[string name]
+        {
+            get
+            {
+                var existingItem = Get(name);
+                if (existingItem != null)
+                {
+                    // 濡傛灉宸插瓨鍦紝鏇存柊鐜版湁椤圭殑鍊�
+                    return existingItem.Value;
+                }
+                return default;
+            }
+            set
+            {
+                var item = _items.FirstOrDefault(i => i.Name == name);
+                if (item != null)
+                {
+                    item.Value = value;
+                }
+            }
+        }
+
+        public void Clear()
+        {
+            _items.Clear();
+            _items.TrimExcess(); // 灏嗗閲忕缉鍑忓埌瀹為檯鍏冪礌鏁伴噺
+        }
+
+        public bool Contains(CollectionItem<T> item)
+        {
+            return _items.Contains(item);
+        }
+
+        public bool Contains(string name)
+        {
+            var item = _items.FirstOrDefault(i => i.Name == name);
+            if (item != null)
+                return true;
+
+            return false;
+        }
+
+        public void CopyTo(CollectionItem<T>[] array, int arrayIndex)
+        {
+            _items.CopyTo(array, arrayIndex);
+        }
+
+        public bool Remove(CollectionItem<T> item)
+        {
+            var removed = _items.Remove(item);
+            if (removed)
+            {
+                // 绉婚櫎鍏冪礌鍚庯紝璋冩暣鍚庣画鍏冪礌鐨勭储寮�
+                UpdateIndexes();
+            }
+            return removed;
+        }
+
+        public IEnumerator<CollectionItem<T>> GetEnumerator()
+        {
+            return _items.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return _items.GetEnumerator();
+        }
+
+        // 閫氳繃鍚嶇О鍒犻櫎
+        public bool Remove(string name)
+        {
+            var namedItem = Get(name);
+            if (namedItem != null)
+            {
+                return Remove(namedItem);
+            }
+            return false;
+        }
+
+        // 閫氳繃绱㈠紩鍒犻櫎
+        public bool Remove(int index)
+        {
+            var namedItem = Get(index);
+            if (namedItem != null)
+            {
+                return Remove(namedItem);
+            }
+            return false;
+        }
+
+        // 鍒犻櫎椤瑰悗锛岃皟鏁村叾浠栭」鐨勭储寮�
+        private void UpdateIndexes()
+        {
+            for (int i = 0; i < _items.Count; i++)
+            {
+                _items[i].Index = i;
+            }
+        }
+    }
+
+    public class CollectionItem<T>
+    {
+        public string Name { get; set; }
+        public int Index { get; set; }
+        public T Value { get; set; }       // 瀛樺偍鐨勫璞�
+
+        public CollectionItem(string name, int index, T value)
+        {
+            Name = name;
+            Index = index;
+            Value = value;
+        }
+
+        public override string ToString()
+        {
+            return $"{Name} (Index: {Index}, Value: {Value})";
+        }
+    }
+}
diff --git a/LB_SmartVision/LB_SmartVision.csproj b/LB_SmartVision/LB_SmartVision.csproj
new file mode 100644
index 0000000..416a4e6
--- /dev/null
+++ b/LB_SmartVision/LB_SmartVision.csproj
@@ -0,0 +1,57 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>WinExe</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <Nullable>enable</Nullable>
+    <UseWindowsForms>true</UseWindowsForms>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <ApplicationIcon>logo.ico</ApplicationIcon>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Content Include="logo.ico" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\LB_VisionControl\LB_VisionControl.csproj" />
+    <ProjectReference Include="..\LB_VisionFlowNode\LB_VisionFlowNode.csproj" />
+    <ProjectReference Include="..\LB_VisionProcesses\LB_VisionProcesses.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Update="Properties\Resources.Designer.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <EmbeddedResource Update="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="Forms\Pages\CameraPage\" />
+    <Folder Include="Forms\Pages\CommunicatorPage\" />
+    <Folder Include="Forms\Pages\ProcessPage\" />
+    <Folder Include="Forms\Pages\SettingPage\" />
+    <Folder Include="ref\" />
+    <Folder Include="ProcessRun\" />
+    <Folder Include="Tool\" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="MaterialSkin.NET5" Version="1.0.2" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Reference Include="halcondotnet">
+      <HintPath>ref\halcondotnet.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+
+</Project>
\ No newline at end of file
diff --git a/LB_SmartVision/LB_SmartVision.sln b/LB_SmartVision/LB_SmartVision.sln
new file mode 100644
index 0000000..9ffe891
--- /dev/null
+++ b/LB_SmartVision/LB_SmartVision.sln
@@ -0,0 +1,67 @@
+锘�
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36804.6
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LB_SmartVision", "LB_SmartVision.csproj", "{BE6C1F96-7C34-4379-A819-D1E31CBF275C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LB_VisionControl", "..\LB_VisionControl\LB_VisionControl.csproj", "{09034C42-D16D-4DD4-8768-051463A2C026}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LB_VisionFlowNode", "..\LB_VisionFlowNode\LB_VisionFlowNode.csproj", "{5DF26C1E-07F7-4515-9855-78FE7C03E502}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LB_VisionProcesses", "..\LB_VisionProcesses\LB_VisionProcesses.csproj", "{A5B2996F-F417-40AE-A405-E39A8C71FFB3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LB_SmartVisionCommon", "..\LB_SmartVisionCommon\LB_SmartVisionCommon.csproj", "{3B0FE686-8AE4-4DFC-B14E-8794AE4557D4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LB_SmartVisionCameraDevice", "..\LB_SmartVisionCameraDevice\LB_SmartVisionCameraDevice.csproj", "{71FCC813-7297-4A75-830B-2ACB3EFF5498}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LB_SmartVisionCameraSDK", "..\LB_SmartVisionCameraSDK\LB_SmartVisionCameraSDK.csproj", "{6F4E5C61-CBA5-7DBA-018F-ADC56077E837}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LB_SmartVisionLoginUI", "..\LB_SmartVisionLoginUI\LB_SmartVisionLoginUI.csproj", "{6E8B08CC-DA76-415E-ABCA-165DA62F72CB}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{BE6C1F96-7C34-4379-A819-D1E31CBF275C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{BE6C1F96-7C34-4379-A819-D1E31CBF275C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BE6C1F96-7C34-4379-A819-D1E31CBF275C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{BE6C1F96-7C34-4379-A819-D1E31CBF275C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{09034C42-D16D-4DD4-8768-051463A2C026}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{09034C42-D16D-4DD4-8768-051463A2C026}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{09034C42-D16D-4DD4-8768-051463A2C026}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{09034C42-D16D-4DD4-8768-051463A2C026}.Release|Any CPU.Build.0 = Release|Any CPU
+		{5DF26C1E-07F7-4515-9855-78FE7C03E502}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{5DF26C1E-07F7-4515-9855-78FE7C03E502}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5DF26C1E-07F7-4515-9855-78FE7C03E502}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{5DF26C1E-07F7-4515-9855-78FE7C03E502}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A5B2996F-F417-40AE-A405-E39A8C71FFB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A5B2996F-F417-40AE-A405-E39A8C71FFB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A5B2996F-F417-40AE-A405-E39A8C71FFB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A5B2996F-F417-40AE-A405-E39A8C71FFB3}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3B0FE686-8AE4-4DFC-B14E-8794AE4557D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B0FE686-8AE4-4DFC-B14E-8794AE4557D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3B0FE686-8AE4-4DFC-B14E-8794AE4557D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3B0FE686-8AE4-4DFC-B14E-8794AE4557D4}.Release|Any CPU.Build.0 = Release|Any CPU
+		{71FCC813-7297-4A75-830B-2ACB3EFF5498}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{71FCC813-7297-4A75-830B-2ACB3EFF5498}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{71FCC813-7297-4A75-830B-2ACB3EFF5498}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{71FCC813-7297-4A75-830B-2ACB3EFF5498}.Release|Any CPU.Build.0 = Release|Any CPU
+		{6F4E5C61-CBA5-7DBA-018F-ADC56077E837}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{6F4E5C61-CBA5-7DBA-018F-ADC56077E837}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6F4E5C61-CBA5-7DBA-018F-ADC56077E837}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{6F4E5C61-CBA5-7DBA-018F-ADC56077E837}.Release|Any CPU.Build.0 = Release|Any CPU
+		{6E8B08CC-DA76-415E-ABCA-165DA62F72CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{6E8B08CC-DA76-415E-ABCA-165DA62F72CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6E8B08CC-DA76-415E-ABCA-165DA62F72CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{6E8B08CC-DA76-415E-ABCA-165DA62F72CB}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {2504174A-303B-40F7-9968-2DB03D8B58D5}
+	EndGlobalSection
+EndGlobal
diff --git a/LB_SmartVision/LB_SqlCommand.cs b/LB_SmartVision/LB_SqlCommand.cs
new file mode 100644
index 0000000..dd2cb12
--- /dev/null
+++ b/LB_SmartVision/LB_SqlCommand.cs
@@ -0,0 +1,573 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.SqlClient;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVision
+{
+    public class LB_SqlCommand
+    {
+        /// <summary>
+        /// 杩炴帴瀛楃涓诧細鎸囧畾 SQL Server 瀹炰緥鍜屾暟鎹簱(瀹為檯浼氳鍙杁ll.config涓殑鍊兼潵鏇存柊杩炴帴瀛楃涓�)
+        /// </summary>
+        public static string ConnectionString = "Data Source=localhost;Initial Catalog=master;Integrated Security=True;";
+
+        /// <summary>
+        /// 鍒ゆ柇鎸囧畾鍒楁槸鍚﹀瓨鍦ㄦ煇鍊�
+        /// </summary>
+        /// <param name="tableName">琛ㄥ悕</param>
+        /// <param name="columnName">鎸囧畾鍒楀悕</param>
+        /// <param name="value">鎸囧畾鍊�</param>
+        /// <param name="connectionString"></param>
+        /// <returns>鍊煎瓨鍦═rue</returns>
+        public static bool IsExist(string tableName, string columnName, string value, string connectionString = "")
+        {
+            if (string.IsNullOrEmpty(connectionString))
+                connectionString = ConnectionString;
+
+            // SQL 鏌ヨ璇彞锛屾鏌� ProcessName 鍒楁槸鍚﹀瓨鍦ㄦ寚瀹氱殑鍊�
+            string sqlQuery = string.Format("SELECT CASE WHEN EXISTS (SELECT 1 FROM [{0}] " +
+                "WHERE [{1}] = @Value) THEN 1 ELSE 0 END", tableName, columnName);
+
+            // 鍒涘缓 SQL 杩炴帴
+            using (SqlConnection connection = new SqlConnection(connectionString))
+            {
+                // 鍒涘缓 SQL 鍛戒护
+                using (SqlCommand command = new SqlCommand(sqlQuery, connection))
+                {
+                    // 娣诲姞鍙傛暟锛岄槻姝� SQL 娉ㄥ叆
+                    command.Parameters.AddWithValue("@Value", value);
+
+                    // 鎵撳紑杩炴帴
+                    connection.Open();
+
+                    // 鎵ц鏌ヨ骞惰幏鍙栫粨鏋�
+                    int result = (int)command.ExecuteScalar();
+
+                    // 濡傛灉 result == 1锛岃〃绀哄瓨鍦ㄨ鍊硷紱鍚﹀垯涓嶅瓨鍦�
+                    if (result == 1)
+                        return true;
+                    else
+                        return false;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鍒ゆ柇鎸囧畾琛ㄦ槸鍚﹀瓨鍦�
+        /// </summary>
+        /// <param name="tableName">琛ㄥ悕</param>
+        /// <param name="connectionString"></param>
+        /// <returns>鍊煎瓨鍦═rue</returns>
+        public static bool IsExistTable(string tableName, string connectionString = "")
+        {
+            if (string.IsNullOrEmpty(connectionString))
+                connectionString = ConnectionString;
+
+            // SQL 鏌ヨ璇彞锛屾鏌� ProcessName 鍒楁槸鍚﹀瓨鍦ㄦ寚瀹氱殑鍊�
+            string sqlQuery = $@"
+            SELECT COUNT(*)
+            FROM INFORMATION_SCHEMA.TABLES
+            WHERE TABLE_NAME = @TableName";
+
+            // 鍒涘缓 SQL 杩炴帴
+            using (SqlConnection connection = new SqlConnection(connectionString))
+            {
+                // 鍒涘缓 SQL 鍛戒护
+                using (SqlCommand command = new SqlCommand(sqlQuery, connection))
+                {
+                    // 娣诲姞琛ㄥ悕鍙傛暟
+                    command.Parameters.AddWithValue("@TableName", tableName);
+
+                    // 鎵撳紑杩炴帴
+                    connection.Open();
+
+                    // 鎵ц鏌ヨ骞惰幏鍙栫粨鏋�
+                    int result = (int)command.ExecuteScalar();
+
+                    // 濡傛灉 result > 0锛岃〃绀哄瓨鍦ㄨ琛紱鍚﹀垯涓嶅瓨鍦�
+                    if (result > 0)
+                        return true;
+                    else
+                        return false;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 閲嶅懡鍚嶈〃
+        /// </summary>
+        /// <param name="oldTableName"></param>
+        /// <param name="newTableName"></param>
+        /// <param name="connectionString"></param>
+        /// <returns></returns>
+        public static bool RenameTable(string oldTableName, string newTableName, string connectionString = "")
+        {
+            if (string.IsNullOrEmpty(connectionString))
+                connectionString = ConnectionString;
+
+            if (!IsExistTable(oldTableName))
+                return false;
+
+            // SQL 鏌ヨ璇彞锛屾鏌� ProcessName 鍒楁槸鍚﹀瓨鍦ㄦ寚瀹氱殑鍊�
+            string sqlQuery = $"EXEC sp_rename '{oldTableName}', '{newTableName}'"; ;
+
+            // 鍒涘缓 SQL 杩炴帴
+            using (SqlConnection connection = new SqlConnection(connectionString))
+            {
+                // 鍒涘缓 SQL 鍛戒护
+                using (SqlCommand command = new SqlCommand(sqlQuery, connection))
+                {
+                    // 鎵撳紑杩炴帴
+                    connection.Open();
+
+                    // 鎵ц鏌ヨ骞惰幏鍙栫粨鏋�
+                    int result = (int)command.ExecuteNonQuery();
+
+                    // 濡傛灉 result == -1锛岃〃绀洪噸鍛藉悕鎴愬姛
+                    if (result == -1)
+                        return true;
+                    else
+                        return false;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鍒ゆ柇鎸囧畾琛ㄦ槸鍚﹀瓨鍦�
+        /// </summary>
+        /// <param name="tableName">琛ㄥ悕</param>
+        /// <param name="connectionString"></param>
+        /// <returns>鍊煎瓨鍦═rue</returns>
+        public static bool DeleteTable(string tableName, string connectionString = "")
+        {
+            if (string.IsNullOrEmpty(connectionString))
+                connectionString = ConnectionString;
+
+            // SQL 鏌ヨ璇彞锛屾鏌� ProcessName 鍒楁槸鍚﹀瓨鍦ㄦ寚瀹氱殑鍊�
+            string sqlQuery = $"DROP TABLE IF EXISTS [{tableName}]";
+
+            // 鍒涘缓 SQL 杩炴帴
+            using (SqlConnection connection = new SqlConnection(connectionString))
+            {
+                // 鍒涘缓 SQL 鍛戒护
+                using (SqlCommand command = new SqlCommand(sqlQuery, connection))
+                {
+                    // 鎵撳紑杩炴帴
+                    connection.Open();
+
+                    // 鎵ц鏌ヨ骞惰幏鍙栫粨鏋�
+                    int result = (int)command.ExecuteNonQuery();
+
+                    // 濡傛灉 result = -1锛岃〃绀哄瓨鍦ㄨ琛ㄧЩ闄ゆ垚鍔�
+                    if (result == -1)
+                        return true;
+                    else
+                        return false;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎵�闇�鐨勫�奸�氳繃绱㈠紩鎸囧畾鍒楃殑鎸囧畾鍊煎畾浣嶅埌鎵�鍦ㄨ鐨勬寚瀹氬垪
+        /// </summary>
+        /// <param name="tableName">琛ㄥ悕</param>
+        /// <param name="indexName">鎸囧畾鍒楀悕</param>
+        /// <param name="indexValue">鎸囧畾鍒楀��</param>
+        /// <param name="columnName">鎵�闇�鍊肩殑鍒楀悕</param>
+        /// <param name="connectionString"></param>
+        /// <returns>鎵�闇�鍒楀��</returns>
+        public static string FindValueFromIndexName(string tableName, string indexName, string indexValue, string columnName, string connectionString = "")
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(connectionString))
+                    connectionString = ConnectionString;
+
+                // SQL 鏌ヨ璇彞锛屾鏌� ProcessName 鍒楁槸鍚﹀瓨鍦ㄦ寚瀹氱殑鍊�
+                string sqlQuery = $"SELECT {columnName} FROM [{tableName}] WHERE {indexName} = @IndexValue";
+                string resultValue = string.Empty;
+
+                // 杩炴帴鏁版嵁搴撳苟鎵ц鏌ヨ
+                using (SqlConnection connection = new SqlConnection(connectionString))
+                {
+                    using (SqlCommand command = new SqlCommand(sqlQuery, connection))
+                    {
+                        // 娣诲姞鍙傛暟浠ラ槻姝� SQL 娉ㄥ叆
+                        command.Parameters.AddWithValue("@IndexValue", indexValue);
+
+                        // 鎵撳紑杩炴帴
+                        connection.Open();
+
+                        // 鎵ц鏌ヨ骞惰幏鍙栫粨鏋�
+                        var result = command.ExecuteScalar();
+
+                        if (result != null)
+                        {
+                            resultValue = result.ToString();
+                        }
+                    }
+                }
+                return resultValue;
+            }
+            catch { return string.Empty; }
+        }
+
+        /// <summary>
+        /// 鍒犻櫎鎸囧畾琛岄�氳繃绱㈠紩鎸囧畾鍒楃殑鎸囧畾鍊�
+        /// </summary>
+        /// <param name="tableName">琛ㄥ悕</param>
+        /// <param name="indexName">鎸囧畾鍒楀悕</param>
+        /// <param name="indexValue">鎸囧畾鍒楀��</param>
+        /// <param name="connectionString"></param>
+        /// <returns>鍒犻櫎鎴愬姛True</returns>
+        public static bool DeleteRowFromIndexName(string tableName, string indexName, string indexValue, string connectionString = "")
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(connectionString))
+                    connectionString = ConnectionString;
+                using (SqlConnection conn = new SqlConnection(connectionString))
+                {
+                    conn.Open();
+
+                    // 鍒犻櫎鎸囧畾琛�
+                    string deleteQuery = string.Format("DELETE FROM [{0}] WHERE {1} = @indexValue", tableName, indexName);
+                    using (SqlCommand cmd = new SqlCommand(deleteQuery, conn))
+                    {
+                        cmd.Parameters.AddWithValue("@indexValue", indexValue);
+                        cmd.ExecuteNonQuery();
+                    }
+
+                    // 鏇存柊鍓╀綑琛岀殑 step
+                    string updateQuery = string.Format(@"
+                WITH OrderedSteps AS (
+                    SELECT {1}, ROW_NUMBER() OVER (ORDER BY {1}) AS NewValue
+                    FROM [{0}]
+                )
+                UPDATE [{0}]
+                SET {1} = NewValue
+                FROM [{0}] s
+                JOIN OrderedSteps o ON s.{1} = o.{1};
+            ", tableName, indexName);
+
+                    using (SqlCommand cmd = new SqlCommand(updateQuery, conn))
+                    {
+                        cmd.ExecuteNonQuery();
+                    }
+                    return true;
+                }
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 浜ゆ崲鎸囧畾琛岀殑鎵�鏈夊�奸�氳繃绱㈠紩鎸囧畾鍒楃殑鎸囧畾鍊�
+        /// </summary>
+        /// <param name="tableName">琛ㄥ悕</param>
+        /// <param name="swapName">鍒楀悕</param>
+        /// <param name="swapValue1">浜ゆ崲鐨勫垪鍊�</param>
+        /// <param name="swapValue2">琚氦鎹㈢殑鍒楀��</param>
+        /// <param name="connectionString"></param>
+        /// <returns>浜ゆ崲鎴愬姛True</returns>
+        public static bool SwapRowFromIndexName(string tableName, string swapName, string swapValue1, string swapValue2, string connectionString = "")
+        {
+
+            if (string.IsNullOrEmpty(connectionString))
+                connectionString = ConnectionString;
+            using (SqlConnection conn = new SqlConnection(connectionString))
+            {
+                conn.Open();
+
+                // 寮�濮嬩簨鍔�
+                SqlTransaction transaction = conn.BeginTransaction();
+                try
+                {
+                    // 浜ゆ崲 step 涓� 3 鍜� 4 鐨勮
+                    string swapQuery = string.Format(@"
+                        BEGIN TRANSACTION;
+                        UPDATE [{0}]
+                        SET {1} = @SwapTempValue
+                        WHERE {1} = @SwapValue1;
+
+                        UPDATE [{0}]
+                        SET {1} = @SwapValue1
+                        WHERE {1} = @SwapValue2;
+
+                        UPDATE [{0}]
+                        SET {1} = @SwapValue2
+                        WHERE {1} = @SwapTempValue;
+                        COMMIT;", tableName, swapName);
+
+                    using (SqlCommand cmd = new SqlCommand(swapQuery, conn, transaction))
+                    {
+                        // 娣诲姞鍙傛暟
+                        cmd.Parameters.AddWithValue("@SwapValue1", swapValue1);
+                        cmd.Parameters.AddWithValue("@SwapValue2", swapValue2);
+                        cmd.Parameters.AddWithValue("@SwapTempValue", Guid.NewGuid().ToString());
+
+                        // 鎵ц鏌ヨ
+                        cmd.ExecuteNonQuery();
+                    }
+
+                    // 鎻愪氦浜嬪姟
+                    transaction.Commit();
+                    return true;
+                }
+                catch (Exception ex)
+                {
+                    Debug.WriteLine("浜ゆ崲澶辫触,鍘熷洜鏄�:" + ex.Message.ToString());
+                    // 鍑虹幇寮傚父鏃跺洖婊氫簨鍔�
+                    transaction.Rollback();
+                    return false;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鏇存柊鎸囧畾鍒楃殑鍊奸�氳繃绱㈠紩鎸囧畾鍒楃殑鎸囧畾鍊�
+        /// </summary>
+        /// <param name="tableName"></param>
+        /// <param name="oriValue"></param>
+        /// <param name="newValue"></param>
+        /// <param name="columnName"></param>
+        /// <param name="connectionString"></param>
+        /// <returns></returns>
+        public static bool UpdataValueFromIndexName(string tableName, string oriValue, string newValue, string columnName, string connectionString = "")
+        {
+            if (string.IsNullOrEmpty(connectionString))
+                connectionString = ConnectionString;
+
+            // SQL 鏌ヨ璇彞锛屾鏌� ProcessName 鍒楁槸鍚﹀瓨鍦ㄦ寚瀹氱殑鍊�
+            string sqlQuery = string.Format("UPDATE [{0}] SET {1} = @NewValue WHERE {1} = @OriValue", tableName, columnName);
+            string resultValue = string.Empty;
+
+            // 杩炴帴鏁版嵁搴撳苟鎵ц鏌ヨ
+            using (SqlConnection connection = new SqlConnection(connectionString))
+            {
+                using (SqlCommand command = new SqlCommand(sqlQuery, connection))
+                {
+                    // 鍙傛暟鍖栨煡璇紝闃叉 SQL 娉ㄥ叆
+                    command.Parameters.AddWithValue("@OriValue", oriValue);  // 瑕佹浛鎹㈢殑鍘熷鍊�
+                    command.Parameters.AddWithValue("@NewValue", newValue);  // 鏇挎崲鍚庣殑鏂板��
+
+                    // 鎵撳紑杩炴帴
+                    connection.Open();
+
+                    // 鎵ц鏇存柊鎿嶄綔
+                    int rowsAffected = command.ExecuteNonQuery();
+
+                    if (rowsAffected > 0)
+                    {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+
+        /// <summary>
+        /// 妫�鏌ユ暟鎹簱鏄惁瀛樺湪
+        /// </summary>
+        /// <param name="connectionString"></param>
+        /// <param name="databaseName"></param>
+        /// <returns></returns>
+        public static bool DatabaseExists(string connectionString, string databaseName)
+        {
+            string query = "SELECT database_id FROM sys.databases WHERE name = @databaseName";
+
+            using (SqlConnection connection = new SqlConnection(connectionString))
+            {
+                connection.Open();
+                using (SqlCommand command = new SqlCommand(query, connection))
+                {
+                    command.Parameters.AddWithValue("@databaseName", databaseName);
+                    var result = command.ExecuteScalar();
+                    return result != null;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鍒涘缓鏁版嵁搴�(闇�瑕乵aster鏉冮檺)
+        /// </summary>
+        /// <param name="connectionString"></param>
+        /// <param name="databaseName"></param>
+        /// <param name="databasePath"></param>
+        /// <param name="logFilePath"></param>
+        public static bool CreateDatabase(string connectionString, string databaseName)
+        {
+            if (string.IsNullOrEmpty(connectionString))
+                connectionString = ConnectionString;
+
+            if (!connectionString.Contains("master"))
+                return false;
+
+            try
+            {
+                string createQuery = $@"CREATE DATABASE {databaseName}";
+
+                using (SqlConnection connection = new SqlConnection(connectionString))
+                {
+                    connection.Open();
+                    using (SqlCommand command = new SqlCommand(createQuery, connection))
+                    {
+                        command.ExecuteNonQuery();
+                    }
+                }
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 鍒犻櫎鏁版嵁搴�(闇�瑕乵aster鏉冮檺)
+        /// </summary>
+        /// <param name="tableName">琛ㄥ悕</param>
+        /// <param name="connectionString"></param>
+        /// <returns>鍊煎瓨鍦═rue</returns>
+        public static bool DeleteDatabase(string databaseName, string connectionString)
+        {
+            if (string.IsNullOrEmpty(connectionString))
+                connectionString = ConnectionString;
+
+            if (!connectionString.Contains("master"))
+                return false;
+
+            // 璁剧疆 SQL DROP DATABASE 璇彞
+            string dropDatabaseQuery = $"DROP DATABASE IF EXISTS {databaseName}";
+
+            using (SqlConnection connection = new SqlConnection(connectionString))
+            {
+                try
+                {
+                    // 鎵撳紑鏁版嵁搴撹繛鎺�
+                    connection.Open();
+
+                    // 1. 璁剧疆鏁版嵁搴撲负鍗曠敤鎴锋ā寮忥紝寮哄埗鏂紑鎵�鏈夎繛鎺�
+                    string setSingleUserQuery = $@"ALTER DATABASE [{databaseName}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;";
+                    using (var cmd = new SqlCommand(setSingleUserQuery, connection))
+                    {
+                        cmd.ExecuteNonQuery();
+                        Debug.WriteLine($"Database {databaseName} is now in single-user mode.");
+                    }
+
+                    // 鍒涘缓 MySqlCommand 瀵硅薄
+                    using (SqlCommand cmd = new SqlCommand(dropDatabaseQuery, connection))
+                    {
+                        // 鎵ц鍒犻櫎鏁版嵁搴撴搷浣�
+                        cmd.ExecuteNonQuery();
+                        Debug.WriteLine("Database dropped successfully.");
+                        return true;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    Debug.WriteLine("Error: " + ex.Message);
+                    return false;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 澶嶅埗琛ㄧ粨鏋勫拰鏁版嵁(闇�瑕乵aster鏉冮檺)
+        /// </summary>
+        /// <param name="connectionString"></param>
+        /// <param name="sourceDatabase"></param>
+        /// <param name="targetDatabase"></param>
+        public static bool CopyDatabaseData(string connectionString, string sourceDatabase, string targetDatabase)
+        {
+            if (string.IsNullOrEmpty(connectionString))
+                connectionString = ConnectionString;
+
+            if (!connectionString.Contains("master"))
+                return false;
+
+            try
+            {
+                using (var connection = new SqlConnection(connectionString))
+                {
+                    connection.Open();
+                    string useSourceDb = $"USE {sourceDatabase};";
+                    string useTargetDb = $"USE {targetDatabase};";
+
+                    // 鍒囨崲鍒版簮鏁版嵁搴�
+                    using (var cmd = new SqlCommand(useSourceDb, connection))
+                    {
+                        cmd.ExecuteNonQuery();
+                    }
+
+                    // 鑾峰彇婧愭暟鎹簱涓墍鏈夎〃鐨勫垪琛�
+                    string getTablesQuery = "SELECT name FROM sys.tables;";
+                    using (var cmd = new SqlCommand(getTablesQuery, connection))
+                    {
+                        // 浣跨敤 CommandBehavior.CloseConnection 鑷姩鍏抽棴杩炴帴
+                        using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
+                        {
+                            while (reader.Read())
+                            {
+                                string tableName = reader.GetString(0);
+                                Debug.WriteLine($"澶嶅埗琛�: {tableName}");
+
+                                // 澶嶅埗琛ㄧ粨鏋�
+                                string createTableQuery = $"SELECT * INTO {targetDatabase}.dbo.{tableName} FROM {sourceDatabase}.dbo.{tableName} WHERE 1 = 0;";
+                                using (var cmdCreateTable = new SqlCommand(createTableQuery, connection))
+                                {
+                                    cmdCreateTable.ExecuteNonQuery();
+                                }
+
+                                // 澶嶅埗琛ㄦ暟鎹�
+                                string insertDataQuery = $"INSERT INTO {targetDatabase}.dbo.{tableName} SELECT * FROM {sourceDatabase}.dbo.{tableName};";
+                                using (var cmdInsertData = new SqlCommand(insertDataQuery, connection))
+                                {
+                                    cmdInsertData.ExecuteNonQuery();
+                                }
+                            }
+                        }
+                    }
+                }
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public static List<string> GetUserDatabases()
+        {
+            List<string> databases = new List<string>();
+            string connectionString = "Server=localhost;Database=master;Integrated Security=True;";
+
+            using (SqlConnection connection = new SqlConnection(connectionString))
+            {
+                try
+                {
+                    connection.Open();
+                    string query = @"
+                        SELECT name 
+                        FROM sys.databases 
+                        WHERE database_id > 4 -- 杩囨护绯荤粺鏁版嵁搴�
+                            AND name NOT IN ('model','msdb','tempdb','DWConfiguration','DWDiagnostics','DWQueue') 
+                            AND source_database_id IS NULL -- 鎺掗櫎鏁版嵁搴撳揩鐓�";
+
+                    using (SqlCommand command = new SqlCommand(query, connection))
+                    using (SqlDataReader reader = command.ExecuteReader())
+                    {
+                        while (reader.Read())
+                        {
+                            databases.Add(reader["name"]?.ToString());
+                        }
+                    }
+                }
+                catch (SqlException ex)
+                {
+                    Debug.WriteLine($"鏁版嵁搴撴煡璇㈠け璐�: {ex.Message}");
+                }
+            }
+            return databases;
+        }
+    }
+}
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantoushangfangxiangshang.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantoushangfangxiangshang.png
new file mode 100644
index 0000000..4832e2c
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantoushangfangxiangshang.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouxiafangxiangxia.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouxiafangxiangxia.png
new file mode 100644
index 0000000..6bb9972
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouxiafangxiangxia.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouyoufangxiangyou.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouyoufangxiangyou.png
new file mode 100644
index 0000000..c27ca1c
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouyoufangxiangyou.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouzuofangxiangzuo.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouzuofangxiangzuo.png
new file mode 100644
index 0000000..1dad637
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-jiantouzuofangxiangzuo.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-xinzengxinzeng.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-xinzengxinzeng.png
new file mode 100644
index 0000000..edcf767
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-xinzengxinzeng.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-zhuangtailoudou.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-zhuangtailoudou.png
new file mode 100644
index 0000000..8311f3b
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/a-mti-zhuangtailoudou.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-APPjianpan.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-APPjianpan.png
new file mode 100644
index 0000000..e90d860
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-APPjianpan.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-bangzhuzhongxin.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-bangzhuzhongxin.png
new file mode 100644
index 0000000..d965e5b
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-bangzhuzhongxin.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-caogaoxiang.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-caogaoxiang.png
new file mode 100644
index 0000000..6288b83
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-caogaoxiang.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-chakanxiangqing.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-chakanxiangqing.png
new file mode 100644
index 0000000..63db522
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-chakanxiangqing.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-chexiao.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-chexiao.png
new file mode 100644
index 0000000..e07eaff
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-chexiao.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-duihao.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-duihao.png
new file mode 100644
index 0000000..c622363
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-duihao.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-fangkongquanpeizhi.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-fangkongquanpeizhi.png
new file mode 100644
index 0000000..978446e
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-fangkongquanpeizhi.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-fuzhi.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-fuzhi.png
new file mode 100644
index 0000000..5d76baa
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-fuzhi.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-gengduo.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-gengduo.png
new file mode 100644
index 0000000..23a9a72
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-gengduo.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanbi.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanbi.png
new file mode 100644
index 0000000..fee9a5b
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanbi.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guankongpeizhi.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guankongpeizhi.png
new file mode 100644
index 0000000..b8f06b1
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guankongpeizhi.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanlian.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanlian.png
new file mode 100644
index 0000000..ddeb264
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanlian.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanzhu.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanzhu.png
new file mode 100644
index 0000000..c71212e
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-guanzhu.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jia.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jia.png
new file mode 100644
index 0000000..a16563f
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jia.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jian.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jian.png
new file mode 100644
index 0000000..85096b9
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jian.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantoushang.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantoushang.png
new file mode 100644
index 0000000..f2450e4
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantoushang.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouxia.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouxia.png
new file mode 100644
index 0000000..87e7f2a
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouxia.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouyou-1.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouyou-1.png
new file mode 100644
index 0000000..9ec7ad5
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouyou-1.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouyou.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouyou.png
new file mode 100644
index 0000000..d6c9275
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouyou.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouzuo-1.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouzuo-1.png
new file mode 100644
index 0000000..7b20e33
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouzuo-1.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouzuo.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouzuo.png
new file mode 100644
index 0000000..ed48284
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiantouzuo.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiemi.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiemi.png
new file mode 100644
index 0000000..e6a3f29
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jiemi.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jieshu.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jieshu.png
new file mode 100644
index 0000000..e167398
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jieshu.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jinzhi.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jinzhi.png
new file mode 100644
index 0000000..a3de4ac
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-jinzhi.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-mima.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-mima.png
new file mode 100644
index 0000000..1d2ed6f
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-mima.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pinglun.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pinglun.png
new file mode 100644
index 0000000..e01e248
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pinglun.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pizhu.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pizhu.png
new file mode 100644
index 0000000..d5c8e6e
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pizhu.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pizhuxinxi.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pizhuxinxi.png
new file mode 100644
index 0000000..ef8f759
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-pizhuxinxi.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-qidongyujing.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-qidongyujing.png
new file mode 100644
index 0000000..0cbdebd
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-qidongyujing.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-qiehuan.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-qiehuan.png
new file mode 100644
index 0000000..657889a
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-qiehuan.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shaixuan.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shaixuan.png
new file mode 100644
index 0000000..9156cec
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shaixuan.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shanchu.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shanchu.png
new file mode 100644
index 0000000..3f6e96a
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shanchu.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shangchuan.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shangchuan.png
new file mode 100644
index 0000000..c9a72f4
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shangchuan.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shezhi.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shezhi.png
new file mode 100644
index 0000000..9c687a0
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shezhi.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shipinpeizhi.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shipinpeizhi.png
new file mode 100644
index 0000000..4356183
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shipinpeizhi.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shousuo.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shousuo.png
new file mode 100644
index 0000000..667cd4d
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shousuo.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shouzhe.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shouzhe.png
new file mode 100644
index 0000000..11f15dd
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shouzhe.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuangjiantouyou.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuangjiantouyou.png
new file mode 100644
index 0000000..646cd3e
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuangjiantouyou.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuangjiantouzuo.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuangjiantouzuo.png
new file mode 100644
index 0000000..cead7fe
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuangjiantouzuo.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuaxin.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuaxin.png
new file mode 100644
index 0000000..3b6ceee
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-shuaxin.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-sousuo.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-sousuo.png
new file mode 100644
index 0000000..faee5f2
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-sousuo.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuisong.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuisong.png
new file mode 100644
index 0000000..cd5b565
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuisong.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuisongjilu.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuisongjilu.png
new file mode 100644
index 0000000..e06cb2e
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuisongjilu.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuozhuaizhongxin.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuozhuaizhongxin.png
new file mode 100644
index 0000000..433137d
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-tuozhuaizhongxin.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-weiguanlian.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-weiguanlian.png
new file mode 100644
index 0000000..cb01aae
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-weiguanlian.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-xiazai.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-xiazai.png
new file mode 100644
index 0000000..699679a
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-xiazai.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhankai.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhankai.png
new file mode 100644
index 0000000..da573a1
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhankai.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhiding.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhiding.png
new file mode 100644
index 0000000..69e1dd9
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhiding.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhongqi.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhongqi.png
new file mode 100644
index 0000000..e817c7a
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-zhongqi.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-ziyuanpeizhi.png b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-ziyuanpeizhi.png
new file mode 100644
index 0000000..1421ef9
--- /dev/null
+++ b/LB_SmartVision/LOGO/icon_7brki18x2r3/mti-ziyuanpeizhi.png
Binary files differ
diff --git a/LB_SmartVision/LOGO/logo.ico b/LB_SmartVision/LOGO/logo.ico
new file mode 100644
index 0000000..5887476
--- /dev/null
+++ b/LB_SmartVision/LOGO/logo.ico
Binary files differ
diff --git a/LB_SmartVision/ProcessRun/ExpressionTreeMappingEngine.cs b/LB_SmartVision/ProcessRun/ExpressionTreeMappingEngine.cs
new file mode 100644
index 0000000..2755b7e
--- /dev/null
+++ b/LB_SmartVision/ProcessRun/ExpressionTreeMappingEngine.cs
@@ -0,0 +1,362 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+using LB_VisionProcesses;
+
+namespace LB_SmartVision.ProcessRun
+{
+    public class ExpressionTreeMappingEngine
+    {
+        private ConcurrentDictionary<string, List<Action<IProcess>>> _compiledMappings;
+        private readonly ConcurrentDictionary<string, IProcess> _processContext;
+
+        public ExpressionTreeMappingEngine(ConcurrentDictionary<string, IProcess> processContext)
+        {
+            _processContext = processContext;
+            _compiledMappings = new ConcurrentDictionary<string, List<Action<IProcess>>>();
+        }
+
+        public void CompileMappings(ConcurrentDictionary<string, List<Tuple<string, string>>> dicInputsMapping)
+        {
+            foreach (var processMapping in dicInputsMapping)
+            {
+                var processName = processMapping.Key;
+                var actions = new List<Action<IProcess>>();
+
+                foreach (var tuple in processMapping.Value)
+                {
+                    if (string.IsNullOrEmpty(tuple.Item2?.Trim()))
+                        continue;
+
+                    var action = CreateMappingAction(tuple.Item1, tuple.Item2);
+                    if (action != null)
+                        actions.Add(action);
+                }
+
+                _compiledMappings[processName] = actions;
+            }
+        }
+
+        private Action<IProcess> CreateMappingAction(string inputPath, string outputPath)
+        {
+            try
+            {
+                // 瑙f瀽杈撳叆璺緞锛歍argetProcess.InputType.InputProperty
+                var inputParts = inputPath.Split('.');
+                if (inputParts.Length < 3) return null;
+
+                string targetProcessName = inputParts[0];
+                string inputType = inputParts[1]; // 閫氬父鏄� "Inputs"
+                string inputProperty = inputParts[2];
+
+                // 瑙f瀽杈撳嚭璺緞锛歋ourceProcess.OutputType.OutputProperty
+                var outputParts = outputPath.Split('.');
+                if (outputParts.Length < 2) return null;
+
+                string sourceProcessName = outputParts[0];
+                string outputType = outputParts[1]; // "Inputs" 鎴� "Outputs"
+                string outputProperty = outputParts.Length == 3 ? outputParts[2] : "";
+
+                // 鍒涘缓琛ㄨ揪寮忓弬鏁�
+                var targetParameter = Expression.Parameter(typeof(IProcess), "targetProcess");
+
+                // 鏋勫缓鑾峰彇婧愬�肩殑琛ㄨ揪寮�
+                var sourceValueExpression = BuildSourceValueExpression(sourceProcessName, outputType, outputProperty);
+                if (sourceValueExpression == null) return null;
+
+                // 鏋勫缓璁剧疆鐩爣鍊肩殑琛ㄨ揪寮�
+                var setTargetExpression = BuildSetTargetExpression(targetParameter, inputType, inputProperty, sourceValueExpression);
+                if (setTargetExpression == null) return null;
+
+                // 缂栬瘧涓哄鎵�
+                var lambda = Expression.Lambda<Action<IProcess>>(setTargetExpression, targetParameter);
+                return lambda.Compile();
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"鍒涘缓鏄犲皠鍔ㄤ綔澶辫触: {ex.Message}");
+                return null;
+            }
+        }
+
+        private Expression BuildSourceValueExpression(string sourceProcessName, string outputType, string outputProperty)
+        {
+            // 鑾峰彇婧愭祦绋嬪疄渚嬶細_processContext[sourceProcessName]
+            var contextField = Expression.Constant(_processContext);
+            var processNameConstant = Expression.Constant(sourceProcessName);
+            var getItemMethod = typeof(ConcurrentDictionary<string, IProcess>).GetMethod("get_Item");
+            var getProcessExpr = Expression.Call(contextField, getItemMethod, processNameConstant);
+
+            // 杞崲涓� IProcess
+            var convertExpr = Expression.Convert(getProcessExpr, typeof(IProcess));
+
+            // 娣诲姞 null 妫�鏌�
+            var nullCheck = Expression.NotEqual(convertExpr, Expression.Constant(null, typeof(IProcess)));
+
+            // 鏍规嵁杈撳嚭绫诲瀷鍜屽睘鎬ф瀯寤鸿幏鍙栧�肩殑琛ㄨ揪寮�
+            Expression valueExpression = outputType switch
+            {
+                "Inputs" => BuildInputsValueExpression(convertExpr, outputProperty),
+                "Outputs" => BuildOutputsValueExpression(convertExpr, outputProperty),
+                _ => Expression.Constant(null, typeof(object))
+            };
+
+            // 濡傛灉婧愭祦绋嬩负 null锛岃繑鍥� null锛屽惁鍒欒繑鍥炲��
+            return Expression.Condition(nullCheck, valueExpression, Expression.Constant(null, typeof(object)));
+        }
+
+        private Expression BuildInputsValueExpression(Expression processExpr, string propertyName)
+        {
+            if (propertyName == "Image")
+            {
+                // 棣栧厛灏濊瘯瀛楁锛岀劧鍚庡皾璇曞睘鎬�
+                return GetMemberExpression(processExpr, "InputImage");
+            }
+            else
+            {
+                return BuildInputsConcurrentDictionaryExpression(processExpr, propertyName);
+            }
+        }
+
+        private Expression BuildOutputsValueExpression(Expression processExpr, string propertyName)
+        {
+            if (propertyName == "Image")
+            {
+                // 棣栧厛灏濊瘯瀛楁锛岀劧鍚庡皾璇曞睘鎬�
+                return GetMemberExpression(processExpr, "OutputImage");
+            }
+            else if (propertyName == "Result")
+            {
+                // 棣栧厛灏濊瘯瀛楁锛岀劧鍚庡皾璇曞睘鎬�
+                return GetMemberExpression(processExpr, "Result");
+            }
+            else if (propertyName == "Fixture")
+            {
+                // 閫氳繃 Params 鑾峰彇 Fixture
+                var paramsExpr = GetMemberExpression(processExpr, "Params");
+                return GetMemberExpression(paramsExpr, "Fixture");
+            }
+            else
+            {
+                return BuildOutputsConcurrentDictionaryExpression(processExpr, propertyName);
+            }
+        }
+
+        private Expression BuildInputsConcurrentDictionaryExpression(Expression processExpr, string propertyName)
+        {
+            // process.Params.Inputs[propertyName]
+            var paramsExpr = GetMemberExpression(processExpr, "Params");
+            var inputsExpr = GetMemberExpression(paramsExpr, "Inputs");
+
+            var indexer = inputsExpr.Type.GetProperty("Item", new[] { typeof(string) });
+            if (indexer == null)
+                throw new InvalidOperationException("Inputs 绫诲瀷娌℃湁瀛楃涓茬储寮曞櫒");
+
+            var propertyNameConstant = Expression.Constant(propertyName);
+            return Expression.Property(inputsExpr, indexer, propertyNameConstant);
+        }
+
+        private Expression BuildOutputsConcurrentDictionaryExpression(Expression processExpr, string propertyName)
+        {
+            // process.Params.Outputs[propertyName]
+            var paramsExpr = GetMemberExpression(processExpr, "Params");
+            var outputsExpr = GetMemberExpression(paramsExpr, "Outputs");
+
+            var indexer = outputsExpr.Type.GetProperty("Item", new[] { typeof(string) });
+            if (indexer == null)
+                throw new InvalidOperationException("Outputs 绫诲瀷娌℃湁瀛楃涓茬储寮曞櫒");
+
+            var propertyNameConstant = Expression.Constant(propertyName);
+            return Expression.Property(outputsExpr, indexer, propertyNameConstant);
+        }
+
+        /// <summary>
+        /// 閫氱敤鐨勬垚鍛樿闂柟娉曪細棣栧厛灏濊瘯瀛楁锛岀劧鍚庡皾璇曞睘鎬�
+        /// </summary>
+        private Expression GetMemberExpression(Expression instance, string memberName)
+        {
+            var type = instance.Type;
+
+            // 棣栧厛灏濊瘯瀛楁
+            var field = type.GetField(memberName, BindingFlags.Public | BindingFlags.Instance);
+            if (field != null)
+            {
+                return Expression.Field(instance, field);
+            }
+
+            // 鐒跺悗灏濊瘯灞炴��
+            var property = type.GetProperty(memberName, BindingFlags.Public | BindingFlags.Instance);
+            if (property != null)
+            {
+                return Expression.Property(instance, property);
+            }
+
+            throw new InvalidOperationException($"鍦ㄧ被鍨� {type.Name} 涓壘涓嶅埌瀛楁鎴栧睘鎬�: {memberName}");
+        }
+
+        private Expression BuildSetTargetExpression(ParameterExpression targetParameter, string inputType, string inputProperty, Expression sourceValueExpression)
+        {
+            return inputProperty switch
+            {
+                "Image" => BuildSetImageExpression(targetParameter, sourceValueExpression),
+                "Fixture" => BuildSetFixtureExpression(targetParameter, sourceValueExpression),
+                "Result" => BuildSetResultExpression(targetParameter, inputProperty, sourceValueExpression),
+                _ => BuildSetInputExpression(targetParameter, inputProperty, sourceValueExpression)
+            };
+        }
+
+        private Expression BuildSetImageExpression(ParameterExpression target, Expression sourceValue)
+        {
+            // target.InputImage = sourceValue
+            var inputImageExpr = GetMemberExpression(target, "InputImage");
+            return Expression.Assign(inputImageExpr, Expression.Convert(sourceValue, inputImageExpr.Type));
+        }
+
+        private Expression BuildSetFixtureExpression(ParameterExpression target, Expression sourceValue)
+        {
+            //// target.Params.Fixture = sourceValue ?? new Fixture()
+            //var paramsExpr = GetMemberExpression(target, "Params");
+            //var fixtureExpr = GetMemberExpression(paramsExpr, "Fixture");
+
+            //// 濡傛灉婧愬�间负null锛屽垱寤烘柊鐨凢ixture
+            //var newFixtureExpr = Expression.New(typeof(Fixture));
+            //var coalesceExpr = Expression.Coalesce(
+            //    Expression.Convert(sourceValue, typeof(Fixture)),
+            //    newFixtureExpr
+            //);
+
+            //return Expression.Assign(fixtureExpr, coalesceExpr);
+
+            // 濡傛灉婧愬�间负null锛屽氨璁剧疆涓簄ull锛屼笉鍒涘缓鏂板璞�
+            var paramsExpr = GetMemberExpression(target, "Params");
+            var fixtureExpr = GetMemberExpression(paramsExpr, "Fixture");
+
+            var convertedSourceValue = Expression.Convert(sourceValue, typeof(Fixture));
+            return Expression.Assign(fixtureExpr, convertedSourceValue);
+        }
+
+        private Expression BuildSetResultExpression(ParameterExpression target, string propertyName, Expression sourceValue)
+        {
+            // target.Params.Inputs[propertyName] = sourceValue
+            var paramsExpr = GetMemberExpression(target, "Params");
+            var inputsExpr = GetMemberExpression(paramsExpr, "Inputs");
+
+            var indexer = inputsExpr.Type.GetProperty("Item", new[] { typeof(string) });
+            if (indexer == null)
+                return Expression.Empty();
+
+            var propertyNameConstant = Expression.Constant(propertyName);
+            var targetIndexExpr = Expression.Property(inputsExpr, indexer, propertyNameConstant);
+
+            return Expression.Assign(targetIndexExpr, Expression.Convert(sourceValue, targetIndexExpr.Type));
+        }
+
+        private Expression BuildSetInputExpression(ParameterExpression target, string propertyName, Expression sourceValue)
+        {
+            // 妫�鏌ュ瓧鍏告槸鍚﹀寘鍚閿紝濡傛灉鍖呭惈鍒欒祴鍊�
+            var paramsExpr = GetMemberExpression(target, "Params");
+            var inputsExpr = GetMemberExpression(paramsExpr, "Inputs");
+
+            var containsMethod = inputsExpr.Type.GetMethod("Contains", new[] { typeof(string) });
+            if (containsMethod == null)
+                return Expression.Empty();
+
+            var propertyNameConstant = Expression.Constant(propertyName);
+            var containsCall = Expression.Call(inputsExpr, containsMethod, propertyNameConstant);
+
+            // 濡傛灉鍖呭惈閿紝鍒欒祴鍊�
+            var indexer = inputsExpr.Type.GetProperty("Item", new[] { typeof(string) });
+            if (indexer == null)
+                return Expression.Empty();
+
+            var targetIndexExpr = Expression.Property(inputsExpr, indexer, propertyNameConstant);
+            var assignExpr = Expression.Assign(
+                targetIndexExpr,
+                Expression.Convert(sourceValue, targetIndexExpr.Type)
+            );
+
+            // 鏉′欢琛ㄨ揪寮忥細if (inputs.Contains(propertyName)) { inputs[propertyName] = sourceValue; }
+            return Expression.IfThen(containsCall, assignExpr);
+        }
+
+        public void UpdateInputs(IProcess process)
+        {
+            if (_compiledMappings.TryGetValue(process.strProcessName, out var actions))
+            {
+                foreach (var action in actions)
+                {
+                    try
+                    {
+                        action(process);
+                    }
+                    catch (Exception ex)
+                    {
+                        // 澶勭悊杩愯鏃跺紓甯�
+                        Debug.WriteLine($"鎵ц鏄犲皠鍔ㄤ綔澶辫触: {ex.Message}");
+                    }
+                }
+            }
+        }
+
+        public void Dispose()
+        {
+            foreach (var list in _compiledMappings.Values)
+            {
+                list.Clear();
+            }
+            _compiledMappings.Clear();
+        }
+
+        public void ClearMappings()
+        {
+            _compiledMappings.Clear();
+        }
+
+        public void RemoveProcessMappings(string processName)
+        {
+            _compiledMappings.TryRemove(processName, out _);
+        }
+    }
+
+    // 杈呭姪鎵╁睍鏂规硶锛岀敤浜庤皟璇�
+    public static class ExpressionTreeDebugExtensions
+    {
+        public static void DebugMemberAccess(this ExpressionTreeMappingEngine engine, IProcess testProcess)
+        {
+            var processType = typeof(IProcess);
+
+            Debug.WriteLine("=== IProcess 鎴愬憳璋冭瘯淇℃伅 ===");
+            Debug.WriteLine("瀛楁:");
+            foreach (var field in processType.GetFields(BindingFlags.Public | BindingFlags.Instance))
+            {
+                Debug.WriteLine($"  {field.Name} : {field.FieldType.Name}");
+            }
+
+            Debug.WriteLine("灞炴��:");
+            foreach (var prop in processType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
+            {
+                Debug.WriteLine($"  {prop.Name} : {prop.PropertyType.Name}");
+            }
+
+            // 娴嬭瘯鍏蜂綋鎴愬憳璁块棶
+            try
+            {
+                var processExpr = Expression.Parameter(typeof(IProcess), "p");
+                var outputImageExpr = Expression.Field(processExpr, "OutputImage");
+                var lambda = Expression.Lambda<Func<IProcess, object>>(outputImageExpr, processExpr).Compile();
+                var result = lambda(testProcess);
+                Debug.WriteLine($"OutputImage 瀛楁璁块棶鎴愬姛: {result ?? "null"}");
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"OutputImage 瀛楁璁块棶澶辫触: {ex.Message}");
+            }
+        }
+    }
+}
diff --git a/LB_SmartVision/ProcessRun/ProcessContext.cs b/LB_SmartVision/ProcessRun/ProcessContext.cs
new file mode 100644
index 0000000..5fabc0c
--- /dev/null
+++ b/LB_SmartVision/ProcessRun/ProcessContext.cs
@@ -0,0 +1,698 @@
+锘縰sing HalconDotNet;
+using LB_SmartVision.Forms.Pages.SettingPage;
+using LB_SmartVision.Tool;
+using LB_VisionFlowNode;
+using LB_VisionProcesses;
+using LB_VisionProcesses.Alogrithms;
+using LB_VisionProcesses.Cameras;
+using LB_VisionProcesses.Communicators;
+using LB_VisionProcesses.Processes.ScriptTool;
+using OpenCvSharp;
+using System.Collections.Concurrent;
+
+namespace LB_SmartVision.ProcessRun
+{
+    public class ProcessContext : IFlowContext
+    {
+        /// <summary>
+        /// 閫氳闆嗗悎(Key:閫氳鍚嶏紝Value:閫氳鍙ユ焺)
+        /// </summary>
+        public ObservableConcurrentDictionary<string, BaseCommunicator> dicCommunicators { get; set; }
+
+        /// <summary>
+        /// 鐩告満闆嗗悎(Key:鐩告満SN锛孷alue:鐩告満鍙ユ焺)
+        /// </summary>
+        public ObservableConcurrentDictionary<string, BaseCamera> dicCameras { get; set; }
+
+        public ConcurrentDictionary<string, List<Tuple<string, string>>> dicInputsMapping { get; set; }
+
+        public ConcurrentDictionary<string, List<string>> dicOutputsMapping { get; set; }
+
+        /// <summary>
+        /// 杩愯娴佺▼
+        /// </summary>
+        public ConcurrentDictionary<string, IProcess> dicContext = new ConcurrentDictionary<string, IProcess>();
+
+        /// <summary>
+        /// 杩愯鏍囪
+        /// </summary>
+        public bool bRuning = false;
+
+        /// <summary>
+        /// 杩愯瀹屾垚
+        /// </summary>
+        public bool bCompleted = true;
+
+        /// <summary>
+        /// 杩愯缁撴灉
+        /// </summary>
+        public bool Result = false;
+
+        /// <summary>
+        /// 杩愯娑堟伅
+        /// </summary>
+        public string Msg = string.Empty;
+
+        /// <summary>
+        /// 杩愯鏃堕棿
+        /// </summary>
+        public double RunTime = 0;
+
+        /// <summary>
+        /// 寮�濮嬫椂闂�
+        /// </summary>
+        public DateTime StartTime = DateTime.Now;
+
+        private HTuple ho_ImageWidth = new HTuple();
+
+        private HTuple ho_ImageHeight = new HTuple();
+
+        /// <summary>
+        /// 鐢ㄤ簬缁樺埗缁撴灉鍥剧殑绐楀彛鎺т欢
+        /// </summary>
+        private HWindowControl hWindowControl = new HWindowControl();
+
+        public ProcessContext(ObservableConcurrentDictionary<string, BaseCamera> dicCameras, ObservableConcurrentDictionary<string, BaseCommunicator> dicCommunicators
+            , ConcurrentDictionary<string, List<Tuple<string, string>>> dicInputsMapping, ConcurrentDictionary<string, List<string>> dicOutputsMapping)
+        {
+            this.dicCameras = dicCameras;
+            this.dicCommunicators = dicCommunicators;
+            this.dicInputsMapping = dicInputsMapping;
+            this.dicOutputsMapping = dicOutputsMapping;
+
+            hWindowControl.Size = new System.Drawing.Size(1920, 1080);
+
+            TAlgorithm.set_display_font(hWindowControl.HalconWindow, 1080 / 20, "mono", "true", "false");
+            HOperatorSet.SetLineWidth(hWindowControl.HalconWindow, 5);
+
+            InitializeMethods();
+            InitializeDelegates();
+
+            mappingEngine = new ExpressionTreeMappingEngine(dicContext);
+        }
+
+        // 鍒濆鍖�
+        ExpressionTreeMappingEngine mappingEngine = null;
+
+        /// <summary>
+        /// 缂栬瘧鏄犲皠
+        /// </summary>
+        public void CompileMappings()
+        {
+            mappingEngine = new ExpressionTreeMappingEngine(dicContext);
+            mappingEngine.CompileMappings(dicInputsMapping);
+        }
+
+        /// <summary>
+        /// 鏇存柊杈撳叆锛堥珮鎬ц兘鎵ц锛�
+        /// </summary>
+        /// <param name="process"></param>
+        public void UpdateInputs(IProcess process)
+        {
+            mappingEngine.UpdateInputs(process);
+        }
+
+        //void UpdateInputs(IProcess process)
+        //{
+        //    string ProcessName = process.strProcessName;
+        //    List<Tuple<string, string>> listTuples = dicInputsMapping[ProcessName];
+
+        //    foreach (var tuple in listTuples)
+        //    {
+        //        if (string.IsNullOrEmpty(tuple.Item2) || tuple.Item2.Trim() == "")
+        //            continue;
+
+        //        string[] arrInputs = tuple.Item1.Split(".");
+        //        if (arrInputs.Length < 3)
+        //            continue;
+
+        //        string InputProcessName = arrInputs[0];
+        //        string strInput = arrInputs[1];
+        //        string InputValueName = arrInputs[2];
+
+        //        string[] arrOutputs = tuple.Item2.Split(".");
+        //        if (arrOutputs.Length < 2)
+        //            continue;
+
+        //        string IndexProcessName = arrOutputs[0];
+        //        string IndexIsInputOrOutput = arrOutputs[1];
+        //        string IndexValueName = arrOutputs.Length == 3 ? arrOutputs[2] : "";
+
+        //        //杩欓噷鐨刼鏄綘鎵�鎸囧悜鐨勮緭鍑烘祦绋�
+        //        object o = dicContext[IndexProcessName];
+
+        //        if (o == null)
+        //            continue;
+        //        else if (o is IProcess)
+        //        {
+        //            IProcess i = (IProcess)o;
+        //            if (i.strProcessName != IndexProcessName)
+        //                continue;
+
+        //            if (InputValueName == "Image")
+        //            {
+        //                switch (IndexIsInputOrOutput)
+        //                {
+        //                    case "Inputs":
+        //                        //瀹為檯涓婁笉鍏佽绱㈠紩鐨勫�兼槸杈撳叆
+        //                        if (IndexValueName == "Image")
+        //                            process.InputImage = i.InputImage;
+        //                        else
+        //                            process.InputImage = i.Params.Inputs[IndexValueName];
+        //                        break;
+        //                    case "Outputs":
+        //                        if (IndexValueName == "Image")
+        //                            process.InputImage = i.OutputImage;
+        //                        else
+        //                            process.InputImage = i.Params.Outputs[IndexValueName];
+        //                        break;
+        //                    default:
+        //                        process.InputImage = null;
+        //                        break;
+        //                }
+
+        //                if (IndexValueName == "")
+        //                    process.InputImage = null;
+        //            }
+        //            else if (InputValueName == "Fixture")
+        //            {
+        //                //璧嬪�煎弬鏁�
+        //                switch (IndexIsInputOrOutput)
+        //                {
+        //                    case "Inputs":
+        //                        //瀹為檯涓婁笉鍏佽绱㈠紩鐨勫�兼槸杈撳叆
+        //                        process.Params.Fixture = i.Params.Fixture;
+        //                        break;
+        //                    case "Outputs":
+        //                        process.Params.Fixture = i.Params.Fixture;
+        //                        break;
+        //                    default:
+        //                        //process.Params.Fixture = new Fixture();
+        //                        break;
+        //                }
+
+        //                if (IndexValueName == "")
+        //                    process.Params.Fixture = new Fixture();
+        //            }
+        //            else if (IndexValueName == "Result")
+        //            {
+        //                //璧嬪�煎弬鏁�
+        //                switch (IndexIsInputOrOutput)
+        //                {
+        //                    case "Inputs":
+        //                        //瀹為檯涓婁笉鍏佽绱㈠紩鐨勫�兼槸杈撳叆
+        //                        process.Params.Inputs[InputValueName] = i.Result;
+        //                        break;
+        //                    case "Outputs":
+        //                        process.Params.Inputs[InputValueName] = i.Result;
+        //                        break;
+        //                    default:
+        //                        process.Params.Inputs[InputValueName] = null;
+        //                        break;
+        //                }
+        //            }
+        //            else if (process.Params.Inputs.Contains(InputValueName))
+        //            {
+        //                //璧嬪�煎弬鏁�
+        //                switch (IndexIsInputOrOutput)
+        //                {
+        //                    case "Inputs":
+        //                        //瀹為檯涓婁笉鍏佽绱㈠紩鐨勫�兼槸杈撳叆
+        //                        process.Params.Inputs[InputValueName] = i.Params.Inputs[IndexValueName];
+        //                        break;
+        //                    case "Outputs":
+        //                        process.Params.Inputs[InputValueName] = i.Params.Outputs[IndexValueName];
+        //                        break;
+        //                    default:
+        //                        process.Params.Inputs[InputValueName] = null;
+        //                        break;
+        //                }
+        //            }
+        //        }
+        //    }
+        //}
+
+        public bool GetValue(string map, out object obj)
+        {
+            obj = null;
+            if (string.IsNullOrEmpty(map))
+                return false;
+
+            try
+            {
+                string[] arrMap = map.Split(".");
+                if (arrMap.Length <= 1)
+                    return false;
+
+                string IndexProcessName = arrMap[0];
+                string IndexIsInputOrOutput = arrMap[1];
+                string IndexValueName = arrMap.Length == 3 ? arrMap[2] : "";
+
+                //杩欓噷鐨刼鏄綘鎵�鎸囧悜鐨勮緭鍑烘祦绋�
+                object o = dicContext[IndexProcessName];
+
+                if (o != null && o is IProcess i)
+                {
+                    if (i.strProcessName != IndexProcessName)
+                        return false;
+
+                    if (IndexValueName == "Result")
+                    {
+                        switch (IndexIsInputOrOutput)
+                        {
+                            case "Inputs":
+                                //瀹為檯涓婁笉鍏佽绱㈠紩鐨勫�兼槸杈撳叆
+                                obj = i.Result;
+                                break;
+                            case "Outputs":
+                                obj = i.Result;
+                                break;
+                            default:
+                                return false;
+                        }
+                    }
+                    else
+                    {
+                        //璧嬪�煎弬鏁�
+                        switch (IndexIsInputOrOutput)
+                        {
+                            case "Inputs":
+                                obj = i.Params.Inputs[IndexValueName];
+                                break;
+                            case "Outputs":
+                                obj = i.Params.Outputs[IndexValueName];
+                                break;
+                            default:
+                                return false;
+                        }
+                    }
+                    return true;
+                }
+                else
+                    return false;
+            }
+            catch { obj = null; return false; }
+        }
+
+        public bool GetStringOutput(string map, out string str)
+        {
+            bool res = GetValue(map, out object obj);
+            str = ProcessParams.ConvertToString(obj);
+            return res;
+        }
+
+        public bool GetImage(Layout layout, out HObject InputImage, out HObject RecordImage)
+        {
+            InputImage = null; RecordImage = null;
+            try
+            {
+                if (layout == null)
+                    return false;
+
+                string ProcessName = layout.ProcessName;
+                string InputImageMap = layout.InputImage;
+                string RecordImageMap1 = layout.RecordImage1;
+                string RecordImageMap2 = layout.RecordImage2;
+                string RecordImageMap3 = layout.RecordImage3;
+
+                string[] arrOutputs = new string[] { };
+                string IndexProcessName = string.Empty;
+                string IndexIsInputOrOutput = string.Empty;
+                string IndexValueName = string.Empty;
+
+                #region 鑾峰彇杈撳叆鍥剧墖
+                arrOutputs = InputImageMap.Split(".");
+                if (arrOutputs.Length > 2)
+                {
+                    IndexProcessName = arrOutputs[0];
+                    IndexIsInputOrOutput = arrOutputs[1];
+                    IndexValueName = arrOutputs[2];
+
+                    object o_InputImage = ((IProcess)dicContext[IndexProcessName]).OutputImage;
+                    if (o_InputImage is HObject ho_image && ho_image.IsInitialized())
+                        InputImage = ho_image;
+                    else if (o_InputImage is Bitmap)
+                    {
+                        //灏哅at杞崲涓篐Object
+                        TAlgorithm.Bitmap2HObject((Bitmap)o_InputImage, out HObject ho_RecordImage);
+                        InputImage = ho_RecordImage;
+                    }
+                    else if (o_InputImage is Mat)
+                    {
+                        //灏哅at杞崲涓篐Object
+                        TAlgorithm.Mat2HObject((Mat)o_InputImage, out HObject ho_RecordImage);
+                        InputImage = ho_RecordImage;
+                    }
+
+                    if (InputImage != null && InputImage.IsInitialized())
+                    {
+                        HOperatorSet.GetImageSize(InputImage, out ho_ImageWidth, out ho_ImageHeight);
+
+                        //鍥剧墖灏哄鍙樺寲鎵嶆洿鏂扮獥鍙e昂瀵竅鎻愰珮閫熷害]
+                        if ((ho_ImageWidth.Length > 0 && ho_ImageWidth.TupleInt() != hWindowControl.Size.Width)
+                            || (ho_ImageHeight.Length > 0 && ho_ImageHeight.TupleInt() != hWindowControl.Size.Height))
+                        {
+                            hWindowControl.Invoke(new Action(() =>
+                            {
+                                hWindowControl.Size = new System.Drawing.Size(ho_ImageWidth, ho_ImageHeight);
+                                TAlgorithm.set_display_font(hWindowControl.HalconWindow, ho_ImageWidth.I / 20, "mono", "true", "false");
+                            }));
+                        }
+                    }
+
+                    TAlgorithm.DispImage(InputImage, hWindowControl.HalconWindow);
+                }
+                #endregion
+
+                #region 缁樺埗缁撴灉鍥�
+                arrOutputs = RecordImageMap1.Split(".");
+                if (arrOutputs.Length > 2)
+                {
+                    IndexProcessName = arrOutputs[0];
+                    IndexIsInputOrOutput = arrOutputs[1];
+                    IndexValueName = arrOutputs[2];
+
+                    if (dicContext.ContainsKey(IndexProcessName))
+                    {
+                        ObjectRecord objectRecord1 = ((IProcess)dicContext[IndexProcessName]).Record;
+                        if (objectRecord1 != null)
+                        {
+                            objectRecord1.Display(hWindowControl.HalconWindow);
+                            objectRecord1.Dispose();
+                        }
+                    }
+                }
+
+                arrOutputs = RecordImageMap2.Split(".");
+                if (arrOutputs.Length > 2)
+                {
+                    IndexProcessName = arrOutputs[0];
+                    IndexIsInputOrOutput = arrOutputs[1];
+                    IndexValueName = arrOutputs[2];
+
+                    if (dicContext.ContainsKey(IndexProcessName))
+                    {
+                        ObjectRecord objectRecord2 = ((IProcess)dicContext[IndexProcessName]).Record;
+                        if (objectRecord2 != null)
+                        {
+                            objectRecord2.Display(hWindowControl.HalconWindow);
+                            objectRecord2.Dispose();
+                        }
+                    }
+                }
+
+                arrOutputs = RecordImageMap3.Split(".");
+                if (arrOutputs.Length > 2)
+                {
+                    IndexProcessName = arrOutputs[0];
+                    IndexIsInputOrOutput = arrOutputs[1];
+                    IndexValueName = arrOutputs[2];
+
+                    if (dicContext.ContainsKey(IndexProcessName))
+                    {
+                        ObjectRecord objectRecord3 = ((IProcess)dicContext[IndexProcessName]).Record;
+                        if (objectRecord3 != null)
+                        {
+                            objectRecord3.Display(hWindowControl.HalconWindow);
+                            objectRecord3.Dispose();
+                        }
+                    }
+                }
+
+                if (Result)
+                {
+                    Msg = "杩愯鎴愬姛";
+                    HOperatorSet.SetColor(hWindowControl.HalconWindow, "green");
+                }
+                else
+                    HOperatorSet.SetColor(hWindowControl.HalconWindow, "red");
+
+                TAlgorithm.DispMsg(Msg, hWindowControl.HalconWindow, Result ? "green" : "red", 0, 0);
+                HOperatorSet.DumpWindowImage(out RecordImage, hWindowControl.HalconWindow);
+                #endregion
+
+                return true;
+            }
+            catch { return false; }
+        }
+        public bool GetCsv(CsvSetting csv, out List<string> DataTitle, out Dictionary<string, object> ResultData)
+        {
+            // 鏁版嵁鏍囬
+            DataTitle = (new string[] { "鍚嶇О", "鏃堕棿", "鑰楁椂", "缁撴灉", "鍘熷洜" }).ToList();
+
+            ResultData = new Dictionary<string, object>();
+            try
+            {
+                ResultData.Add("鍚嶇О", csv.ProcessName);
+                ResultData.Add("鏃堕棿", DateTime.Now.ToString("HH:mm:ss.ff"));
+                ResultData.Add("鑰楁椂", $"{RunTime.ToString("F2")}");
+                ResultData.Add("缁撴灉", Result);
+                ResultData.Add("鍘熷洜", Msg);
+
+                for (int i = 0; i < csv.Others.Count; i++)
+                {
+                    string title = $"鏁版嵁{i}";
+                    string map = csv.Others[i];
+                    GetValue(map, out object obj);
+                    if (obj == null)
+                        continue;
+
+                    Type type = obj.GetType();
+                    switch (type)
+                    {
+                        case Type t when t == typeof(double):
+                            ResultData.Add(title, ((double)obj).ToString("F4"));
+                            DataTitle.Add(title);
+                            break;
+                        default:
+                            ResultData.Add(title, ProcessParams.ConvertToString(obj));
+                            DataTitle.Add(title);
+                            break;
+                    }
+                }
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 闈炲垎鏀妭鐐圭殑缁熶竴璋冪敤鏂瑰紡
+        /// </summary>
+        private void RunNodeAsync(FlowNode node)
+        {
+            // 璧伴粯璁ゅ垎鏀�
+            node.BranchIndex = "0";
+            string ProcessName = node.Text;
+            try
+            {
+                if (dicContext.TryGetValue(ProcessName, out IProcess obj)
+                    && obj is IProcess process)
+                {
+                    process.InputImage = null;
+                    UpdateInputs(process);
+
+                    // 涓嶅悓鑺傜偣璺宠繃鐨勬柟寮忎笉鍚�
+                    if (node.Break)
+                    {
+                        switch (node.Description)
+                        {
+                            case "T306閫氳":
+                                node.BranchIndex = "0";
+                                node.Result = true;
+                                process.Result = false;
+                                process.Msg = "T306閫氳鏈惎鐢�";
+                                return;
+                            default:
+                                node.BranchIndex = "0";
+                                node.Result = true;
+                                process.Result = true;
+                                process.Msg = string.Empty;
+                                return;
+                        }
+                    }
+
+                    if (!process.Run())
+                    {
+                        node.Result = false;
+                        Result &= false;
+
+                        if (!string.IsNullOrEmpty(process.Msg)
+                            && !Msg.Contains($"[{process.strProcessName}]{process.Msg}"))
+                            Msg += $"[{process.strProcessName}]{process.Msg}";
+                    }
+                    else
+                        node.Result = true;
+                }
+            }
+            catch (Exception ex)
+            {
+                node.Result = false;
+                Result &= false;
+                Msg += $"[{ProcessName}]杩愯鍙戠敓鎰忓,{ex.Message}";
+            }
+        }
+
+        [Node("寮�濮�", "鎺у埗", "Logic", "寮�濮�")]
+        public override void 寮�濮�(FlowNode node)
+        {
+            StartTime = DateTime.Now;
+            RunTime = 0;
+
+            Result = true;
+            bRuning = true;
+            bCompleted = false;
+            Msg = string.Empty;
+
+            HOperatorSet.ClearWindow(hWindowControl.HalconWindow);
+            HOperatorSet.SetColor(hWindowControl.HalconWindow, "green");
+        }
+
+        [Node("缁撴潫", "鎺у埗", "Logic", "缁撴潫")]
+        public override void 缁撴潫(FlowNode node)
+        {
+            bRuning = false;
+            bCompleted = true;
+
+            if (Result)
+                Msg = "杩愯鎴愬姛";
+
+            RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
+        }
+
+        [Node("鍒嗘敮", "鎺у埗", "Logic", "鍒嗘敮")]
+        public override void 鍒嗘敮(FlowNode node)
+        {
+            string ProcessName = node.Text;
+            node.BranchIndex = "-1";
+            node.Result = true;
+            try
+            {
+                if (dicContext.TryGetValue(ProcessName, out IProcess obj) && obj is ScriptTool script)
+                {
+                    UpdateInputs(script);
+                    if (node.Break)
+                    {
+                        node.BranchIndex = "0";
+                        node.Result = true;
+                        script.Result = true;
+                        script.Msg = string.Empty;
+                        return;
+                    }
+
+                    if (script.Params.Outputs.Count >= 2)
+                    {
+                        if (!script.Run())
+                        {
+                            node.Result = false;
+                            Result &= false;
+                            Msg = $"[{ProcessName}]{script.Msg}";
+                        }
+
+                        for (int i = 0; i < script.Params.Outputs.Count; i++)
+                        {
+                            if (script.Params.Outputs[$"Branch{i}"] != null
+                                && Convert.ToBoolean(script.Params.Outputs[$"Branch{i}"]))
+                            {
+                                node.BranchIndex = i.ToString();
+                                return;
+                            }
+                        }
+
+                        node.Result = false;
+                        Result &= false;
+                        Msg = $"[{ProcessName}]鏃犳弧瓒虫潯浠剁殑鍒嗘敮";
+                    }
+                    else
+                    {
+                        node.Result = false;
+                        Result &= false;
+                        Msg = $"[{ProcessName}]鍒嗘敮鏁伴噺涓嶄负2";
+                    }
+                }
+                else
+                {
+                    node.Result = false;
+                    Result &= false;
+                }
+            }
+            catch (Exception ex)
+            {
+                node.Result = false;
+                Result &= false;
+                Msg = $"[{ProcessName}]杩愯鍙戠敓鎰忓,{ex.Message}";
+            }
+        }
+
+        [Node("澶氬垎鏀�", "鎺у埗", "Logic", "澶氬垎鏀�")]
+        public override void 澶氬垎鏀�(FlowNode node)
+        {
+            if (node.Break)
+            {
+                node.BranchIndex = "0";
+                node.Result = true;
+                return;
+            }
+
+            string ProcessName = node.Text;
+            node.BranchIndex = "-1";
+            node.Result = true;
+            try
+            {
+                if (dicContext.TryGetValue(ProcessName, out IProcess obj) && obj is ScriptTool script)
+                {
+                    UpdateInputs(script);
+                    if (node.Break)
+                    {
+                        node.BranchIndex = "0";
+                        node.Result = true;
+                        script.Result = true;
+                        script.Msg = string.Empty;
+                        return;
+                    }
+
+                    if (script.Params.Outputs.Count >= 1)
+                    {
+                        if (!script.Run())
+                        {
+                            node.Result = false;
+                            Result &= false;
+                            Msg = $"[{ProcessName}]{script.Msg}";
+                        }
+
+                        for (int i = 0; i < script.Params.Outputs.Count; i++)
+                        {
+                            if (script.Params.Outputs[$"Branch{i}"] != null
+                                && Convert.ToBoolean(script.Params.Outputs[$"Branch{i}"]))
+                            {
+                                node.BranchIndex = i.ToString();
+                                return;
+                            }
+                        }
+
+                        node.Result = false;
+                        Result &= false;
+                        Msg = $"[{ProcessName}]鏃犳弧瓒虫潯浠剁殑鍒嗘敮";
+                    }
+                    else
+                    {
+                        node.Result = false;
+                        Result &= false;
+                        Msg = $"[{ProcessName}]澶氬垎鏀暟閲忓皬浜�1";
+                    }
+                }
+                else
+                {
+                    node.Result = false;
+                    Result &= false;
+                }
+            }
+            catch (Exception ex)
+            {
+                node.Result = false;
+                Result &= false;
+                Msg = $"[{ProcessName}]杩愯鍙戠敓鎰忓,{ex.Message}";
+            }
+        }
+    }
+}
diff --git a/LB_SmartVision/ProcessRun/ProcessRunBll.cs b/LB_SmartVision/ProcessRun/ProcessRunBll.cs
new file mode 100644
index 0000000..0555a01
--- /dev/null
+++ b/LB_SmartVision/ProcessRun/ProcessRunBll.cs
@@ -0,0 +1,958 @@
+锘縰sing HalconDotNet;
+using LB_SmartVision.Forms.Pages.SettingPage;
+using LB_SmartVision.Tool;
+using LB_VisionFlowNode;
+using LB_VisionProcesses;
+using LB_VisionProcesses.Cameras;
+using LB_VisionProcesses.Communicators;
+using LB_VisionProcesses.Processes.ScriptTool;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using OpenCvSharp;
+using System.Collections.Concurrent;
+using System.Data;
+using System.Diagnostics;
+using System.Reflection;
+using System.Text;
+
+namespace LB_SmartVision.ProcessRun
+{
+    public class ProcessRunBll
+    {
+
+        private ProcessContext ProcessContext = null;
+
+        public static string Node2ToolClassName(string NodeName)
+        {
+            foreach (var item in IProcess.dicProcesses)
+            {
+                if (NodeName.StartsWith(item.Key))
+                    return item.Value.ToString();
+            }
+
+            return string.Empty;
+        }
+
+        /// <summary>
+        /// 娴佺▼鍚嶇О
+        /// </summary>
+        public string Name = string.Empty;
+
+        /// <summary>
+        /// 杩愯鏍囪
+        /// </summary>
+        public bool bPruning
+        {
+            set
+            {
+                if (ProcessContext == null)
+                    return;
+                ProcessContext.bRuning = value;
+            }
+            get
+            {
+                if (ProcessContext == null)
+                    return false;
+                return ProcessContext.bRuning;
+            }
+        }
+
+        /// <summary>
+        /// 杩愯瀹屾垚
+        /// </summary>
+        public bool bCompleted
+        {
+            set
+            {
+                if (ProcessContext == null)
+                    return;
+                ProcessContext.bCompleted = value;
+            }
+            get
+            {
+                if (ProcessContext == null)
+                    return false;
+                return ProcessContext.bCompleted;
+            }
+        }
+
+        /// <summary>
+        /// 杩愯缁撴灉
+        /// </summary>
+        public bool Result
+        {
+            set
+            {
+                if (ProcessContext == null)
+                    return;
+                ProcessContext.Result = value;
+            }
+            get
+            {
+                if (ProcessContext == null)
+                    return false;
+                return ProcessContext.Result;
+            }
+        }
+
+        /// <summary>
+        /// 杩愯娑堟伅
+        /// </summary>
+        public string Msg
+        {
+            set
+            {
+                if (ProcessContext == null)
+                    return;
+                ProcessContext.Msg = value;
+            }
+            get
+            {
+                if (ProcessContext == null)
+                    return "杩愯澶辫触";
+                return ProcessContext.Msg;
+            }
+        }
+
+        /// <summary>
+        /// 杩愯鏃堕棿(ms)
+        /// </summary>
+        public double RunTime = 0;
+
+        public bool GetImage(Forms.Pages.SettingPage.Layout layout, out HObject InputImage, out HObject RecordImage)
+        {
+            return ProcessContext.GetImage(layout, out InputImage, out RecordImage);
+        }
+
+        public bool GetImage(out HObject InputImage, out HObject RecordImage)
+        {
+            InputImage = null;
+            RecordImage = null;
+            foreach (var layout in GlobalVar.dicLayout)
+            {
+                if (layout.Value.ProcessName == Name)
+                    return ProcessContext.GetImage(layout.Value, out InputImage, out RecordImage);
+            }
+            return false;
+        }
+
+        public bool GetCsv(CsvSetting csv, out List<string> DataTitle, out Dictionary<string, object> ResultData)
+        {
+            return ProcessContext.GetCsv(csv, out DataTitle, out ResultData);
+        }
+
+        public bool GetOutput(string map, out object obj)
+        {
+            return ProcessContext.GetValue(map, out obj);
+        }
+
+        public bool GetStringOutput(string map, out string str)
+        {
+            bool res = GetOutput(map, out object obj);
+            str = ProcessParams.ConvertToString(obj);
+            return res;
+        }
+
+        public bool GetBooleanOutput(string map, out bool ret)
+        {
+            try
+            {
+                if (!GetOutput(map, out object obj))
+                {
+                    ret = false;
+                    return ret;
+                }
+                ret = Convert.ToBoolean(obj);
+                return true;
+            }
+            catch
+            {
+                ret = false;
+                return ret;
+            }
+
+        }
+
+        public ConcurrentDictionary<string, IProcess> GetSteps()
+        {
+            if (ProcessContext.dicContext == null)
+                return new ConcurrentDictionary<string, IProcess>();
+
+            return ProcessContext.dicContext;
+        }
+
+        /// <summary>
+        /// 杩愯娴佺▼
+        /// </summary>
+        public FlowPanel nodesControl = null;
+
+        /// <summary>
+        /// 閫氳闆嗗悎(Key:閫氳鍚嶏紝Value:閫氳鍙ユ焺)
+        /// </summary>
+        public ObservableConcurrentDictionary<string, BaseCommunicator> dicCommunicators { get; set; }
+
+        /// <summary>
+        /// 鐩告満闆嗗悎(Key:鐩告満SN锛孷alue:鐩告満鍙ユ焺)
+        /// </summary>
+        public ObservableConcurrentDictionary<string, BaseCamera> dicCameras { get; set; }
+
+
+        public Action<string, LogInfoType> LogInfo;
+
+        public string allProcessPath
+        {
+            get
+            {
+                return GlobalVar.allProcessPath + Name + "\\default.nds";
+            }
+        }
+
+        public string allProcessInputsSettingPath
+        {
+            get
+            {
+                return GlobalVar.allProcessPath + Name + "\\A_ProcessInputs.json";
+            }
+        }
+
+        public string allProcessOutputsSettingPath
+        {
+            get
+            {
+                return GlobalVar.allProcessPath + Name + "\\A_ProcessOutputs.json";
+            }
+        }
+
+        public ConcurrentDictionary<string, List<Tuple<string, string>>> dicInputsMapping = new ConcurrentDictionary<string, List<Tuple<string, string>>>();
+
+        public ConcurrentDictionary<string, List<string>> dicOutputsMapping = new ConcurrentDictionary<string, List<string>>();
+
+        public ProcessRunBll() { }
+
+        public ProcessRunBll(string Name
+            , ObservableConcurrentDictionary<string, BaseCamera> dicCameras
+            , ObservableConcurrentDictionary<string, BaseCommunicator> dicCommunicators)
+        {
+            this.Name = Name;
+            this.dicCameras = dicCameras;
+            this.dicCommunicators = dicCommunicators;
+
+        }
+
+        public bool Load(out string msg)
+        {
+            try
+            {
+                if (!LoadInputs())
+                {
+                    msg = "鍔犺浇杈撳叆澶辫触";
+                    return false;
+                }
+                if (!LoadOutputs())
+                {
+                    msg = "鍔犺浇杈撳嚭澶辫触";
+                    return false;
+                }
+
+                if (!allProcessPath.Contains(".nds"))
+                {
+                    msg = "鏂囦欢璺緞涓嶅畬鏁�";
+                    return false;
+                }
+
+                ProcessContext = new ProcessContext(dicCameras, dicCommunicators, dicInputsMapping, dicOutputsMapping);
+                nodesControl = new FlowPanel(ProcessContext);
+
+                if (!File.Exists(allProcessPath))
+                {
+                    Save(out msg);
+                    msg = "鏂囦欢涓嶅瓨鍦�,鍒涘缓榛樿甯冨眬";
+                }
+                else
+                {
+                    byte[] bytes = File.ReadAllBytes(allProcessPath);
+                    try
+                    {
+                        nodesControl.Load(allProcessPath);
+                    }
+                    catch
+                    {
+                        msg = $"鏂囦欢鎹熷潖,闀垮害涓簕bytes.Length}";
+                        return false;
+                    }
+                }
+
+                foreach (var node in nodesControl.GetAllNodes().Values)
+                {
+                    string ProcessName = node.Text;
+                    string ClassDescription = node.Description;
+                    string ClassName = Node2ToolClassName(ClassDescription);
+                    string ProcessPath = GlobalVar.allProcessPath + Name + "\\" + ProcessName + ".json";
+                    if (!AddStep(Name, ProcessName, ClassName, ProcessPath))
+                        LogInfo?.Invoke(string.Format("娴佺▼[{0}]娣诲姞\"{1}\"澶辫触", Name, ProcessName), LogInfoType.ERROR);
+                }
+                msg = "鍔犺浇甯冨眬鎴愬姛";
+
+                CompileMappings();
+
+                return true;
+            }
+            catch { msg = "鍔犺浇甯冨眬澶辫触"; return false; }
+        }
+
+        public bool Save(out string msg)
+        {
+            try
+            {
+                if (!SaveInputs())
+                {
+                    msg = "淇濆瓨杈撳叆澶辫触";
+                    return false;
+                }
+                if (!SaveOutputs())
+                {
+                    msg = "淇濆瓨杈撳嚭澶辫触";
+                    return false;
+                }
+
+                var dicSteps = GetSteps();
+
+                if (nodesControl.Save(allProcessPath))
+                {
+                    msg = "淇濆瓨甯冨眬鎴愬姛";
+                    return true;
+                }
+                else
+                {
+                    msg = "淇濆瓨甯冨眬澶辫触";
+                    return false;
+                }
+
+            }
+            catch { msg = "淇濆瓨甯冨眬澶辫触"; return false; }
+        }
+
+        public bool LoadInputs()
+        {
+            try
+            {
+                if (!allProcessInputsSettingPath.Contains(".json"))
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                if (!File.Exists(allProcessInputsSettingPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                    string directoryPath = Path.GetDirectoryName(allProcessInputsSettingPath);
+                    SaveInputs();
+                    return true;
+                }
+
+                // 濡傛灉鏂囦欢瀛樺湪锛屽垯鍏堢Щ闄ら殣钘忓睘鎬�
+                if (File.Exists(allProcessInputsSettingPath))
+                    File.SetAttributes(allProcessInputsSettingPath, File.GetAttributes(allProcessInputsSettingPath) & ~FileAttributes.Hidden);
+
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(allProcessInputsSettingPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+
+                dicInputsMapping = JsonConvert.DeserializeObject<ConcurrentDictionary<string, List<Tuple<string, string>>>>(strJson);
+
+                if (File.Exists(allProcessInputsSettingPath))
+                {
+                    // 鑾峰彇鏂囦欢淇℃伅
+                    FileInfo fileInfo = new FileInfo(allProcessInputsSettingPath);
+
+                    // 璁剧疆鏂囦欢涓洪殣钘�
+                    fileInfo.Attributes |= FileAttributes.Hidden;
+                }
+
+                if (dicInputsMapping == null)
+                    return false;
+
+                SaveInputs();
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool SaveInputs()
+        {
+            string strJson = string.Empty;
+            var settings = new JsonSerializerSettings
+            {
+                Formatting = Newtonsoft.Json.Formatting.Indented,
+                // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                ContractResolver = new DefaultContractResolver
+                {
+                    NamingStrategy = new CamelCaseNamingStrategy()
+                }
+            };
+
+            strJson = JsonConvert.SerializeObject(dicInputsMapping, settings);
+            //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+            if (!Directory.Exists(Path.GetDirectoryName(allProcessInputsSettingPath)))
+            {
+                try
+                {
+                    Directory.CreateDirectory(Path.GetDirectoryName(allProcessInputsSettingPath));
+                }
+                catch (Exception)
+                { }
+            }
+
+            // 濡傛灉鏂囦欢瀛樺湪锛屽垯鍏堢Щ闄ら殣钘忓睘鎬�
+            if (File.Exists(allProcessInputsSettingPath))
+                File.SetAttributes(allProcessInputsSettingPath, File.GetAttributes(allProcessInputsSettingPath) & ~FileAttributes.Hidden);
+
+            File.WriteAllText(allProcessInputsSettingPath, strJson, Encoding.UTF8);
+
+            if (File.Exists(allProcessInputsSettingPath))
+            {
+                // 鑾峰彇鏂囦欢淇℃伅
+                FileInfo fileInfo = new FileInfo(allProcessInputsSettingPath);
+
+                // 璁剧疆鏂囦欢涓洪殣钘�
+                fileInfo.Attributes |= FileAttributes.Hidden;
+            }
+
+            CompileMappings();
+
+            return true;
+        }
+
+        public bool LoadOutputs()
+        {
+            try
+            {
+                if (!allProcessOutputsSettingPath.Contains(".json"))
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                if (!File.Exists(allProcessOutputsSettingPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                    string directoryPath = Path.GetDirectoryName(allProcessOutputsSettingPath);
+                    SaveInputs();
+                    return true;
+                }
+
+                // 濡傛灉鏂囦欢瀛樺湪锛屽垯鍏堢Щ闄ら殣钘忓睘鎬�
+                if (File.Exists(allProcessOutputsSettingPath))
+                    File.SetAttributes(allProcessOutputsSettingPath, File.GetAttributes(allProcessOutputsSettingPath) & ~FileAttributes.Hidden);
+
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(allProcessOutputsSettingPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+
+                dicOutputsMapping = JsonConvert.DeserializeObject<ConcurrentDictionary<string, List<string>>>(strJson);
+
+                if (File.Exists(allProcessOutputsSettingPath))
+                {
+                    // 鑾峰彇鏂囦欢淇℃伅
+                    FileInfo fileInfo = new FileInfo(allProcessOutputsSettingPath);
+
+                    // 璁剧疆鏂囦欢涓洪殣钘�
+                    fileInfo.Attributes |= FileAttributes.Hidden;
+                }
+
+                if (dicOutputsMapping == null)
+                    return false;
+
+                SaveOutputs();
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool SaveOutputs()
+        {
+            string strJson = string.Empty;
+            var settings = new JsonSerializerSettings
+            {
+                Formatting = Newtonsoft.Json.Formatting.Indented,
+                // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                ContractResolver = new DefaultContractResolver
+                {
+                    NamingStrategy = new CamelCaseNamingStrategy()
+                }
+            };
+
+            strJson = JsonConvert.SerializeObject(dicOutputsMapping, settings);
+            //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+            if (!Directory.Exists(Path.GetDirectoryName(allProcessOutputsSettingPath)))
+            {
+                try
+                {
+                    Directory.CreateDirectory(Path.GetDirectoryName(allProcessOutputsSettingPath));
+                }
+                catch (Exception)
+                { }
+            }
+
+            // 濡傛灉鏂囦欢瀛樺湪锛屽垯鍏堢Щ闄ら殣钘忓睘鎬�
+            if (File.Exists(allProcessOutputsSettingPath))
+                File.SetAttributes(allProcessOutputsSettingPath, File.GetAttributes(allProcessOutputsSettingPath) & ~FileAttributes.Hidden);
+
+            File.WriteAllText(allProcessOutputsSettingPath, strJson, Encoding.UTF8);
+
+            if (File.Exists(allProcessOutputsSettingPath))
+            {
+                // 鑾峰彇鏂囦欢淇℃伅
+                FileInfo fileInfo = new FileInfo(allProcessOutputsSettingPath);
+
+                // 璁剧疆鏂囦欢涓洪殣钘�
+                fileInfo.Attributes |= FileAttributes.Hidden;
+            }
+
+            CompileMappings();
+
+            return true;
+        }
+
+        /// <summary>
+        /// 娣诲姞鍗曚釜姝ラ鍒版祦绋嬮槦鍒椾腑
+        /// </summary>
+        /// <param name="Camera"></param>
+        /// <param name="ProcessName"></param>
+        /// <param name="ClassName"></param>
+        /// <param name="ProcessPath"></param>
+        /// <param name="listProcesses"></param>
+        public bool AddStep(string Name, string ProcessName, string ClassName, string ProcessPath)
+        {
+            try
+            {
+                if (nodesControl == null || !(nodesControl.Context is ProcessContext))
+                    return false;
+
+                if (((ProcessContext)nodesControl.Context).dicContext.ContainsKey(ProcessName))
+                {
+                    LogInfo?.Invoke(string.Format("娴佺▼[{0}]宸插瓨鍦ㄦ楠{1}]娣诲姞澶辫触", Name, ProcessName), LogInfoType.WARN);
+                    return false;
+                }
+
+                //鍒╃敤鍙嶅皠杩涜鍒涘缓
+                if (ClassName.Contains("Cameras"))
+                {
+                    Type type = IProcess.GetExecutingAssembly().GetType(ClassName.Split(',')[0]);
+                    if (type == null)
+                    {
+                        Debug.WriteLine("Class not found.");
+                        return false;
+                    }
+                    CameraConfig CameraConfig = Activator.CreateInstance(type, new object[] { dicCameras.Items }) as CameraConfig;
+                    if (CameraConfig == null)
+                    {
+                        Debug.WriteLine("Cameras not found.");
+                        return false;
+                    }
+                    CameraConfig.Load(ProcessPath);
+                    CameraConfig.strProcessName = ProcessName;
+                    AddInputsAndOutputs(CameraConfig.strProcessName, CameraConfig);
+                }
+                else if (ClassName.Contains("Communicators"))
+                {
+                    Type type = IProcess.GetExecutingAssembly().GetType(ClassName.Split(',')[0]);
+                    if (type == null)
+                    {
+                        Debug.WriteLine("Class not found.");
+                        return false;
+                    }
+
+                    CommunicatorConfig CommunicatorConfig = Activator.CreateInstance(type, new object[] { dicCommunicators.Items }) as CommunicatorConfig;
+                    if (CommunicatorConfig == null)
+                    {
+                        Debug.WriteLine("Communicators not found.");
+                        return false;
+                    }
+                    CommunicatorConfig.Load(ProcessPath);
+                    CommunicatorConfig.strProcessName = ProcessName;
+                    AddInputsAndOutputs(CommunicatorConfig.strProcessName, CommunicatorConfig);
+                }
+                else if (!string.IsNullOrEmpty(ClassName))
+                {
+                    //鍒╃敤鍙嶅皠杩涜鍒涘缓
+                    Type type = IProcess.GetExecutingAssembly().GetType(ClassName.Split(',')[0]);
+                    if (type == null)
+                    {
+                        Debug.WriteLine("Class not found.");
+                        return false;
+                    }
+                    IProcess process = Activator.CreateInstance(type) as IProcess;
+                    if (process == null)
+                    {
+                        Debug.WriteLine("IProcess not found.");
+                        return false;
+                    }
+
+                    process.Load(ProcessPath);
+                    process.strProcessName = ProcessName;
+
+                    //if (process is VisionProTool && Tool.ContainsChinese(ProcessName))
+                    //    MessageBox.Show($"VisionPro宸ュ叿涓嶆敮鎸佸懡鍚嶄负涓枃:{ProcessName}", "寮傚父");
+
+                    if (process is ScriptTool script)
+                    {
+                        if (script.Params.Outputs.Count <= 0)
+                            script.Params.Outputs.Add("Branch0", true);
+
+                        if (script.Params.Outputs.Count <= 1)
+                            script.Params.Outputs.Add("Branch1", false);
+                    }
+
+                    AddInputsAndOutputs(process.strProcessName, process);
+                }
+
+                LogInfo?.Invoke(string.Format("娴佺▼[{0}]娣诲姞姝ラ[{1}]", Name, ProcessName), LogInfoType.INFO);
+                return true;
+            }
+            catch (Exception ex) { Debug.WriteLine("AddProcessToList澶辫触,鍘熷洜鏄�" + ex.Message.ToString()); return false; }
+        }
+
+        public void AddInputsAndOutputs(string name, IProcess obj)
+        {
+            try
+            {
+                if (obj == null)
+                    return;
+
+                if (nodesControl.Context == null || !(nodesControl.Context is ProcessContext))
+                    return;
+
+                ((ProcessContext)nodesControl.Context).dicContext.TryAdd(name, obj);
+
+                if (obj is IProcess process)
+                {
+                    if (!dicInputsMapping.ContainsKey(name))
+                    {
+                        dicInputsMapping.TryAdd(name, new List<Tuple<string, string>>());
+                        dicInputsMapping[name].Add(new Tuple<string, string>(name + ".Inputs.Image", ""));
+                        //dicInputsMapping[name].Add(new Tuple<string, string>(name + ".Inputs.Fixture", ""));
+
+                        foreach (var item in process.Params.Inputs)
+                            dicInputsMapping[name].Add(new Tuple<string, string>(name + ".Inputs." + item.Name, ""));
+                    }
+
+                    if (!dicOutputsMapping.ContainsKey(name))
+                    {
+                        dicOutputsMapping.TryAdd(name, new List<string>());
+                        dicOutputsMapping[name].Add(name + ".Outputs.Image");
+                        dicOutputsMapping[name].Add(name + ".Outputs.Record");
+                        dicOutputsMapping[name].Add(name + ".Outputs.Result");
+                        //dicOutputsMapping[name].Add(name + ".Outputs.Fixture");
+
+                        foreach (var item in process.Params.Outputs)
+                            dicOutputsMapping[name].Add(name + ".Outputs." + item.Name);
+                    }
+
+                    CompileMappings();
+                }
+            }
+            catch { }
+        }
+
+        public void CompileMappings()
+        {
+            try
+            {
+                if (ProcessContext != null)
+                {
+                    ProcessContext.CompileMappings();
+                }
+            }
+            catch { }
+        }
+
+
+        public void UpdataInputsAndOutputs(string name, IProcess obj)
+        {
+            if (obj == null)
+                return;
+
+            if (obj is IProcess process)
+            {
+                if (dicInputsMapping.ContainsKey(name))
+                {
+                    foreach (var item in process.Params.Inputs)
+                    {
+                        if (dicInputsMapping[name].Where(x => x.Item1 == name + ".Inputs." + item.Name).Count() == 0)
+                            dicInputsMapping[name].Add(new Tuple<string, string>(name + ".Inputs." + item.Name, ""));
+                    }
+                }
+
+                if (dicOutputsMapping.ContainsKey(name))
+                {
+                    foreach (var item in process.Params.Outputs)
+                    {
+                        if (dicOutputsMapping[name].Where(x => x == name + ".Outputs." + item.Name).Count() == 0)
+                            dicOutputsMapping[name].Add(name + ".Outputs." + item.Name);
+                    }
+                }
+
+                CompileMappings();
+            }
+        }
+
+        public bool Remove(string ProcessName)
+        {
+            try
+            {
+                if (ProcessContext == null)
+                    return false;
+
+                ConcurrentDictionary<string, IProcess> dicSteps = GetSteps();
+                if (!dicSteps.ContainsKey(ProcessName))
+                    return false;
+
+                Object obj = dicSteps[ProcessName];
+
+                if (obj == null)
+                    return false;
+
+                string strProcessName = ((IProcess)obj).strProcessName;
+                if (!string.IsNullOrEmpty(strProcessName))
+                {
+                    dicInputsMapping.TryRemove(strProcessName, out List<Tuple<string, string>> tempInputs);
+                    dicOutputsMapping.TryRemove(strProcessName, out List<string> tempOutputs);
+                    if (dicSteps.TryRemove(strProcessName, out IProcess tempObj))
+                        LogInfo?.Invoke(string.Format("娴佺▼[{0}]绉婚櫎姝ラ[{1}]", Name, strProcessName), LogInfoType.INFO);
+                    else
+                        LogInfo?.Invoke(string.Format("娴佺▼[{0}]绉婚櫎姝ラ[{1}]澶辫触", Name, strProcessName), LogInfoType.WARN);
+                    SaveInputs();
+                    SaveOutputs();
+
+                    CompileMappings();
+                    return true;
+                }
+                return false;
+            }
+            catch { return false; }
+        }
+
+        void Rename(IProcess obj, string newName)
+        {
+            if (obj == null)
+                return;
+
+            ((IProcess)obj).strProcessName = newName;
+            LogInfo?.Invoke(string.Format("娴佺▼[{0}]閲嶅懡鍚嶆楠{1}]", Name, newName), LogInfoType.INFO);
+        }
+
+        /// <summary>
+        /// 閲嶅懡鍚嶆楠�(锛佷笉鏄噸鍛藉悕娴佺▼锛�)
+        /// </summary>
+        /// <param name="oldName"></param>
+        /// <param name="newName"></param>
+        public void Rename(string oldName, string newName)
+        {
+            if (ProcessContext == null)
+                return;
+
+            var dicSteps = GetSteps();
+            if (!dicSteps.ContainsKey(oldName))
+                return;
+
+            dicSteps.TryRemove(oldName, out IProcess process);
+            dicSteps.TryAdd(newName, process);
+
+            Rename(process, newName);
+
+            ConcurrentDictionary<string, List<Tuple<string, string>>> dicInputsMapping = new ConcurrentDictionary<string, List<Tuple<string, string>>>();
+            foreach (var InputsMapping in this.dicInputsMapping)
+            {
+                if (InputsMapping.Key == oldName)
+                {
+                    List<Tuple<string, string>> tempTuples = new List<Tuple<string, string>>();
+                    foreach (var tuple in InputsMapping.Value)
+                    {
+                        string[] arrInputs = tuple.Item1.Split(".");
+                        string InputProcessName = arrInputs[0];
+                        string strInput = arrInputs[1];
+                        string InputValueName = arrInputs[2];
+
+                        string Input = "";
+                        if (InputProcessName == oldName)
+                            Input = newName + "." + strInput + "." + InputValueName;
+                        else
+                            Input = tuple.Item1;
+
+                        tempTuples.Add(Tuple.Create(Input, tuple.Item2));
+                    }
+                    dicInputsMapping.TryAdd(newName, tempTuples);
+                }
+                else
+                {
+                    List<Tuple<string, string>> tempTuples = new List<Tuple<string, string>>();
+                    foreach (var tuple in InputsMapping.Value)
+                    {
+                        string[] arrInputs = tuple.Item1.Split(".");
+                        if (arrInputs.Length < 3)
+                        {
+                            tempTuples.Add(tuple);
+                            continue;
+                        }
+
+                        string InputProcessName = arrInputs[0];
+                        string strInput = arrInputs[1];
+                        string InputValueName = arrInputs[2];
+
+                        string[] arrOutputs = tuple.Item2.Split(".");
+                        if (arrOutputs.Length < 3)
+                        {
+                            tempTuples.Add(tuple);
+                            continue;
+                        }
+
+                        string IndexProcessName = arrOutputs[0];
+                        string IndexIsInputOrOutput = arrOutputs[1];
+                        string IndexValueName = arrOutputs[2];
+
+                        if (IndexProcessName == oldName)
+                        {
+                            tempTuples.Add(new Tuple<string, string>(tuple.Item1
+                                , string.Format("{0}.{1}.{2}", newName, IndexIsInputOrOutput, IndexValueName)));
+                        }
+                        else
+                            tempTuples.Add(tuple);
+                    }
+
+                    dicInputsMapping.TryAdd(InputsMapping.Key, tempTuples);
+                }
+            }
+            this.dicInputsMapping = ProcessContext.dicInputsMapping = dicInputsMapping;
+
+            ConcurrentDictionary<string, List<string>> dicOutputsMapping = new ConcurrentDictionary<string, List<string>>();
+            foreach (var OutputsMapping in this.dicOutputsMapping)
+            {
+                if (OutputsMapping.Key == oldName)
+                {
+                    List<string> listOutputs = new List<string>();
+                    foreach (string Output in OutputsMapping.Value)
+                    {
+                        string[] arrOutputs = Output.Split(".");
+                        if (arrOutputs.Length < 3)
+                        {
+                            listOutputs.Add(Output);
+                            continue;
+                        }
+
+                        string IndexProcessName = arrOutputs[0];
+                        string IndexIsInputOrOutput = arrOutputs[1];
+                        string IndexValueName = arrOutputs[2];
+
+                        if (IndexProcessName == oldName)
+                        {
+                            listOutputs.Add(string.Format("{0}.{1}.{2}", newName, IndexIsInputOrOutput, IndexValueName));
+                        }
+                        else
+                            listOutputs.Add(Output);
+                    }
+                    dicOutputsMapping.TryAdd(newName, listOutputs);
+                }
+                else
+                    dicOutputsMapping.TryAdd(OutputsMapping.Key, OutputsMapping.Value);
+            }
+            this.dicOutputsMapping = ProcessContext.dicOutputsMapping = dicOutputsMapping;
+
+            SaveInputs();
+            SaveOutputs();
+
+            CompileMappings();
+        }
+
+        double total_OK;
+        double total_NG;
+
+        public double total
+        {
+            get { return total_OK + total_NG; }
+        }
+
+        public double Rate_OK
+        {
+            get
+            {
+                if (total == 0)
+                    return 100;
+                return (total_OK / total) * 100;
+            }
+        }
+
+        public void ClearTotal()
+        {
+            total_OK = 0;
+            total_NG = 0;
+        }
+
+        /// <summary>
+        /// 璋冪敤Run蹇呴』鏄湪Inovk涓惁鍒欎細鎶ョ嚎绋嬮敊璇紝璇ョ被鐨凴un璋冪敤闇�瑕佸皝瑁呭湪UI鍐�
+        /// </summary>
+        /// <param name="control"></param>
+        /// <returns></returns>
+        public bool Run()
+        {
+            bPruning = true;
+            bCompleted = false;
+
+            DateTime StartTime = DateTime.Now;
+            try
+            {
+                Result = true;
+                if (!nodesControl.Run(out string msg) && !string.IsNullOrEmpty(msg))
+                {
+                    Msg += $"銆恵msg}銆�";
+                    Result &= false;
+                }
+            }
+            catch (Exception ex)
+            {
+                Result = false;
+                Msg = string.Format("杩愯鍙戦�佷簡鎰忓{0}", ex.Message.Trim());
+            }
+
+            RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
+
+            bPruning = false;
+            bCompleted = true;
+
+            if (Result)
+            {
+                total_OK++;
+                Msg = "杩愯鎴愬姛";
+            }
+            else
+                total_NG++;
+
+            if (IProcess.dicGlobalVars.ContainsKey($"{Name}.Result"))
+                IProcess.dicGlobalVars[$"{Name}.Result"] = Result;
+            else
+                IProcess.dicGlobalVars.TryAdd($"{Name}.Result", Result);
+
+            if (IProcess.dicGlobalVars.ContainsKey($"{Name}.Msg"))
+                IProcess.dicGlobalVars[$"{Name}.Msg"] = Msg;
+            else
+                IProcess.dicGlobalVars.TryAdd($"{Name}.Msg", Msg);
+
+            // 鎵嬪姩瑙﹀彂鍨冨溇鍥炴敹
+            GC.Collect();
+            return Result;
+        }
+
+        public void LogoInfo(string info, LogInfoType logInfoType)
+        {
+            LogInfo?.Invoke(info, logInfoType);
+        }
+    }
+}
diff --git a/LB_SmartVision/Program.cs b/LB_SmartVision/Program.cs
new file mode 100644
index 0000000..e0369dd
--- /dev/null
+++ b/LB_SmartVision/Program.cs
@@ -0,0 +1,17 @@
+namespace LB_SmartVision
+{
+    internal static class Program
+    {
+        /// <summary>
+        ///  The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            // To customize application configuration such as set high DPI settings or default font,
+            // see https://aka.ms/applicationconfiguration.
+            ApplicationConfiguration.Initialize();
+            Application.Run(new VisionForm());
+        }
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/Properties/Resources.Designer.cs b/LB_SmartVision/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..b8f6b6c
--- /dev/null
+++ b/LB_SmartVision/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+锘�//------------------------------------------------------------------------------
+// <auto-generated>
+//     姝や唬鐮佺敱宸ュ叿鐢熸垚銆�
+//     杩愯鏃剁増鏈�:4.0.30319.42000
+//
+//     瀵规鏂囦欢鐨勬洿鏀瑰彲鑳戒細瀵艰嚧涓嶆纭殑琛屼负锛屽苟涓斿鏋�
+//     閲嶆柊鐢熸垚浠g爜锛岃繖浜涙洿鏀瑰皢浼氫涪澶便��
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace LB_SmartVision.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   涓�涓己绫诲瀷鐨勮祫婧愮被锛岀敤浜庢煡鎵炬湰鍦板寲鐨勫瓧绗︿覆绛夈��
+    /// </summary>
+    // 姝ょ被鏄敱 StronglyTypedResourceBuilder
+    // 绫婚�氳繃绫讳技浜� ResGen 鎴� Visual Studio 鐨勫伐鍏疯嚜鍔ㄧ敓鎴愮殑銆�
+    // 鑻ヨ娣诲姞鎴栫Щ闄ゆ垚鍛橈紝璇风紪杈� .ResX 鏂囦欢锛岀劧鍚庨噸鏂拌繍琛� ResGen
+    // (浠� /str 浣滀负鍛戒护閫夐」)锛屾垨閲嶆柊鐢熸垚 VS 椤圭洰銆�
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.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 (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LB_SmartVision.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/LB_SmartVision/Properties/Resources.resx b/LB_SmartVision/Properties/Resources.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/LB_SmartVision/Properties/Resources.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/LB_SmartVision/README.md b/LB_SmartVision/README.md
new file mode 100644
index 0000000..266d8f2
--- /dev/null
+++ b/LB_SmartVision/README.md
@@ -0,0 +1 @@
+# LB_SmartVision
\ No newline at end of file
diff --git a/LB_SmartVision/Tool/ObservableConcurrentDictionary.cs b/LB_SmartVision/Tool/ObservableConcurrentDictionary.cs
new file mode 100644
index 0000000..b2f4083
--- /dev/null
+++ b/LB_SmartVision/Tool/ObservableConcurrentDictionary.cs
@@ -0,0 +1,186 @@
+锘縰sing System.Collections;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+
+namespace LB_SmartVision.Tool
+{
+    public class ObservableConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>
+    {
+
+        public readonly ConcurrentDictionary<TKey, TValue> Items = new();
+
+        public ICollection<TKey> Keys => ((IDictionary<TKey, TValue>)Items).Keys;
+
+        public ICollection<TValue> Values => ((IDictionary<TKey, TValue>)Items).Values;
+
+        public int Count => ((ICollection<KeyValuePair<TKey, TValue>>)Items).Count;
+
+        public bool IsReadOnly => ((ICollection<KeyValuePair<TKey, TValue>>)Items).IsReadOnly;
+
+        public event EventHandler<DictionaryChangedEventArgs<TKey, TValue>> DictionaryChanged;
+
+        public TValue this[TKey key]
+        {
+            get
+            {
+                return Items.TryGetValue(key, out TValue Value) ? Value : default;
+            }
+            set
+            {
+                //bool exists = Items.TryGetValue(key, out TValue oldValue);
+                if (Items.ContainsKey(key))
+                    Items[key] = value;
+                //if (exists)
+                //    OnDictionaryChanged(DictionaryChangeType.Updated, key, key, value, oldValue);
+            }
+        }
+
+        public bool TryAdd(TKey key, TValue value)
+        {
+            if (Items.ContainsKey(key))
+            {
+                Items[key] = value;
+                return true;
+            }
+            if (Items.TryAdd(key, value))
+            {
+                OnDictionaryChanged(DictionaryChangeType.Added, key, key, value, value);
+                return true;
+            }
+            return false;
+        }
+
+        public bool TryRemove(TKey key, out TValue value)
+        {
+            if (Items.TryRemove(key, out value))
+            {
+                OnDictionaryChanged(DictionaryChangeType.Removed, key, key, default, value);
+                return true;
+            }
+            return false;
+        }
+
+        public bool TryRename(TKey oldKey, TKey newKey)
+        {
+            if (Items.TryRemove(oldKey, out TValue value))
+            {
+                Items.TryAdd(newKey, value);
+                OnDictionaryChanged(DictionaryChangeType.Renamed, newKey, oldKey, value, value);
+                return true;
+            }
+
+            return false;
+        }
+
+        protected virtual void OnDictionaryChanged(DictionaryChangeType changeType, TKey newKey, TKey oldKey, TValue newValue, TValue oldValue)
+        {
+            var handlers = DictionaryChanged;
+            if (handlers != null)
+            {
+                foreach (EventHandler<DictionaryChangedEventArgs<TKey, TValue>> handler in handlers.GetInvocationList())
+                {
+                    try
+                    {
+                        handler(this, new DictionaryChangedEventArgs<TKey, TValue>(changeType, newKey, oldKey, newValue, oldValue));
+                    }
+                    catch (Exception ex)
+                    {
+                        Debug.WriteLine($"浜嬩欢澶勭悊寮傚父: {ex.Message}");
+                    }
+                }
+            }
+
+            //DictionaryChanged?.Invoke(this,
+            //    new DictionaryChangedEventArgs<TKey, TValue>(changeType, newKey, oldKey, newValue, oldValue));
+        }
+
+        public void Add(TKey key, TValue value)
+        {
+            ((IDictionary<TKey, TValue>)Items).Add(key, value);
+        }
+
+        // 鍦ㄧ被涓坊鍔犵被鍨嬫鏌�
+        private static readonly bool IsStringKey = typeof(TKey) == typeof(string);
+
+        public bool ContainsKey(TKey key)
+        {
+            if (!IsStringKey || key == null)
+                return ((IDictionary<TKey, TValue>)Items).ContainsKey(key);
+
+            var searchKey = key as string;
+            return ((IDictionary<TKey, TValue>)Items).Keys.Any(k =>
+                string.Equals(k as string, searchKey, StringComparison.OrdinalIgnoreCase));
+        }
+
+        public bool Remove(TKey key)
+        {
+            return ((IDictionary<TKey, TValue>)Items).Remove(key);
+        }
+
+        public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
+        {
+            return ((IDictionary<TKey, TValue>)Items).TryGetValue(key, out value);
+        }
+
+        public void Add(KeyValuePair<TKey, TValue> item)
+        {
+            ((ICollection<KeyValuePair<TKey, TValue>>)Items).Add(item);
+        }
+
+        public void Clear()
+        {
+            foreach (var kvp in Items)
+                OnDictionaryChanged(DictionaryChangeType.Removed, kvp.Key, kvp.Key, default, kvp.Value);
+
+            ((ICollection<KeyValuePair<TKey, TValue>>)Items).Clear();
+        }
+
+        public bool Contains(KeyValuePair<TKey, TValue> item)
+        {
+            return ((ICollection<KeyValuePair<TKey, TValue>>)Items).Contains(item);
+        }
+
+        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+        {
+            ((ICollection<KeyValuePair<TKey, TValue>>)Items).CopyTo(array, arrayIndex);
+        }
+
+        public bool Remove(KeyValuePair<TKey, TValue> item)
+        {
+            return ((ICollection<KeyValuePair<TKey, TValue>>)Items).Remove(item);
+        }
+
+        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+        {
+            return ((IEnumerable<KeyValuePair<TKey, TValue>>)Items).GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return ((IEnumerable)Items).GetEnumerator();
+        }
+
+        // 瀹炵幇鍏朵粬IDictionary鎴愬憳...
+    }
+
+    public enum DictionaryChangeType { Added, Removed, Renamed, Updated }
+
+    public class DictionaryChangedEventArgs<TKey, TValue> : EventArgs
+    {
+        public DictionaryChangeType ChangeType { get; }
+        public TKey NewKey { get; }
+        public TKey OldKey { get; }
+        public TValue NewValue { get; }
+        public TValue OldValue { get; }
+
+        public DictionaryChangedEventArgs(DictionaryChangeType changeType, TKey newKey, TKey oldKey, TValue newValue, TValue oldValue)
+        {
+            ChangeType = changeType;
+            NewKey = newKey;
+            OldKey = oldKey;
+            NewValue = newValue;
+            OldValue = oldValue;
+        }
+    }
+}
diff --git a/LB_SmartVision/Tool/OperateIniHelper.cs b/LB_SmartVision/Tool/OperateIniHelper.cs
new file mode 100644
index 0000000..829b7f5
--- /dev/null
+++ b/LB_SmartVision/Tool/OperateIniHelper.cs
@@ -0,0 +1,161 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection.Metadata;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static System.Collections.Specialized.BitVector32;
+
+namespace LB_SmartVision.Tool
+{
+    public class OperateIniHelper
+    {
+        private string _iniFilePath = "Config";
+
+        /// <summary>
+        /// IniFilePath闇�瑕佸寘鍚�.ini锛屽湪寮曠敤鍓嶉渶瑕佽缃瓼ileName
+        /// </summary>
+        public string IniFilePath
+        {
+            get
+            {
+                return System.IO.Path.Combine(Application.StartupPath, _iniFilePath, _iniFileName);
+            }
+            set
+            {
+                _iniFilePath = value;
+            }
+        }
+
+        private string _iniFileName = "Default.ini";
+
+        public static string Suffix = ".ini";
+
+        private bool bClosedIni = false;
+        public string IniFileName
+        {
+            get
+            {
+                return _iniFileName;
+            }
+            set
+            {
+                int index = value.LastIndexOf('.');
+
+                // 濡傛灉娌℃湁鎵惧埌鍒嗛殧绗︼紝鍒欒繑鍥炲師濮嬪瓧绗︿覆
+                if (index == -1)
+                    _iniFileName = value + Suffix;
+                else
+                    _iniFileName = value.Substring(0, index) + Suffix;
+            }
+        }
+
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
+        private static extern int WritePrivateProfileString(string section, string key, string value, string filePath);
+
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
+        private static extern int GetPrivateProfileString(string section, string key, string defaultValue, StringBuilder returnValue, int size, string filePath);
+
+        public OperateIniHelper() { }
+
+        public OperateIniHelper(string iniFileName = "MyAlgorithm_1", string iniFilePath = "MyAlgorithm")
+        {
+            IniFileName = iniFileName;
+            IniFilePath = iniFilePath;
+            GetValidFilePath(IniFilePath);
+        }
+
+        public void SetValue(string section, string key, object value, string path = "")
+        {
+            // 閫夋嫨鍚堥�傜殑缂栫爜
+            Encoding encoding = Encoding.UTF8;
+            if (path != "" && value != null)
+            {
+                WritePrivateProfileString(section.Trim(), key.Trim(), value.ToString(), path);
+                int index = path.LastIndexOf('.');
+                if (index != -1)
+                {
+                    string EncryptPath = path.Substring(0, index) + "_closed" + Suffix;
+                    Tool.EncryptFile(path, EncryptPath);
+                }
+            }
+            else if (value != null)
+            {
+                WritePrivateProfileString(section.Trim(), key.Trim(), value.ToString(), IniFilePath);
+                int index = IniFilePath.LastIndexOf('.');
+                if (index != -1)
+                {
+                    string EncryptPath = IniFilePath.Substring(0, index) + "_closed" + Suffix;
+                    Tool.EncryptFile(IniFilePath, EncryptPath);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇Ini鏂囦欢鍊�
+        /// </summary>
+        /// <param name="section"></param>
+        /// <param name="key"></param>
+        /// <param name="path"></param>
+        /// <returns></returns>
+        public string GetValue(string section, string key, string path = "")
+        {
+            StringBuilder returnValue = new StringBuilder(255);
+
+            if (path != "" && path != null && GetValidFilePath(path).Item1)
+                GetPrivateProfileString(section.Trim(), key.Trim(), string.Empty, returnValue, returnValue.Capacity, path);
+
+            else if (GetValidFilePath(IniFilePath).Item1)
+                GetPrivateProfileString(section.Trim(), key.Trim(), string.Empty, returnValue, returnValue.Capacity, IniFilePath);
+
+            //涓嶅瓨鍦ㄥ�兼椂鍐欏叆榛樿鍊�0
+            if (string.IsNullOrEmpty(returnValue.ToString().Trim()))
+            {
+                string strDefalut = "0";
+                if (path != "" && path != null)
+                    SetValue(section.Trim(), key.Trim(), strDefalut, path);
+                else
+                    SetValue(section.Trim(), key.Trim(), strDefalut);
+
+                return strDefalut;
+            }
+
+            return returnValue.ToString();
+        }
+
+        static (bool, string) GetValidFilePath(string path)
+        {
+            try
+            {
+                if (path == "" || path == null)
+                    return (false, null);
+
+                // 妫�鏌ヨ矾寰勬槸鍚﹀寘鍚潪娉曞瓧绗�
+                string fullPath = Path.GetFullPath(path);
+                bool result = !string.IsNullOrWhiteSpace(fullPath) && path.Equals(fullPath, StringComparison.OrdinalIgnoreCase);
+
+                // 涓嶅瓨鍦ㄩ潪娉曞瓧绗﹀垯鍒ゆ柇鏄惁闇�瑕佸垱寤�
+                if (result)
+                {
+                    string parentPath = Path.GetDirectoryName(path);
+                    // 鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦�
+                    if (!Directory.Exists(parentPath) && parentPath != null)
+                    {
+                        try
+                        {
+                            Directory.CreateDirectory(parentPath);
+                            // 鏂囦欢涓嶅瓨鍦ㄥ垯鍐欏叆榛樿鍊�
+                        }
+                        catch { return (false, null); }
+                    }
+
+                }
+                return (result, path);
+            }
+            catch { return (false, null); }
+        }
+    }
+}
diff --git a/LB_SmartVision/Tool/Tool.cs b/LB_SmartVision/Tool/Tool.cs
new file mode 100644
index 0000000..94ae8ca
--- /dev/null
+++ b/LB_SmartVision/Tool/Tool.cs
@@ -0,0 +1,1134 @@
+锘縰sing HalconDotNet;
+using Microsoft.Win32;
+using System.Collections.Concurrent;
+using System.Configuration;
+using System.Diagnostics;
+using System.Drawing.Imaging;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Cryptography;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+
+namespace LB_SmartVision.Tool
+{
+    public sealed class Tool : IDisposable
+    {
+        // 闈欐�佹瀯閫犲嚱鏁板惎鍔ㄦ秷璐硅�呬换鍔�
+        static Tool()
+        {
+            // 鍚姩娑堣垂鑰呬换鍔�
+            _logConsumerTask = Task.Factory.StartNew(
+                () => ProcessLogQueue(_logCts.Token),
+                _logCts.Token,
+                TaskCreationOptions.LongRunning,
+                TaskScheduler.Default);
+
+            // FIFO 琛屼负锛岃秴鍑哄閲忔椂闃诲
+            _RealImageQueue = new BlockingCollection<ImageSaveTask>(capacity);
+            _RealImageCts = new CancellationTokenSource();
+            StartRealImageConsumer();
+        }
+
+        public void Dispose()
+        {
+            try
+            {
+                // 鍋滄鎺ュ彈鏂版棩蹇�
+                _logQueue.CompleteAdding();
+                // 鍙栨秷姝e湪杩涜鐨勬搷浣�
+                _logCts.Cancel();
+                // 绛夊緟瀹屾垚
+                if (!_logConsumerTask.Wait(TimeSpan.FromSeconds(5)))
+                    Debug.WriteLine("鏃ュ織绾跨▼鍏抽棴瓒呮椂");
+
+                _RealImageCts.Cancel();
+                _RealImageQueue.CompleteAdding();
+                while (_RealImageQueue.TryTake(out var task))
+                {
+                    if (task.Image is Bitmap bitmap)
+                        bitmap.Dispose();
+                    else if (task.Image is HObject hobject)
+                        hobject.Dispose();
+                }
+                _RealImageCts.Dispose();
+                _RealImageQueue.Dispose();
+                _RealImageConsumerTask?.Dispose();
+            }
+            catch { }
+            finally
+            {
+                _logCts.Dispose();
+                _logQueue.Dispose();
+            }
+        }
+
+        #region 鏃ュ織鍔熻兘
+        public static string _logFilePath = Path.Combine(GlobalVar.strPathLog, $"{GlobalVar.strStartTime}.log");
+        public static string _logFilePathBackup = Path.Combine(GlobalVar.strPathLog, $"{GlobalVar.strStartTime}(鍓湰).log");
+
+        private static readonly BlockingCollection<string> _logQueue = new BlockingCollection<string>(1024);
+        private static readonly CancellationTokenSource _logCts = new CancellationTokenSource();
+        private static Task _logConsumerTask;
+        private static readonly object _fileLock = new object();
+
+        // 娣诲姞鏃ュ織鍒伴槦鍒�
+        public static bool AddLog(string message)
+        {
+            if (!_logQueue.IsAddingCompleted)
+            {
+                try
+                {
+                    _logQueue.Add(message, _logCts.Token);
+                    return true;
+                }
+                catch (InvalidOperationException)
+                {
+                    // 闃熷垪宸插叧闂�
+                    return false;
+                }
+            }
+            return false;
+        }
+
+        // 娑堣垂鑰呬换鍔″鐞嗛槦鍒�
+        private static void ProcessLogQueue(CancellationToken ct)
+        {
+            try
+            {
+                foreach (var logEntry in _logQueue.GetConsumingEnumerable(ct))
+                {
+                    lock (_fileLock)
+                    {
+                        try
+                        {
+                            File.AppendAllText(_logFilePath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {logEntry}{Environment.NewLine}");
+                        }
+                        catch
+                        {
+                            try
+                            {
+                                // 鏃ュ織鍐欏叆澶辫触浜屾灏濊瘯
+                                File.AppendAllText(_logFilePath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {logEntry}{Environment.NewLine}");
+                            }
+                            catch
+                            {
+                                try
+                                {
+                                    // 鏃ュ織鍐欏叆澶辫触澶勭悊锛堝彲娣诲姞鍒板鐢ㄩ槦鍒楁垨鎺у埗鍙拌緭鍑猴級
+                                    File.AppendAllText(_logFilePathBackup, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {logEntry}{Environment.NewLine}");
+                                }
+                                catch (Exception ex)
+                                {
+                                    Debug.WriteLine($"鏃ュ織鍐欏叆澶辫触: {ex.Message}");
+                                }
+                            }
+                        }
+                    }
+
+                }
+            }
+            catch (OperationCanceledException)
+            {
+                // 姝e父鍙栨秷
+            }
+        }
+
+        // 灏濊瘯鍐欏叆鏂囦欢鐨勮緟鍔╂柟娉�
+        private static bool TryWriteToFile(string path, byte[] data)
+        {
+            try
+            {
+                using (var stream = new FileStream(
+                    path,
+                    FileMode.Append,
+                    FileAccess.Write,
+                    FileShare.ReadWrite,
+                    bufferSize: 4096,
+                    useAsync: true))
+                {
+                    stream.Write(data, 0, data.Length);
+                    return true;
+                }
+            }
+            catch
+            {
+                return false;
+            }
+        }
+        #endregion
+
+        #region 瀛樺師鍥惧姛鑳�
+        /// <summary>
+        /// 瓒呭嚭瀹归噺鏃堕樆濉�
+        /// </summary>
+        private static readonly BlockingCollection<ImageSaveTask> _RealImageQueue;
+        private static readonly CancellationTokenSource _RealImageCts;
+        private static Task _RealImageConsumerTask;
+        private static int _restartCount;
+        private const int MaxRestarts = 5;
+        private static int capacity = 10; // 闃熷垪瀹归噺
+
+        // 鑾峰彇鎸囧畾鍥惧儚鏍煎紡鐨勭紪鐮佸櫒淇℃伅
+        private static ImageCodecInfo GetEncoder(ImageFormat format)
+        {
+            // 鑾峰彇鎵�鏈夊凡瀹夎鐨勫浘鍍忕紪鐮佸櫒
+            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
+
+            // 鏌ユ壘鍖归厤鎸囧畾鏍煎紡鐨勭紪鐮佸櫒
+            return codecs.FirstOrDefault(codec => codec.FormatID == format.Guid);
+        }
+
+        public static long _imageQuality = 100L;
+        static ImageCodecInfo jpegEncoder = null;
+        static EncoderParameters encoderParams = null;
+        static char[] invalidChars = Path.GetInvalidFileNameChars();
+
+        // 鍥剧墖淇濆瓨浠诲姟缁撴瀯
+        public struct ImageSaveTask
+        {
+            public object Image { get; set; }
+            public string FullPath { get; set; }
+
+            public string ImageType { get; set; }
+
+            public long Quality { get; set; }
+
+            public ImageSaveTask(object image, string fullPath, string imageType = "jpg", long quality = 50L)
+            {
+                Image = image;
+                FullPath = fullPath;
+                ImageType = imageType.ToLower();
+                Quality = quality;
+            }
+        }
+
+        private static void StartRealImageConsumer()
+        {
+            _RealImageConsumerTask = Task.Run(async () =>
+            {
+                try
+                {
+                    await RealImageProcessQueue();
+                }
+                catch when (_RealImageCts.IsCancellationRequested)
+                {
+                    // 姝e父鍏抽棴
+                }
+                catch (Exception ex)
+                {
+                    if (++_restartCount <= MaxRestarts)
+                    {
+                        StartRealImageConsumer(); // 鑷姩閲嶅惎
+                    }
+                    AddLog($"淇濆瓨鍥剧墖StartRealImageConsumer鍑虹幇寮傚父:{ex.Message}");
+                }
+            }, _RealImageCts.Token);
+        }
+
+        private static async Task RealImageProcessQueue()
+        {
+            foreach (var task in _RealImageQueue.GetConsumingEnumerable(_RealImageCts.Token))
+            {
+                try
+                {
+                    await SaveImageAsync(task);
+                }
+                catch (Exception ex)
+                {
+                    AddLog($"淇濆瓨鍥剧墖RealImageProcessQueue鍑虹幇寮傚父:{ex.Message}");
+                }
+                finally
+                {
+                    if (task.Image != null)
+                    {
+                        if (task.Image is Bitmap bitmap)
+                            bitmap.Dispose();
+                        if (task.Image is HObject hobject)
+                            hobject.Dispose();
+                    }
+                }
+            }
+        }
+
+        public static void AddRealImage(object image, string filePath, string fileName, string imageType = "jpg", long quality = 50L)
+        {
+            if (_RealImageCts.IsCancellationRequested)
+                throw new InvalidOperationException("Processor is shutting down");
+
+            if (IsSave(filePath))
+            {
+                string fullPath = Path.Combine(filePath, $"{fileName}.{imageType.ToLower()}");
+
+                // FIFO 琛屼负锛岃秴鍑哄閲忔椂闃诲
+                //// 缂撳瓨鍥剧墖澶т簬瀹归噺璇存槑纾佺洏瀛樺偍涓嶈繃鏉ヤ簡,鍙栧嚭鎵�鏈夊厓绱犵洿鍒伴槦鍒椾负绌�
+                //if (_RealImageQueue.Count >= capacity + 1)
+                //{
+                //    AddLog("缂撳瓨鍥剧墖瓒呰繃10寮�,娓呯┖宸茬粡缂撳瓨鐨勬棫鍥剧墖");
+                //    while (_RealImageQueue.TryTake(out _)) { }
+                //}
+
+                if (image is HObject hObject)
+                {
+                    _RealImageQueue.Add(new ImageSaveTask
+                    {
+                        Image = hObject.Clone(),
+                        FullPath = fullPath,
+                        ImageType = imageType.ToLower(),
+                        Quality = quality
+                    }, _RealImageCts.Token);
+                }
+                else if (image is Bitmap bitmap)
+                {
+                    _RealImageQueue.Add(new ImageSaveTask
+                    {
+                        Image = bitmap.Clone(),
+                        FullPath = fullPath,
+                        ImageType = imageType.ToLower(),
+                        Quality = quality
+                    }, _RealImageCts.Token);
+                }
+            }
+        }
+
+        // 绋嬪簭鍚姩鏃跺垵濮嬪寲缂栫爜鍣ㄧ紦瀛�
+        private static readonly Dictionary<Guid, ImageCodecInfo> _encoderCache =
+            ImageCodecInfo.GetImageEncoders()
+                .ToDictionary(codec => codec.FormatID);
+
+        // 閫氳繃ImageFormat鑾峰彇缂栫爜鍣�
+        private static ImageCodecInfo GetEncoderByFormat(ImageFormat format)
+        {
+            _encoderCache.TryGetValue(format.Guid, out var encoder);
+            return encoder;
+        }
+
+        // 閫氳繃瀛楃涓茬被鍨嬭幏鍙栫紪鐮佸櫒
+        private static ImageCodecInfo GetEncoderByType(string imageType)
+        {
+            var format = GetImageFormat(imageType);
+            return GetEncoderByFormat(format);
+        }
+
+        // 鑾峰彇ImageFormat鐨勮緟鍔╂柟娉�
+        private static ImageFormat GetImageFormat(string imageType)
+        {
+            switch (imageType.ToLowerInvariant())
+            {
+                case "jpg":
+                case "jpeg": return ImageFormat.Jpeg;
+                case "png": return ImageFormat.Png;
+                case "bmp": return ImageFormat.Bmp;
+                case "gif": return ImageFormat.Gif;
+                case "tif":
+                case "tiff": return ImageFormat.Tiff;
+                default: throw new NotSupportedException($"涓嶆敮鎸佺殑鍥剧墖鏍煎紡: {imageType}");
+            }
+        }
+
+        private static async Task SaveImageAsync(ImageSaveTask task)
+        {
+            try
+            {
+                // 鍙傛暟鏍¢獙
+                if (task.Image == null) throw new ArgumentNullException(nameof(task.Image));
+                if (string.IsNullOrWhiteSpace(task.FullPath))
+                    throw new ArgumentException("Invalid file path");
+
+                var dir = Path.GetDirectoryName(task.FullPath);
+                if (!Directory.Exists(dir))
+                {
+                    Directory.CreateDirectory(dir);
+                }
+
+                if (task.Image is HObject hObject && hObject.IsInitialized())
+                {
+                    try
+                    {
+                        //Halcon瀛樺浘闇�瑕佺敤鏂滄潬
+                        task.FullPath.Replace("\\", "/");
+                        HOperatorSet.WriteImage(hObject, task.ImageType, 0, task.FullPath);
+                    }
+                    catch { AddLog("淇濆瓨鍥剧墖鏃禜OperatorSet.WriteImage鍙戠敓寮傚父"); }
+                }
+                else if (task.Image is Bitmap bitmap)
+                {
+                    // 鑾峰彇瀵瑰簲鏍煎紡鐨勭紪鐮佸櫒
+                    ImageCodecInfo encoder = GetEncoderByType(task.ImageType);
+
+                    // 閰嶇疆缂栫爜鍙傛暟
+                    var encoderParams = new EncoderParameters(1);
+                    encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, task.Quality);
+
+                    // 浣跨敤鍐呭瓨娴佷腑杞伩鍏嶆枃浠堕攣鍐茬獊
+                    using (var memoryStream = new MemoryStream())
+                    {
+                        // 鍚屾缂栫爜杞紓姝ユ搷浣滐紙绾跨▼姹犱紭鍖栵級
+                        await Task.Run(() =>
+                        {
+                            bitmap.Save(memoryStream, encoder, encoderParams);
+                            memoryStream.Position = 0; // 閲嶇疆娴佷綅缃�
+                        }).ConfigureAwait(false);
+
+                        // 鍘熷瓙鎬у啓鍏ワ紙涓存椂鏂囦欢+鏇挎崲锛�
+                        var tempPath = $"{task.FullPath}.{Guid.NewGuid()}.tmp";
+
+                        // 寮傛鏂囦欢鍐欏叆锛堝甫缂撳啿鍖轰紭鍖栵級
+                        using (var fileStream = new FileStream(
+                            tempPath,
+                            FileMode.Create,
+                            FileAccess.Write,
+                            FileShare.None,
+                            bufferSize: 81920, // 80KB缂撳啿鍖�
+                            useAsync: true))
+                        {
+                            await memoryStream.CopyToAsync(fileStream)
+                                .ConfigureAwait(false);
+                        }
+
+                        // 鍘熷瓙鏇挎崲鏂囦欢锛堣法骞冲彴鍏煎锛�
+                        File.Move(tempPath, task.FullPath);
+                    }
+                }
+            }
+            catch (Exception ex) when (IsRetryableException(ex))
+            {
+                AddLog($"淇濆瓨鍥剧墖IsRetryableException鍑虹幇寮傚父:{ex.Message}");
+            }
+            catch (Exception ex)
+            {
+                AddLog($"淇濆瓨鍥剧墖SaveImageAsync鍑虹幇寮傚父:{ex.Message}");
+            }
+        }
+
+        // 鍒ゆ柇鏄惁鍙噸璇曠殑寮傚父
+        private static bool IsRetryableException(Exception ex)
+        {
+            return ex is IOException
+                or UnauthorizedAccessException
+                or TimeoutException;
+        }
+        #endregion
+
+        #region 纾佺洏鍥炴敹鍔熻兘
+        public static double MinSpace = 10;
+        /// <summary>
+        /// 鑾峰彇纾佺洏鍓╀綑绌洪棿
+        /// </summary>
+        /// <param name="strPath"></param>
+        /// <returns></returns>
+        public static double GetHardDiskFreeSpace(string strPath)
+        {
+            //纾佺洏鍚嶇О
+            string strHardDiskName = strPath.Substring(0, 1);
+
+            //鑾峰彇C鐩樼殑鍓╀綑绌洪棿
+            DriveInfo cDrive = new DriveInfo(strHardDiskName);
+            // 妫�鏌ラ┍鍔ㄥ櫒鏄惁鏄湁鏁堢殑
+            if (cDrive.IsReady)
+            {
+                // 鑾峰彇鍓╀綑绌洪棿
+                long freeSpace = cDrive.AvailableFreeSpace;
+
+                // 灏嗗瓧鑺傛暟杞崲涓篏B鍗曚綅
+                return (double)freeSpace / (1024 * 1024 * 1024);
+            }
+            else
+                return 0;
+        }
+
+        /// <summary>
+        /// 鍒ゆ柇鏄惁鍏佽淇濆瓨
+        /// </summary>
+        /// <param name="fullPath">淇濆瓨鏂囦欢鐨勫畬鏁磋矾寰�</param>
+        /// <returns></returns>
+        public static bool IsSave(string fullPath)
+        {
+            // 鑾峰彇涓婁竴绾х洰褰曪紙鐖剁洰褰曪級
+            string parentDirectory = Path.GetDirectoryName(fullPath);
+            if (GetHardDiskFreeSpace(parentDirectory) >= MinSpace)
+                return true;
+            else
+            {
+                if (DeletOutTimeFiles(parentDirectory))
+                {
+                    // 鍒犻櫎瓒呮湡鏂囦欢鍚庡啀娆″垽鏂閲忚兘鍚﹀瓨鍌�
+                    if (GetHardDiskFreeSpace(parentDirectory) >= MinSpace)
+                        return true;
+
+                    return false;
+                }
+                else
+                    return false;
+            }
+        }
+
+        /// <summary>
+        ///鍒犻櫎瓒呭嚭鏃堕棿鐨勬枃浠跺す璺緞
+        /// </summary>
+        /// <param name="directoryPath"></param>
+        /// <returns></returns>
+        public static bool DeletOutTimeFiles(string directoryPath, int days = 30)
+        {
+            try
+            {
+                // 淇濆瓨鏃堕棿涓嶈秴杩�30澶�
+                DateTime NowTime = DateTime.Now; // 褰撳墠鏃ユ湡浣滀负鎴鏃ユ湡
+                DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath);
+                DirectoryInfo[] directories = directoryInfo.GetDirectories();
+
+                for (int i = 0; i < directories.Length; i++)
+                {
+                    if (directories[i].CreationTime.AddDays(days) < NowTime)
+                    {
+                        try
+                        {
+                            Directory.Delete(directories[i].FullName, recursive: true);
+                            Debug.WriteLine($"Deleted {directories[i].FullName}");
+                        }
+                        catch (Exception ex)
+                        {
+                            // 鍙互閫夋嫨鍦ㄨ繖閲岃褰曟棩蹇楃户缁鐞嗕笅涓�涓枃浠�
+                            Debug.WriteLine($"Error deleting {directories[i].FullName}: {ex.Message}");
+                        }
+                    }
+                }
+
+                AddLog($"纾佺洏绌洪棿涓嶈冻,宸插垹闄よ矾寰刐{directoryPath}]瓒呰繃{days}澶╃殑鏂囦欢,绱{directories.Length}涓�!");
+                return true;
+            }
+            catch { return false; }
+        }
+
+        #endregion
+
+        public static bool ContainsChinese(string text)
+        {
+            if (string.IsNullOrEmpty(text))
+                return false;
+
+            return Regex.IsMatch(text, @"[\u4e00-\u9fa5]");
+        }
+
+        /// <summary>
+        /// 淇濆瓨CSV鍒版湰鍦�
+        /// </summary>
+        /// <param name="fileDirectoryAndName"></param>
+        /// <param name="obj"></param>
+        public static void WriteDataToFile(string fileDirectoryAndName, object[] obj)
+        {
+            try
+            {
+                string text = "";
+                // 鍐欏叆CSV鏂囦欢
+                using (var streamWriter = new StreamWriter(fileDirectoryAndName, true, Encoding.UTF8))
+                {
+                    for (int i = 0; i < obj.Length; i++)
+                    {
+                        text += (obj[i].ToString().Replace(",", "锛�"));
+                        if (i < obj.Length - 1)
+                            text += ",";
+                    }
+                    streamWriter.Write(text);
+                    streamWriter.WriteLine(); // 鍐欏叆鎹㈣绗�
+                }
+            }
+            catch { }
+        }
+
+        /// <summary>
+        /// 淇濆瓨鏁版嵁鍒版湰鍦�
+        /// </summary>
+        /// <param name="strCCDName"></param>
+        /// <param name="timeCode"></param>
+        /// <param name="productCode"></param>
+        /// <param name="result"></param>
+        /// <param name="resultData"></param>
+        public static void SaveData(string filePath, List<string> DataTitle, Dictionary<string, object> resultData)
+        {
+            try
+            {
+                if (resultData.Count <= 0 || resultData == null)
+                    return;
+
+                var dir = Path.GetDirectoryName(filePath);
+                if (!Directory.Exists(dir))
+                    Directory.CreateDirectory(dir);
+
+                if (!File.Exists(filePath))
+                    WriteDataToFile(filePath, DataTitle.ToArray());
+
+                List<string> SaveData = new List<string>();
+
+                foreach (var item in DataTitle)
+                {
+                    if (resultData.ContainsKey(item))
+                    {
+                        double dData = 0;
+                        if (double.TryParse(resultData[item].ToString(), out dData))
+                            SaveData.Add(dData.ToString("F2"));
+                        else
+                            SaveData.Add((resultData[item]?.ToString()).Replace(",", "锛�").ToString());
+                    }
+                    else
+                        SaveData.Add("NULL");
+                }
+                try
+                {
+                    WriteDataToFile(filePath, SaveData.ToArray());
+                }
+                catch (Exception ex)
+                {
+                    //鏂囦欢琚崰鐢ㄤ繚瀛樺埌鍓湰涓�
+                    try
+                    {
+                        //鍐嶆灏濊瘯鍐欏叆
+                        WriteDataToFile(filePath, SaveData.ToArray());
+                    }
+                    catch
+                    {
+                        //鍐欏叆澶辫触鍐欏埌鍓湰涓�
+                        filePath = AddCopySuffix(filePath, "(鍓湰)");
+                        if (!File.Exists(filePath))
+                            WriteDataToFile(filePath, DataTitle.ToArray());
+
+                        WriteDataToFile(filePath, SaveData.ToArray());
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                AddLog("鐢熶骇鏁版嵁淇濆瓨澶辫触,鍘熷洜鏄�:" + ex.ToString());
+            }
+        }
+
+        public static string AddCopySuffix(string filePath, string suffix = "(鍓湰)")
+        {
+            if (string.IsNullOrEmpty(filePath))
+                return filePath;
+
+            string directory = Path.GetDirectoryName(filePath);
+            string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath);
+            string extension = Path.GetExtension(filePath);
+
+            return Path.Combine(directory, $"{fileNameWithoutExtension}({suffix}){extension}");
+        }
+
+        /// <summary>
+        /// 鍔犲瘑鏂囦欢
+        /// </summary>
+        /// <param name="inputFilePath"></param>
+        /// <param name="outputFilePath"></param>
+        /// <param name="key"></param>
+        /// <param name="iv"></param>
+        public static void EncryptFile(string inputFilePath, string outputFilePath, string key = "", string iv = "")
+        {
+            using (Aes aes = Aes.Create())
+            {
+                if (key != "")
+                {
+                    aes.Key = Convert.FromBase64String(key);
+                    aes.IV = Convert.FromBase64String(iv);
+                }
+                else
+                {
+                    aes.Key = new byte[32];
+                    aes.IV = new byte[16];
+                }
+
+                using (FileStream outputFileStream = new FileStream(outputFilePath, FileMode.Create))
+                using (ICryptoTransform encryptor = aes.CreateEncryptor())
+                using (CryptoStream cryptoStream = new CryptoStream(outputFileStream, encryptor, CryptoStreamMode.Write))
+                using (FileStream inputFileStream = new FileStream(inputFilePath, FileMode.Open))
+                {
+                    inputFileStream.CopyTo(cryptoStream);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 瑙e瘑鏂囦欢
+        /// </summary>
+        /// <param name="inputFilePath"></param>
+        /// <param name="outputFilePath"></param>
+        /// <param name="key"></param>
+        /// <param name="iv"></param>
+        public static void DecryptFile(string inputFilePath, string outputFilePath, string key = "", string iv = "")
+        {
+            using (Aes aes = Aes.Create())
+            {
+                if (key != "")
+                {
+                    aes.Key = Convert.FromBase64String(key);
+                    aes.IV = Convert.FromBase64String(iv);
+                }
+                else
+                {
+                    aes.Key = new byte[32];
+                    aes.IV = new byte[16];
+                }
+
+                using (FileStream inputFileStream = new FileStream(inputFilePath, FileMode.Open))
+                using (ICryptoTransform decryptor = aes.CreateDecryptor())
+                using (CryptoStream cryptoStream = new CryptoStream(inputFileStream, decryptor, CryptoStreamMode.Read))
+                using (FileStream outputFileStream = new FileStream(outputFilePath, FileMode.Create))
+                {
+                    cryptoStream.CopyTo(outputFileStream);
+                }
+            }
+        }
+
+        #region 鍔犲瘑鐙�
+        private const string DOG_AES_SALT = "MYAPP_KEY_SALT";
+        private const string DOG_AES_KEY = "MYAPP_AES_KEY";
+        private const string DOG_AES_IV = "MYAPP_AES_IV";
+        private const string REGISTRY_PATH = @"SOFTWARE\MyApp\SoftDog";
+
+        private static bool SetRegistryValue(RegistryKey baseKey, string valueName, string value)
+        {
+            try
+            {
+                using (RegistryKey key = baseKey.CreateSubKey(REGISTRY_PATH, RegistryKeyPermissionCheck.ReadWriteSubTree))
+                {
+                    if (key != null)
+                    {
+                        key.SetValue(valueName, value, RegistryValueKind.String);
+                        return true;
+                    }
+                }
+            }
+            catch (SecurityException)
+            {
+                // 鏉冮檺涓嶈冻锛屾甯告儏鍐�
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"璁剧疆娉ㄥ唽琛ㄥ�煎け璐�: {ex.Message}");
+            }
+
+            return false;
+        }
+
+        private static string GetRegistryValue(string valueName)
+        {
+            // 鍏堝皾璇旽KLM
+            string value = GetRegistryValue(Registry.LocalMachine, valueName);
+            if (!string.IsNullOrEmpty(value))
+                return value;
+
+            // 鍐嶅皾璇旽KCU
+            return GetRegistryValue(Registry.CurrentUser, valueName);
+        }
+
+        private static string GetRegistryValue(RegistryKey baseKey, string valueName)
+        {
+            try
+            {
+                using (RegistryKey key = baseKey.OpenSubKey(REGISTRY_PATH, false))
+                {
+                    return key?.GetValue(valueName) as string;
+                }
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇AES鍔犲瘑鍙傛暟
+        /// </summary>
+        public static (byte[] Key, byte[] IV) GetAesParameters()
+        {
+            try
+            {
+                string keyBase64 = GetRegistryValue(DOG_AES_KEY);
+                string ivBase64 = GetRegistryValue(DOG_AES_IV);
+
+                // 濡傛灉绯荤粺绾ф病鏈夛紝灏濊瘯鐢ㄦ埛绾�
+
+                if (!string.IsNullOrEmpty(keyBase64) && !string.IsNullOrEmpty(ivBase64))
+                {
+                    byte[] key = Convert.FromBase64String(keyBase64);
+                    byte[] iv = Convert.FromBase64String(ivBase64);
+
+                    return (key, iv);
+                }
+
+                return (null, null);
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"鑾峰彇AES鍙傛暟澶辫触: {ex.Message}");
+                return (null, null);
+            }
+        }
+
+        /// <summary>
+        /// 楠岃瘉鍔犲瘑鐙�
+        /// </summary>
+        public static bool ValidateAesDog()
+        {
+            var (key, iv) = GetAppBoundKey("VisionUltra");
+
+            if (key == null || iv == null)
+                return false;
+
+            // 楠岃瘉瀵嗛挜鍜孖V鐨勬牸寮忓拰闀垮害
+            return key.Length == 32 && iv.Length == 16; // AES-256: 32瀛楄妭瀵嗛挜, 16瀛楄妭IV
+        }
+
+        /// <summary>
+        /// 鐢熸垚涓庡簲鐢ㄧ粦瀹氱殑AES鍔犲瘑鐙�
+        /// </summary>
+        public static bool GenerateAppBoundDog(string appIdentifier)
+        {
+            try
+            {
+                using (Aes aes = Aes.Create())
+                {
+                    aes.GenerateKey();
+                    aes.GenerateIV();
+
+                    // 浣跨敤搴旂敤鏍囪瘑绗︿綔涓虹洂鍊�
+                    byte[] salt = Encoding.UTF8.GetBytes(appIdentifier);
+
+                    // 鍔犲瘑瀵嗛挜鏈韩锛堝彲閫夌殑瀹夊叏澧炲己锛�
+                    byte[] encryptedKey = EncryptKeyWithSalt(aes.Key, salt, aes.IV);
+
+                    // 瀛樺偍鍔犲瘑鍚庣殑瀵嗛挜鍜岀洂鍊�
+                    string encryptedKeyBase64 = Convert.ToBase64String(encryptedKey);
+                    string saltBase64 = Convert.ToBase64String(salt);
+                    string ivBase64 = Convert.ToBase64String(aes.IV);
+
+                    bool success = SetRegistryValue(Registry.CurrentUser, DOG_AES_KEY, encryptedKeyBase64);
+                    success &= SetRegistryValue(Registry.CurrentUser, DOG_AES_SALT, saltBase64);
+                    success &= SetRegistryValue(Registry.CurrentUser, DOG_AES_IV, ivBase64);
+
+                    return success;
+                }
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"鐢熸垚搴旂敤缁戝畾鍔犲瘑鐙楀け璐�: {ex.Message}");
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// 楠岃瘉骞惰幏鍙栧簲鐢ㄧ粦瀹氬瘑閽�
+        /// </summary>
+        public static (byte[] Key, byte[] IV) GetAppBoundKey(string expectedAppIdentifier)
+        {
+            try
+            {
+                string encryptedKeyBase64 = GetRegistryValue(DOG_AES_KEY);
+                string saltBase64 = GetRegistryValue(DOG_AES_SALT);
+                string ivBase64 = GetRegistryValue(DOG_AES_IV);
+
+                if (string.IsNullOrEmpty(encryptedKeyBase64) || string.IsNullOrEmpty(saltBase64) || string.IsNullOrEmpty(ivBase64))
+                {
+                    return (null, null);
+                }
+
+                byte[] encryptedKey = Convert.FromBase64String(encryptedKeyBase64);
+                byte[] salt = Convert.FromBase64String(saltBase64);
+                byte[] iv = Convert.FromBase64String(ivBase64);
+
+                // 楠岃瘉搴旂敤鏍囪瘑绗�
+                string storedAppIdentifier = Encoding.UTF8.GetString(salt);
+                if (storedAppIdentifier != expectedAppIdentifier)
+                {
+                    return (null, null);
+                }
+
+                // 瑙e瘑瀵嗛挜
+                byte[] key = DecryptKeyWithSalt(encryptedKey, salt, iv);
+
+                return (key, iv);
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"鑾峰彇搴旂敤缁戝畾瀵嗛挜澶辫触: {ex.Message}");
+                return (null, null);
+            }
+        }
+
+        private static byte[] EncryptKeyWithSalt(byte[] key, byte[] salt, byte[] iv)
+        {
+            using (var deriveBytes = new Rfc2898DeriveBytes(key, salt, 10000, HashAlgorithmName.SHA256))
+            {
+                byte[] derivedKey = deriveBytes.GetBytes(32); // AES-256
+                                                              // 杩欓噷鍙互娣诲姞棰濆鐨勫姞瀵嗛�昏緫
+                return derivedKey;
+            }
+        }
+
+        private static byte[] DecryptKeyWithSalt(byte[] encryptedKey, byte[] salt, byte[] iv)
+        {
+            // 鍙嶅悜瑙e瘑杩囩▼
+            using (var deriveBytes = new Rfc2898DeriveBytes(encryptedKey, salt, 10000, HashAlgorithmName.SHA256))
+            {
+                return deriveBytes.GetBytes(32);
+            }
+        }
+
+        /// <summary>
+        /// 浣跨敤鍔犲瘑鐙椾腑鐨勫瘑閽ュ姞瀵嗘暟鎹�
+        /// </summary>
+        public static string EncryptWithDog(string plainText)
+        {
+            var (key, iv) = GetAesParameters();
+
+            if (key == null || iv == null)
+                throw new InvalidOperationException("鏈壘鍒版湁鏁堢殑鍔犲瘑鐙�");
+
+            using (Aes aes = Aes.Create())
+            {
+                aes.Key = key;
+                aes.IV = iv;
+
+                ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
+
+                using (var ms = new MemoryStream())
+                using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
+                {
+                    using (var sw = new StreamWriter(cs))
+                    {
+                        sw.Write(plainText);
+                    }
+                    return Convert.ToBase64String(ms.ToArray());
+                }
+            }
+        }
+
+        /// <summary>
+        /// 浣跨敤鍔犲瘑鐙椾腑鐨勫瘑閽ヨВ瀵嗘暟鎹�
+        /// </summary>
+        public static string DecryptWithDog(string cipherText)
+        {
+            var (key, iv) = GetAesParameters();
+
+            if (key == null || iv == null)
+                throw new InvalidOperationException("鏈壘鍒版湁鏁堢殑鍔犲瘑鐙�");
+
+            using (Aes aes = Aes.Create())
+            {
+                aes.Key = key;
+                aes.IV = iv;
+
+                ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
+
+                byte[] cipherBytes = Convert.FromBase64String(cipherText);
+
+                using (var ms = new MemoryStream(cipherBytes))
+                using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
+                using (var sr = new StreamReader(cs))
+                {
+                    return sr.ReadToEnd();
+                }
+            }
+        }
+
+        /// <summary>
+        /// 娉ㄥ唽鍔犲瘑鐙�
+        /// </summary>
+        public static bool RegistrationDog()
+        {
+            Debug.WriteLine("姝e湪鐢熸垚AES鍔犲瘑鐙�...");
+
+            if (GenerateAppBoundDog("VisionUltra"))
+            {
+                Debug.WriteLine("AES鍔犲瘑鐙楃敓鎴愭垚鍔燂紒");
+
+                // 寤鸿鐢ㄦ埛澶囦唤杩欎簺鍊�
+                Debug.WriteLine("\n璇峰Ε鍠勪繚瀛樹互涓婂瘑閽ヤ俊鎭紒");
+                return true;
+            }
+            else
+            {
+                Debug.WriteLine("鍔犲瘑鐙楃敓鎴愬け璐ワ紝璇蜂互绠$悊鍛樿韩浠借繍琛�");
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// 妫�鏌ヨ蒋鍔犲瘑鐙�
+        /// </summary>
+        /// <returns></returns>
+        public static bool CheckDog()
+        {
+            if (!ValidateAesDog())
+            {
+                Debug.WriteLine("鏈壘鍒版湁鏁堢殑AES鍔犲瘑鐙�");
+
+                return false;
+            }
+
+            Debug.WriteLine("AES鍔犲瘑鐙楅獙璇佹垚鍔�");
+            return true;
+        }
+
+
+
+        #endregion
+
+        /// <summary>
+        /// 澶嶅埗鏂囦欢澶瑰強鍏跺唴瀹�
+        /// </summary>
+        /// <param name="sourceDir"></param>
+        /// <param name="destDir"></param>
+        /// <returns></returns>
+        public static bool CopyDirectory(string sourceDir, string destDir)
+        {
+            try
+            {
+                // 妫�鏌ョ洰鏍囨枃浠跺す鏄惁瀛樺湪锛屽鏋滀笉瀛樺湪锛屽垯鍒涘缓瀹�
+                if (!Directory.Exists(destDir))
+                {
+                    Directory.CreateDirectory(destDir);
+                }
+
+                // 澶嶅埗鎵�鏈夋枃浠跺埌鐩爣鏂囦欢澶�
+                foreach (string file in Directory.GetFiles(sourceDir))
+                {
+                    string destFile = Path.Combine(destDir, Path.GetFileName(file));
+                    File.Copy(file, destFile, true); // 绗笁涓弬鏁颁负 true锛岃〃绀哄鏋滄枃浠跺凡瀛樺湪锛屽垯瑕嗙洊瀹�
+                }
+
+                // 閫掑綊澶嶅埗鎵�鏈夊瓙鏂囦欢澶�
+                foreach (string subDir in Directory.GetDirectories(sourceDir))
+                {
+                    string destSubDir = Path.Combine(destDir, Path.GetFileName(subDir));
+                    CopyDirectory(subDir, destSubDir); // 閫掑綊璋冪敤澶嶅埗瀛愭枃浠跺す
+                }
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 閲嶅懡鍚嶆枃浠跺す
+        /// </summary>
+        /// <param name="oldDir"></param>
+        /// <param name="newDir"></param>
+        /// <returns></returns>
+        public static bool RenameDirectory(string oldDir, string newDir)
+        {
+            try
+            {
+                // 閲嶅懡鍚嶆枃浠跺す
+                if (Directory.Exists(oldDir))
+                {
+                    Directory.Move(oldDir, newDir);
+                    return true;
+                }
+                Debug.WriteLine($"鏂囦欢涓嶅瓨鍦�: {oldDir}");
+                return false;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 閲嶅懡鍚嶆枃浠�
+        /// </summary>
+        /// <param name="oldFile"></param>
+        /// <param name="newFile"></param>
+        /// <returns></returns>
+        public static bool RenameFile(string oldFile, string newFile)
+        {
+            try
+            {
+                if (!File.Exists(newFile))
+                {
+                    // 閲嶅懡鍚嶆枃浠�
+                    File.Move(oldFile, newFile);
+                    Debug.WriteLine($"鏂囦欢宸查噸鍛藉悕: {oldFile} -> {newFile}");
+                    return true;
+                }
+
+                Debug.WriteLine($"鏂囦欢涓嶅瓨鍦�: {oldFile}");
+                return false;
+            }
+            catch { return false; }
+        }
+
+        #region 璇诲啓鍒癳xe.Config鏂囦欢
+        public static void WriteConfig(string node, string value)
+        {
+            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
+            if (config.AppSettings.Settings[node] == null)
+            {
+                config.AppSettings.Settings.Add(node, value);
+            }
+            else
+            {
+                config.AppSettings.Settings[node].Value = value;
+            }
+            config.Save(ConfigurationSaveMode.Modified);
+            ConfigurationManager.RefreshSection("appSettings");//閲嶆柊鍔犺浇鏂扮殑閰嶇疆鏂囦欢   
+        }
+        public static bool ReadStringConfig(string node, out string result)
+        {
+            result = "";
+            try
+            {
+                if (ConfigurationManager.AppSettings[node] != null)
+                {
+                    result = ConfigurationManager.AppSettings[node].ToString();
+                    if (result == null)
+                    {
+                        WriteConfig(node, "");
+                        result = "";
+                        return false;
+
+                    }
+                    else
+                    {
+                        return true;
+                    }
+                }
+                else
+                {
+                    return false;
+                }
+
+            }
+            catch
+            {
+                WriteConfig(node, "");
+                result = "";
+                return false;
+            }
+        }
+
+        public static bool ReadBoolenConfig(string node, out bool result)
+        {
+            result = false;
+            try
+            {
+                result = Convert.ToBoolean(ConfigurationManager.AppSettings[node]);
+                if (result == null)
+                {
+                    WriteConfig(node, (false).ToString());
+                    result = false;
+                    return false;
+
+                }
+                else
+                    return true;
+            }
+            catch
+            {
+                WriteConfig(node, (false).ToString());
+                result = false;
+                return false;
+            }
+        }
+        #endregion
+    }
+}
+
+
diff --git a/LB_SmartVision/VisionForm.Designer.cs b/LB_SmartVision/VisionForm.Designer.cs
new file mode 100644
index 0000000..218c68b
--- /dev/null
+++ b/LB_SmartVision/VisionForm.Designer.cs
@@ -0,0 +1,369 @@
+锘縩amespace LB_SmartVision
+{
+    partial class VisionForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(VisionForm));
+            theme_VisionForm = new ReaLTaiizor.Forms.ThemeForm();
+            sc_VisionForm = new SplitContainer();
+            sc_VisionMainViewer = new SplitContainer();
+            tlp_VisionMainForm = new Sunny.UI.UITableLayoutPanel();
+            tlp_VisionMainOperator = new Sunny.UI.UITableLayoutPanel();
+            ckb_AllowRun = new Sunny.UI.UICheckBox();
+            btn_Login = new ReaLTaiizor.Controls.Button();
+            btn_GlobalVar = new ReaLTaiizor.Controls.Button();
+            com_ProductName = new ReaLTaiizor.Controls.AloneComboBox();
+            materialTabSelector = new MaterialSkin.Controls.MaterialTabSelector();
+            materialTabControl = new MaterialSkin.Controls.MaterialTabControl();
+            tabPage1 = new TabPage();
+            tabPage2 = new TabPage();
+            grb_Info = new Sunny.UI.UIGroupBox();
+            rich_Info = new Sunny.UI.UIRichTextBox();
+            cb_VisionForm = new ReaLTaiizor.Controls.ControlBox();
+            theme_VisionForm.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)sc_VisionForm).BeginInit();
+            sc_VisionForm.Panel1.SuspendLayout();
+            sc_VisionForm.Panel2.SuspendLayout();
+            sc_VisionForm.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)sc_VisionMainViewer).BeginInit();
+            sc_VisionMainViewer.Panel1.SuspendLayout();
+            sc_VisionMainViewer.Panel2.SuspendLayout();
+            sc_VisionMainViewer.SuspendLayout();
+            tlp_VisionMainForm.SuspendLayout();
+            tlp_VisionMainOperator.SuspendLayout();
+            materialTabControl.SuspendLayout();
+            grb_Info.SuspendLayout();
+            SuspendLayout();
+            // 
+            // theme_VisionForm
+            // 
+            theme_VisionForm.BackColor = Color.FromArgb(32, 41, 50);
+            theme_VisionForm.Controls.Add(sc_VisionForm);
+            theme_VisionForm.Controls.Add(cb_VisionForm);
+            theme_VisionForm.Dock = DockStyle.Fill;
+            theme_VisionForm.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            theme_VisionForm.Image = (Image)resources.GetObject("theme_VisionForm.Image");
+            theme_VisionForm.Location = new Point(0, 0);
+            theme_VisionForm.Name = "theme_VisionForm";
+            theme_VisionForm.Padding = new Padding(10, 70, 10, 9);
+            theme_VisionForm.RoundCorners = true;
+            theme_VisionForm.Sizable = true;
+            theme_VisionForm.Size = new Size(1440, 960);
+            theme_VisionForm.SmartBounds = true;
+            theme_VisionForm.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            theme_VisionForm.TabIndex = 0;
+            theme_VisionForm.Text = "杞儙澶栬瑙嗚妫�娴嬬郴缁�";
+            // 
+            // sc_VisionForm
+            // 
+            sc_VisionForm.Dock = DockStyle.Fill;
+            sc_VisionForm.Location = new Point(10, 70);
+            sc_VisionForm.Name = "sc_VisionForm";
+            sc_VisionForm.Orientation = Orientation.Horizontal;
+            // 
+            // sc_VisionForm.Panel1
+            // 
+            sc_VisionForm.Panel1.Controls.Add(sc_VisionMainViewer);
+            // 
+            // sc_VisionForm.Panel2
+            // 
+            sc_VisionForm.Panel2.Controls.Add(grb_Info);
+            sc_VisionForm.Size = new Size(1420, 881);
+            sc_VisionForm.SplitterDistance = 699;
+            sc_VisionForm.TabIndex = 1;
+            // 
+            // sc_VisionMainViewer
+            // 
+            sc_VisionMainViewer.Dock = DockStyle.Fill;
+            sc_VisionMainViewer.Location = new Point(0, 0);
+            sc_VisionMainViewer.Name = "sc_VisionMainViewer";
+            sc_VisionMainViewer.Orientation = Orientation.Horizontal;
+            // 
+            // sc_VisionMainViewer.Panel1
+            // 
+            sc_VisionMainViewer.Panel1.Controls.Add(tlp_VisionMainForm);
+            // 
+            // sc_VisionMainViewer.Panel2
+            // 
+            sc_VisionMainViewer.Panel2.Controls.Add(materialTabControl);
+            sc_VisionMainViewer.Size = new Size(1420, 699);
+            sc_VisionMainViewer.SplitterDistance = 100;
+            sc_VisionMainViewer.TabIndex = 0;
+            // 
+            // tlp_VisionMainForm
+            // 
+            tlp_VisionMainForm.BackColor = Color.FromArgb(39, 51, 63);
+            tlp_VisionMainForm.ColumnCount = 1;
+            tlp_VisionMainForm.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tlp_VisionMainForm.Controls.Add(tlp_VisionMainOperator, 0, 1);
+            tlp_VisionMainForm.Controls.Add(materialTabSelector, 0, 0);
+            tlp_VisionMainForm.Dock = DockStyle.Fill;
+            tlp_VisionMainForm.Location = new Point(0, 0);
+            tlp_VisionMainForm.Name = "tlp_VisionMainForm";
+            tlp_VisionMainForm.RowCount = 2;
+            tlp_VisionMainForm.RowStyles.Add(new RowStyle(SizeType.Absolute, 61F));
+            tlp_VisionMainForm.RowStyles.Add(new RowStyle(SizeType.Absolute, 39F));
+            tlp_VisionMainForm.Size = new Size(1420, 100);
+            tlp_VisionMainForm.TabIndex = 0;
+            tlp_VisionMainForm.TagString = null;
+            // 
+            // tlp_VisionMainOperator
+            // 
+            tlp_VisionMainOperator.BackColor = Color.FromArgb(39, 51, 63);
+            tlp_VisionMainOperator.ColumnCount = 9;
+            tlp_VisionMainOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11.11111F));
+            tlp_VisionMainOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11.1111107F));
+            tlp_VisionMainOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11.1111107F));
+            tlp_VisionMainOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11.1111107F));
+            tlp_VisionMainOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11.1111107F));
+            tlp_VisionMainOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11.1111107F));
+            tlp_VisionMainOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11.1111107F));
+            tlp_VisionMainOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11.1111107F));
+            tlp_VisionMainOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 11.1111107F));
+            tlp_VisionMainOperator.Controls.Add(ckb_AllowRun, 0, 0);
+            tlp_VisionMainOperator.Controls.Add(btn_Login, 1, 0);
+            tlp_VisionMainOperator.Controls.Add(btn_GlobalVar, 7, 0);
+            tlp_VisionMainOperator.Controls.Add(com_ProductName, 8, 0);
+            tlp_VisionMainOperator.Dock = DockStyle.Fill;
+            tlp_VisionMainOperator.Location = new Point(3, 64);
+            tlp_VisionMainOperator.Name = "tlp_VisionMainOperator";
+            tlp_VisionMainOperator.RowCount = 1;
+            tlp_VisionMainOperator.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tlp_VisionMainOperator.Size = new Size(1414, 33);
+            tlp_VisionMainOperator.TabIndex = 0;
+            tlp_VisionMainOperator.TagString = null;
+            // 
+            // ckb_AllowRun
+            // 
+            ckb_AllowRun.Dock = DockStyle.Fill;
+            ckb_AllowRun.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            ckb_AllowRun.ForeColor = SystemColors.Control;
+            ckb_AllowRun.Location = new Point(3, 3);
+            ckb_AllowRun.MinimumSize = new Size(1, 1);
+            ckb_AllowRun.Name = "ckb_AllowRun";
+            ckb_AllowRun.Size = new Size(151, 27);
+            ckb_AllowRun.TabIndex = 2;
+            ckb_AllowRun.Text = "杩愯妯″紡";
+            // 
+            // btn_Login
+            // 
+            btn_Login.BackColor = Color.Transparent;
+            btn_Login.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_Login.Dock = DockStyle.Fill;
+            btn_Login.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Login.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_Login.Font = new Font("Microsoft Sans Serif", 12F);
+            btn_Login.Image = null;
+            btn_Login.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_Login.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_Login.Location = new Point(160, 3);
+            btn_Login.Name = "btn_Login";
+            btn_Login.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Login.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_Login.Size = new Size(151, 27);
+            btn_Login.TabIndex = 3;
+            btn_Login.Text = "鐢ㄦ埛鐧诲綍";
+            btn_Login.TextAlignment = StringAlignment.Center;
+            // 
+            // btn_GlobalVar
+            // 
+            btn_GlobalVar.BackColor = Color.Gray;
+            btn_GlobalVar.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_GlobalVar.Dock = DockStyle.Fill;
+            btn_GlobalVar.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_GlobalVar.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_GlobalVar.Font = new Font("Microsoft Sans Serif", 12F);
+            btn_GlobalVar.Image = null;
+            btn_GlobalVar.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_GlobalVar.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_GlobalVar.Location = new Point(1102, 3);
+            btn_GlobalVar.Name = "btn_GlobalVar";
+            btn_GlobalVar.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_GlobalVar.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_GlobalVar.Size = new Size(151, 27);
+            btn_GlobalVar.TabIndex = 4;
+            btn_GlobalVar.Text = "鍏ㄥ眬鍙橀噺";
+            btn_GlobalVar.TextAlignment = StringAlignment.Center;
+            // 
+            // com_ProductName
+            // 
+            com_ProductName.Dock = DockStyle.Fill;
+            com_ProductName.DrawMode = DrawMode.OwnerDrawFixed;
+            com_ProductName.DropDownStyle = ComboBoxStyle.DropDownList;
+            com_ProductName.EnabledCalc = true;
+            com_ProductName.FormattingEnabled = true;
+            com_ProductName.ItemHeight = 20;
+            com_ProductName.Location = new Point(1259, 3);
+            com_ProductName.Name = "com_ProductName";
+            com_ProductName.Size = new Size(152, 26);
+            com_ProductName.TabIndex = 5;
+            // 
+            // materialTabSelector
+            // 
+            materialTabSelector.BaseTabControl = materialTabControl;
+            materialTabSelector.Depth = 0;
+            materialTabSelector.Dock = DockStyle.Fill;
+            materialTabSelector.Location = new Point(3, 3);
+            materialTabSelector.MouseState = MaterialSkin.MouseState.HOVER;
+            materialTabSelector.Name = "materialTabSelector";
+            materialTabSelector.Size = new Size(1414, 55);
+            materialTabSelector.TabIndex = 1;
+            // 
+            // materialTabControl
+            // 
+            materialTabControl.AccessibleRole = AccessibleRole.Sound;
+            materialTabControl.Controls.Add(tabPage1);
+            materialTabControl.Controls.Add(tabPage2);
+            materialTabControl.Depth = 0;
+            materialTabControl.Dock = DockStyle.Fill;
+            materialTabControl.Location = new Point(0, 0);
+            materialTabControl.MouseState = MaterialSkin.MouseState.HOVER;
+            materialTabControl.Name = "materialTabControl";
+            materialTabControl.SelectedIndex = 0;
+            materialTabControl.Size = new Size(1420, 595);
+            materialTabControl.TabIndex = 0;
+            // 
+            // tabPage1
+            // 
+            tabPage1.Font = new Font("Microsoft YaHei UI", 9F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            tabPage1.Location = new Point(4, 30);
+            tabPage1.Name = "tabPage1";
+            tabPage1.Size = new Size(1412, 561);
+            tabPage1.TabIndex = 0;
+            tabPage1.Text = "tabPage1";
+            tabPage1.UseVisualStyleBackColor = true;
+            // 
+            // tabPage2
+            // 
+            tabPage2.Font = new Font("Microsoft YaHei UI", 9F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            tabPage2.Location = new Point(4, 26);
+            tabPage2.Name = "tabPage2";
+            tabPage2.Size = new Size(1412, 565);
+            tabPage2.TabIndex = 1;
+            tabPage2.Text = "tabPage2";
+            tabPage2.UseVisualStyleBackColor = true;
+            // 
+            // grb_Info
+            // 
+            grb_Info.Controls.Add(rich_Info);
+            grb_Info.Dock = DockStyle.Fill;
+            grb_Info.FillColor = Color.FromArgb(32, 41, 50);
+            grb_Info.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            grb_Info.ForeColor = SystemColors.Control;
+            grb_Info.Location = new Point(0, 0);
+            grb_Info.Margin = new Padding(4, 5, 4, 5);
+            grb_Info.MinimumSize = new Size(1, 1);
+            grb_Info.Name = "grb_Info";
+            grb_Info.Padding = new Padding(0, 32, 0, 0);
+            grb_Info.Size = new Size(1420, 178);
+            grb_Info.TabIndex = 1;
+            grb_Info.Text = "鏃ュ織鏄剧ず鍖猴細";
+            grb_Info.TextAlignment = ContentAlignment.MiddleLeft;
+            // 
+            // rich_Info
+            // 
+            rich_Info.Dock = DockStyle.Fill;
+            rich_Info.FillColor = Color.FromArgb(32, 41, 50);
+            rich_Info.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            rich_Info.Location = new Point(0, 32);
+            rich_Info.Margin = new Padding(4, 5, 4, 5);
+            rich_Info.MinimumSize = new Size(1, 1);
+            rich_Info.Name = "rich_Info";
+            rich_Info.Padding = new Padding(2);
+            rich_Info.ShowText = false;
+            rich_Info.Size = new Size(1420, 146);
+            rich_Info.TabIndex = 0;
+            rich_Info.TextAlignment = ContentAlignment.MiddleLeft;
+            // 
+            // cb_VisionForm
+            // 
+            cb_VisionForm.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            cb_VisionForm.BackColor = Color.FromArgb(32, 34, 37);
+            cb_VisionForm.CloseHoverColor = Color.FromArgb(230, 17, 35);
+            cb_VisionForm.DefaultLocation = true;
+            cb_VisionForm.EnableHoverHighlight = true;
+            cb_VisionForm.EnableMaximizeButton = true;
+            cb_VisionForm.EnableMinimizeButton = true;
+            cb_VisionForm.ForeColor = Color.FromArgb(155, 155, 155);
+            cb_VisionForm.Location = new Point(1340, 18);
+            cb_VisionForm.MaximizeHoverColor = Color.FromArgb(74, 74, 74);
+            cb_VisionForm.MinimizeHoverColor = Color.FromArgb(63, 63, 65);
+            cb_VisionForm.Name = "cb_VisionForm";
+            cb_VisionForm.Size = new Size(90, 25);
+            cb_VisionForm.TabIndex = 0;
+            cb_VisionForm.Text = "controlBox1";
+            // 
+            // VisionForm
+            // 
+            AutoScaleDimensions = new SizeF(96F, 96F);
+            AutoScaleMode = AutoScaleMode.Dpi;
+            ClientSize = new Size(1440, 960);
+            Controls.Add(theme_VisionForm);
+            FormBorderStyle = FormBorderStyle.None;
+            Icon = (Icon)resources.GetObject("$this.Icon");
+            MinimumSize = new Size(261, 61);
+            Name = "VisionForm";
+            Text = "杞儙澶栬瑙嗚妫�娴嬬郴缁�";
+            TransparencyKey = Color.Fuchsia;
+            Load += VisionForm_Load;
+            theme_VisionForm.ResumeLayout(false);
+            sc_VisionForm.Panel1.ResumeLayout(false);
+            sc_VisionForm.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)sc_VisionForm).EndInit();
+            sc_VisionForm.ResumeLayout(false);
+            sc_VisionMainViewer.Panel1.ResumeLayout(false);
+            sc_VisionMainViewer.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)sc_VisionMainViewer).EndInit();
+            sc_VisionMainViewer.ResumeLayout(false);
+            tlp_VisionMainForm.ResumeLayout(false);
+            tlp_VisionMainOperator.ResumeLayout(false);
+            materialTabControl.ResumeLayout(false);
+            grb_Info.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ReaLTaiizor.Forms.ThemeForm theme_VisionForm;
+        private ReaLTaiizor.Controls.ControlBox cb_VisionForm;
+        private SplitContainer sc_VisionForm;
+        private SplitContainer sc_VisionMainViewer;
+        private Sunny.UI.UITableLayoutPanel tlp_VisionMainOperator;
+        private Sunny.UI.UICheckBox ckb_AllowRun;
+        private ReaLTaiizor.Controls.Button btn_Login;
+        private ReaLTaiizor.Controls.Button btn_GlobalVar;
+        private Sunny.UI.UITableLayoutPanel tlp_VisionMainForm;
+        private Sunny.UI.UIGroupBox grb_Info;
+        private Sunny.UI.UIRichTextBox rich_Info;
+        private MaterialSkin.Controls.MaterialTabControl materialTabControl;
+        private ReaLTaiizor.Controls.AloneComboBox com_ProductName;
+        private MaterialSkin.Controls.MaterialTabSelector materialTabSelector;
+        private TabPage tabPage1;
+        private TabPage tabPage2;
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVision/VisionForm.cs b/LB_SmartVision/VisionForm.cs
new file mode 100644
index 0000000..7d8803e
--- /dev/null
+++ b/LB_SmartVision/VisionForm.cs
@@ -0,0 +1,997 @@
+锘縰sing HalconDotNet;
+using LB_SmartVision.Forms.Pages;
+using LB_SmartVision.Forms.Pages.CameraPage;
+using LB_SmartVision.Forms.Pages.CommunicatorPage;
+using LB_SmartVision.Forms.Pages.MESPage;
+using LB_SmartVision.Forms.Pages.MotionControlPage;
+using LB_SmartVision.Forms.Pages.ProcessPage;
+using LB_SmartVision.Forms.Pages.SettingPage;
+using LB_SmartVision.Forms.Pages.UserManagementPage;
+using LB_SmartVision.ProcessRun;
+using LB_SmartVision.Tool;
+using LB_VisionProcesses;
+using LB_VisionProcesses.Cameras;
+using LB_VisionProcesses.Communicators;
+using LB_VisionProcesses.Communicators.TCom;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using Sunny.UI;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVision
+{
+    public partial class VisionForm : Form
+    {
+        AllProcessesPage AllProcessesPage = new AllProcessesPage();
+        CamerasEditPage CamerasEditPage = new CamerasEditPage();
+        CommunicatorsEditPage CommunicatorsEditPage = new CommunicatorsEditPage();
+        SettingEditPage SettingEditPage = new SettingEditPage();
+        MESEditPage MESEditPage = new MESEditPage();
+        MotionControlEditPage MotionControlEditPage = new MotionControlEditPage();
+        UserManagementEditPage UserManagementEditPage = new UserManagementEditPage();
+
+        byte[] Assembly_LB_VisionProcessesBytes = File.ReadAllBytes("LB_VisionProcesses.dll");
+        /// <summary>
+        /// 鐢ㄤ簬鍙嶅簭鍒楀寲鐨勭▼搴忛泦寮曠敤
+        /// </summary>
+        Assembly Assembly_LB_VisionProcessesDll = null;
+
+
+        public VisionForm()
+        {
+            InitializeComponent();
+            HOperatorSet.SetWindowAttr("background_color", "gray");
+            Assembly_LB_VisionProcessesDll = Assembly.Load(Assembly_LB_VisionProcessesBytes);
+
+            GlobalVar.dicCommunicators.DictionaryChanged += CommunicatorsChanged;
+            GlobalVar.dicProcesses.DictionaryChanged += ProcessRunBllChanged;
+
+            //鏈�寮�濮嬪氨娓呯┖鎵�鏈塗ab椤�
+            materialTabControl.TabPages.Clear();
+            materialTabControl.Controls.Add(AllProcessesPage);
+
+            CamerasEditPage.LogInfo += LogInfo;
+            materialTabControl.Controls.Add(new MyPage(CamerasEditPage));
+
+            CommunicatorsEditPage.LogInfo += LogInfo;
+            materialTabControl.Controls.Add(new MyPage(CommunicatorsEditPage));
+
+            SettingEditPage.LogInfo += LogInfo;
+            materialTabControl.Controls.Add(new MyPage(SettingEditPage));
+
+            MESEditPage.LogInfo += LogInfo;
+            materialTabControl.Controls.Add(new MyPage(MESEditPage));
+
+            MotionControlEditPage.LogInfo += LogInfo;
+            materialTabControl.Controls.Add(new MyPage(MotionControlEditPage));
+
+            UserManagementEditPage.LogInfo += LogInfo;
+            materialTabControl.Controls.Add(new MyPage(UserManagementEditPage));
+
+            for (int i = 0; i < materialTabControl.TabPages.Count; i++)
+            {
+                //materialTabControl.TabPages[i].Font= new Font("Microsoft YaHei UI", 18F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            }
+
+            materialTabSelector.BaseTabControl = materialTabControl;
+            //materialTabSelector.Font = new Font("Microsoft YaHei UI", 18F, FontStyle.Regular, GraphicsUnit.Point, 0);
+        }
+
+        private void ProcessRunBllChanged(object? sender, DictionaryChangedEventArgs<string, ProcessRunBll> e)
+        {
+            try
+            {
+                string msg = string.Empty;
+                List<MyPage> removeMyPage = new List<MyPage>();
+                switch (e.ChangeType)
+                {
+                    case DictionaryChangeType.Added:
+                        string AddProcessName = e.NewKey;
+                        GlobalVar.dicProcesses[AddProcessName].LogInfo += LogInfo;
+                        if (GlobalVar.dicProcesses[AddProcessName].Load(out msg))
+                        {
+                            LogInfo($"娴佺▼[{AddProcessName}]鍔犺浇鎴愬姛", LogInfoType.PASS);
+                            IProcess.dicGlobalVars.TryAdd($"{AddProcessName}.Result", false);
+                            IProcess.dicGlobalVars.TryAdd($"{AddProcessName}.Msg", "");
+
+                            ProcessRunBll processRunBll = GlobalVar.dicProcesses[AddProcessName];
+                            ProcessPage ProcessPage = new ProcessPage(processRunBll.Name, processRunBll);
+                            ProcessPage.LogInfo += LogInfo;
+                            if (materialTabControl.InvokeRequired)
+                            {
+                                materialTabControl.Invoke(new Action(() =>
+                                {
+                                    materialTabControl.Controls.Add(new MyPage(ProcessPage));
+                                }));
+                            }
+                            else
+                                materialTabControl.Controls.Add(new MyPage(ProcessPage));
+                        }
+                        else
+                            LogInfo($"娴佺▼[{AddProcessName}]鍔犺浇澶辫触,鍘熷洜鏄瘂msg}", LogInfoType.ERROR);
+
+                        LogInfo($"娣诲姞娴佺▼[{AddProcessName}]", LogInfoType.INFO);
+                        break;
+                    case DictionaryChangeType.Removed:
+                        string RemoveProcessName = e.OldKey;
+                        foreach (var control in materialTabControl.Controls)
+                        {
+                            if (control != null && control is MyPage && ((MyPage)control).UserControl is ProcessPage processPage)
+                            {
+                                if (processPage.Text == RemoveProcessName)
+                                {
+                                    IProcess.dicGlobalVars.TryRemove($"{RemoveProcessName}.Result", out _);
+                                    IProcess.dicGlobalVars.TryRemove($"{RemoveProcessName}.Msg", out _);
+                                    processPage.LogInfo -= LogInfo;
+                                    removeMyPage.Add((MyPage)control);
+                                }
+                            }
+                        }
+
+                        foreach (var myPage in removeMyPage)
+                        {
+                            if (materialTabControl.InvokeRequired)
+                            {
+                                materialTabControl.Invoke(new Action(() =>
+                                {
+                                    materialTabControl.Controls.Remove(myPage);
+                                }));
+                            }
+                            else
+                                materialTabControl.Controls.Remove(myPage);
+                        }
+
+                        LogInfo($"绉婚櫎娴佺▼[{RemoveProcessName}]", LogInfoType.INFO);
+                        break;
+                    case DictionaryChangeType.Renamed:
+                        string OldProcessName = e.OldKey;
+                        string NewProcessName = e.NewKey;
+                        try
+                        {
+                            IProcess.dicGlobalVars.TryRemove($"{OldProcessName}.Result", out object obj1);
+                            IProcess.dicGlobalVars.TryAdd($"{NewProcessName}.Result", obj1);
+
+                            IProcess.dicGlobalVars.TryRemove($"{OldProcessName}.Msg", out object obj2);
+                            IProcess.dicGlobalVars.TryAdd($"{NewProcessName}.Msg", obj2);
+                        }
+                        catch { }
+
+                        LB_SmartVision.Tool.Tool.RenameDirectory(GlobalVar.allProcessPath + "\\" + OldProcessName
+                            , GlobalVar.allProcessPath + "\\" + NewProcessName);
+                        e.NewValue.Name = NewProcessName;
+
+                        foreach (var control in materialTabControl.Controls)
+                        {
+                            if (control != null && control is MyPage && ((MyPage)control).UserControl is ProcessPage)
+                            {
+                                ProcessPage processPage = ((MyPage)control).UserControl as ProcessPage;
+                                if (processPage.Text == OldProcessName)
+                                {
+                                    if (materialTabControl.InvokeRequired)
+                                    {
+                                        materialTabControl.Invoke(new Action(() =>
+                                        {
+                                            materialTabControl.Controls.Remove((MyPage)control);
+                                        }));
+                                    }
+                                    else
+                                        materialTabControl.Controls.Remove((MyPage)control);
+
+
+                                    if (GlobalVar.dicProcesses[NewProcessName].Load(out msg))
+                                    {
+                                        LogInfo($"娴佺▼[{NewProcessName}]閲嶅懡鍚嶅悗鍔犺浇鎴愬姛", LogInfoType.PASS);
+
+                                        IProcess.dicGlobalVars.TryAdd($"{NewProcessName}.Result", false);
+                                        IProcess.dicGlobalVars.TryAdd($"{NewProcessName}.Msg", "");
+
+                                        ProcessRunBll processRunBll = GlobalVar.dicProcesses[NewProcessName];
+                                        ProcessPage ProcessPage = new ProcessPage(processRunBll.Name, processRunBll);
+                                        ProcessPage.LogInfo += LogInfo;
+                                        if (materialTabControl.InvokeRequired)
+                                        {
+                                            materialTabControl.Invoke(new Action(() =>
+                                            {
+                                                materialTabControl.Controls.Add(new MyPage(ProcessPage));
+                                            }));
+                                        }
+                                        else
+                                            materialTabControl.Controls.Add(new MyPage(ProcessPage));
+                                    }
+                                    else
+                                        LogInfo($"娴佺▼[{NewProcessName}]閲嶅懡鍚嶅悗鍔犺浇澶辫触,鍘熷洜鏄瘂msg}", LogInfoType.ERROR);
+                                }
+                            }
+                        }
+
+                        LogInfo(string.Format("閲嶅懡鍚嶆祦绋嬪悕[{0}]淇敼涓篬{1}]", OldProcessName, NewProcessName), LogInfoType.INFO);
+                        break;
+                }
+            }
+            catch { }
+
+        }
+
+        private void CommunicatorsChanged(object? sender, DictionaryChangedEventArgs<string, BaseCommunicator> e)
+        {
+
+        }
+
+        private void LogInfo(string arg1, LogInfoType type)
+        {
+
+        }
+
+        public static bool SaveAllLayout()
+        {
+            try
+            {
+                string strJson = string.Empty;
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+
+                strJson = JsonConvert.SerializeObject(GlobalVar.dicLayout, settings);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                string directoryPath = Path.GetDirectoryName(GlobalVar.allLayoutPath);
+                if (!Directory.Exists(directoryPath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(directoryPath);
+                    }
+                    catch { }
+                }
+
+                File.WriteAllText(GlobalVar.allLayoutPath, strJson, Encoding.UTF8);
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public static bool LoadAllCsv(string allCsvPath)
+        {
+            try
+            {
+                if (!File.Exists(allCsvPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                    string directoryPath = Path.GetDirectoryName(allCsvPath);
+                    SaveAllCsv();
+                    return true;
+                }
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(allCsvPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+
+                GlobalVar.dicCsvSetting.Clear();
+                GlobalVar.dicCsvSetting = JsonConvert.DeserializeObject<ConcurrentDictionary<string, CsvSetting>>(strJson);
+                if (GlobalVar.dicCsvSetting == null)
+                {
+                    GlobalVar.dicCsvSetting = new ConcurrentDictionary<string, CsvSetting>();
+                    return false;
+                }
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public static bool SaveAllCsv()
+        {
+            try
+            {
+                string strJson = string.Empty;
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+
+                strJson = JsonConvert.SerializeObject(GlobalVar.dicCsvSetting, settings);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                string directoryPath = Path.GetDirectoryName(GlobalVar.allCsvPath);
+                if (!Directory.Exists(directoryPath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(directoryPath);
+                    }
+                    catch { }
+                }
+
+                File.WriteAllText(GlobalVar.allCsvPath, strJson, Encoding.UTF8);
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool LoadAllProcessSetting(string allProcessSettingStringPath)
+        {
+            try
+            {
+                if (!File.Exists(allProcessSettingStringPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                    string directoryPath = Path.GetDirectoryName(allProcessSettingStringPath);
+                    SaveAllProcessSetting();
+                    return true;
+                }
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(allProcessSettingStringPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+
+                GlobalVar.dicProcessSetting = JsonConvert.DeserializeObject<ConcurrentDictionary<int, ConcurrentDictionary<string, string>>>(strJson);
+
+                if (GlobalVar.dicProcessSetting == null)
+                    GlobalVar.dicProcessSetting = new ConcurrentDictionary<int, ConcurrentDictionary<string, string>>();
+
+                try
+                {
+                    string json = File.ReadAllText(GlobalVar.allRunSettingStringPath);
+                    var settings = new JsonSerializerSettings
+                    {
+                        TypeNameHandling = TypeNameHandling.Auto // 澶勭悊澶氭�佺被鍨�
+                    };
+
+                    GlobalVar.ControlStates = JsonConvert.DeserializeObject<Dictionary<string, object>>(json, settings);
+                }
+                catch { }
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public static bool SaveAllProcessSetting()
+        {
+            try
+            {
+                string strJson = string.Empty;
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+
+                strJson = JsonConvert.SerializeObject(GlobalVar.dicProcessSetting, settings);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                string directoryPath = Path.GetDirectoryName(GlobalVar.allProcessSettingStringPath);
+                if (!Directory.Exists(directoryPath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(directoryPath);
+                    }
+                    catch { }
+                }
+                File.WriteAllText(GlobalVar.allProcessSettingStringPath, strJson, Encoding.UTF8);
+                //LogInfo($"娴佺▼璁剧疆淇濆瓨鎴愬姛", LogInfoType.INFO);
+                return true;
+            }
+            catch { return false; }
+        }
+
+        private void VisionForm_Load(object sender, EventArgs e)
+        {
+            if (!LB_SmartVision.Tool.Tool.ReadStringConfig("鏁版嵁搴撳悕绉�", out string DateBaseName))
+            {
+                DateBaseName = "浜у搧0";
+                LB_SmartVision.Tool.Tool.WriteConfig("鏁版嵁搴撳悕绉�", DateBaseName);
+                LB_SmartVision.Tool.Tool.WriteConfig("浜у搧鍒楄〃", DateBaseName);
+            }
+            LB_SmartVision.Tool.Tool.ReadStringConfig("User ID", out string User_ID);
+            LB_SmartVision.Tool.Tool.ReadStringConfig("Password", out string Password);
+
+            GlobalVar.strProductName = DateBaseName;
+
+            //鍔犺浇閫氳
+            foreach (BaseCommunicator com in GlobalVar.dicCommunicators.Values)
+                com.Disconnect();
+            GlobalVar.dicCommunicators.Clear();
+            if (LoadAllCommunicators(GlobalVar.allCommunicatorsConnectionStringPath))
+                LogInfo("閫氳鍔犺浇鎴愬姛", LogInfoType.PASS);
+            else
+                LogInfo("閫氳鍔犺浇澶辫触", LogInfoType.ERROR);
+
+            //鍔犺浇鐩告満
+            foreach (BaseCamera camera in GlobalVar.dicCameras.Values)
+                camera.Dispose();
+            GlobalVar.dicCameras.Clear();
+            if (LoadAllCameras(GlobalVar.allCamerasConnectionStringPath))
+                LogInfo("鐩告満鍔犺浇鎴愬姛", LogInfoType.PASS);
+            else
+                LogInfo("鐩告満鍔犺浇澶辫触", LogInfoType.ERROR);
+
+            //蹇呴』鍏堝姞杞界浉鏈哄拰閫氳绔彛,鍥犱负娴佺▼鍔犺浇杩囩▼涓細鐢ㄥ埌鐩告満鍜岄�氳鍙�
+
+            //鍔犺浇鍏ㄥ眬鍙橀噺
+            IProcess.dicGlobalVars.Clear();
+            if (LoadAllProcessVars(GlobalVar.allProcessVarsPath))
+                LogInfo("鍏ㄥ眬鍙橀噺鍔犺浇鎴愬姛", LogInfoType.PASS);
+            else
+                LogInfo("鍏ㄥ眬鍙橀噺鍔犺浇澶辫触", LogInfoType.ERROR);
+
+            //鍔犺浇娴佺▼
+            GlobalVar.dicProcesses.Clear();
+            if (LoadAllProcess(GlobalVar.allProcessConnectionStringPath))
+                LogInfo("娴佺▼鍔犺浇鎴愬姛", LogInfoType.PASS);
+            else
+                LogInfo("娴佺▼鍔犺浇澶辫触", LogInfoType.ERROR);
+
+            //鍔犺浇瑙﹀彂璁剧疆
+            if (LoadAllProcessSetting(GlobalVar.allProcessSettingStringPath))
+                LogInfo("娴佺▼璁剧疆鍔犺浇鎴愬姛", LogInfoType.PASS);
+            else
+                LogInfo("娴佺▼璁剧疆鍔犺浇澶辫触", LogInfoType.ERROR);
+
+            //鍔犺浇娴佺▼甯冨眬
+            GlobalVar.dicLayout.Clear();
+            if (LoadAllLayout(GlobalVar.allLayoutPath))
+                LogInfo("娴佺▼甯冨眬鍔犺浇鎴愬姛", LogInfoType.PASS);
+            else
+                LogInfo("娴佺▼甯冨眬鍔犺浇澶辫触", LogInfoType.ERROR);
+
+            //鍔犺浇娴佺▼琛ㄦ牸
+            GlobalVar.dicCsvSetting.Clear();
+            if (LoadAllCsv(GlobalVar.allCsvPath))
+                LogInfo("娴佺▼琛ㄦ牸鍔犺浇鎴愬姛", LogInfoType.PASS);
+            else
+                LogInfo("娴佺▼琛ㄦ牸鍔犺浇澶辫触", LogInfoType.ERROR);
+
+            //鏄剧ず鎵�鏈変骇鍝�
+            com_ProductName.Items.Clear();
+            LB_SmartVision.Tool.Tool.ReadStringConfig("浜у搧鍒楄〃", out string Products);
+            List<string> lstProduct = (Products.Split(',')).ToList();
+            foreach (string DatabaseName in lstProduct)
+                com_ProductName.Items.Add(DatabaseName);
+            com_ProductName.Items.Add("鏂板");
+
+            com_ProductName.Text = GlobalVar.strProductName;
+        }
+
+        public void SaveAllSetting()
+        {
+            SaveAllProcess();
+            SaveAllProcessVars();
+            SaveAllCommunicators();
+            SaveAllCameras();
+            SaveAllProcessSetting();
+            SaveAllLayout();
+            SaveAllCsv();
+        }
+
+        public bool LoadAllCameras(string allCamerasConnectionStringPath)
+        {
+            if (!File.Exists(allCamerasConnectionStringPath))
+            {
+                Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                string directoryPath = Path.GetDirectoryName(allCamerasConnectionStringPath);
+                SaveAllCameras();
+                return true;
+            }
+            string strJson = string.Empty;
+            using (StreamReader streamReader = new StreamReader(allCamerasConnectionStringPath, Encoding.UTF8))
+            {
+                strJson = streamReader.ReadToEnd();
+                streamReader.Close();
+            }
+
+            GlobalVar.allCamerasConnectionString = JsonConvert.DeserializeObject<ConcurrentDictionary<string, string>>(strJson);
+            if (GlobalVar.allCamerasConnectionString == null)
+            {
+                MessageBox.Show("鐩告満鍔犺浇澶辫触!", "寮傚父");
+                return false;
+            }
+            BaseCamera camera = null;
+            foreach (var CameraConnectionString in GlobalVar.allCamerasConnectionString)
+            {
+                Enum.TryParse<CameraBrand>(CameraConnectionString.Value, out CameraBrand brand);
+                switch (brand)
+                {
+                    case CameraBrand.HRCamera:
+                        //camera = new HRCamera();
+                        break;
+                    case CameraBrand.LBCamera:
+                        //camera = new LBCamera();
+                        break;
+                    default:
+                        MessageBox.Show($"[{CameraConnectionString.Key}]鍝佺墝涓嶆敮鎸�!", "寮傚父");
+                        continue;
+                }
+
+                camera.SN = CameraConnectionString.Key;
+                if (!camera.InitDevice(CameraConnectionString.Key, this.Handle))
+                {
+                    LogInfo($"鍒濆鍖栫浉鏈篬{CameraConnectionString.Key}]澶辫触", LogInfoType.ERROR);
+                    if (camera != null)
+                        camera.isGrabbing = false;
+                }
+
+                GlobalVar.dicCameras.TryAdd(CameraConnectionString.Key, camera);
+            }
+
+            return true;
+        }
+
+        public bool SaveAllCameras()
+        {
+            try
+            {
+                string strJson = string.Empty;
+                GlobalVar.allCamerasConnectionString = new ConcurrentDictionary<string, string>();
+
+                foreach (var item in GlobalVar.dicCameras)
+                {
+                    string CameraSN = item.Value.SN;// "TCP"
+                    string CameraBrand = item.Value.Brand.ToString();//"1111"
+
+                    if (string.IsNullOrEmpty(CameraSN) || string.IsNullOrEmpty(CameraBrand))
+                        break;
+
+                    GlobalVar.allCamerasConnectionString.TryAdd(CameraSN, CameraBrand);
+                }
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+
+                strJson = JsonConvert.SerializeObject(GlobalVar.allCamerasConnectionString, settings);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                string directoryPath = Path.GetDirectoryName(GlobalVar.allCamerasConnectionStringPath);
+                if (!Directory.Exists(directoryPath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(directoryPath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+                File.WriteAllText(GlobalVar.allCamerasConnectionStringPath, strJson, Encoding.UTF8);
+                return true;
+            }
+            catch { return false; }
+        }
+
+
+        public bool LoadAllCommunicators(string allCommunicatorsConnectionStringPath)
+        {
+            try
+            {
+                if (!File.Exists(allCommunicatorsConnectionStringPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                    string directoryPath = Path.GetDirectoryName(allCommunicatorsConnectionStringPath);
+                    SaveAllCommunicators();
+                    return true;
+                }
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(allCommunicatorsConnectionStringPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+
+                GlobalVar.allCommunicatorsConnectionString = JsonConvert.DeserializeObject<ConcurrentDictionary<string, string>>(strJson);
+                if (GlobalVar.allCommunicatorsConnectionString == null)
+                {
+                    MessageBox.Show("閫氳绔彛鍔犺浇澶辫触!", "寮傚父");
+                    return false;
+                }
+
+                //娓呯┖閫氳鍙d細鎶婃墍鏈夐�氳鍙f柇寮�杩炴帴
+                GlobalVar.dicCommunicators.Clear();
+                ConcurrentDictionary<string, string> clientsCommunicatorsConnectionString = new ConcurrentDictionary<string, string>();
+                foreach (var CommunicatorConnectionString in GlobalVar.allCommunicatorsConnectionString)
+                {
+                    string CommunicatorName = CommunicatorConnectionString.Key;
+                    string CommunicatorAddress = CommunicatorConnectionString.Value;
+
+                    // 瀹氫箟姝e垯琛ㄨ揪寮忎互鎻愬彇鍗忚銆両P 鍦板潃鍜岀鍙�
+                    //1.    \((.*?)\)锛歕(鍜� \) 鏄敤浜庡尮閰嶆嫭鍙风殑杞箟瀛楃銆�
+                    //      (.*?) 鏄竴涓潪璐┆鐨勫尮閰嶏紝鐢ㄦ潵鍖归厤绫诲悕锛圡yProcesses.Communicators.TCPServer 鎴� MyProcesses.Communicators.UARTPort锛夈��
+                    //2.    ([^:] +)锛氬尮閰嶅啋鍙蜂箣鍓嶇殑閮ㄥ垎锛屽嵆鍦板潃锛�127.0.0.1 鎴� COM5锛夈�傝繖閲屼娇鐢ㄤ簡[^:] 鏉ュ尮閰嶉櫎浜嗗啋鍙蜂箣澶栫殑浠绘剰瀛楃銆�
+                    //3.    (\d +) 锛氬尮閰嶇鍙e彿锛岀‘淇濆畠鍖归厤涓�涓垨澶氫釜鏁板瓧銆�
+
+                    string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<PORT>[^]]+)\]$";
+                    Match match = Regex.Match(CommunicatorAddress, pattern);
+
+                    if (match.Success)
+                    {
+                        string ClassName = match.Groups["ClassName"].Value;   // "TCP"
+                        string IP = match.Groups["IP"].Value;          // "127.0.0.1"
+                        string PORT = match.Groups["PORT"].Value;        // "1111"
+
+                        if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT))
+                            break;
+
+                        //鍒╃敤鍙嶅皠鍒涘缓瀹炰緥
+                        Type type = IProcess.GetExecutingAssembly().GetType(ClassName);
+                        if (type == null)
+                        {
+                            Debug.WriteLine("Class not found.");
+                            return false;
+                        }
+                        var Communicator = Activator.CreateInstance(type, CommunicatorName) as BaseCommunicator;
+
+                        if (Communicator == null)
+                        {
+                            Debug.WriteLine("BaseCommunicator not found.");
+                            return false;
+                        }
+
+                        //TCP瀹㈡埛绔渶鍚庡啀杩炴帴
+                        if (Communicator is TCPClient)
+                        {
+                            clientsCommunicatorsConnectionString.TryAdd(CommunicatorConnectionString.Key, CommunicatorConnectionString.Value);
+                            continue;
+                        }
+
+                        Communicator.CommunicatorConnections.Add("鍦板潃", IP);
+                        Communicator.CommunicatorConnections.Add("绔彛", PORT);
+                        Communicator.CommunicatorName = CommunicatorName;
+                        if (!Communicator.Connect())
+                            LogInfo($"鍒濆鍖栭�氳鍙{CommunicatorName}]澶辫触,鍘熷洜鏄瘂Communicator.Msg}", LogInfoType.ERROR);
+                        else
+                            LogInfo($"鍒濆鍖栭�氳鍙{CommunicatorName}]鎴愬姛", LogInfoType.PASS);
+                        GlobalVar.dicCommunicators.TryAdd(CommunicatorName, Communicator);
+                    }
+                    else
+                    {
+                        Debug.WriteLine("No match found.");
+                    }
+
+                }
+
+                //TCP瀹㈡埛绔渶鍚庤繛鎺�
+                foreach (var CommunicatorConnectionString in clientsCommunicatorsConnectionString)
+                {
+                    string CommunicatorName = CommunicatorConnectionString.Key;
+                    string CommunicatorAddress = CommunicatorConnectionString.Value;
+
+                    // 瀹氫箟姝e垯琛ㄨ揪寮忎互鎻愬彇鍗忚銆両P 鍦板潃鍜岀鍙�
+                    //1.    \((.*?)\)锛歕(鍜� \) 鏄敤浜庡尮閰嶆嫭鍙风殑杞箟瀛楃銆�
+                    //      (.*?) 鏄竴涓潪璐┆鐨勫尮閰嶏紝鐢ㄦ潵鍖归厤绫诲悕锛圡yProcesses.Communicators.TCPServer 鎴� MyProcesses.Communicators.UARTPort锛夈��
+                    //2.    ([^:] +)锛氬尮閰嶅啋鍙蜂箣鍓嶇殑閮ㄥ垎锛屽嵆鍦板潃锛�127.0.0.1 鎴� COM5锛夈�傝繖閲屼娇鐢ㄤ簡[^:] 鏉ュ尮閰嶉櫎浜嗗啋鍙蜂箣澶栫殑浠绘剰瀛楃銆�
+                    //3.    (\d +) 锛氬尮閰嶇鍙e彿锛岀‘淇濆畠鍖归厤涓�涓垨澶氫釜鏁板瓧銆�
+
+                    var regex = new Regex(@"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<PORT>[^]]+)\]$");
+                    var match = regex.Match(CommunicatorAddress);
+
+                    if (match.Success)
+                    {
+                        string ClassName = match.Groups[1].Value;   // "TCP"
+                        string IP = match.Groups[2].Value;          // "127.0.0.1"
+                        string PORT = match.Groups[3].Value;        // "1111"
+
+                        if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT))
+                            break;
+
+                        //鍒╃敤鍙嶅皠鍒涘缓瀹炰緥
+                        Type type = IProcess.GetExecutingAssembly().GetType(ClassName);
+                        if (type == null)
+                        {
+                            Debug.WriteLine("Class not found.");
+                            return false;
+                        }
+                        var Communicator = Activator.CreateInstance(type, CommunicatorName) as BaseCommunicator;
+
+                        if (Communicator == null)
+                        {
+                            Debug.WriteLine("BaseCommunicator not found.");
+                            return false;
+                        }
+
+                        Communicator.CommunicatorConnections.Add("鍦板潃", IP);
+                        Communicator.CommunicatorConnections.Add("绔彛", PORT);
+                        Communicator.CommunicatorName = CommunicatorName;
+                        if (!Communicator.Connect())
+                            LogInfo($"鍒濆鍖栭�氳鍙{CommunicatorName}]澶辫触,鍘熷洜鏄瘂Communicator.Msg}", LogInfoType.ERROR);
+                        else
+                            LogInfo($"鍒濆鍖栭�氳鍙{CommunicatorName}]鎴愬姛", LogInfoType.PASS);
+
+                        GlobalVar.dicCommunicators.TryAdd(CommunicatorName, Communicator);
+                    }
+                    else
+                    {
+                        Debug.WriteLine("No match found.");
+                    }
+
+                }
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool SaveAllCommunicators()
+        {
+            try
+            {
+                string strJson = string.Empty;
+                GlobalVar.allCommunicatorsConnectionString = new ConcurrentDictionary<string, string>();
+
+                foreach (var item in GlobalVar.dicCommunicators)
+                {
+                    string ClassName = item.Value.GetType().FullName;// "TCP"
+                    string IP = item.Value.CommunicatorConnections["鍦板潃"].ToString();//"127.0.0.1"
+                    string PORT = item.Value.CommunicatorConnections["绔彛"].ToString();//"1111"
+
+                    if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT))
+                        break;
+
+                    string CommunicatorConnectionString = $"({ClassName})[{IP}][{PORT}]";
+                    GlobalVar.allCommunicatorsConnectionString.TryAdd(item.Key, CommunicatorConnectionString);
+                }
+
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+
+                strJson = JsonConvert.SerializeObject(GlobalVar.allCommunicatorsConnectionString, settings);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                string directoryPath = Path.GetDirectoryName(GlobalVar.allCommunicatorsConnectionStringPath);
+                if (!Directory.Exists(directoryPath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(directoryPath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+                File.WriteAllText(GlobalVar.allCommunicatorsConnectionStringPath, strJson, Encoding.UTF8);
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool LoadAllProcess(string allProcessConnectionStringPath)
+        {
+            try
+            {
+                if (!File.Exists(allProcessConnectionStringPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                    string directoryPath = Path.GetDirectoryName(allProcessConnectionStringPath);
+                    SaveAllProcess();
+                    return true;
+                }
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(allProcessConnectionStringPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+
+                List<string> lstProcessName = JsonConvert.DeserializeObject<List<string>>(strJson);
+
+                if (lstProcessName == null)
+                    return false;
+
+                // 浣跨敤鏂瑰紡
+                var sortedKeys = lstProcessName
+                    .OrderBy(k => k, new NaturalStringComparer())
+                    .ToList();
+                GlobalVar.dicProcesses.Clear();
+                foreach (var ProcessName in sortedKeys)
+                    GlobalVar.dicProcesses.TryAdd(ProcessName
+                        , new ProcessRunBll(ProcessName, GlobalVar.dicCameras, GlobalVar.dicCommunicators));
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool SaveAllProcess()
+        {
+            try
+            {
+                string strJson = string.Empty;
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+
+                strJson = JsonConvert.SerializeObject(GlobalVar.dicProcesses.Keys.ToList(), settings);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                string directoryPath = Path.GetDirectoryName(GlobalVar.allProcessConnectionStringPath);
+                if (!Directory.Exists(directoryPath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(directoryPath);
+                    }
+                    catch { }
+                }
+                File.WriteAllText(GlobalVar.allProcessConnectionStringPath, strJson, Encoding.UTF8);
+
+                foreach (var process in GlobalVar.dicProcesses.Values)
+                {
+                    if (!process.Save(out string msg))
+                        LogInfo($"娴佺▼[{process.Name}]淇濆瓨澶辫触,鍘熷洜:{msg}", LogInfoType.NOSHOW);
+                }
+
+                try
+                {
+                    string json = JsonConvert.SerializeObject(GlobalVar.ControlStates, settings);
+                    File.WriteAllText(GlobalVar.allRunSettingStringPath, json);
+                    LogInfo($"娴佺▼杩愯璁剧疆淇濆瓨鎴愬姛", LogInfoType.INFO);
+                }
+                catch { }
+
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool LoadAllProcessVars(string allProcessVarsPath)
+        {
+            try
+            {
+                if (!File.Exists(allProcessVarsPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                    string directoryPath = Path.GetDirectoryName(allProcessVarsPath);
+                    SaveAllProcessVars();
+                    return true;
+                }
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(allProcessVarsPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+
+                IProcess.dicGlobalVars.Clear();
+                IProcess.dicGlobalVars = JsonConvert.DeserializeObject<ConcurrentDictionary<string, object>>(strJson);
+                if (IProcess.dicGlobalVars == null)
+                {
+                    IProcess.dicGlobalVars = new ConcurrentDictionary<string, object>();
+                    return false;
+                }
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool SaveAllProcessVars()
+        {
+            try
+            {
+                string strJson = string.Empty;
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+
+                strJson = JsonConvert.SerializeObject(IProcess.dicGlobalVars, settings);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                string directoryPath = Path.GetDirectoryName(GlobalVar.allProcessVarsPath);
+                if (!Directory.Exists(directoryPath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(directoryPath);
+                    }
+                    catch { }
+                }
+
+                File.WriteAllText(GlobalVar.allProcessVarsPath, strJson, Encoding.UTF8);
+                LogInfo($"鍏ㄥ眬鍙橀噺淇濆瓨鎴愬姛", LogInfoType.INFO);
+
+                strJson = JsonConvert.SerializeObject(GlobalVar.dicLayout, settings);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                directoryPath = Path.GetDirectoryName(GlobalVar.allLayoutPath);
+                if (!Directory.Exists(directoryPath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(directoryPath);
+                    }
+                    catch { }
+                }
+
+                File.WriteAllText(GlobalVar.allLayoutPath, strJson, Encoding.UTF8);
+                LogInfo($"鍏ㄥ眬甯冨眬淇濆瓨鎴愬姛", LogInfoType.INFO);
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool LoadAllLayout(string allLayoutPath)
+        {
+            try
+            {
+                if (!File.Exists(allLayoutPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                    string directoryPath = Path.GetDirectoryName(allLayoutPath);
+                    SaveAllLayout();
+                    return true;
+                }
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(allLayoutPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+
+                GlobalVar.dicLayout.Clear();
+                GlobalVar.dicLayout = JsonConvert.DeserializeObject<ConcurrentDictionary<int, Forms.Pages.SettingPage.Layout>>(strJson);
+                if (GlobalVar.dicLayout == null)
+                {
+                    GlobalVar.dicLayout = new ConcurrentDictionary<int, Forms.Pages.SettingPage.Layout>();
+                    return false;
+                }
+                return true;
+            }
+            catch { return false; }
+        }
+    }
+}
diff --git a/LB_SmartVision/VisionForm.resx b/LB_SmartVision/VisionForm.resx
new file mode 100644
index 0000000..5e25f3c
--- /dev/null
+++ b/LB_SmartVision/VisionForm.resx
@@ -0,0 +1,1080 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="theme_VisionForm.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        vAAADrwBlbxySQAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
+        BkVBUPCBCEG8BXNQ48GLeImCehIJxMsqhsSZruod46K4HtSIGjU+4iOr0c1I9fSsM3/PLNtCPO0H36m/
+        evz/X11VnreKVRTAHPOZumkY6lFwqURws3BwZ8ywTQnuiCP/+iTCzY1qaUPzdm/Atf3PaHre6XPsjyQM
+        2xLGV4XwIyX4QRj+UMK/lPFvJTyhBMeV8IgQvmRJuH4Ko+l5p9UjGBbCJ5RxTgj+VMZmXxKcSAjekHE/
+        NNs5DgaTKLinEQYVO4Trf1mkV81wixLUslPmA3bzF2XcKeP+hWY/u3n0fCXcrQwLyjAvjNsb1dI6N05P
+        mFAIHlHG73sEypPgGwnhfpn0zzH7jzddcK4Q7kqfKNMI4a9K+MwBDgbdeF04MBWsFYYdQvhbLlBvfhKT
+        f+vMtLfG7C0JJXxKGY67WnvCmPAFGRs7z42boul5AzHBfdK6TjdQtzPGk8oos5F/5Y7sfVvPhg+lp+1h
+        0yIsxARPmtaN78WEl8eEX+SNclxUhne0glUrNrN9zfMGlPAuZTzaQ99FYfwuDv3ruoLvq5bWaQSvZCfL
+        GXUYLwrj240Qxtu2lkSN4FpdWfKZH9jb9RQ1Cq62f9sVOlxUxn3KQXnJ0PO8QxU/jBm1h74v7ZniEG9K
+        Hdg/quzvXO709k0Y3u08ucGqWgheX862H4XgxbR47SqU8D1X0EXC2VmGizqDz0xPr0kYH9eO360gNe0b
+        jWppozB+1kOQEb5MCLa0C64NoeGrhOGrvH6lhK81GiIvnggmrDLzgvTkvwvDA+5wsU4nhG/m9AUoBD/F
+        HFzWN4H0XQn2vF8eXN8Z3FAPYasl59oUYjuB+sTImDB+nhfgYQ39STf4fmu1DHtz+oIUgiM1KkWtwcFw
+        sOujVT3hrnaL7UQc+hcL5W+sKIXhw0OVjaW0iwnBc47gqIQ45QY32PKRzv8eTguRYM9SS5YouEEZjv37
+        EffbzbjBDdZyxZYQ12EB2qS0bWrJqRVazPDWkojwZbuZrsgZtDJ0iY1g12khEtTicMTvclwn2CKE32YJ
+        7G5PORfZ1HtMCH7MOV4BrQ3XCe92+4onk5Nn2PolDAvWXnuOzAwzo6Nnx4Q3SrojwqfKeMxWMpsXWVs+
+        2WrfKRdbW1W6Hf0shM/33Y7my4PrleFZIfhAaWjU/e5ivlw+y3S2FySMtynjvcrwsFiLJv/RhPBB2ws1
+        hK2WcBLBFf1qawlplwvxaQlxe786OOU4PBWsjSO85mBlQ8n99r/BisSdAas4FfgHpdEUZpwUX7sAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAA0AICAQAAEABADoAgAA1gAAABAQEAABAAQAKAEAAL4DAAAwMAAAAQAIAKgOAADmBAAAICAAAAEA
+        CACoCAAAjhMAABAQAAABAAgAaAUAADYcAAAAAAAAAQAgAC0RAACeIQAAQEAAAAEAIAAoQgAAyzIAADAw
+        AAABACAAqCUAAPN0AAAoKAAAAQAgAGgaAACbmgAAICAAAAEAIACoEAAAA7UAABgYAAABACAAiAkAAKvF
+        AAAUFAAAAQAgALgGAAAzzwAAEBAAAAEAIABoBAAA69UAACgAAAAgAAAAQAAAAAEABAAAAAAAgAIAAAAA
+        AAAAAAAAEAAAAAAAAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD/
+        /wD/AAAA/wD/AP//AAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAIkAAAAAAAAAAAAAAAAAAACXAAAA
+        AAiXk5k5GXmAAAAJOAAAAAB5OZGTkZk5kAAAeZgAAAAJGZOTmTkZk5kAAJGXAAAACTk5kZOZk5OTAAiT
+        mQAAAAkZk5ORk5kZmXAHmZGAAAAJmTmRmZOTk5FwB5OTkAAABzmTk5OZGZOZMAmZGZcAAACZOZGZGTk5
+        k5AHk5OZAAAAeRk5OTmRkZmQCZOZk5AAAAmZOZGZOTmTcAeTk5k5AAAAOZOTkZmTmZAImZGTmXAAAHmT
+        mZOTk5GAAHk5k5OXAAAHk5OZGZOZAAB5mTmRmXAAAJmRk5ORlwAABxk5OTmXAAAHk5mTmZAAAACZOZGZ
+        GXAAAJmTk5MAAAAAB5OZOTmZAACDkZmXAAAAAACZk5kZOXAACJmXgAAAAAAAB5k5ORk5gACDkAAAAAAA
+        AAAJOZmZOZcAAAAAAAAAAAAAAAd5OZOZcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////
+        ////////+/////P////z/gAH4/wAB8P4AAPD+AADg/gAAYH4AAGB+AABgPwAAYD8AAGAfgABgD8AAYAf
+        AAHAD4ADwAfAA+AD4AfwAfAP+ADwD/wAeB/+ABx//4AP///gB////////////////////////////ygA
+        AAAQAAAAIAAAAAEABAAAAAAAwAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAACAAACAAAAAgIAAgAAAAIAA
+        gACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8AAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAHAACZeXlwAJcACDmRmTkAmQAImRk5OQg5cAA5OZkZiJlwAHmZOTmAGZkABzkZmQB5OXAAmZ
+        OXAAk5lwADkZAAAJmTkAiZgAAAB5mZgAAAAAAACHeAAAAAAAAAAAAAAAAAAAAAAAAAD//wAA//8AAP//
+        AADeAwAAnAEAAJwBAAAOAAAADgAAAIcBAACDgQAAwcMAAODDAADwPwAA/D8AAP//AAD//wAAKAAAADAA
+        AABgAAAAAQAIAAAAAACACgAAAAAAAAAAAAAAAQAAAAAAAAAAAAAbKswAHCvMAB4szAAgL80AIjHNACUz
+        zgAmNc4AKDbPACo4zwAqONAALDrQAC480AAwPtAAMkDRADRB0QA3RNIAOUbTADtI1AA/TNQAQE3UAENQ
+        1QBFUdUASVXWAE1Y1wBPWtgAUFvYAFFd2ABVYNkAWGPZAFpl2gBeadsAYGrbAGNu3ABkbtwAZ3HdAGhy
+        3QBrdN0AbHbeAG943wBxet8AcnzfAHR93wB0feAAd4DgAHmC4QB7hOEAfYbhAIGK4gCDjOMAho7kAImQ
+        5ACMk+UAALB5AADPjwAA8KYAEf+0ADH/vgBR/8gAcf/TAJH/3ACx/+UA0f/wAP///wAAAAAAAC8OAABQ
+        GAAAcCIAAJAsAACwNgAAz0AAAPBKABH/WwAx/3EAUf+HAHH/nQCR/7IAsf/JANH/3wD///8AAAAAAAIv
+        AAAEUAAABnAAAAiQAAAKsAAAC88AAA7wAAAg/xIAPf8xAFv/UQB5/3EAmP+RALX/sQDU/9EA////AAAA
+        AAAULwAAIlAAADBwAAA9kAAATLAAAFnPAABn8AAAeP8RAIr/MQCc/1EArv9xAMD/kQDS/7EA5P/RAP//
+        /wAAAAAAJi8AAEBQAABacAAAdJAAAI6wAACpzwAAwvAAANH/EQDY/zEA3v9RAOP/cQDp/5EA7/+xAPb/
+        0QD///8AAAAAAC8mAABQQQAAcFsAAJB0AACwjgAAz6kAAPDDAAD/0hEA/9gxAP/dUQD/5HEA/+qRAP/w
+        sQD/9tEA////AAAAAAAvFAAAUCIAAHAwAACQPgAAsE0AAM9bAADwaQAA/3kRAP+KMQD/nVEA/69xAP/B
+        kQD/0rEA/+XRAP///wAAAAAALwMAAFAEAABwBgAAkAkAALAKAADPDAAA8A4AAP8gEgD/PjEA/1xRAP96
+        cQD/l5EA/7axAP/U0QD///8AAAAAAC8ADgBQABcAcAAhAJAAKwCwADYAzwBAAPAASQD/EVoA/zFwAP9R
+        hgD/cZwA/5GyAP+xyAD/0d8A////AAAAAAAvACAAUAA2AHAATACQAGIAsAB4AM8AjgDwAKQA/xGzAP8x
+        vgD/UccA/3HRAP+R3AD/seUA/9HwAP///wAAAAAALAAvAEsAUABpAHAAhwCQAKUAsADEAM8A4QDwAPAR
+        /wDyMf8A9FH/APZx/wD3kf8A+bH/APvR/wD///8AAAAAABsALwAtAFAAPwBwAFIAkABjALAAdgDPAIgA
+        8ACZEf8ApjH/ALRR/wDCcf8Az5H/ANyx/wDr0f8A////AAAAAAAIAC8ADgBQABUAcAAbAJAAIQCwACYA
+        zwAsAPAAPhH/AFgx/wBxUf8AjHH/AKaR/wC/sf8A2tH/AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADImAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAKwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAtBBkAAAAAAAAAAAAAAAAAAAAAAAAAMisnIyMjJistMgAAAAAAAAAAAAAAAAAAADQEAS4A
+        AAAAAAAAAAAAAAAAAC0VCgQBAQEBAQEBAQEBAQEEBAYkAAAAAAAAAAAAAAoBAQAAAAAAAAAAAAAAAAAj
+        CgEBAQEBAQEBAQEBAQEBAQEBAQEEAAAAAAAAAAAAFwEBBAAAAAAAAAAAAAAAABkBAQEBAQEBAQEBAQEB
+        AQEBAQEBAQEBDgAAAAAAAAAyBAEBAQAAAAAAAAAAAAAALQQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBASMA
+        AAAAAAASAQEBATAAAAAAAAAAAAAAFQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQoAAAAAAAAEAQEBARwA
+        AAAAAAAAAAAADgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEtAAAAABwBAQEBAQwAAAAAAAAAAAAAEAEB
+        AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEVAAAAAAwBAQEBAQE0AAAAAAAAAAAAFwEBAQEBAQEBAQEBAQEB
+        AQEBAQEBAQEBAQEGAAAAAAQBAQEBAQEVAAAAAAAAAAAALQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEC
+        AAAAAAEBAQEBAQEEAAAAAAAAAAAAAAgBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBLQAALAEBAQEBAQEB
+        EgAAAAAAAAAAABwBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBIwAAJgEBAQEBAQEBASYAAAAAAAAAAAAG
+        AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBHwAAJgEBAQEBAQEBAQYAAAAAAAAAAAAeAQEBAQEBAQEBAQEB
+        AQEBAQEBAQEBAQEBHwAALQEBAQEBAQEBAQEQAAAAAAAAAAAACwEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
+        IwAAAAEBAQEBAQEBAQECGQAAAAAAAAAAMQQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBMAAAAAQBAQEBAQEB
+        AgEBASEAAAAAAAAAABoBAQEBAQEBAQEBAQEBAQEBAQEBAQECAAAAAA4BAQEBAQEBAQECAQQrAAAAAAAA
+        AAAOAQEBAQEBAQEBAQEBAQEBAQEBAQEKAAAAAB8BAQEBAQEBAgEBAQEEMAAAAAAAAAAABgEBAQEBAQEB
+        AQEBAQEBAQEBAQEYAAAAAAAEAQEBAQEBAQECAQEBBjIAAAAAAAAAKwIBAQEBAQEBAQEBAQEBAQEBAQMA
+        AAAAAAAWAQEBAQEBAgEBAQEBAQYyAAAAAAAAAB4BAQEBAQEBAQEBAQEBAQEBARAAAAAAAAAABAEBAQEB
+        AQECAQEBAQEGMgAAAAAAAAAVAQEBAQEBAQEBAQEBAQEBAzIAAAAAAAAAHQEBAQEBAgEBAQEBAgEBBC4A
+        AAAAAAAAEAEBAQEBAQEBAQEBAQEBFgAAAAAAAAAAAA8BAQEBAQECAQEBAQECAQQnAAAAAAAAAAsBAQEB
+        AQEBAQEBAQEIAAAAAAAAAAAAAAAIAQEBAgEBAQEBAgEBAQEEIAAAAAAAAAAIAQEBAQEBAQEBAQQzAAAA
+        AAAAAAAAAAAABQEBAQECAQEBAQECAQEBAhoAAAAAAAAABQEBAQEBAQEBAykAAAAAAAAAAAAAAAAAAAgB
+        AgEBAQEBAgEBAQEBAQETAAAAAAAAMAQBAQEBAQEEJwAAAAAAAAAAAAAAAAAAAAAOAQECAQEBAQECAQEB
+        AQEBDgAAAAAAAC0EAQEBAQYwAAAAAAAAAAAAAAAAAAAAAAAAGgMBAQEBAgEBAQEBAQEBAQgyAAAAAAAp
+        AwEBEQAAAAAAAAAAAAAAAAAAAAAAAAAAADMPAQEBAQECAQEBAQEBAQEEIwAAAAAAJgokAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAALhADAgEBAQEBAQEBAgECAhgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAHAwDAQEBAQEBAQECAQIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALh4X
+        EQ8ODxIWHSsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD///////8AAP///////wAA////////AAD///////8AAP///////wAA////////AAD/P/////8AAP5/
+        /////wAA/H//8AP/AAD4f/4AAB8AAPj/+AAAHwAA8P/wAAAPAADg/+AAAAcAAOB/4AAABwAA4H/gAAAD
+        AADAf+AAAAMAAMA/4AAAAwAAwD/gAAADAADAP/AAAAEAAIAf8AAAAQAAgA/4AAABAACAD/gAAAEAAIAH
+        /AAAAQAAwAP8AAABAADAAf4AAAMAAMAA/wAAAwAAwAB/gAADAADgAD+AAAcAAOAAH8AABwAA8AAP4AAH
+        AADwAAfwAA8AAPgAA/gAHwAA/AAB/AAfAAD+AAD+AD8AAP8AAH4AfwAA/4AAPwD/AAD/wAAPg/8AAP/g
+        AAfH/wAA//gAA///AAD//wAB//8AAP//4AP//wAA////////AAD///////8AAP///////wAA////////
+        AAD///////8AAP///////wAA////////AAAoAAAAIAAAAEAAAAABAAgAAAAAAIAEAAAAAAAAAAAAAAAB
+        AAAAAAAAAAAAABsqzAAcK8wAHizMACAvzQAhMM0AJDLOACY0zgAoNs8AKDbQACo40AAtOtAALjzQADA+
+        0QAzQdIANULRADdE0gA6R9MAO0jUAD1K1ABBTtQARlLVAElV1wBMWNcAT1rYAFBb2ABRXdgAWGPZAFpl
+        2gBeaNoAZG7cAGlz3QBpdN4Ab3jfAHF63wB1fuAAeoLgAHuE4QB8heIAgYniAIqR5AAx8f8AUfP/AHH1
+        /wCR9/8Asfn/ANH7/wD///8AAAAAAAAvIQAAUDcAAHBMAACQYwAAsHkAAM+PAADwpgAR/7QAMf++AFH/
+        yABx/9MAkf/cALH/5QDR//AA////AAAAAAAALw4AAFAYAABwIgAAkCwAALA2AADPQAAA8EoAEf9bADH/
+        cQBR/4cAcf+dAJH/sgCx/8kA0f/fAP///wAAAAAAAi8AAARQAAAGcAAACJAAAAqwAAALzwAADvAAACD/
+        EgA9/zEAW/9RAHn/cQCY/5EAtf+xANT/0QD///8AAAAAABQvAAAiUAAAMHAAAD2QAABMsAAAWc8AAGfw
+        AAB4/xEAiv8xAJz/UQCu/3EAwP+RANL/sQDk/9EA////AAAAAAAmLwAAQFAAAFpwAAB0kAAAjrAAAKnP
+        AADC8AAA0f8RANj/MQDe/1EA4/9xAOn/kQDv/7EA9v/RAP///wAAAAAALyYAAFBBAABwWwAAkHQAALCO
+        AADPqQAA8MMAAP/SEQD/2DEA/91RAP/kcQD/6pEA//CxAP/20QD///8AAAAAAC8UAABQIgAAcDAAAJA+
+        AACwTQAAz1sAAPBpAAD/eREA/4oxAP+dUQD/r3EA/8GRAP/SsQD/5dEA////AAAAAAAvAwAAUAQAAHAG
+        AACQCQAAsAoAAM8MAADwDgAA/yASAP8+MQD/XFEA/3pxAP+XkQD/trEA/9TRAP///wAAAAAALwAOAFAA
+        FwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/kbIA/7HIAP/R3wD///8AAAAAAC8A
+        IABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/cdEA/5HcAP+x5QD/0fAA////AAAA
+        AAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0Uf8A9nH/APeR/wD5sf8A+9H/AP//
+        /wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCmMf8AtFH/AMJx/wDPkf8A3LH/AOvR
+        /wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+Ef8AWDH/AHFR/wCMcf8AppH/AL+x
+        /wDa0f8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJhQAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEIAAAAAAAAAAAACASCQQEAQEBAQIEBgkmAAAAAAAADQEm
+        AAAAAAAAAAAKAQEBAQEBAQEBAQEBAQkAAAAAAB0BASEAAAAAAAAADQEBAQEBAQEBAQEBAQEBARYAAAAA
+        CQEBGAAAAAAAAAADAQEBAQEBAQEBAQEBAQEBBAAAACYBAQELAAAAAAAAAAQBAQEBAQEBAQEBAQEBAQEB
+        IAAAFwEBAQEnAAAAAAAACwIBAQEBAQEBAQEBAQEBAQEUAAAQAQEBAQ4AAAAAAAAcAQEBAQEBAQEBAQEB
+        AQEBAQwAAAsBAQEBASAAAAAAAAAGAQEBAQEBAQEBAQEBAQEBCQAACwEBAQEBBgAAAAAAAB4BAQEBAQEB
+        AQEBAQEBAQEJAAAQAQEBAQEBDgAAAAAAAA4BAQEBAQEBAQEBAQEBAQ0AABkBAQEBAQEBFgAAAAAAAAQB
+        AQEBAQEBAQEBAQECFQAAJwEBAQEBAQEBGgAAAAAAHgIBAQEBAQEBAQEBAQEjAAAACgEBAQEBAQECHAAA
+        AAAAFgEBAQEBAQEBAQEBBgAAAAAgAQEBAQEBAQECHAAAAAAAEAEBAQEBAQEBAQEcAAAAAAAPAQEBAQEB
+        AQECGgAAAAAACwEBAQEBAQEBCwAAAAAAAAAHAQEBAQEBAQEBFgAAAAAABgEBAQEBAQUAAAAAAAAAAAAG
+        AQEBAQEBAQEBEgAAAAAoBgEBAQEEJAAAAAAAAAAAAAALAQEBAQEBAQEBDQAAAAAnBAEBBicAAAAAAAAA
+        AAAAAAAWAwEBAQEBAQEBCScAAAAkBRIAAAAAAAAAAAAAAAAAAAAAFAQBAQECAQEBAx4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAB8TCgQDAwMFDCIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD/////////////////////+/////P////z/gAH4/wAB8P4AAPD+AADg/gAAYH4
+        AAGB+AABgPwAAYD8AAGAfgABgD8AAYAfAAHAD4ADwAfAA+AD4AfwAfAP+ADwD/wAeB/+ABx//4AP///g
+        B////////////////////////////ygAAAAQAAAAIAAAAAEACAAAAAAAQAEAAAAAAAAAAAAAAAEAAAAA
+        AAAAAAAAGyrMAB4szAAiMM0AJTPOACY0zgApN9AAKznQAC070AAvPdAANULRADtI0wA8SdMAQEzUAEhU
+        1wBPWtgAVmHZAGRu3ABpct0AbHbeAHeA4AB4geAAf4fiAH+I4gCBieMAhIzjAIeP5ACIkOQAkc//ALHd
+        /wDR6/8A////AAAAAAAALC8AAEtQAABocAAAhpAAAKWwAADDzwAA4fAAEe//ADHx/wBR8/8AcfX/AJH3
+        /wCx+f8A0fv/AP///wAAAAAAAC8hAABQNwAAcEwAAJBjAACweQAAz48AAPCmABH/tAAx/74AUf/IAHH/
+        0wCR/9wAsf/lANH/8AD///8AAAAAAAAvDgAAUBgAAHAiAACQLAAAsDYAAM9AAADwSgAR/1sAMf9xAFH/
+        hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAIkAAACrAAAAvPAAAO8AAAIP8SAD3/
+        MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAwcAAAPZAAAEywAABZzwAAZ/AAAHj/
+        EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABAUAAAWnAAAHSQAACOsAAAqc8AAMLw
+        AADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAvJgAAUEEAAHBbAACQdAAAsI4AAM+p
+        AADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAAAAAALxQAAFAiAABwMAAAkD4AALBN
+        AADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8DAABQBAAAcAYAAJAJ
+        AACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAAAAAvAA4AUAAXAHAA
+        IQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP///wAAAAAALwAgAFAA
+        NgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R8AD///8AAAAAACwA
+        LwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx/wD70f8A////AAAA
+        AAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R/wDcsf8A69H/AP//
+        /wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx/wCmkf8Av7H/ANrR
+        /wD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAA
+        ABEKBgQEBggAAAAMDgAAABUBAQEBAQEBCgAAAgYAAAAUAQEBAQEBAQIAGgEBEgAAAAQBAQEBAQEBGBsB
+        AQQAAAASAQEBAQEBARgAAgEBCQAAAAsBAQEBAQIAAA0BAQEKAAAABwEBAQELAAAABAEBAQoAAAAEAQED
+        AAAAAAAFAQEBCAAAGwMEGQAAAAAAAA8DAQEEFgAAAAAAAAAAAAAAABsTEhcAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD//wAA//8AAN4DAACcAQAAnAEAAA4AAAAOAAAAhwEAAIOB
+        AADBwwAA4MMAAPA/AAD8PwAA//8AAP//AACJUE5HDQoaCgAAAA1JSERSAAABAAAAAQAIBgAAAFxyqGYA
+        ABD0SURBVHja7d0/etzGGcfxAbhUytCVH4mFmcoWXXj1SKrNnMCbE4Q+gekThDlB6BOEPoHlE4SuJT+i
+        i1BKFbqg9KQyWUpcAsHsCuZqxSUGwAzmz/v9FJZk0xS4u/PDzDt/kCkAYmW+LwCAPwQAIBgBAAhGAACC
+        EQCAYAQAIBgBAAhGAACCEQCAYAQAIBgBAAhGAACCEQCAYAQAIBgBAAhGAACCEQCAYAQAIBgBAAhGAACC
+        EQCAYAQAIBgBAAhGAACCEQCAYAQAIBgBAAhGAACCEQCAYAQAIBgBAAhGAACCEQCAYAQAIBgBAAhGAACC
+        EQAJeb59bzzNsg39+7xQO/W/LzM1rv65sfz1mcq+vOn7FEXxS5Zn5x/+l+w8K9Xx9fctT8ssO9W/H41G
+        xw9++fVcISoEQGSefr65k5XlVlZmW3XDzlRZ/Zr/0fe1aYVSv1bXc1qHRR0SBESYCIBAPf/0462rPB9n
+        Kh9XjWinVNlWrtQnvq+rn+Ki+jmOqw/dcVlkp+WaOn7877Mj31clGQEQiNmd/aq6o+eqauxqHH9jN6eH
+        HHmWH5dVj2EtL48enLw67v9dYYIA8ESP16+KbEc3+OpN+Mr39YRF9xTyo2o8cUQguEUADOT5F59sXF1e
+        Tqqx+47KikkoY/Y4FBdFlk8YLthHADg0G8evre1UL/OEu3xXVW+gVLuPXrx+4vtKUkQAWFbf6avf7q6a
+        ZoMZXRsY5dkuQwB3CABLnt2/O1FZvsud3o5SqR/X1ke7TB26RQD0oLv4xdraXvVx3WVMb09ZqG8fvTw7
+        8H0dEhAAHczv9tkeXXzbKPYNjQAwNBvbv5nulrnakzRHP5TZeP8Pd3bo8g+LAGgw6+bno12VFXt08x0p
+        1fcPX5zt+r4MiQiAFd41/P3qFfqr72tJWanKrx+dvDr0fR1SEQBLaPhDKS5yle0MOcX38/3NQ/1rXkz3
+        H/znf6e+X4EQEADv6DF+cXm5X70k3/i+ltT5GO/PGv/voV5cqDI/yO+MDqTXHMQHwKzhv53uMcYfiIfx
+        /vuNf9Fsd+Ke5CGI6AB4tn1vt/oA7FPVH4aP8f7qxn9N90jUWr4ncfpRZADMduIpdcA8/lCGH+9rJo3/
+        PVXvpBoW7EkaFogKAMb5w/M1v9+68V9fsahhgZgA0Kv3skwdMs4fkKf5/e6Nf/HSy5/Wrq52U58tSD4A
+        5ltyRwds0hmWr/l9G43/WtUbKPL9lPclJB0Azz7b3MvyYp+7/pD8jPe1+fut/mH7+856A+vrkxRrA0kG
+        wHxP/vSQu/6wZuP9spj46DbrGZ1MZf90+NMleTBJcgHAWN8TjxV0943/vR/0u3x9fT+V3kBSAfDz9r0D
+        KvwelOrvD1+c7fv4q4dt/HMpnVSURADoQt80y5/kef6F72uRxW+32EfjD+VntyX6AKDL74d+AtBIlRNf
+        d0G/jX9R+d3Dk1d7vq+iq6gD4Of7m3rX3t98X4c0vg/vmId+/oPv16EW8/mFUQYAVX6PPB/eoZdxF6o8
+        Cq3HF2tdILoAYLzvj+/DOkNt/Nf8rYHoKqoACP8DkCr/Ba943vu49hJEEwAU+/zwXezT4mn812I56iyK
+        AAin4iuL72Kfpus908vpcZRnNnhcH2Eq+ACg8XsSwEm9s8b/5u1R1PWeAF7H2wQdAKzs8ySAO1cSjb8W
+        cAgEGwB2t3XCTBgFrKQafy3QEAgyAGj8PoQzhZXs+x9gCAQXAMm++QHzuY13WfLvf2AhEFQAsLR3eCFU
+        +mvJN/5aADWWWjABQLXfg4DuRq5O8wlVKOsEgggAGr8HAd2FpL7/IYSA9wB4+vnmTl6qf/m+DklC+ODV
+        pDb+Of+FV68BEOMSz7gVF0WWT0J5Ag7vv1aFwFUx9lWA9RYA84d0vD2V/eYPyf/dZhGN/5rPQqyXAEhy
+        oUfAQqr0a7NHsK/lxzT+a/pQkUcnZ5Oh/14vASBmuicAwTV+wn81D4XZwQNA2nSPVwFN82k0/mZlWfxl
+        yHMXBg2A+bgvez7k3ylWYI1fo+dnYtii4GABQNFvOCFN89Vo/Ob0sO3xy9fjIf6uwQLg2fbmEw7xdC/E
+        xs+wr4OB6gGDBAAfgCH4P7fvJrIX+vRTZOrPrtdsOA8Axv1DCGuOv8Z738/sPMb10djlDI7zAHj62d1j
+        qr4uhdz4WejTn9snDzkNALb3uhXaHH8t6oM8A+RyKOAsAOj+uRV042eu3yqXQwFnAUDX351QG7/GdJ8j
+        jmYFnAQAVX+HSvV9fme0F2Tj5xRnp/Kr6Z9sLxCyHgAs+HEowNV9Nab73CtV+dOjk1c7Nr+n9QCgC+hI
+        wI2fQ12GY3uvgNUA4IPgSMCNn+m+YemC4OOTsy1b389qAFTdwKOqG/jl4K9K0tzOA/dBxd8TiwVBawHA
+        GNC+ENf1L2Kmx5fiIl+/s2WjEGwtAJ5ub56y8MOe0Bs/tR7PLPUCrAQAd3+7Qm/8vN8hsNMLsBIA3P3t
+        Cb3xU+gNiIVeQO8A4G5gT+iNn4p/aPr3AnoHAHd/O4Jv/FT8w9SzF9ArALj72xF649c40SlUxcXDk9cb
+        Xf/vvgHAvH9PMTR+tnWHrc9nqHMAUAzqL4bG/+z+3UmW5T/4vg6s1ucQ0c4BwDxwPzE0fop+8eh6aEin
+        AJjv+Jv+5vuHjlUUjZ+iX1w67hfpFADs9+8uhsavUfSLT74++qjtlGCnAGDqr5toGj8BH6Uun6/WAcBZ
+        f92Uhfr20cuzA9/X0YTibry6FANbBwDFvw4C3s+/iNOc4tf22LD2AbB995wPSAuRNH6NdR3xa9vTbBUA
+        zAm3FFHjZ7FPGtoOA1oFAN3/FiJq/Iz709JmGNAqAKj+mwn53P5ljPvT02YYYBwAVP/NxNT4Ncb96SmV
+        +vHRydnE5GuNA4AxYrMhnuZqE+9puh6enBm1beMA4E7RJMyn9K7CuD9tps8PMAoA1v43iavx8/ReCcyO
+        kzcKAKb/bmf7aS2usc4/faaPETMKAMaKq8Wyvr/GKU5ymNQBzHoAjP9XCPepPTd5/unHW8VafsyUnwwm
+        ZwSY9QC2N0vfP0xwIlroUyPIhTE4MLQxAJj//1Bsc/0awzh5TNYDNAYAY8b3xTbXrxHiMpnsC2gMAO4c
+        i+Ka7qvxEE+5mgqBJj0Axo3vxDbdpxHgsjUVAhsDgA1Ac7Gc6LOIrj+ablrNQwBmAKKs+Gt0/dE0E3Br
+        AHAHibPir9H1x0zDzevWAGDDSHGRXxXjNmeshWC+4Gf0X9/XAf+algTfGgDSj4fu+rQV3yjcotY0FXhr
+        AIjuRvZ87LIvrNvAstumAgmAG7Q5USUkHO+Fm3QOAIldyRhX+tU4tBU3ue2QUAJgSa7KB7Gt9NMo2GKV
+        22pZBMCCGBf71JjzxyoEgAHTE1RCROEPtyEAGhUX+fqdrRjH/RT+0KRzAEh5DmCMm3xqUmdqYK5HAEjY
+        BxDXsV6LWPEHEwTACjFP+WlM+8EEAbBCrFN+Ghu1YIoi4E0iXepbS/q9gVUEwPIL0vIZ6qFh0Q/aIACW
+        xNz111J9X+AGAfCeeKv+Gnd/tEUA1C9E5FV/LbX3BO71mAW4d1B9yTe+f4AhXogYUPlHF5wHoOLd47+I
+        eX90QQBEerbfIlb9oavOAZBMwSnyOX8tnTDGkHodCppCAKRQ+NOkbMyCXb0CYL7VdPqb7x+i5wvwdfUC
+        HPq+jj7Y74/ubp/2TvrJQDEf8rGIqT901ufJQFrMH77Yp/00in/oo/ezAZ9tbz6pvugr3z9I6x88kbt/
+        amsxMKzeTweOtfp821HIMeHpzOjjtilArfnx4DHOBET6NN9lrPxDH3oG7PHJ2dZtX9MYADGOQVO5+9P9
+        Rx8mq18bA0CLag46kbu/RvcfvRgsgDMKgJgKgSlU/rUYe14Ii0lbMOsBRFIITKXyr0l/NDv6y9dHHzWt
+        gDUKgFgKgTGf778spl4XwmNSANSMAkALfUWg6Q8cC8b/6MWwFmYcAKHfkWJ+sOcyxv/oy3QPjHkABD4m
+        NRnvxOLZ/buTLMt/8H0diJfpVLhxAAS9KCWhqT8tlqIrwtRmOGwcAFqo49JUpv5qoQ+3EDrzk69bBUCI
+        K9NSK/5pMe/AhH9tZsNaBUCYw4C4z/m/Sag9LcSguHh48nrD9KtbBYAW2ocz9qf83CT0KVcErGU9rHUA
+        hDQMSLH7rxEA6KrtYrjWARDWMCC97r9GAKCbdt1/rXUAaKEMA1Kr/tcIAHTSYTq8UwCEsSiofdrFggBA
+        F132wnQKgBCOC0/hUV+rEABoq2s9rFMAaL6fU5fS2v9lBABa6/j0q84B4HuLcIrTfzUWAqGtrsfgdQ4A
+        7elnd4/zPP/Cxw/cdNppzFgKjDb6DId7NSJfj6xK6eSfm7AZCG30mQ3rfRf1MyWY5vx/zffwCvEoiuKX
+        xy9fj7v+/70DwEcvIIUHfjahEAgTfduClXH00L2AVBcALaIOgCY2lsJbCYChewEpnf6zCo8ERxMbPWFr
+        lfQhewEpzwAsiuqBLBiUrY1w1hrSUHesVHcA3oTZAKxiqw5m9U46xLqA1KcAF82XXL89pReARTZvgnYD
+        YIDpK0kBoIWx8QohsVkEtz6Wdl29lhYAGkuDUbP9+bceAPOHWuTHzrqtHTc9xMz5a4po2N4D46Sa7rR4
+        JTAANB4WAhcrYJ1NpzkrCAoNAI21AZIVF/n6nS3b61+cBYC7swPT3gfQhBCQydWTr50uqHFxgrDEIuAy
+        QkAWl6dfOV9RZ3soQADMzadciycUBlPnputfcx4AtocCBMA1PTtwtbZ2yBRhulx1/WuDrKm3OyuQ7mnA
+        Xc1f32KP3kBiBnjq9WCbamwuZpGyGaiNeW9gdMAW4jTo5b6j9dHY9a7XwRqSzXXtKR8I2peuDWRluc+w
+        IG5DfcYHvZPa2ivgelyUAoIgXkOeeDV4V9rK5hbBi4Hami0jzke6RjChRhCBAcb9i7yMpfs+VISZgPb0
+        EOzq8rIKgWxCnSBMfQ/47MJLAOgP4/TN26Pu6wOYCejj/TAodugZhMDtfP8q3qrpfYuCFALtmdVmCrVT
+        ZuUONQMfqsavsh0fn2ev02nzRULlUZcQSPnZgL7NCohXapxlalyUxdjX05+k8HnKtff59K4zAz7GS5K9
+        m1XYyspsS/cUyqLcIBhW0/P4mSpP53/KzrNSze7uZanOy7X570dlee67F+s9ALSum1u6PhAR9uhZhulo
+        tJUVxUam8lkg64CY/ZpASOiC8+KfqwA8Wvxzkavf/zwajY5jO64+iADQuoQAw4C46F7E4p913WHV19Yh
+        0kXVSE+rX05Xfu+Fu/Ci0XR6Ku2GEkwAaG1DgGEA0E9QAaC1DQFmA4DuggsArVUIDLxyCkhJkAGgmYeA
+        nwUUQAqCDQDNOATYGwB0EnQAaGYhQC8A6CL4ANCMzr+jFwC0FkUAaM3LhqtewFUxljaPC/QRTQBos1Vn
+        Wf5k5eoyZgSAVqIKAG2+lXV6uGpPu8+NFUBsoguA2qqThm0+Ox1IXbQBoM0fmKkOP6gLUBAEjEQdAJou
+        Dk6L8nC5LsBQAGgWfQBos9OF3k4PFs8ZHOpcdSBmSQRAbXlI4PKhikAKkgoA7YPn5VEPAFZKLgBq8+cP
+        FPu6N8CDRICbJRsA2nVvoBz7OnUVCFnSAVDTvYEyV3sUBYH3iQgAbbaC8M10lzMEgWtiAgDAhwgAQDAC
+        ABCMAAAEIwAAwQgAQDACABCMAAAEIwAAwQgAQDACABCMAAAEIwAAwQgAQDACABCMAAAEIwAAwQgAQDAC
+        ABCMAAAEIwAAwQgAQDACABCMAAAE+z9wtceXg+mMXgAAAABJRU5ErkJggigAAABAAAAAgAAAAAEAIAAA
+        AAAAAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//BAAA/wEAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8CGCrIKhkqzDwA
+        P78EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc
+        HMYJGynNXBopzJIdJ80aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAcKtQSGyrMhBopzNUcKM4/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeKMsZGSrMnRoqzfYaKcyOACrUBgAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeKMsZGirMoxopzfoaKs3mHSzNNAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/Aioq1AYcOOIJIjPMDxkmzBQWLNIXHSfNGh0nzRod
+        J80aFy7QFhkmzBQeLcMREyfEDR8f3wgqKtQGAD+/BAAAfwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZJswUGyvNoBopzfob
+        Ks3/GynMshcu0AsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKoDHCrGEhwnyy0ZKctPGirNchoqy5AbKsyoGynLuRspzMQb
+        KczLGinN0BspzNUbKczVGynM1Rspzc8bKczLGyrMxhoqzb8aKs22GyrMqhsqzJwbKcuMGinNexopzmka
+        KcxWHibQIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ
+        M8wKGyrNihopzPkbKs3/GyrN/RsqzHgAAP8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQkyA4bKsxCGyrNihspzcQaKs3mGirM9xsqzP0b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzP4bKcz8GinM+RopzbkZKsweAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAKoDGinNYhoqzPEbKs3/GyrN/xoqzPgdKc5PAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirUBhkoy0UbKsywGinM7hsqzP4b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKc37GinMmBUq1AwAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGinKMRoqzNobKs3/GyrN/xsqzf8bKs3wHSrQPAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFy65CxopznQb
+        KczoGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzfIa
+        KsxgAAD/AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEyfEDRopzaQbKsz+GyrN/xsqzf8b
+        Ks3/GinN7Rsp0DcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAD+/BBspy24bKszyGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GirL0hwqzSQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARsozVIa
+        KszxGyrN/xsqzf8bKs3/GyrN/xspzfMbKtBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAABwt0S0aKs3dGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzPwaKsuFAD+/BAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAB4twxEbKcy3GyrN/xsqzf8bKs3/GyrN/xsqzf8aKc36HCrMWwAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wEcKcx1GyrN/Bsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GinN3BgqzioA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaK81NGyrM8hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrM/hopy4YA
+        AH8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqKqoGGynMpxsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzPwbKcx6AAD/AgAAAAAAAAAAAAAAAAAAAAAkJNoHGirMoRsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKsy6JyfEDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAHx+/CBopzLcbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirNxxkz2BQAAAAAAAAAAAAAAAAAAAAAGynOJRopzN0b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirN5hop0DEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAACQk2gcbKcyxGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xopzPAbK89BAAAAAAAAAAAA
+        AAAAAAAAABwqzlkaKsz4GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzPwbKsx4AAB/AgAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVf8DGyrNlRsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ksz+GirMfwAA/wEAAAAAAAAAAABV/wMbKcyTGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GinNyR4oyxkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsqz2Ub
+        Kcz7GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqy7McOOIJAAAAAAAAAAAkJMgOGinNvhsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xoqzfYaKs1hAAD/AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAaKs8wGirN5hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKczVHCXPGwAAAAAAAAAAGivTHRsqzNkb
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrMxhwlzxsAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFy7QCxsqzLAbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GynM6RoqzzAA
+        AAAAAAAAABss0i4bKczoGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xspzPkc
+        Kc12AFX/AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcKsxbGirN9hsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xspzPQbKtBCAAAAAAAAAAAdKsw8GyrN8Bsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GinN3BkoyzIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAHyrJGBsqzMYbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8aKs34GyjNUgAAAAAAAAAAGinNQxsqzPQbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzP4bKsyoHy/PEAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAA/wEcK8tkGirN9hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GinM+RopzFYAAAAAAAAAABsq0EIb
+        Ksz0GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GinN9hsozHAA
+        P78EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCTCFRsqzLsbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xopzPka
+        KcxWAAAAAAAAAAAeK887GyrN7xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKc3iGyvPQQAA/wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEa
+        K8xMGinM7Rsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8aKsz4GSnMUAAAAAAAAAAAHC3LLRspzecbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzMYbKc4lAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAHDjGCRspy5UbKs38GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrM8hwozj8AAAAAAAAAABwlzxsbKczWGyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs38GynNphkzzBQA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaKMkmGynMzxsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xoqzOUdKc8rAAAAAAAAAAAX
+        LtALGinNuBsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xopzPkbKs2LFSq/DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/Ah0pzVca
+        KczuGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        KsvNGCTOFQAAAAAAAAAAAAD/AhorzIgbKsz+GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GynM8xopzHQkJNoHAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAcOMYJGivMjhspzPsbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GirMoyoq1AYAAAAAAAAAAAAAAAAaK81NGynL9Rsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8aKcztGSjLZDMzzAUA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABst0RwbKsy8GyrM/hsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GynM+xopy2gAAAAAAAAAAAAAAAAAAAAAGivKHRoqzdMb
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xoqzeYZKstaAD+/BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGivOOhopzdwb
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xopzOQcJ9EtAAAAAAAAAAAA
+        AAAAAAAAAAA/vwQbKcyNGyrM/hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GynN4hsrzVMAP78EAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAABVqgMaKs5fGinM7xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8a
+        KcyrGTPMCgAAAAAAAAAAAAAAAAAAAAAAAAAAGivKOhspzegbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKc3hGyvKUwA/vwQA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHDjGCRsqzIQaKsz4GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKcz0GyrOVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABw4xgkbKcygGyrM/hsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xspzeEbK81TAD+/BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaKNYTGynNpBsqzfwb
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrMvBooyRMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAGivOOhoqzOQbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirM4xwqzFszM8wFAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAB4t0iIaKcy/GyrM/hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrM8hopzVcAAP8BAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAq1AYaKs2FGynN+xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8aKc3nGSnOYyQktgcA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8BHSfNNBoqzdIbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrM/hsqzKcS
+        JMgOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGivKHRoqzMEbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzewbKMxwGTPMCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfwIZK9BHGyrM4Bsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xopzNsZKM0zAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wEb
+        K89BGynM4hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirN8RspzYAiM8wPAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAFX/AxwqzFsbKs3pGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzPIbKsxlAFWqAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAD+/BBsqzGUaKszvGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8aKcz2GynMkxYsxxcA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqKtQGGSrNbRoqzfAbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xopzPkbKcuMFy7QCwAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcHMYJGynMehspzPQbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xopzfobKsyoFi3KIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABw44gkaKst9GynM9Bsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xspzfsaKcukGDDOFQAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUq1Awb
+        KsyEGynM8xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/Bopzb0ZKNEyAAD/AQAAAAAAAAAAAAAAAAAAAAAA
+        AAAAEyfXDRsqy4saKs33GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xspzfsa
+        KcytGivKHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAFSq/DBsqzHgaKc3tGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKsz+GinM0RspykkA
+        P78EAAAAAAAAAAAAAAAAAAAAAAAAAAAeLdIRGyrLlhopzPkbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xopzPkaKc2kGivKHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfH78IGirOXxsqzN4bKsz+GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKc3iHCjOZBwcxgkAAAAAAAAAAAAAAAAAAAAAAAAAABgkzhUbKc2fGinN+hsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzPIbKcyNFy7FFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wMZ
+        Ksw8GyrMvBopzfobKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xopzO8bKMyDGijJEwAAAAAAAAAAAAAAAAAAAAAA
+        AAAAHijLGRoqzKMbKc37GyrN/xsqzf8bKs3/GyrM/hoqzN4bKs1nFy7QCwAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAR0nzRobKc2AGinN4xsqzP4bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirM+Bopy6Qd
+        K8sjAAD/AQAAAAAAAAAAAAAAAAAAAAAcL88bGinMrBspzfsbKs3/GirN9hkpzLEbKMw4AFX/AwAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMzPMBRoszTkaKculGinM7hsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs38GynNwxkqzDwAAKoDAAAAAAAAAAAAAAAAAAAAABkqzB4bKs2qGyrMzhopy2gc
+        KtQSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAFSq/DBwqzUgaKc2mGynN6Bsqzf0bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzP4bKc3cGynNXB8fvwgAAAAAAAAAAAAAAAAA
+        AAAAGDDOFRoryh0AAP8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGTPMChsozDgaKc2GGyrNzBsqzfEbKsz+GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xopzO4b
+        KsyDGijWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWqAxUqyRgZ
+        KM5FGynNghsqzbkaKczdGyrN8RspzfobKsz+GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ksz9GirN9xsqzesaKs3TGinLpRwryjUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAfwIVKtQMHi3KIhsry0AaKsxgGirMfhsrzZQaKculGirMrRopzLca
+        Ks2uGyrMpxopzZoaKc2HGynMbxwozFEYLMk0HSfNGh8fvwgAAP8BAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA
+        VaoDMzPMBSQktgcfH78IJCS2Byoq1AYAP78EAAD/AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////////////////////////////////
+        ///////////8//////////D/////////4f/////////D/////////4P/////////B///8AAH//4H//4A
+        AAB//Af/+AAAAD/4D//gAAAAH/gP/8AAAAAP8A//gAAAAA/gD/+AAAAAB+AP/wAAAAAH4Af/AAAAAAPA
+        B/8AAAAAA8AH/wAAAAADwAP/AAAAAAGAA/+AAAAAAYAB/4AAAAABgAH/gAAAAAGAAP/AAAAAAYAA/8AA
+        AAABgAB/wAAAAAGAAD/gAAAAAYAAH+AAAAABgAAf8AAAAAGAAA/4AAAAAYAAB/gAAAABgAAD/AAAAAHA
+        AAH+AAAAA8AAAP8AAAADwAAAfwAAAAPgAAA/gAAAB+AAAB/AAAAH8AAAD+AAAAfwAAAH4AAAD/gAAAPw
+        AAAf+AAAAfgAAB/8AAAA/AAAP/4AAAB+AAB//wAAAB8AAP//gAAAD4AB///AAAAHwAP//+AAAAPgB///
+        8AAAAPAP///8AAAAeD////8AAAA8f////8AAAB//////8AAAH//////+AAAf///////wB///////////
+        //////////////////////////////////////////////////////////////////////////////8o
+        AAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAD/Ah4oyxkcHMYJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAcHMYJGinNVxsrylMAM8wFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAABwqxhIaKc2GGyrOpxooyRMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGSbMFBopzZobKs3rGivQTAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA
+        AKoDAD+/BCoq1AYqKtQGKirUBgAzzAUAVf8DAAB/AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeLdIRGinMmRopzfkbKszGGijJEwAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/8EHyrJGBwryjUb
+        KsxVGirNchsqzYoaKc2aGirMoxopzasaKsytGinMrBspy6UbKc2fGyrNlRoqzIkbKcx6GivOaRkqy1kc
+        K8xHHyrJGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8fvwgbKMyDGirM+Bsqzf8a
+        KsuRAAD/AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEyfXDRspzkka
+        KcyZGinN0BsqzewaKcz5GyrM/hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ksz+GyrN/RspzfobKc31GyrMqBkmzBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/ARsqz1Ua
+        KczuGyrN/xsqzP4ZKs1sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wEd
+        Kc8rGyrMqBsqzfEbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GinM+RoqzH4zM8wFAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAHibQIRsqzc0bKs3/GyrN/xspzPwaKsxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAABonyicbKszGGyrM/hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xoqzeYZKcw9AAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAP78EGyjMgxsqzPwbKs3/GyrN/xsqzP4cKs1tAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAADPMBRopzJIbKs39GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf4b
+        Ks2pFSq/DAAAAAAAAAAAAAAAAAAAAAAZLMwoGinM2xsqzf8bKs3/GyrN/xsqzf8aKs2PAAD/AgAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHijLGRoqzNQbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8aKc3tGyrMQgAAAAAAAAAAAAAAAAAA/wEaKstzGynM/Bsqzf8bKs3/GyrN/xsqzf8a
+        Kcy/EiTIDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGi3KJxoqy+YbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKsz+GyvNlAA/vwQAAAAAAAAAABIk2g4aKc29GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKczpGCzNNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCrNJBspzOIb
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirN0xwlzxsAAAAAAAAAABsrzi8a
+        KczoGyrN/xsqzf8bKs3/GyrN/xsqzf8bKsz9GynNgAAA/wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAGijJExspzMsbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GynM8xopzUMA
+        AAAAAAAAABorzVgaKc36GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirN0xcvzyAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAD+/BBsqzJcbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrM/Rspzm8AAAAAAAAAABoqzn0bKsz+GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GynN+xorzXwA
+        P78EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABorzEwbKc3zGyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xspzZQAAP8CAACqAxsqzJcbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzd4aKdAxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwq1BIaKszAGyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xopzasAM8wFAD+/BBopzaQbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzP4bKc2mIiLMDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wEb
+        K85eGinM9hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzbMfH78IAD+/BBoqzqMb
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8aKcz2HCrNbQBV/wMAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAcKtQSGinMtxsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzbMf
+        H78IAAD/AhsqzZYbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GynN4hsqzEIA
+        AP8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGSjORRsqzOobKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzakAM8wFAAAAABspzHobKsz+GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xopzMkZLMwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCS2Bxkqy4obKc37GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xopzI4AAH8CAAAAABsrylMaKsz4GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf0bKsywHijLGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoryh0a
+        Ks3CGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GynM/BsqzWYAAAAAAAAAABgrzSkaKczjGyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKc37GirMnBwqxhIAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAEaKc1DGirM5Bsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GinM7RsozDgAAAAAAAAAABcu0Asb
+        Ks2zGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirM+BopzI4S
+        JMgOAAAAAAAAAAAAAAAAAAAAAAAAAAAAP78EGynMbxsqzfUbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GynMxRwq1BIA
+        AAAAAAAAAAAAAAAcK85jGinM+Rsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xoqzfYaKc2GEyfXDQAAAAAAAAAAAAAAAAAAAAAAAAAAEiTIDhopy5obKcz8GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks38GinNewAAfwIAAAAAAAAAAAAAAAAaK8odGynMzxsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs31GinNhhMn1w0AAAAAAAAAAAAAAAAAAAAAAAAAABoryh0b
+        Ks26GyrM/hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8aKs3eFynJKwAAAAAAAAAAAAAAAAAAAAAAAH8CHCrNbRoqzfgbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN9RsqzYofH88QAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAaKcoxGirM0Rsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzfwaKc2GAD//BAAAAAAAAAAAAAAAAAAAAAAAAAAAGCTOFRsqzbob
+        Ks3+GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xoqzfcb
+        KcyTGSbMFAAAAAAAAAAAAAAAAAAAAAAAAP8BGSvLRhspzeEbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xspzM8dK8sjAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAABwpzT4bKcziGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8aKcz5GinMoRwlzxsAAAAAAAAAAAAAAAAAAAAAAAD/AxspzVwbKs3rGyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GinM7xopzVcAAP8BAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAA/vwQbKs1nGyrN8Bsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GynN+xspzLEaKNAmAAAAAQAAAAAAAAAAAAAAACoq1AYb
+        KcxvGyrN8Rsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8aKsz4GyrMhB8f3wgA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcHMYJGijOfRspzfUbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzP0bKc3DHCrLNgAAfwIA
+        AAAAAAAAAAAAAAAZM8wKGirMfxspzfUbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xspzPsb
+        KsydHCrGEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFSrUDBoqzn4b
+        Ks3xGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ksz+GinM1Rsoy0sAP78EAAAAAAAAAAAAAAAAEyfXDRspy4waKsz4GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GinM+RspzaAVKskYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAABw44gkaK8xqGirM5Rsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xoqzOUbKs1nHBzGCQAAAAAAAAAAAAAAAB4t0hEbKs2WGinM+Rsqzf8b
+        Ks3/GyrN/xsqzf8bKczzGynMjRkmzBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP78EGSjLRRspzcQbKc37GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8aKszxGinNhhoo1hMAAAAAAAAAAAAAAAAZ
+        JswUGirMnBspzfobKs3/GyrM/hopzd0bKs1mFy7QCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/ARoryh0bKcuCGynN4RsqzP4b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GinM+RsozKgb
+        Kc4lAAD/AQAAAAAAAAAAFizHFxoqzKIaKc3tGyrMqBgszTQAAKoDAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        M8wFGSjLMhspzJMbKszfGynM/Bsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzP0aKs3HHCjOPwBVqgMAAAAAAAAAABcu0BYcKM4/EyfEDQAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAADMzzAUeKs4qGirLcxsqzLwbKczoGynN+hsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirM3hopzFYAAP8DAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/ARIkyA4aKskwGirMYBoqy5Ea
+        Ksy2GyrNzRopzNsbKcziGirM5RspzeEaKs3aGyrNzhsqzLoaKcyZGSrNbRkozTMAAKoDAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAA/wIcOMYJGijWExkqzB4cKs0kGifRJx0ryyMZKsweGSbMFBkzzAoAAKoDAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAA////////AAD///////8AAP///////wAA////////AAD/j/////8AAP8P////
+        /wAA/h//////AAD8P//wB/8AAPg//gAAHwAA8D/4AAAPAADgf+AAAAcAAOB/4AAABwAAwH/AAAADAADA
+        P8AAAAMAAIA/wAAAAQAAgD/AAAABAACAH8AAAAEAAIAfwAAAAQAAgA/gAAAAAAAAD+AAAAAAAAAH4AAA
+        AAAAAAPwAAAAAAAAAfgAAAAAAIAB+AAAAAAAgAD8AAABAACAAHwAAAEAAIAAPgAAAQAAwAAfAAABAADA
+        AA+AAAMAAMAAB8AAAwAA4AADwAAHAADwAAHgAAcAAPAAAHAADwAA+AAAOAAfAAD8AAAcAD8AAP4AAA4A
+        fwAA/wAABwD/AAD/gAABgf8AAP/gAADH/wAA//gAAH//AAD//gAAf/8AAP//4AP//wAA////////AAD/
+        //////8AAP///////wAA////////AAD///////8AAP///////wAAKAAAACgAAABQAAAAAQAgAAAAAABA
+        GgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHx/fCCQk2gcA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8BGijJJhopzVcnJ9cNAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AP8CHCjOPxoqzLAcKss2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH8CGSvLRhsqzNkbKsuVADPMBQAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//wQSJMgOHyrJGB4m0CEa
+        J9EnHCjKLBwo0CwYK80pGynOJRgpzR8fKtQYHCrUEhUqvwwqKtQGAAD/AQAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAABGifOOhsqzdgbKc31GynOSgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAATJ8QNGijNORoqy3MaKcukGynLwxspzNUbKszfGirM5RspzegbKczpGirN5hspzeIa
+        Kc3dGynN1RsqzcwaKc2/GirMrRoqzU4AAP8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGSrMHhsqzcIb
+        Ks3+GirM5Bot0ScAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVqgMcKMo/GyrMsBsqzewb
+        Ksz9GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8a
+        Ks3aHijNMwAAAAAAAAAAAAAAAAAAAAAAAAAAKirUBhspy4wbKcz8GyrN/xopzNsZKsweAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAA/wEaK8xMGynN4Rsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrM/hopzK0RIswPAAAAAAAAAAAA
+        AAAAAAAAABonzjobKczoGyrN/xsqzf8bKc3iGynHJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ
+        JtgUGynNxBsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKcz0GinMVgAAAAAAAAAAAAAAACoq1AYaKc2aGyrM/hsqzf8b
+        Ks3/GyrM8hwozj8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGynLNxopzO4bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xoqzLYTJ9cNAAAAAAAAAAAaKMkmGyrN3hsqzf8bKs3/GyrN/xsqzP0bKM13AAD/AQAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAABsrz0AbKcz0GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3sGyjMOAAAAAAA
+        AAAAGynNXBopzfobKs3/GyrN/xsqzf8bKs3/GirMwB4t0hEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
+        Ks8wGyrM6hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/RoqznMAAAAAAAD/AhspzJMbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzfIaKs1OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGijJExoqzcgbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKcynADPMBRwcxgkaKcy3GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GinMtx4t0hEA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAA/wIbKc2BGyrM/Rsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrNxSIizA8e
+        LcMRGirOyBsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xoqzfYbKs1nAAD/AgAAAAAAAAAAAAAAAAAAAAAA
+        AAAAGyzNLhspzeIbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzdQfKskYGijJExsqzs4bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN2RoqzzAAAAAAAAAAAAAAAAAAAAAAAAAAADMzzAUbKsuLGyrM/Rsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKc3XHSfNGh8vzxAaKs3IGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzP4b
+        KsywGDDOFQAAAAAAAAAAAAAAAAAAAAAAAAAAGynOJRoqzNQbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirN0xYs0hcf
+        H98IGirNtBsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GinN+RsqzIkZM8wKAAAAAAAAAAAA
+        AAAAAAAAAAAAfwIaKc1iGynM9Bsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzcIkJMgOAAB/Ahspzo0bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKszyGSrNbDMzzAUAAAAAAAAAAAAAAAAAAAAAEyfEDRspzZ8b
+        Ksz9GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKcufAD+/BAAAAAAbKs5UGirM+Bsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzOoZKstaAFX/AwAAAAAAAAAAAAAAAAAAAAAaKMkmGyrNzBsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKc37GyrMZQAAAAAA
+        AAAAFyfPIBsqzdcbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GinM4xwpz1AA
+        AKoDAAAAAAAAAAAAAAAAAAD/ARspykkaKs3mGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GynN4h0pySsAAAAAAAAAAAAAvwQbKs2LGyrN/Rsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKszgGSnLTwAAqgMAAAAAAAAAAAAAAAAA
+        P/8EHCrNbRspzfMbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrM/hspy58kJNoHAAAAAAAAAAAAAAAAGybNLhsqzd4bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xspzeEbK81SAD+/BAAAAAAAAAAAAAAAABcu0AsaKcyOGynN+hsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xspzOkZKcw9AAAAAAAAAAAA
+        AAAAAAAAAAAA/wMbKM13GinM+Rsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GirN5BspzVwzM8wFAAAAAAAAAAAAAAAAGCTOFRsqzKgbKs38GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzPwbKc6NJCS2BwAAAAAAAAAAAAAAAAAAAAAAAAAAGSbMFBoqza4b
+        Ksz+GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKszqGirMaxwcxgkA
+        AAAAAAAAAAAAAAAXJ88gGyrNuxsqzP4bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Kc3DGCnNHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYK80pGirNyBsqzP4bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzPEcKs5/IiLMDwAAAAAAAAAAAAAAABwo0Cwa
+        Kc3JGyrM/hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8aKszaGSvLOwAAAAEAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAD/ARwryjUaKczLGyrM/hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GirM9xsqzpceKMsZAAAAAAAAAAAAAP8BGynLNxopzNMbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8aKc3dGynOSgAA/wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AP8BGybHLhopzbgbKc37GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Kc37GynMshgrzSkAAP8BAAAAAAAA/wEbJ8tAGyrM2Rsqzf8bKs3/GyrN/xsqzP4bKczPGinNQwAA/wIA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJ80aGynLjBsqzewb
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf0aKszLGyvPQQAAqgMA
+        AAAAAAB/Ahkoy0YaKczdGyrN/xoqzfYbKs2pFynPKwAA/wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQk2gcYKs1IGirNthspzPQbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xspzeEaKc1iHBzGCQAAAAAAAP8CGyjLSxspzLob
+        Ks1mHx/PEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAB8vzxAcKMxRGinMqxoqzOUbKc37GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GirN8BopzYcZJswUAAAAAAAA/wIiIswPAAB/AgAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAABw4xgkcLcstGyrNZxoqzaEaKc3JGyrM4BsqzewbKszyGynM9BoqzfEbKs3rGyrM3xopzckb
+        Kc2fGSjNMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        M8wFHCrGEh0ryyMZKMsyGSrMPBsry0AaK846GirPMB4u0CEeLdIRMzPMBQAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
+        /////wAAAP//////AAAA//////8AAAD/P////wAAAPw/////AAAA+H////8AAADwf/gADwAAAOD/wAAH
+        AAAA4P8AAAcAAADA/gAAAwAAAMD+AAADAAAAgP4AAAEAAACAfgAAAQAAAIB+AAABAAAAAH4AAAAAAAAA
+        PgAAAAAAAAAfAAAAAAAAAB8AAAAAAAAAD4AAAAAAAAAHgAAAAAAAAAPAAAAAAACAAeAAAQAAAIAA4AAB
+        AAAAgABwAAEAAADAADgAAwAAAMAAHAADAAAA4AAOAAcAAADwAAcABwAAAPAAAwAPAAAA+AAAgB8AAAD+
+        AABAPwAAAP8AACD/AAAA/8AAEf8AAAD/8AAf/wAAAP/+AD//AAAA//////8AAAD//////wAAAP//////
+        AAAA//////8AAAD//////wAAACgAAAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AQBV/wMAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABw44gkbK8tAFizHFwAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfL88QGyjMgxsozGUA
+        AKoDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEiTaDhoqzZEa
+        KczRGCnNHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCTaBxgpzR8ZK887GyrOVBsqzWca
+        Ks1yGyrMeBkpzXYbKc5uHCvOZBoozVgbKctKGivOOh8vzxAAAAAAAAAAAAAAAAAAAAAAAAAAADMzzAUb
+        Kcx6GirM9xopzKsqKtQGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHx+/CBspy0obKsynGinM2xsqzfEa
+        Kc36GyrN/RsqzP4bKs3+GyrM/hsqzP4bKsz9GynN+xoqzfcaKs3wGynMkxcu0AsAAAAAAAAAAAAAAAAA
+        AAAAGinKRBspzOkbKs3/GynNlAAAfwIAAAAAAAAAAAAAAAAAAAAAAAAAACoq1AYbKs13GinM7hsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKczzGynKXQAA/wEA
+        AAAAAAAAABIkyA4aKsu0GyrN/xsqzf8bKc2gAACqAwAAAAAAAAAAAAAAAAAAAAAAAAAAGCzNNBopzecb
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8a
+        Kc3JHijLGQAAAAAAAAAAHCvMRxoqzfEbKs3/GyrN/xspzcQfL88QAAAAAAAAAAAAAAAAAAAAAAAAAAAb
+        Kc1cGyrM/Bsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xoqzPgcKsxbAAAAAAAAqgMaKcySGyrN/xsqzf8bKs3/GyrN7BsozDgAAAAAAAAAAAAAAAAA
+        AAAAAAAAABopzVcbKc36GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xopzaUqKtQGHy/PEBoqzccbKs3/GyrN/xsqzf8bKsz+GynMjQA/vwQA
+        AAAAAAAAAAAAAAAAAAAAGSjLMhspzOobKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirM0yEs0hceLcoiGyrM4Bsqzf8bKs3/GyrN/xsqzf8b
+        Kc3iGSjNMwAAAAAAAAAAAAAAAAAAAAATJ8QNGirMthsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8aKczoFynJKxwtyy0bKszqGyrN/xsqzf8b
+        Ks3/GyrN/xsqzP4aKc2lEiTIDgAAAAAAAAAAAAAAAAAAAAAaKMpYGynN9Rsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xopze8cKss2HC3LLRsqzOob
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xspzfUaKsxrAFX/AwAAAAAAAAAAAAAAAB8vzxAbKcyyGyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GinM7xwqyzYX
+        LtAhGyrM3xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xoqzeMaKc5EAAD/AQAAAAAAAAAAAAAAAB0pzD0a
+        KszlGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8a
+        Ks3mGCvNKSIizA8bKc3DGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xspzc8aKs8wAAAAAAAAAAAA
+        AAAAPz+/BBsqzngaKs34GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzc0ZJswUAAD/AhkqzYobKsz+GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrM/hoqzMEa
+        KNAmAAAAAAAAAAAAAAAAHCrGEhopzKsbKsz+GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GinMmQA/vwQAAAAAHCnJPhopze0bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/RsqzbkcKs0kAAAAAAAAAAAAAAAAGSzSKBsqy80bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xspzPMbKMtLAAAAAAAAAAAXLrkLGivNphsqzP4bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrM/RsqzLoaKNAmAAAAAAAAAAAAAP8BGinJQxspzeEbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirMtiIizA8AAAAAAAAAAAAAAAAbKcs3GynL4Rsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/RoqzcAbLM0uAAD/AQAAAAAAAKoDGynNXBsqzewb
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzOoZKMtFAAAAAAAAAAAAAAAAAAAAAAAA/wMa
+        KctoGyrM8hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrM/hsqzcwZK887AAB/AgAAAAAq
+        KtQGGyrNcRspzPMbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8aKs33GinLfCoq1AYAAAAAAAAAAAAAAAAA
+        AAAAAAAAABw4xgkaKsx/GynM9Bsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzdkZ
+        KctPAD+/BAAAAAAZM8wKGynNgRoqzfYbKs3/GyrN/xsqzf8bKs3/GinM+Rspy5UiIswPAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAABcu0AsaKcx1GyrN6xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xopzecaKMxqGTPMCgAAAAATJ9cNGynMjRoqzPgbKs3/GyrN/xspzPMbKc2MHCrGEgAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoq1AYaKs1OGinNyRspzfsbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzfIbKs2KGSbMFAAAAAAfL88QGynNlBoqzfcaKs3aGyrMZRcu0AsA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wEaK8odGynMehsqzdQa
+        Kcz5GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xopzfoaKc6sGSbMKAAA/wEcKtQSHCvOZBwo0CwA
+        AP8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AP8CGSrUHhoqzl8bKs6nGynM1hopze0aKsz4GynN+xsqzfwbKc36GinN9hspzegbKcyeFy7QFgAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAACoq1AYdJ80aHCvKNRorzEwcKsxbGirLXxopzVcZK8tGGyvOLxcu0BYA
+        Vf8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAA///////////8////+P////D////h/gAHwfgAA8HwAAGB8AABgfAAAQHwAAAA
+        8AAAAPAAAAB4AAAAOAAAABwAAAAcAAAADgAAgAcAAYADAAHAAIADwABAA+AAIAfwABAP+AAIH/wAAD//
+        AAP//+AD//////////////////////8oAAAAGAAAADAAAAABACAAAAAAAGAJAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/ARgpzR8dJ80aAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AP8BGSrQPBspzYESJMgOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAzzAUZM8wKEiTIDiIizA8T
+        J9cNGTPMCioq1AYAAKoDAAAAAAAAAAAAAAAAAAAAAAAAAAAdLM00GynNzxoqzl8AAAAAAAAAAAAAAAAA
+        AAAAAAAAABUqvwwbKsxCGynNgBsqzKgaKc29GyrNxRoqzccbKc3DGyrMvBsqzLAbKsycGSvPOwAA/wEA
+        AAAAAAAAABgkzhUbKc24GyrN8hgpzT4AAAAAAAAAAAAAAAAAAAAAGSbMFBoqzJwaKs3wGyrM/hsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrMxhoryh0AAAAAAAD/ARsqzWcaKs34GinN9hwqyUgA
+        AAAAAAAAAAAAAAAAAAAAHCnLYxopzfobKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GynN+xsozXcAAH8CIjPMDxoqzMAbKs3/GyrM/hspzHoAAP8BAAAAAAAAAAAAAAAAGyrMhBsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xopzckZJswUGirPMBsqzOob
+        Ks3/GyrN/xsqzMYYJM4VAAAAAAAAAAAAAAAAGSnLYxspzfsbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xopzO4bKcs3GivNTRoqzfgbKs3/GyrN/xoqzfcbKs1mAAB/AgAAAAAA
+        AAAAGi3RJxsqzd4bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xopzfob
+        K81TGSjLWRspzfsbKs3/GyrN/xsqzf8bKc3XHCjQLAAAAAAAAAAAAD+/BBopzIgbKs38GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzfwbK81dGivNTRoqzPgbKs3/GyrN/xsqzf8b
+        Ksz+GirNrhgkzhUAAAAAAAAAAB4lyiIbKczPGyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xopy/obK81SGyzNLhspzegbKs3/GyrN/xsqzf8bKs3/GinN+hoqzZETJ9cNAAAAAAAA/wEb
+        Ks5UGinN7hsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzesZKM0zEyfXDRsqzLsb
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xoqzfYbKc2CFy7QCwAAAAAkJNoHGirNhRopzPkbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xoqzMEfL88QAAAAARoqy18aKs32GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Kcz0GynNgRUq1AwAAAAAGijJExsqzKgbKsz9GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GirN+Bopy2gA
+        AP8BAAAAAB4twxEaKs2uGyrM/hsqzf8bKs3/GyrN/xsqzf8bKs3/GynN9RsqzYoeLcMRAAAAAB4u0CEa
+        Kc2/GyrM/hsqzf8bKs3/GyrN/xsqzf8bKsz+GinNuBgkwhUAAAAAAAAAAAAAAAAcKMosGyrNzBsqzP4b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xoqzfgaKs2cHijLGQAAAAAbK84vGyrNzRsqzf8bKs3/GyrN/xsqzf8b
+        KczVHSfNNAAAAAAAAAAAAAAAAAAAAAAAAP8BGCzNNBspzcQbKsz9GyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Kc37GyrNsxgrzSkAAH8CGifOOhspzNUbKs3/GyrM/hspzc8cKM4/AAD/AQAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAARcu0CEbKs2VGyrN7Bsqzf8bKs3/GyrN/xsqzf8bKs3/GyrM/hspzcwbKsxCAD+/BBsry0Eb
+        KczPGynMphcpySsAAP8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfH78IGyvLQBoqzJwa
+        Ks3aGynN9Rsqzf0bKs3/GyrN/xsqzP4bKszfGinMVgAzzAUYKc0fFSrUDAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzzAUXJ8cgHCvMRxoqzGsbKc2BGirNhRsqzngb
+        KcpdGyzNLgAAqgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////APv//wDj//8Aw/AHAMfAAQCHgAEAB4AAAAOAAAAD
+        gAAAAYAAAAGAAAAAwAAAAEAAAAAgAAAAEAAAgAgBAMAEAwDAAAMA4AAHAPgAHwD+AH8A////AP///wD/
+        //8AKAAAABQAAAAoAAAAAQAgAAAAAACQBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAD/ASoq1AYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzzAUaKc1DHCrNJAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKoDGynNXRopzJgc
+        HMYJAAAAAAAAAAAAAAAAAAD/AhgpzR8aKMxMGynLbhspy4EaKc2HGyrMgxsqzHkaKctpGinNQwAzzAUA
+        AAAAAAAAABooyTkbKc3hGynNgQAAAAAAAAAAAAAAAAA/vwQaKsxgGynN1RoqzPcbKsz+GyrN/xsqzf8b
+        Ks3/GyrN/xsqzP4aKs3mGinORAAAAAAcOMYJGynMpxsqzf4bKc2MAAD/AQAAAAAAAAAAHibIIRoqzdob
+        Ks3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKcyyFSrUDBsrzi8aKc3nGyrN/xoqzcAf
+        L88QAAAAAAAAAAAdKc8rGynM6Bsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzOwc
+        K841HCrLWhspzfsbKs3/GyrM8hoqyk4AAAAAAAAAABwqxhIbKszGGyrN/xsqzf8bKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GyrN/BoqzGAbK8xwGyrN/hsqzf8bKs3/GinNvx4oyxkAAAAAAAD/ARspy24a
+        Kc35GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/HCvKdRopzWgbKs39GyrN/xsqzf8b
+        Kcz7GynLjBkzzAoAAAAAFizHFxoqzb8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzP4c
+        KsttGinKRBspzfMbKs3/GyrN/xsqzf8bKczzGynObioq1AYAAAAAGinNQxoqzeYbKs3/GyrN/xsqzf8b
+        Ks3/GyrN/xsqzf8bKs3/GynN9RwqzUgWLMcXGinMyxsqzf8bKs3/GyrN/xsqzf8bKs3sGSvOZDMzzAUA
+        P78EGynMbxspzfUbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8aKczQHSfNGgAA/wEaKc1oGirM9xsqzf8b
+        Ks3/GyrN/xsqzf8bKszsGinNaCQk2gcXLtALGirNkBopzfobKs3/GyrN/xsqzf8bKs3/GinM+RsozHAA
+        AH8CAAAAACIzzA8aKs2hGynM/Bsqzf8bKs3/GyrN/xsqzf8aKczvGyrMeBUqvwwZJswUGynMphsqzfwb
+        Ks3/GyrN/xsqzP0aKcyrGijJEwAAAAAAAAAAAAAAABwlzxsaKculGinM+Rsqzf8bKs3/GyrN/xsqzf8b
+        Kc31GirNkBcuxRYbLdEcGynMshsqzP0bKcz7GyrNsBcnzyAAAAAAAAAAAAAAAAAAAAAAAAAAABwqxhIZ
+        Kc12GinN3BsqzfwbKs3/GyrN/xsqzf8bKc36GirNrhkmzCgeLdIiGyrNqRsqzIQWLMcXAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAqgMZLMwoGinMdRspzbkaKczbGynM6RsqzOobKc3hGirNmxcuxRYV
+        KtQMMzPMBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8BFy7QCxor0x0c
+        KMosGyzNLhspxyUaKNYTAACqAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///AA5//wAMf/8ACHABAAjgAQAAYAAAAGAAAABgAAAAIAAAAB
+        AAAAAIAAAAAAAAAAAAAAgAAQAMAAMADgAHAA8ADwAPwD8AD///AA///wACgAAAAQAAAAIAAAAAEAIAAA
+        AAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcHMYJGCTOFQAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVKtQMGSnLbhks0igAAAAAAAAAAAAAAAAZ
+        M8wKGynOJRorzjoaKc1DGyrMQhkryzsbLM0uFy7QCwAAAAAAAKoDGynLbhsqzLwSJMgOAAAAAAAAAAAc
+        KMosGinMrBspzeIbKs3xGynN9RspzfUbKszyGynM6RspzHoAP78EHSvLIxsqzNkbKs3MGijJEwAAAAAA
+        AP8CGyrLlhsqzP4bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKszgGCrOKhsoy14bKcz7GinN7hwozj8A
+        AAAAAAD/AhsqzJcbKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/BsqzWcaKs2FGyrN/xsqzf4b
+        KcynEyfEDQAAAAAaKs1OGynM8xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrN/xsqzf8bKc2MGyrMhBsqzf8b
+        Ks3/GynN9RoqzGsAP78EEyfXDRopzasbKsz+GyrN/xsqzf8bKs3/GyrN/xsqzf8bKs3/GyrNixwqzFsb
+        Kc36GyrN/xsqzf8aKcznHCjMUQAA/wIaKcoxGirM2hsqzf8bKs3/GyrN/xsqzf8bKs3/GynN+xopzWIX
+        J88gGynM1Rsqzf8bKs3/GyrN/xsqzOAaK8pNADPMBRopzVcbKs3sGyrN/xsqzf8bKs3/GyrN/xoqzNoc
+        Ks0kAAD/AhsqzGUbKczzGyrN/xsqzf8bKs3/GynM4hopzVcXLrkLGirLcxspzfMbKs3/GyrN/xopzPYb
+        KcxvAACqAwAAAAAZM8wKGinNfBopzfAbKs3/GyrN/xsqzf8bKszqGynLbhkmzBQbKs6DGirN9hspzfMa
+        KcyIFSrUDAAAAAAAAAAAAAAAAB8fvwgbKsxVGynNxBspzfUbKs3/GyrN/xspzfMaKcyOHSvLIxsqzHka
+        Ks1hGTPMCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/ARgkzhUbKMtLGyrOgxoqzKMbKc2mGivMjhoqyTAA
+        AKoDAAD/AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAVaoDAD+/BAAA/wEA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAM//AACOAQAADAAAAAgAAAAIAAAABAAAAAAAAAAA
+        AAAAAAAAAAAAAACAAQAAwAMAAOAHAAD8PwAA//8AAA==
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_SmartVision/logo.ico b/LB_SmartVision/logo.ico
new file mode 100644
index 0000000..5887476
--- /dev/null
+++ b/LB_SmartVision/logo.ico
Binary files differ
diff --git a/LB_SmartVision/ref/halcondotnet.dll b/LB_SmartVision/ref/halcondotnet.dll
new file mode 100644
index 0000000..bb41201
--- /dev/null
+++ b/LB_SmartVision/ref/halcondotnet.dll
Binary files differ
diff --git a/LB_SmartVisionCameraDevice/CameraUserRole.cs b/LB_SmartVisionCameraDevice/CameraUserRole.cs
new file mode 100644
index 0000000..f3f96e2
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/CameraUserRole.cs
@@ -0,0 +1,27 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCameraDevice
+{
+    /// <summary>
+    /// 鐩告満鍙傛暟鍙鍖栨潈闄�
+    /// </summary>
+    public enum CameraUserRole
+    {
+        /// <summary>
+        /// 鍒濈骇
+        /// </summary>
+        Primary,
+        /// <summary>
+        /// 涓撳
+        /// </summary>
+        Expert,
+        /// <summary>
+        /// 澶у笀
+        /// </summary>
+        Master,
+    }
+}
diff --git a/LB_SmartVisionCameraDevice/Data/StateIcon.cs b/LB_SmartVisionCameraDevice/Data/StateIcon.cs
new file mode 100644
index 0000000..e0b4389
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/Data/StateIcon.cs
@@ -0,0 +1,31 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCameraDevice.Data
+{
+    /// <summary>
+    /// StateIcon
+    /// </summary>
+    public class StateIcon
+    {
+        /// <summary>
+        /// Connect
+        /// </summary>
+        public const string Connect = "Connect";
+        /// <summary>
+        /// DisConnect
+        /// </summary>
+        public const string DisConnect = "disConnect";
+        /// <summary>
+        /// Start
+        /// </summary>
+        public const string Start = "Start";
+        /// <summary>
+        /// StartRepeat
+        /// </summary>
+        public const string StartRepeat = "StartRepeat";
+    }
+}
diff --git a/LB_SmartVisionCameraDevice/DeviceType.cs b/LB_SmartVisionCameraDevice/DeviceType.cs
new file mode 100644
index 0000000..cc93a90
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/DeviceType.cs
@@ -0,0 +1,27 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCameraDevice
+{
+    /// <summary>
+    /// CameraType
+    /// </summary>
+    public enum DeviceType
+    {
+        /// <summary>
+        /// 6000绯诲垪鎵弿澶村瓙
+        /// </summary>
+        PHM6000Series,
+        /// <summary>
+        /// 5000绯诲垪鎵弿澶村瓙
+        /// </summary>
+        PHM5000Series,
+        /// <summary>
+        /// 2000绯诲垪鎵弿澶村瓙
+        /// </summary>
+        PHM2000Series
+    }
+}
diff --git a/LB_SmartVisionCameraDevice/LB_SmartVisionCameraDevice.csproj b/LB_SmartVisionCameraDevice/LB_SmartVisionCameraDevice.csproj
new file mode 100644
index 0000000..494c1fd
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/LB_SmartVisionCameraDevice.csproj
@@ -0,0 +1,25 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Library</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <Nullable>enable</Nullable>
+    <UseWindowsForms>true</UseWindowsForms>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\LB_SmartVisionCameraSDK\LB_SmartVisionCameraSDK.csproj" />
+    <ProjectReference Include="..\LB_SmartVisionCommon\LB_SmartVisionCommon.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="ref\" />
+  </ItemGroup>
+
+</Project>
\ No newline at end of file
diff --git a/LB_SmartVisionCameraDevice/PHM6000/CaliModel.cs b/LB_SmartVisionCameraDevice/PHM6000/CaliModel.cs
new file mode 100644
index 0000000..2ed42fd
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/PHM6000/CaliModel.cs
@@ -0,0 +1,73 @@
+锘縰sing LB_SmartVisionCommon;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVisionCameraDevice.PHM6000
+{
+    [JsonObject(MemberSerialization.OptOut)]
+    [TypeConverter(typeof(PropertySorter))]
+    [DefaultProperty("骞抽潰鍖�")]
+    public class CaliModel
+    {
+        protected const string ROIInfo = "鏍囧畾ROI鏁版嵁";
+        protected const string CameraInfo = "鐩告満瀹夎鍙傛暟";
+        [Category(ROIInfo), PropertyOrder(10)]
+        [DisplayName("骞抽潰鍖�")]
+        public string Plane { get; set; } = "0,0,0,0";
+        [Category(ROIInfo), PropertyOrder(11)]
+        [DisplayName("瀛斿尯1")]
+        public string Hole1 { get; set; } = "0,0,0,0";
+        [Category(ROIInfo), PropertyOrder(12)]
+        [DisplayName("瀛斿尯2")]
+        public string Hole2 { get; set; } = "0,0,0,0";
+        [Category(ROIInfo), PropertyOrder(13)]
+        [DisplayName("瀛斿尯3")]
+        public string Hole3 { get; set; } = "0,0,0,0";
+        //[Browsable(false)]
+        [Category(CameraInfo), PropertyOrder(14)]
+        [DisplayName("x鍊掑簭")]
+        public int IsReverse { get; set; } = 0;        //x鍊掑簭
+        [Category(CameraInfo), PropertyOrder(15)]
+        [DisplayName("z鐩稿")]
+        //[Browsable(false)]
+        public int IsOpposite { get; set; } = 0;       //z鐩稿
+        [Category(CameraInfo), PropertyOrder(16)]
+        [DisplayName("鏍囧噯璺濈")]
+        //[Browsable(false)]
+        public float fStdDistance { get; set; } = 325;
+        [Category(CameraInfo), PropertyOrder(17)]
+        [DisplayName("X杞翠腑蹇�")]
+        //[Browsable(false)]
+        public float fXCenter { get; set; } = 215.04f;
+        [Category(CameraInfo), PropertyOrder(18)]
+        [DisplayName("X杞�")]
+        //[Browsable(false)]
+        public float x { get; set; } = 0;
+        [Category(CameraInfo), PropertyOrder(19)]
+        [DisplayName("Y杞�")]
+        //[Browsable(false)]
+        public float y { get; set; } = 0;
+        [Category(CameraInfo), PropertyOrder(20)]
+        [DisplayName("Z杞�")]
+        //[Browsable(false)]
+        public float z { get; set; } = 417.75f;
+        [Category(CameraInfo), PropertyOrder(21)]
+        [DisplayName("X杞磋搴�")]
+        //[Browsable(false)]
+        public float xAngle { get; set; } = 0;
+        [Category(CameraInfo), PropertyOrder(22)]
+        [DisplayName("Y杞磋搴�")]
+        //[Browsable(false)]
+        public float yAngle { get; set; } = 0;
+        [Category(CameraInfo), PropertyOrder(23)]
+        [DisplayName("Z杞磋搴�")]
+        //[Browsable(false)]
+        public float zAngle { get; set; } = 0;
+    }
+}
diff --git a/LB_SmartVisionCameraDevice/PHM6000/CaliOutLine.cs b/LB_SmartVisionCameraDevice/PHM6000/CaliOutLine.cs
new file mode 100644
index 0000000..5ebcdc4
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/PHM6000/CaliOutLine.cs
@@ -0,0 +1,23 @@
+锘縰sing LB_SmartVisionCommon;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVisionCameraDevice.PHM6000
+{
+    [JsonObject(MemberSerialization.OptOut)]
+    [TypeConverter(typeof(PropertySorter))]
+    [DefaultProperty("杞粨绾�")]
+    public class CaliOutLine
+    {
+        protected const string ROIInfo = "鏍囧畾ROI鏁版嵁";
+        [Category(ROIInfo), PropertyOrder(1)]
+        [DisplayName("杞粨绾垮尯鍩�")]
+        public string OutLine { get; set; } = "0,0,0,0";
+    }
+}
diff --git a/LB_SmartVisionCameraDevice/PHM6000/PHM6000Sensor.cs b/LB_SmartVisionCameraDevice/PHM6000/PHM6000Sensor.cs
new file mode 100644
index 0000000..6f81e95
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/PHM6000/PHM6000Sensor.cs
@@ -0,0 +1,1230 @@
+锘縰sing LB_SmartVisionCameraSDK;
+using LB_SmartVisionCameraSDK.PHM6000;
+using LB_SmartVisionCommon;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVisionCameraDevice.PHM6000
+{
+    /// <summary>
+    /// PHM6000Series-Sensor
+    /// </summary>
+    public class PHM6000Sensor
+    {
+        public IntPtr Entry { get; set; }//杩炴帴浼犳劅鍣ㄧ殑鎺ュ彛
+        public string IP { get; set; }//浼犳劅鍣↖P
+        public string SerialNo { get; set; }//浼犳劅鍣ㄥ簭鍒楀彿
+        public int Port { get; set; }//绔彛
+        List<byte[]> LineDatas { get; set; } = new List<byte[]>();//瀛樺偍鎵弿鍒扮殑琛屾暟鎹�
+        public IntPtr CaliEntry = IntPtr.Zero;//娴嬮噺鏍囧畾鍏ュ彛
+        readonly object _lock = new object();
+        readonly object _lockIntPtr = new object();
+        //public PanelControl PointPanel { get; set; }
+        //WaitForm ssm;
+        public int Index { get; set; }//浼犳劅鍣ㄥ簭鍙凤紝涓昏鐢ㄤ簬鏍囧畾
+        public IntPtr lightPic = IntPtr.Zero;//浜害鍥�
+        public IntPtr deepPic = IntPtr.Zero;//娣卞害鍥�
+        public IntPtr pointPic = IntPtr.Zero;//鐐逛簯鍥�
+        public IntPtr outlinePic = IntPtr.Zero;//杞粨鍥�
+        public IntPtr outlineMainPic = IntPtr.Zero;//涓荤晫闈㈣疆寤撳浘
+        public CaliModel CaliModel { get; set; }//娴嬮噺鐢ㄥ弬鏁�
+        public CaliOutLine CaliOutLine { get; set; }//娴嬮噺鐢ㄥ弬鏁�
+
+        public bool isContinuousScan = false;
+
+        CancellationTokenSource lightCts;
+        CancellationTokenSource deepCts;
+        CancellationTokenSource pointCts;
+        CancellationTokenSource outlineCts;
+        //PILOT2D_FUNC func2d;
+        //VTK3D_FUNC func3d;
+        AcquisitionCallbackZA sendDatacallback;//鍥炶皟濮旀墭(琛屾暟鎹彂閫佺粰鏈郴缁�)
+
+        string path = string.Empty;
+
+        //int currentRowNumber = 0;
+        /// <summary>
+        /// 鍒濆鍖栦紶鎰熷櫒
+        /// </summary>
+        /// <param name="ip">浼犳劅鍣↖P</param>
+        /// <param name="serialNo">浼犳劅鍣ㄥ簭鍒楀彿</param>
+        /// <param name="port">浼犳劅鍣ㄧ鍙�</param>
+        /// <param name="localPtr">鏈郴缁熺敤浜庢壙杞藉浘鐗囩殑鎺т欢鎸囬拡</param>
+        public PHM6000Sensor(string ip, string serialNo, int port, int index/*, WaitForm ssm*/)
+        {
+            this.IP = ip;
+            this.SerialNo = serialNo;
+            this.Port = port;
+            this.Index = index;
+            //this.ssm = ssm;
+            CaliEntry = SysCalibration.CreateSysCalibrationEntry();//娴嬮噺鏍囧畾鍏ュ彛
+        }
+        public int GetLineCount()
+        {
+            int count;
+            lock (_lock)
+            {
+                count = LineDatas.Count;
+            }
+            return count;
+        }
+        public List<byte[]> GetLineDatas()
+        {
+            LineDatas.Clear();
+            var o = new List<byte[]>();
+            lock (_lock)
+            {
+                IntPtr pData = IntPtr.Zero;
+                ulong nIndex = 0;
+                //Config config;
+                //if (!IP.Equals("0.0.0.0"))
+                //{
+                //    config = GetConfig();
+                //}
+                //else
+                //{
+                //    config = new Config();
+                //}
+                uint count = 0;
+                while ((pData = PHM6000Profiler.GetLineDataByIndex(Entry, nIndex)) != IntPtr.Zero)
+                {
+                    unsafe
+                    {
+                        LBLineHeadInfo pInfo = Marshal.PtrToStructure<LBLineHeadInfo>(pData);
+                        count = pInfo.nPointCount;
+                    }
+                    LBLineDataZA lBLineDataZA = new LBLineDataZA
+                    {
+                        info = new LBLineHeadInfo(),
+                        data = new LBPointZA[count]
+                    };
+                    long length = Marshal.SizeOf(lBLineDataZA) + Marshal.SizeOf(new LBPointZA()) * count;
+                    int datacount = int.Parse(length.ToString());
+                    byte[] byteArray = new byte[length];
+                    Marshal.Copy(pData, byteArray, 0, datacount);
+                    LineDatas.Add(byteArray);
+                    nIndex++;
+                }
+                o.AddRange(LineDatas);
+            }
+            return o;
+        }
+        IntPtr Temp = IntPtr.Zero;
+        public IntPtr GetLineLastData()
+        {
+            lock (_lock)
+            {
+                IntPtr pData = IntPtr.Zero;
+
+                Temp = IntPtr.Zero;
+                ulong nIndex = 0;
+                uint count = 0;
+                while ((pData = PHM6000Profiler.GetLineDataByIndex(Entry, nIndex)) != IntPtr.Zero)
+                {
+                    //Marshal.FreeHGlobal(Temp);
+                    Temp = pData;
+                    //SysCalibration.AddLineDataArray(CaliEntry, Index, Temp, false, 1);
+                    SysCalibration.SetLineDataArray(CaliEntry, Index, Temp);
+                    nIndex++;
+                }
+                if (pData == IntPtr.Zero)
+                {
+
+                }
+            }
+            return Temp;
+        }
+
+        #region 鍒涘缓鍥剧墖鎺т欢
+        public IntPtr CreatePicPtr(IntPtr localPtr, EnumFetchPicType picType)
+        {
+            IntPtr ptr = IntPtr.Zero;
+            PHM6000SensorConfig config;
+            if (!IP.Equals("0.0.0.0"))
+            {
+                config = GetConfig();
+            }
+            else
+            {
+                config = new PHM6000SensorConfig();
+            }
+            switch (picType)
+            {
+                case EnumFetchPicType.light:
+                    if (lightPic == IntPtr.Zero)
+                    {
+                        ptr = Pilot2D.CreatePilot2DEntry(localPtr);
+                        Pilot2D.SetImageSize(ptr, 4096, config.ScanLineCount);
+                        lightPic = ptr;
+                    }
+                    break;
+                case EnumFetchPicType.deep:
+                    if (deepPic == IntPtr.Zero)
+                    {
+                        ptr = Pilot2D.CreatePilot2DEntry(localPtr);
+                        Pilot2D.SetImageSize(ptr, 4096, config.ScanLineCount);
+                        deepPic = ptr;
+                    }
+                    break;
+                case EnumFetchPicType.pointCloud:
+                    if (pointPic == IntPtr.Zero)
+                    {
+                        ptr = PclEntry.CreatePCLWindow(localPtr);
+                        //PclInvoke.RenderPCLWindow(ptr, 800, 600);
+                        pointPic = ptr;
+                    }
+                    break;
+                case EnumFetchPicType.outline:
+                    if (outlinePic == IntPtr.Zero)
+                    {
+                        ptr = Pilot2D.CreatePilot2DEntry(localPtr);
+                        Pilot2D.SetImageSize(ptr, 4096, 2048);
+                        outlinePic = ptr;
+                    }
+                    break;
+                case EnumFetchPicType.mainOutLine:
+                    if (outlineMainPic == IntPtr.Zero)
+                    {
+                        ptr = Pilot2D.CreatePilot2DEntry(localPtr);
+                        Pilot2D.SetImageSize(ptr, 4096, 2048);
+                        outlineMainPic = ptr;
+                    }
+                    break;
+            }
+            return ptr;
+        }
+        #endregion
+        event AcquisitionCompletedCallback acquisitionCompletedCallback = null;
+
+        public event AcquisitionCompletedCallback acquisitionCompleted = null;
+
+        public event ShowDebugInfoCallback registerShowDebugInfoCallback = null;
+
+        public void RegisterShowDebugInfoCallback(ShowDebugInfoCallback callback)
+        {
+            PHM6000Profiler.RegisterShowDebugInfoCallback(Entry, callback);
+        }
+
+        PILOT2D_FUNC func2d = new PILOT2D_FUNC
+        {
+            AddBarycentreDataZA = Pilot2D.AddBarycentreDataZA,
+            AddDepthData = Pilot2D.AddDepthData,
+            AddIntensityData = Pilot2D.AddIntensityData,
+            ClearAllPoints = Pilot2D.ClearAllPoints,
+            RefreshPilot2D = Pilot2D.RefreshPilot2D,
+            SetImageSize = Pilot2D.SetImageSize,
+        };
+
+        VTK3D_FUNC func3d = new VTK3D_FUNC
+        {
+            AddZAPoints = PclEntry.AddZAPoints,
+            ClearPCLPoints = PclEntry.ClearPCLPoints,
+            GetPointCloudBound = PclEntry.GetPointCloudBound,
+            RenderPCLWindow = PclEntry.RenderPCLWindow,
+            SetLookUpTableRange = PclEntry.SetLookUpTableRange,
+            ShowCubeAxes = PclEntry.ShowCubeAxes,
+            ShowLookUpTable = PclEntry.ShowLookUpTable,
+            UpdatePCLPointColors = PclEntry.UpdatePCLPointColors,
+        };
+
+        public void StartDataProcess()
+        {
+            //SetShowHandles(Entry, lightPic, deepPic, outlinePic, pointPic);
+            acquisitionCompletedCallback += PHM6000Sensor_acquisitionCompletedCallback;
+
+            PHM6000Profiler.SetPilot2dFunc(Entry, func2d);
+            PHM6000Profiler.SetVTK3dFunc(Entry, func3d);
+            PHM6000Profiler.RegisterAcquisitionCompletedCallback(Entry, acquisitionCompletedCallback, new IntPtr());
+        }
+        public void CameraShow()
+        {
+            PHM6000Profiler.SetShowHandles(Entry, lightPic, deepPic, outlinePic, pointPic);
+        }
+        public void MainShow()
+        {
+            PHM6000Profiler.SetShowHandles(Entry, lightPic, deepPic, outlineMainPic, pointPic);
+        }
+
+        public IntPtr hWnd;
+        private void PHM6000Sensor_acquisitionCompletedCallback(IntPtr pInstance, int nOption)
+        {
+            if (nOption == 2)
+            {
+                //鏄剧ず鐐逛簯
+                bool result = PclEntry.PostMessage(hWnd, CommonVar.WM_RENDER_VTK, 0, (ulong)pInstance);  // m_hMainWnd鏄富绐楀彛鍙ユ焺
+            }
+            if (acquisitionCompleted != null)
+            {
+                acquisitionCompleted(pInstance, nOption);
+            }
+        }
+        public IntPtr PInstance;
+
+
+        #region 杩炴帴浼犳劅鍣�
+        public bool ConnectCamera()
+        {
+            Entry = PHM6000Profiler.CreateCameraEntry();
+            var addr = Encoding.ASCII.GetBytes(IP);
+            var result = PHM6000Profiler.ConnectToCamera(Entry, addr, Port);
+            if (result == 0)
+            {
+                return true;
+            }
+            return false;
+        }
+        #endregion
+        #region 浠庝紶鎰熷櫒鑾峰彇鍙傛暟閰嶇疆
+        public PHM6000SensorConfig GetConfig()
+        {
+            //鑾峰彇鍙傛暟
+            PHM6000SensorConfig config;
+            if (IP.Equals("0.0.0.0"))
+            {
+                config = new PHM6000SensorConfig();
+                return config;
+            }
+            //鍏堜粠鏈湴鑾峰彇閰嶇疆
+            path = $"{SerialNo}-config.lb";
+            if (File.Exists(path))
+            {
+                config = ConfigManager<PHM6000SensorConfig>.LoadConfig<PHM6000SensorConfig>(@path);
+            }
+            else
+            {
+                config = new PHM6000SensorConfig();
+            }
+            //-----------------
+            PropertyInfo[] props = config.GetType().GetProperties();
+            foreach (PropertyInfo p in props)
+            {
+                //璺宠繃鑷畾涔夊弬鏁�
+                var iscustomAttr = p.GetCustomAttribute<IsCustomAttribute>();
+                if (iscustomAttr != null) continue;
+                var nameId = Enum.Parse(typeof(EnumNameId), p.Name);
+                int intValue = 0;
+                double doubleValue = 0;
+                int enumValue = 0;
+                var id = Convert.ToInt32(nameId);
+                var rst = PHM6000Profiler.GetProfilerParameter(Entry, id, ref intValue, ref doubleValue, ref enumValue);
+                if (rst == 0)
+                {
+                    if (p.PropertyType == typeof(int))
+                    {
+                        p.SetValue(config, intValue);
+                    }
+                    else if (p.PropertyType == typeof(float))
+                    {
+                        var value = Convert.ToSingle(doubleValue);
+                        p.SetValue(config, value);
+                    }
+                    else
+                    {
+                        if (p.Name.Equals("ROI"))
+                        {
+
+                        }
+                        else
+                        {
+                            p.SetValue(config, enumValue);
+                        }
+                    }
+                }
+            }
+            return config;
+        }
+        #endregion
+        void SetTargetParam(PHM6000SensorConfig config)
+        {
+            TARGET_INFO tARGET_INFO = new TARGET_INFO()
+            {
+                //fHeight = config.fHeight,
+                //fWidth = config.fWidth,
+                //fMarginRangeX = config.fMarginRangeX,
+                //fMarginRangeY = config.fMarginRangeY,
+                //fMarginX = config.fMarginX,
+                //fMarginY = config.fMarginY,
+                //nPartitionX = config.nPartitionX,
+                //nPartitionY = config.nPartitionY,
+            };
+            SysCalibration.SetTargetParameter(CaliEntry, tARGET_INFO);
+        }
+        #region 璁剧疆鍙傛暟
+        public bool SetConfig(PHM6000SensorConfig config)
+        {
+            //灏嗛厤缃繚瀛樺埌鏈湴
+            path = $"{SerialNo}-config.lb";
+            ConfigManager<PHM6000SensorConfig>.SaveConfig<PHM6000SensorConfig>(config, @path);
+            SetTargetParam(config);
+            //-----------
+
+            int result = 0;
+            var type = config.GetType();
+            var propLineScan = type.GetProperty(nameof(config.LineScanTriggerSource));
+            var val = (EnumLineScanTriggerSource)propLineScan.GetValue(config);
+            var props = config.GetType().GetProperties();
+
+            //鎺掗櫎Y杞�
+            props = props.Where(d => d.Name != nameof(config.YResolution)).ToArray();
+            //鎺掗櫎涓嶉渶瑕佺殑椤�
+            if (val == EnumLineScanTriggerSource.鍥哄畾棰戠巼)
+            {
+                props = props.Where(d => d.Name != nameof(config.EncoderTriggerDirection) && d.Name != nameof(config.EncoderTriggerInterval) && d.Name != nameof(config.EncoderTriggerSignalCountingMode)).ToArray();
+            }
+            else
+            {
+                props = props.Where(d => d.Name != nameof(config.SoftwareTriggerRate)).ToArray();
+            }
+            foreach (var p in props)
+            {
+                //璺宠繃鑷畾涔夊弬鏁�
+                var iscustomAttr = p.GetCustomAttribute<IsCustomAttribute>();
+                if (iscustomAttr != null) continue;
+                //鍒ゆ柇鏄�6030浼犳劅鍣ㄨ繕鏄櫘閫氫紶鎰熷櫒
+                if (SerialNo.StartsWith("LX030") && p.Name == nameof(config.AnalogGain))
+                {
+                    continue;
+                }
+                if (!SerialNo.StartsWith("LX030") && p.Name == nameof(config.AnalogGainFor6030))
+                {
+                    continue;
+                }
+                var id = Convert.ToInt32(Enum.Parse(typeof(EnumNameId), p.Name));
+                if (p.PropertyType == typeof(int))
+                {
+                    var value = Convert.ToInt32(p.GetValue(config));
+                    result = PHM6000Profiler.SetProfilerParameter(Entry, id, value, 0, 0);
+                }
+                else if (p.PropertyType == typeof(float))
+                {
+                    var value = Convert.ToDouble(p.GetValue(config));
+                    result = PHM6000Profiler.SetProfilerParameter(Entry, id, 0, value, 0);
+                }
+                else
+                {
+
+                    var value = Convert.ToInt32(p.GetValue(config));
+                    result = PHM6000Profiler.SetProfilerParameter(Entry, id, 0, 0, value);
+                    //if (p.Name == nameof(config.AnalogGainFor6030))
+                    //{
+                    //    var a = value;
+                    //}
+                }
+                if (result == -1)
+                {
+                    var disattr = p.GetCustomAttribute<DisplayNameAttribute>();
+                    var name = disattr?.DisplayName ?? p.Name;
+                    throw new Exception($"璁剧疆鍙傛暟{name}鏃朵笉鎴愬姛锛�");
+                }
+            }
+            var finalResult = PHM6000Profiler.SaveAllParametersToDevice(Entry);
+            if (finalResult != 0)
+            {
+                return false;
+            }
+            return true;
+        }
+        #endregion
+
+
+
+        #region 鏂紑浼犳劅鍣�
+        public void DisConnectCamera()
+        {
+            if (IP == "0.0.0.0") return;
+
+            var result = PHM6000Profiler.DisconnectFromCamera(Entry, IP);
+
+            if (result == -1)
+            {
+                AsyncLogHelper.Error("鏂紑鎽勫儚澶村け璐ワ紒");
+                throw new Exception("鏂紑鎽勫儚澶村け璐ワ紒");
+            }
+        }
+        public void DestoryCamera()
+        {
+            if (Entry != IntPtr.Zero)
+            {
+                PHM6000Profiler.DestroyCameraEntry(Entry);
+                Entry = IntPtr.Zero;
+            }
+            //if (pointPic != IntPtr.Zero)
+            //{
+            //    PclEntry.ClearPCLPoints(pointPic);
+            //    PclEntry.DestroyPCLWindow(pointPic);
+            //    pointPic = IntPtr.Zero;
+            //}
+            if (lightPic != IntPtr.Zero)
+            {
+                Pilot2D.ClearAllPoints(lightPic);
+                Pilot2D.DestroyPilot2DEntry(lightPic);
+                lightPic = IntPtr.Zero;
+            }
+            if (outlinePic != IntPtr.Zero)
+            {
+                Pilot2D.ClearAllPoints(outlinePic);
+                Pilot2D.DestroyPilot2DEntry(outlinePic);
+                outlinePic = IntPtr.Zero;
+            }
+            if (outlineMainPic != IntPtr.Zero)
+            {
+                Pilot2D.ClearAllPoints(outlineMainPic);
+                Pilot2D.DestroyPilot2DEntry(outlineMainPic);
+                outlineMainPic = IntPtr.Zero;
+            }
+            if (deepPic != IntPtr.Zero)
+            {
+                Pilot2D.ClearAllPoints(deepPic);
+                Pilot2D.DestroyPilot2DEntry(deepPic);
+                deepPic = IntPtr.Zero;
+            }
+        }
+        public void ClearDatas()
+        {
+            //if (pointPic != IntPtr.Zero)
+            //{
+            //    PclEntry.ClearPCLPoints(pointPic);
+            //}
+            if (lightPic != IntPtr.Zero)
+            {
+                Pilot2D.ClearAllPoints(lightPic);
+            }
+            if (outlinePic != IntPtr.Zero)
+            {
+                Pilot2D.ClearAllPoints(outlinePic);
+            }
+            if (outlineMainPic != IntPtr.Zero)
+            {
+                Pilot2D.ClearAllPoints(outlineMainPic);
+            }
+            if (deepPic != IntPtr.Zero)
+            {
+                Pilot2D.ClearAllPoints(deepPic);
+            }
+        }
+        #endregion
+        #region 鍗曟閲囬泦,鍚姩鍥炶皟
+        public void StartScan()
+        {
+            if (IP == "0.0.0.0") return;
+            lock (_lock)
+            {
+                LineDatas.Clear();
+            }
+            int result = PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero);//璁剧疆鏁伴噰鍥炶皟,娉ㄦ剰濂藉儚娌″湴鏂规湁閿�姣�
+            if (result == 0)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero)璁剧疆鎴愬姛锛�");
+            }
+            else if (result == -1)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero)璁剧疆澶辫触锛�");
+            }
+            result = PHM6000Profiler.SetAcquisitionMode(Entry, 1, 0);//璁剧疆鏁伴噰妯″紡
+            if (result == 0)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionMode(Entry, 1, 0)璁剧疆鎴愬姛锛�");
+            }
+            else if (result == -1)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionMode(Entry, 1, 0)璁剧疆澶辫触锛�");
+            }
+            result = PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0);//寮�濮嬮噰闆�
+            if (result == 0)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0)璁剧疆鎴愬姛锛�");
+            }
+            else if (result == -1)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0)璁剧疆澶辫触锛�");
+            }
+        }
+        #endregion
+
+        #region 鍚姩杩炵画閲囬泦
+        public void ContinuousScan()
+        {
+            if (IP.Equals("0.0.0.0"))
+            {
+                return;
+            }
+            lock (_lock)
+            {
+                LineDatas.Clear();
+            }
+            int result = PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero);//璁剧疆鏁伴噰鍥炶皟,娉ㄦ剰濂藉儚娌″湴鏂规湁閿�姣�
+            if (result == 0)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero)璁剧疆鎴愬姛锛�");
+            }
+            else if (result == -1)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero)璁剧疆澶辫触锛�");
+            }
+            result = PHM6000Profiler.SetAcquisitionMode(Entry, 1, 1);//璁剧疆鏁伴噰妯″紡
+            if (result == 0)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionMode(Entry, 1, 1)璁剧疆鎴愬姛锛�");
+            }
+            else if (result == -1)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionMode(Entry, 1, 1)璁剧疆澶辫触锛�");
+            }
+            result = PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0);//寮�濮嬮噰闆�
+            if (result == 0)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0)璁剧疆鎴愬姛锛�");
+            }
+            else if (result == -1)
+            {
+                AsyncLogHelper.Info("PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0)璁剧疆澶辫触锛�");
+            }
+        }
+        #endregion
+        #region 鍋滄閲囬泦锛屽仠姝㈠浘鐗囨樉绀�
+        public void StopScan()
+        {
+            if (IP != "0.0.0.0")
+            {
+                PHM6000Profiler.StopAcquisition(Entry);
+            }
+        }
+        #endregion
+
+        private void RenderVtk(IntPtr instance)
+        {
+            // 鑾峰彇褰撳墠鎺т欢灏哄
+            int width = 800;
+            int height = 600;
+
+            // 璋冪敤VTK娓叉煋鏂规硶
+            PclEntry.RenderPCLWindow(pointPic, width, height);
+            PclEntry.UpdatePCLPointColors(pointPic, "z");
+            PclEntry.ShowCubeAxes(pointPic, 1);
+            PclEntry.ShowLookUpTable(pointPic);
+
+            // 澶勭悊棰滆壊鑼冨洿
+            double fMin = 0, fMax = 0;
+            if (PclEntry.GetPointCloudBound(pointPic, ref fMin, ref fMax) != 0)
+            {
+                PclEntry.SetLookUpTableRange(pointPic, fMin, fMax);
+            }
+        }
+
+        #region 淇濆瓨lb3d鏂囦欢
+        public void SaveLb3dData(string filePath)
+        {
+            try
+            {
+                // 浣跨敤GB2312缂栫爜鏂囦欢鍚�
+                Encoding gb2312 = Encoding.GetEncoding("GB2312");
+                byte[] encodedBytes = gb2312.GetBytes(filePath);
+                //byte[] encodedBytes = Encoding.UTF8.GetBytes(filePath);
+
+                // 璋冪敤鍘熺敓淇濆瓨鏂规硶
+                //switch (MainForm.PicModeflg)
+                //{
+                //    case 0:
+                //        int result0 = Pilot2D.SavePicture(lightPic, encodedBytes);
+                //        break;
+                //    case 1:
+                //        int result1 = PclInvoke.SaveDataToFile(Entry, encodedBytes);
+                //        break;
+                //}
+            }
+            catch (EncoderFallbackException)
+            {
+                MessageBox.Show("鏂囦欢鍚嶅寘鍚獹B2312涓嶆敮鎸佺殑瀛楃", "閿欒", MessageBoxButtons.OK, MessageBoxIcon.Error);
+            }
+        }
+
+        #endregion
+
+        #region
+        // 瀹氫箟濮旀墭鍜屼簨浠�
+        public class AcquisitionCompletedEventArgs : EventArgs
+        {
+            public IntPtr Instance { get; set; }
+            public int Option { get; set; }
+        }
+
+
+        // 澹版槑浜嬩欢
+        public event EventHandler<AcquisitionCompletedEventArgs> AcquisitionCompleted;
+
+        // 瑙﹀彂浜嬩欢鐨勬柟娉�
+        public void OnAcquisitionCompleted(IntPtr pInstance, int nOption)
+        {
+            if (nOption == 2)
+            {
+                int width = 800;
+                int height = 600;
+
+                // 璋冪敤VTK娓叉煋鏂规硶
+                PclEntry.RenderPCLWindow(pointPic, width, height);
+                PclEntry.UpdatePCLPointColors(pointPic, "z");
+                PclEntry.ShowCubeAxes(pointPic, 1);
+                PclEntry.ShowLookUpTable(pointPic);
+
+                // 澶勭悊棰滆壊鑼冨洿
+                double fMin = 0, fMax = 0;
+                if (PclEntry.GetPointCloudBound(pointPic, ref fMin, ref fMax) != 0)
+                {
+                    PclEntry.SetLookUpTableRange(pointPic, fMin, fMax);
+                }
+            }
+        }
+
+
+        #endregion
+        //杞粨鍥炬爣瀹�
+        public async Task<float[]> StartOutlineCali(string roiTxt)
+        {
+            var config = GetConfig();
+            PARAM_BAR pARAM_BAR = new PARAM_BAR()
+            {
+                Height = config.BarHeight,
+                Width = config.BarWidth,
+                HoleCount = config.BarHoleCount,
+                HoleDiameter = config.BarHoleDiameter,
+                HoleDistance = config.BarHoleDistance,
+                DOF = config.BarDOF,
+            };
+            SENSOR_POSITION stPosition = new SENSOR_POSITION
+            {
+                IsReverse = config.IsReverse,
+                IsOpposite = config.IsOpposite,
+                fStdDistance = config.fStdDistance,
+                fXCenter = config.fXCenter,
+                x = config.x,
+                y = config.y,
+                z = config.z,
+                xAngle = config.xAngle,
+                yAngle = config.yAngle,
+                zAngle = config.zAngle
+            };
+            SysCalibration.SetSensorPosition(CaliEntry, Index, stPosition);
+            var roi = GetROICaliThkiness(roiTxt, config);
+            SysCalibration.SetLineROI(CaliEntry, Index, roi, false);
+            IntPtr lineLastdatas = GetLineLastData();
+            await Task.Run(() =>
+            {
+                bool result = SysCalibration.AlignmentBar(CaliEntry, Index, Constants.TYPE_STATIONARY, pARAM_BAR);
+            });
+            return new float[] { };
+        }
+
+        public async Task StartOutlineDD(string roiTxt)
+        {
+            var config = GetConfig();
+            PARAM_BAR param_bar = new PARAM_BAR()
+            {
+                Height = config.BarHeight,
+                Width = config.BarWidth,
+                HoleCount = config.BarHoleCount,
+                HoleDiameter = config.BarHoleDiameter,
+                HoleDistance = config.BarHoleDistance,
+                DOF = config.BarDOF,
+            };
+            SENSOR_POSITION stPosition = new SENSOR_POSITION
+            {
+                IsReverse = config.IsReverse,
+                IsOpposite = config.IsOpposite,
+                fStdDistance = config.fStdDistance,
+                fXCenter = config.fXCenter,
+                x = config.x,
+                y = config.y,
+                z = config.z,
+                xAngle = config.xAngle,
+                yAngle = config.yAngle,
+                zAngle = config.zAngle
+            };
+            SysCalibration.SetSensorPosition(CaliEntry, Index, stPosition);
+            var roi = GetROICaliThkiness(roiTxt, config);
+            SysCalibration.SetLineROI(CaliEntry, Index, roi, false);
+            IntPtr lineLastdatas = GetLineLastData();
+            //var linedata = linedatas[linedatas.Count - 1];
+            //var ptr = Marshal.AllocHGlobal(linedata.Length);
+            //Marshal.Copy(linedata, 0, ptr, linedata.Length);
+            //Marshal.FreeHGlobal(lineLastdatas);
+            //await Task.Run(() =>
+            //{
+            //    bool result = SysCalibration.AlignmentBar(CaliEntry, Index, SysCalibration.TYPE_STATIONARY, pARAM_BAR);
+            //});
+        }
+
+        public async Task<float> MeasureDistanceOutLine()
+        {
+            var config = GetConfig();
+            SENSOR_POSITION sENSOR_POSITION = new SENSOR_POSITION
+            {
+                IsReverse = config.IsReverse,
+                IsOpposite = config.IsOpposite,
+                fStdDistance = config.fStdDistance,
+                fXCenter = config.fXCenter,
+                x = config.x,
+                y = config.y,
+                z = config.z,
+                xAngle = config.xAngle,
+                yAngle = config.yAngle,
+                zAngle = config.zAngle
+            };
+            SysCalibration.SetSensorPosition(CaliEntry, Index, sENSOR_POSITION);//璁剧疆浼犳劅鍣ㄤ綅缃�
+            SysCalibration.SetRate(CaliEntry, Index, config.XAxisResolution / 1000, config.YResolution / 1000);
+            SysCalibration.ClearData(CaliEntry, Index);//娓呴櫎浠ュ墠鏁版嵁
+            var r = await Task.Run<float>(() =>
+            {
+                //杈撳叆鏂版暟鎹�
+                unsafe
+                {
+                    IntPtr pdata = IntPtr.Zero;
+
+                    if (sline + eline != 0 && eline > sline)
+                    {
+                        for (ulong i = sline; i < eline; i++)
+                        {
+                            bool useEncoder = false;
+                            if (config.LineScanTriggerSource == EnumLineScanTriggerSource.缂栫爜鍣�) useEncoder = true;
+                            //浣跨敤浜嗗紩鐢紝浠�涔堟椂鍊欏畬鎴愪娇鐢紵濡傛灉闀挎椂闂达紝浠g爜浼氭湁鍐呭瓨椋庨櫓
+                            pdata = PHM6000Profiler.GetLineDataByIndex(Entry, i);
+                            if (pdata == IntPtr.Zero)
+                                break;
+                            SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//鏈�鍚庝釜鍙傛暟鏄粈涔堟剰鎬�
+                        }
+                    }
+                    else
+                    {
+                        ulong nindex = 0;
+
+                        while ((pdata = PHM6000Profiler.GetLineDataByIndex(Entry, nindex)) != IntPtr.Zero)
+                        {
+                            bool useEncoder = false;
+                            if (config.LineScanTriggerSource == EnumLineScanTriggerSource.缂栫爜鍣�) useEncoder = true;
+                            //浣跨敤浜嗗紩鐢紝浠�涔堟椂鍊欏畬鎴愪娇鐢紵濡傛灉闀挎椂闂达紝浠g爜浼氭湁鍐呭瓨椋庨櫓
+                            SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//鏈�鍚庝釜鍙傛暟鏄粈涔堟剰鎬�          
+                            nindex++;
+                        }
+                    }
+                }
+                SetTargetParam(config);//璁剧疆鐩爣娴嬮噺鍙傛暟
+                //var result = SysCalibration.MeasureDistance(CaliEntry);
+                float measuredValue = SysCalibration.MeasureTargetHigh(CaliEntry, Index);
+                var result = (float)Math.Round(measuredValue, 3);
+                return result;
+            });
+            return r;
+        }
+
+        public async Task<float[,]> MeasureOutLine鈥婽hickness鈥�()
+        {
+            var result = await Task.Run(() =>
+            {
+                var config = GetConfig();
+                SetTargetParam(config);//璁剧疆鐩爣娴嬮噺鍙傛暟
+                float[,] datas = new float[config.nPartitionX, config.nPartitionY];
+                data = new float[config.nPartitionX * config.nPartitionY];
+                int number = 0;
+                for (int i = 0; i < config.nPartitionX; i++)
+                {
+                    for (int j = 0; j < config.nPartitionY; j++)
+                    {
+                        number++;
+                        float measuredValue = SysCalibration.MeasureRoiHigh(CaliEntry, Index, number);
+                        // 淇濈暀3浣嶅皬鏁�
+                        datas[i, j] = (float)Math.Round(measuredValue, 3);
+                    }
+                }
+
+                //lBCMap = SysCalibration.GetDepthMap(CaliEntry, Index, 4);
+                return datas;
+            });
+            return result;
+        }
+
+
+
+
+        //浜岀淮鍥炬爣瀹�
+        public async Task StartLiaghtAndDeepCali(CaliModel caliModel)
+        {
+            //LBLineDataZA lBLineDataZA = new LBLineDataZA();
+
+            SENSOR_POSITION sENSOR_POSITION = new SENSOR_POSITION
+            {
+                IsReverse = caliModel.IsReverse,
+                IsOpposite = caliModel.IsOpposite,
+                fStdDistance = caliModel.fStdDistance,
+                fXCenter = caliModel.fXCenter,
+                x = caliModel.x,
+                y = caliModel.y,
+                z = caliModel.z,
+                xAngle = caliModel.xAngle,
+                yAngle = caliModel.yAngle,
+                zAngle = caliModel.zAngle,
+            };
+            var config = GetConfig();
+            PARAM_BOARD pARAM_BOARD = new PARAM_BOARD()
+            {
+                //Height = config.Height,
+                //Width = config.Width,
+                //HoleDiameter = config.HoleDiameter,
+                //HoleDistance = config.HoleDistance,
+                //LocationHoleX1 = config.LocationHoleX1,
+                //LocationHoleX2 = config.LocationHoleX2,
+                //LocationHoleY1 = config.LocationHoleY1,
+                //LocationHoleY2 = config.LocationHoleY2,
+            };
+
+
+
+            SysCalibration.SetSensorPosition(CaliEntry, Index, sENSOR_POSITION);//璁剧疆浼犳劅鍣ㄤ綅缃�
+            var roi = caliModel.Plane.Split(',');
+
+            var roi1 = GetROI(caliModel.Plane, config);
+            var roi2 = GetROI(caliModel.Hole1, config);
+            var roi3 = GetROI(caliModel.Hole2, config);
+            var roi4 = GetROI(caliModel.Hole3, config);
+
+            SysCalibration.SetRate(CaliEntry, Index, config.XAxisResolution / 1000, config.YResolution / 1000);
+            SysCalibration.SetFlatROI(CaliEntry, Index, roi1, true);
+            SysCalibration.SetHoleROI(CaliEntry, Index, 0, roi2, true);
+            SysCalibration.SetHoleROI(CaliEntry, Index, 1, roi3, true);
+            SysCalibration.SetHoleROI(CaliEntry, Index, 2, roi4, true);
+            SysCalibration.SetBoardParameter(CaliEntry, pARAM_BOARD);
+            SysCalibration.ClearData(CaliEntry, Index);//娓呴櫎浠ュ墠鏁版嵁
+            await Task.Run(() =>
+            {
+                //淇敼姝ゆ浠g爜
+                //foreach (var item in GetLineDatas())
+                unsafe
+                {
+                    IntPtr pdata = IntPtr.Zero;
+
+                    //if (sline + eline != 0 && eline > sline)
+                    //{
+                    //    for (ulong i = sline; i < eline; i++)
+                    //    {
+                    //        bool useEncoder = false;
+                    //        if (config.LineScanTriggerSource == EnumLineScanTriggerSource.缂栫爜鍣�) useEncoder = true;
+                    //        //浣跨敤浜嗗紩鐢紝浠�涔堟椂鍊欏畬鎴愪娇鐢紵濡傛灉闀挎椂闂达紝浠g爜浼氭湁鍐呭瓨椋庨櫓
+                    //        pdata = GetLineDataByIndex(Entry, i);
+                    //        if (pdata == IntPtr.Zero)
+                    //            break;
+                    //        SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//鏈�鍚庝釜鍙傛暟鏄粈涔堟剰鎬�
+                    //    }
+                    //}
+                    //else
+                    {
+                        ulong nindex = 0;
+
+                        while ((pdata = PHM6000Profiler.GetLineDataByIndex(Entry, nindex)) != IntPtr.Zero)
+                        {
+                            bool useEncoder = false;
+                            if (config.LineScanTriggerSource == EnumLineScanTriggerSource.缂栫爜鍣�) useEncoder = true;
+                            //浣跨敤浜嗗紩鐢紝浠�涔堟椂鍊欏畬鎴愪娇鐢紵濡傛灉闀挎椂闂达紝浠g爜浼氭湁鍐呭瓨椋庨櫓
+                            SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//鏈�鍚庝釜鍙傛暟鏄粈涔堟剰鎬�          
+                            nindex++;
+                        }
+                    }
+                }
+                SysCalibration.AlignmentMovingFlat(CaliEntry, Index);//涓嬫鎵撳紑绋嬪簭鏃跺彲鑳戒細搴忓彿閿欒
+                //SysCalibration.SystemCalibration(caliEntry);//error娌℃湁鐪熷疄鐨勫瓟锛屽氨浼氬崱杩涚▼
+            });
+        }
+
+
+        //娴嬮噺鍘氬害
+        public async Task<float> MeasureDistance()
+        {
+
+            var config = GetConfig();
+            SENSOR_POSITION sENSOR_POSITION = new SENSOR_POSITION
+            {
+                //IsReverse = CaliModel.IsReverse,
+                //IsOpposite = CaliModel.IsOpposite,
+                //fStdDistance = CaliModel.fStdDistance,
+                //fXCenter = CaliModel.fXCenter,
+                //x = CaliModel.x,
+                //y = CaliModel.y,
+                //z = CaliModel.z,
+                //xAngle = CaliModel.xAngle,
+                //yAngle = CaliModel.yAngle,
+                //zAngle = CaliModel.zAngle,
+            };
+            SysCalibration.SetSensorPosition(CaliEntry, Index, sENSOR_POSITION);//璁剧疆浼犳劅鍣ㄤ綅缃�
+            SysCalibration.SetRate(CaliEntry, Index, config.XAxisResolution / 1000, config.YResolution / 1000);
+            SysCalibration.ClearData(CaliEntry, Index);//娓呴櫎浠ュ墠鏁版嵁
+            var r = await Task.Run<float>(() =>
+            {
+                //杈撳叆鏂版暟鎹�
+                unsafe
+                {
+                    IntPtr pdata = IntPtr.Zero;
+
+                    if (sline + eline != 0 && eline > sline)
+                    {
+                        for (ulong i = sline; i < eline; i++)
+                        {
+                            bool useEncoder = false;
+                            if (config.LineScanTriggerSource == EnumLineScanTriggerSource.缂栫爜鍣�) useEncoder = true;
+                            //浣跨敤浜嗗紩鐢紝浠�涔堟椂鍊欏畬鎴愪娇鐢紵濡傛灉闀挎椂闂达紝浠g爜浼氭湁鍐呭瓨椋庨櫓
+                            pdata = PHM6000Profiler.GetLineDataByIndex(Entry, i);
+                            if (pdata == IntPtr.Zero)
+                                break;
+                            SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//鏈�鍚庝釜鍙傛暟鏄粈涔堟剰鎬�
+                        }
+                    }
+                    else
+                    {
+                        ulong nindex = 0;
+
+                        while ((pdata = PHM6000Profiler.GetLineDataByIndex(Entry, nindex)) != IntPtr.Zero)
+                        {
+                            bool useEncoder = false;
+                            if (config.LineScanTriggerSource == EnumLineScanTriggerSource.缂栫爜鍣�) useEncoder = true;
+                            //浣跨敤浜嗗紩鐢紝浠�涔堟椂鍊欏畬鎴愪娇鐢紵濡傛灉闀挎椂闂达紝浠g爜浼氭湁鍐呭瓨椋庨櫓
+                            SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//鏈�鍚庝釜鍙傛暟鏄粈涔堟剰鎬�          
+                            nindex++;
+                        }
+                    }
+                }
+                SetTargetParam(config);//璁剧疆鐩爣娴嬮噺鍙傛暟
+                //var result = SysCalibration.MeasureDistance(CaliEntry);
+                float measuredValue = SysCalibration.MeasureTargetHigh(CaliEntry, Index);
+                var result = (float)Math.Round(measuredValue, 3);
+                return result;
+            });
+            return r;
+        }
+
+        public static ulong sline = 0;
+        public static ulong eline = 0;
+
+
+        public static IntPtr lBCMap = IntPtr.Zero;
+        public static float[] data = null;
+
+        //娴嬮噺鍑瑰嚫
+        public async Task<float[,]> Measure鈥婾neven鈥�()
+        {
+
+            var result = await Task.Run(() =>
+            {
+                var config = GetConfig();
+                //SENSOR_POSITION sENSOR_POSITION = new SENSOR_POSITION
+                //{
+                //    IsReverse = CaliModel.IsReverse,
+                //    IsOpposite = CaliModel.IsOpposite,
+                //    fStdDistance = CaliModel.fStdDistance,
+                //    fXCenter = CaliModel.fXCenter,
+                //    x = CaliModel.x,
+                //    y = CaliModel.y,
+                //    z = CaliModel.z,
+                //    xAngle = CaliModel.xAngle,
+                //    yAngle = CaliModel.yAngle,
+                //    zAngle = CaliModel.zAngle,
+                //};
+                //SysCalibration.SetSensorPosition(CaliEntry, Index, sENSOR_POSITION);//璁剧疆浼犳劅鍣ㄤ綅缃�
+                //SysCalibration.SetRate(CaliEntry, Index, config.XAxisResolution / 1000, config.YResolution / 1000);
+                //SysCalibration.ClearData(CaliEntry, Index);//娓呴櫎浠ュ墠鏁版嵁
+
+                ////杈撳叆鏂版暟鎹�
+                //unsafe
+                //{
+                //    IntPtr pdata = IntPtr.Zero;
+
+                //    if (sline + eline != 0 && eline > sline)
+                //    {
+                //        for (ulong i = sline; i < eline; i++)
+                //        {
+                //            bool useEncoder = false;
+                //            if (config.LineScanTriggerSource == EnumLineScanTriggerSource.缂栫爜鍣�) useEncoder = true;
+                //            //浣跨敤浜嗗紩鐢紝浠�涔堟椂鍊欏畬鎴愪娇鐢紵濡傛灉闀挎椂闂达紝浠g爜浼氭湁鍐呭瓨椋庨櫓
+                //            pdata = GetLineDataByIndex(Entry, i);
+                //            if (pdata == IntPtr.Zero)
+                //                break;
+                //            SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//鏈�鍚庝釜鍙傛暟鏄粈涔堟剰鎬�
+                //        }
+                //    }
+                //    else
+                //    {
+                //        ulong nindex = 0;
+
+                //        while ((pdata = GetLineDataByIndex(Entry, nindex)) != IntPtr.Zero)
+                //        {
+                //            bool useEncoder = false;
+                //            if (config.LineScanTriggerSource == EnumLineScanTriggerSource.缂栫爜鍣�) useEncoder = true;
+                //            //浣跨敤浜嗗紩鐢紝浠�涔堟椂鍊欏畬鎴愪娇鐢紵濡傛灉闀挎椂闂达紝浠g爜浼氭湁鍐呭瓨椋庨櫓
+                //            SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//鏈�鍚庝釜鍙傛暟鏄粈涔堟剰鎬�          
+                //            nindex++;
+                //        }
+                //    }
+                //}
+                SetTargetParam(config);//璁剧疆鐩爣娴嬮噺鍙傛暟
+                float[,] datas = new float[config.nPartitionX, config.nPartitionY];
+                data = new float[config.nPartitionX * config.nPartitionY];
+                int number = 0;
+                for (int i = 0; i < config.nPartitionX; i++)
+                {
+                    for (int j = 0; j < config.nPartitionY; j++)
+                    {
+                        number++;
+                        float measuredValue = SysCalibration.MeasureRoiHigh(CaliEntry, Index, number);
+                        // 淇濈暀3浣嶅皬鏁�
+                        datas[i, j] = (float)Math.Round(measuredValue, 3);
+                    }
+                }
+
+                //lBCMap = SysCalibration.GetDepthMap(CaliEntry, Index, 4);
+                return datas;
+            });
+            return result;
+        }
+
+
+        LB_ROI GetROI(string s, PHM6000SensorConfig config)
+        {
+
+            var roi = s.Split(',');
+            LB_ROI lB_ROI = new LB_ROI()
+            {
+                left = Convert.ToInt32(roi[0]) * config.XAxisResolution / 1000,
+                top = Convert.ToInt32(roi[1]) * config.YResolution / 1000,
+                right = Convert.ToInt32(roi[2]) * config.XAxisResolution / 1000,
+                bottom = Convert.ToInt32(roi[3]) * config.YResolution / 1000,
+                //    left = Convert.ToInt32(roi[0]) * 4096 / 2048,
+                //    top = (int)(325.0 - 225.0 - float.Parse(roi[1]) * (470.0 - 225.0) / (1024.0 - 1.0) + 0.5),
+                //    right = Convert.ToInt32(roi[2]) * 4096 / 2048,
+                //    bottom = (int)(325.0 - 225.0 - float.Parse(roi[3]) * (470.0 - 225.0) / (1024.0 - 1.0) + 0.5),
+                //};
+                //float fTemp;
+                //if (lB_ROI.left > lB_ROI.right)
+                //{
+                //    fTemp = lB_ROI.left;
+                //    lB_ROI.left = lB_ROI.right;
+                //    lB_ROI.right = fTemp;
+                //}
+                //if (lB_ROI.top > lB_ROI.bottom)
+                //{
+                //    fTemp = lB_ROI.top;
+                //    lB_ROI.top = lB_ROI.bottom;
+                //    lB_ROI.bottom = fTemp;
+                //}
+            };
+            return lB_ROI;
+        }
+        LB_ROI GetROICaliThkiness(string s, PHM6000SensorConfig config)
+        {
+
+            var roi = s.Split(',');
+            LB_ROI lB_ROI = new LB_ROI()
+            {
+                //left = Convert.ToInt32(roi[0]) * config.XAxisResolution / 1000,
+                //top = Convert.ToInt32(roi[1]) * config.YResolution / 1000,
+                //right = Convert.ToInt32(roi[2]) * config.XAxisResolution / 1000,
+                //bottom = Convert.ToInt32(roi[3]) * config.YResolution / 1000,
+                left = Convert.ToInt32(roi[0]) * 4096 / 2048,
+                top = (int)(325.0 - 225.0 - float.Parse(roi[1]) * (470.0 - 225.0) / (1024.0 - 1.0) + 0.5),
+                right = Convert.ToInt32(roi[2]) * 4096 / 2048,
+                bottom = (int)(325.0 - 225.0 - float.Parse(roi[3]) * (470.0 - 225.0) / (1024.0 - 1.0) + 0.5),
+            };
+            float fTemp;
+            if (lB_ROI.left > lB_ROI.right)
+            {
+                fTemp = lB_ROI.left;
+                lB_ROI.left = lB_ROI.right;
+                lB_ROI.right = fTemp;
+            }
+            if (lB_ROI.top > lB_ROI.bottom)
+            {
+                fTemp = lB_ROI.top;
+                lB_ROI.top = lB_ROI.bottom;
+                lB_ROI.bottom = fTemp;
+            }
+            return lB_ROI;
+        }
+    }
+
+    #region 浼犳劅鍣ㄥ垪琛ㄦā鍨嬬被
+
+    /// <summary>
+    /// PHM6000SensorModel
+    /// </summary>
+    [JsonObject(MemberSerialization.OptOut)]
+    [TypeConverter(typeof(PropertySorter))]
+
+    public class PHM6000SensorModel
+    {
+        /// <summary>
+        /// IP鍦板潃
+        /// </summary>
+        [Category("PHM6000SensorModel"), PropertyOrder(2)]
+        [DisplayName("IP鍦板潃")]
+        [Browsable(true)]
+        public string IP { get; set; }
+        /// <summary>
+        /// 绔彛
+        /// </summary>
+        [Category("PHM6000SensorModel"), PropertyOrder(3)]
+        [DisplayName("绔彛")]
+        [Browsable(true)]
+        public int Port { get; set; }
+        /// <summary>
+        /// 搴忓垪鍙�
+        /// </summary>
+        [Category("PHM6000SensorModel"), PropertyOrder(1)]
+        [DisplayName("搴忓垪鍙�")]
+        [Browsable(true)]
+        public string SerialNo { get; set; }
+        /// <summary>
+        /// 鐘舵��
+        /// </summary>
+        [Category("PHM6000SensorModel"), PropertyOrder(0)]
+        [DisplayName("鐘舵��")]
+        [Browsable(true)]
+        public string State { get; set; }
+        /// <summary>
+        /// PHM6000Sensor
+        /// </summary>
+        [Category("PHM6000SensorModel"), PropertyOrder(4)]
+        [Browsable(false)]
+        public PHM6000Sensor Sensor { get; set; }
+        /// <summary>
+        /// Model
+        /// </summary>
+        [Category("PHM6000SensorModel"), PropertyOrder(5)]
+        [Browsable(false)]
+        public string Model { get; set; }
+    }
+    #endregion
+
+    //閲囬泦鏁版嵁鏃惰鏄剧ず鐨勫浘绫诲舰
+    public enum EnumFetchPicType
+    {
+        light, deep, pointCloud, outline, mainOutLine
+    }
+
+    public class FloatArrayToIntPtrConverter
+    {
+        public unsafe static IntPtr ConvertFloatArrayToIntPtr(float[] data)
+        {
+            if (data == null || data.Length == 0)
+            {
+                return IntPtr.Zero;
+            }
+            fixed (float* p = data)
+            {
+                return (IntPtr)p;
+            }
+        }
+    }
+}
diff --git a/LB_SmartVisionCameraDevice/PHM6000/PHM6000SensorConfig.cs b/LB_SmartVisionCameraDevice/PHM6000/PHM6000SensorConfig.cs
new file mode 100644
index 0000000..ded7fc6
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/PHM6000/PHM6000SensorConfig.cs
@@ -0,0 +1,1055 @@
+锘縰sing LB_SmartVisionCameraSDK.PHM6000;
+using LB_SmartVisionCommon;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Security.Permissions;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCameraDevice.PHM6000
+{
+    /// <summary>
+    /// PHM6000Sensor閰嶇疆鍙傛暟绫�
+    /// </summary>
+    [JsonObject(MemberSerialization.OptOut)]
+    public class PHM6000SensorConfig
+    {
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(39)]
+        [DisplayName("ZROI")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public EnumZDirectionRoi ZDirectionRoi { get; set; }            //ZROI
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(40)]
+        [DisplayName("Filter")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        public EnumFilter Filter { get; set; }            //Filter
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(41)]
+        [DisplayName("MeanFilterWindowSize")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public EnumMeanFilterWindowSize MeanFilterWindowSize { get; set; }            //MeanFilterWindowSize
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(42)]
+        [DisplayName("MedianFilterWindowSize")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public EnumMedianFilterWindowSize MedianFilterWindowSize { get; set; }            //MedianFilterWindowSize
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(43)]
+        [DisplayName("GapFilling")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        public int GapFilling { get; set; }            //GapFilling
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(44)]
+        [DisplayName("GapFillingEdgePreservation")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        public int GapFillingEdgePreservation { get; set; }            //GapFilling
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(45)]
+        [DisplayName("闄嶉噰鏍�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public EnumDownsampling Downsampling { get; set; } = EnumDownsampling.X1;
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(46)]
+        [DisplayName("閲嶉噰鏍�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        public EnumResampling Resampling { get; set; } = EnumResampling.Nearest;
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(47)]
+        [DisplayName("閲嶉噰鏍疯竟缂樹繚鎸�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Range(0, 1)]
+        [Browsable(false)]
+        public int ResamplingEdgePreservation { get; set; }
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(48)]
+        [DisplayName("鍚敤 Z 杞村榻�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public bool EnableZAxisAlignment { get; set; }
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(49)]
+        [DisplayName("鍚敤 X 杞村榻�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public bool EnableXAxisAlignment { get; set; }
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(50)]
+        [DisplayName("鍚敤鐩茬偣杩囨护")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public bool EnableBlindSpotFiltering { get; set; }
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(51)]
+        [DisplayName("鍚敤鍣0娑堥櫎")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public bool EnableNoiseRemoval { get; set; }
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(52)]
+        [DisplayName("鍣0鍘婚櫎寮哄害")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public EnumNoiseRemovalIntensity NoiseRemovalIntensity { get; set; }
+
+        [Category("杞粨绾垮叴瓒e尯鍨�"), PropertyOrder(53)]
+        [DisplayName("XOZ-ROI")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public LBProfileROI ROI { get; set; }            //ROI
+
+        [Category("鐩告満灞炴��"), PropertyOrder(54)]
+        [DisplayName("NameIdMax")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public int NameIdMax { get; set; }            //NameIdMax
+
+        [Category("瑙﹀彂璁剧疆"), PropertyOrder(0)]
+        [DisplayName("鏁版嵁閲囬泦瑙﹀彂婧�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Primary)]
+        public EnumDataAcquisitionTriggerSource DataAcquisitionTriggerSource { get; set; } = EnumDataAcquisitionTriggerSource.杞Е鍙�;            //鏁版嵁閲囬泦瑙﹀彂婧�:0=Software,1=External
+
+        [Category("瑙﹀彂璁剧疆"), PropertyOrder(1)]
+        [DisplayName("琛屾壂鎻忚Е鍙戞簮")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Primary)]
+        public EnumLineScanTriggerSource LineScanTriggerSource { get; set; } = EnumLineScanTriggerSource.鍥哄畾棰戠巼;            //濡傛灉閫夋嫨鍥哄畾棰戠巼涓嬮潰鍙湁涓�涓鐜囧�� 锛屽惁鍒欐樉绀鸿Е鍙戞柟鍚戙�佽Е鍙戜俊鍙疯鏁版ā寮忋�佽Е鍙戦棿闅�
+
+        [Category("瑙﹀彂璁剧疆"), PropertyOrder(2)]
+        [DisplayName("瑙﹀彂棰戠巼")]
+        public float SoftwareTriggerRate { get; set; } = 1000;            //瑙﹀彂棰戠巼
+
+        [Category("瑙﹀彂璁剧疆"), PropertyOrder(3)]
+        [DisplayName("鏈�澶ф壂鎻忛�熺巼")]
+        [Browsable(false)]
+        [IsCustom]
+        public float MaxScanRate { get; set; }            //鏈�澶ф壂鎻忛�熺巼
+
+        [Category("瑙﹀彂璁剧疆"), PropertyOrder(4)]
+        [DisplayName("瑙﹀彂寤惰繜")]
+        public int TriggerDelay { get; set; }            //瑙﹀彂寤惰繜
+
+        [Category("瑙﹀彂璁剧疆"), PropertyOrder(5)]
+        [DisplayName("瑙﹀彂鏂瑰悜")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Primary)]
+        public EnumEncoderTriggerDirection EncoderTriggerDirection { get; set; } = EnumEncoderTriggerDirection.鍙屽悜;            //瑙﹀彂鏂瑰悜
+
+        [Category("瑙﹀彂璁剧疆"), PropertyOrder(6)]
+        [DisplayName("瑙﹀彂淇″彿璁℃暟妯″紡")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Primary)]
+        public EnumEncoderTriggerSignalCountingMode EncoderTriggerSignalCountingMode { get; set; } = EnumEncoderTriggerSignalCountingMode.X4;           //瑙﹀彂淇″彿璁℃暟妯″紡
+
+        [Category("瑙﹀彂璁剧疆"), PropertyOrder(7)]
+        [DisplayName("瑙﹀彂闂撮殧")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Primary)]
+        public int EncoderTriggerInterval { get; set; } = 100;            //瑙﹀彂闂撮殧
+
+        [Category("琛屾壂鎻忚缃�"), PropertyOrder(8)]
+        [DisplayName("鎵弿琛屾暟")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Primary)]
+        public int ScanLineCount { get; set; } = 5000;            //鎵弿琛屾暟
+
+        [Category("琛屾壂鎻忚缃�"), PropertyOrder(9)]
+        [DisplayName("姣忎釜閰嶇疆鏂囦欢鐨勬暟鎹偣鏁�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Primary)]
+        [Browsable(false)]
+        [IsCustom]
+        public int DataPointsPerProfile { get; set; } = 50000 * 4096;            //姣忎釜閰嶇疆鏂囦欢鐨勬暟鎹偣鏁�
+
+        [Category("琛屾壂鎻忚缃�"), PropertyOrder(10)]
+        [DisplayName("鏇濆厜寤惰繜")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Primary)]
+        [IsCustom]
+        public int ExposureDelay { get; set; } = 0;            //鏇濆厜寤惰繜
+
+        [Category("琛屾壂鎻忚缃�"), PropertyOrder(11)]
+        [DisplayName("鎵归噺妫�绱㈣秴鏃�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Primary)]
+        [Browsable(false)]
+        public int BatchRetrievalTimeout { get; set; } = 4000;
+
+        [Category("琛屾壂鎻忚缃�"), PropertyOrder(12)]
+        [DisplayName("瓒呮椂鏃堕棿")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Primary)]
+        public int CallbackRetrievalTimeout { get; set; } = 4000;
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(13)]
+        [DisplayName("X杞村垎杈ㄧ巼")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        public float XAxisResolution { get; set; } = 105f;
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(14)]
+        [DisplayName("Y杞村垎杈ㄧ巼")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        public float YResolution { get; set; } = 105f;            //YAxisResolution
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(15)]
+        [DisplayName("鍊炬枩鏍℃瑙掑害")]
+        [Browsable(false)]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        public float TiltCorrectionAngle { get; set; }          //TiltCorrectionAngle
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(16)]
+        [DisplayName("楂樺害鏍℃姣�")]
+        [Browsable(false)]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        public float HeightCorrectionRatio { get; set; }          //HeightCorrectionRatio
+
+        [Category("鐐逛簯璁剧疆"), PropertyOrder(17)]
+        [DisplayName("鍧愭爣鍙樻崲")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        [IsCustom]
+        public float[] CoordinateTransformation { get; set; }          //CoordinateTransformation
+
+
+        [Category("杞粨绾挎彁鍙�"), PropertyOrder(18)]
+        [DisplayName("鏈�灏忕伆搴�")]
+        [Description("鏈�灏忕伆搴�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        public int MinGrayscaleValue { get; set; }            //鏈�灏忕伆搴�
+
+        [Category("杞粨绾挎彁鍙�"), PropertyOrder(19)]
+        [DisplayName("鎻愬彇鐐规渶灏忓己搴�")]
+        [Description("鎻愬彇鐐规渶灏忓己搴�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        public int MinSpotIntensity { get; set; }            //
+
+        [Category("杞粨绾挎彁鍙�"), PropertyOrder(20)]
+        [DisplayName("鎻愬彇鐐规渶澶у己搴�")]
+        [Description("鎻愬彇鐐规渶澶у己搴�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        public int MaxSpotIntensity { get; set; }            //
+
+        [Category("杞粨绾挎彁鍙�"), PropertyOrder(21)]
+        [DisplayName("闃堝��")]
+        [Description("闃堝��")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [IsCustom]
+        public int ProductThresholdValues { get; set; } //
+
+        [Category("杞粨绾挎彁鍙�"), PropertyOrder(22)]
+        [DisplayName("婵�鍏夌嚎鏈�灏忓搴�")]
+        [Description("婵�鍏夌嚎鏈�灏忓搴�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        public int MinLaserLineWidth { get; set; }            //婵�鍏夌嚎鏈�灏忓搴�
+
+        [Category("杞粨绾挎彁鍙�"), PropertyOrder(23)]
+        [DisplayName("婵�鍏夌嚎鏈�澶у搴�")]
+        [Description("婵�鍏夌嚎鏈�澶у搴�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        public int MaxLaserLineWidth { get; set; }            //婵�鍏夌嚎鏈�澶у搴�
+
+        [Category("杞粨绾挎彁鍙�"), PropertyOrder(24)]
+        [DisplayName("鎻愬彇鐐归�夋嫨")]
+        [Description("鎻愬彇鐐归�夋嫨")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        public EnumSpotSelection SpotSelection { get; set; }            //鎻愬彇鐐归�夋嫨
+
+        [Category("杞粨绾挎彁鍙�"), PropertyOrder(25)]
+        [DisplayName("杈圭紭閫夋嫨")]
+        [Description("杈圭紭閫夋嫨")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        public EnumEdgeSelection EdgeSelection { get; set; }
+
+        [Category("杞粨绾挎彁鍙�"), PropertyOrder(26)]
+        [DisplayName("鏈�灏忛攼搴�")]
+        [Description("鏈�灏忛攼搴�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        public int MinSharpness { get; set; }
+
+        [Category("杞粨绾挎彁鍙�"), PropertyOrder(27)]
+        [DisplayName("浜害璋冭妭")]
+        [Description("浜害璋冭妭")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        public EnumBrightnessAdjustment BrightnessAdjustment { get; set; }
+
+        [Category("浼犳劅鍣ㄥ弬鏁�"), PropertyOrder(28)]
+        [DisplayName("鏇濆厜妯″紡")]
+        [Description("鏇濆厜妯″紡")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        public EnumExposureMode ExposureMode { get; set; } = EnumExposureMode.Timed;
+        [Category("浼犳劅鍣ㄥ弬鏁�"), PropertyOrder(29)]
+        [DisplayName("鏇濆厜鏃堕棿")]
+        [Description("鏇濆厜鏃堕棿")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        public int ExposureTime { get; set; }//鏇濆厜鏃堕棿
+
+        [Category("浼犳劅鍣ㄥ弬鏁�"), PropertyOrder(30)]
+        [DisplayName("浜у搧鏇濆厜鏃堕棿")]
+        [Description("鏇濆厜鏃堕棿")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Master)]
+        [Browsable(false)]
+        [IsCustom]
+        public int ProductExpTime { get; set; }            //鏇濆厜鏃堕棿
+
+        [Category("浼犳劅鍣ㄥ弬鏁�"), PropertyOrder(31)]
+        [DisplayName("hdr璋冭妭1")]
+        [Description("hdr璋冭妭1")]
+        [Range(0, 100)]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        [IsCustom]
+        public int HdrExposureTimeProportion1 { get; set; }            //hdr璋冭妭1
+
+        [Category("浼犳劅鍣ㄥ弬鏁�"), PropertyOrder(32)]
+        [DisplayName("hdr璋冭妭2")]
+        [Description("hdr璋冭妭2")]
+        [Range(0, 100)]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        [IsCustom]
+        public int HdrExposureTimeProportion2 { get; set; }            //hdr璋冭妭2
+
+        [Category("浼犳劅鍣ㄥ弬鏁�"), PropertyOrder(33)]
+        [DisplayName("hdr闃堝��1")]
+        [Description("hdr闃堝��")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        [IsCustom]
+        public int HdrFirstThreshold { get; set; }            //hdr闃堝��
+
+        [Category("浼犳劅鍣ㄥ弬鏁�"), PropertyOrder(34)]
+        [DisplayName("hdr闃堝��2")]
+        [Description("hdr闃堝��")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        [IsCustom]
+        public int HdrSecondThreshold { get; set; }            //hdr闃堝��2
+
+        [Category("浼犳劅鍣ㄥ弬鏁�"), PropertyOrder(35)]
+        [DisplayName("妯℃嫙澧炵泭")]
+        [Description("妯℃嫙澧炵泭")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        public EnumAnalogGain AnalogGain { get; set; }            //妯℃嫙澧炵泭
+
+        [Category("浼犳劅鍣ㄥ弬鏁�"), PropertyOrder(36)]
+        [DisplayName("妯℃嫙澧炵泭6030")]
+        [Description("妯℃嫙澧炵泭6030")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        public EnumAnalogGainFor6030 AnalogGainFor6030 { get; set; }            //妯℃嫙澧炵泭for6030
+
+        [Category("浼犳劅鍣ㄥ弬鏁�"), PropertyOrder(37)]
+        [DisplayName("鏁板瓧澧炵泭")]
+        [Description("鏁板瓧澧炵泭")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        [Browsable(false)]
+        public int DigitalGain { get; set; }            //鏁板瓧澧炵泭
+
+        [Category("浼犳劅鍣ㄥ弬鏁�"), PropertyOrder(38)]
+        [DisplayName("婵�鍏夊姛鐜�")]
+        [Description("婵�鍏夊姛鐜�")]
+        [Permission(typeof(CameraUserRole), CameraUserRole.Expert)]
+        public int LaserPower { get; set; }            //婵�鍏夊姛鐜�
+
+        #region 杞粨绾挎爣瀹�
+        [Category("PARAM_BAR"), PropertyOrder(60)]
+        [DisplayName("Height")]
+        [Browsable(false)]
+        [IsCustom]
+        public float BarHeight { get; set; } = 2;
+        [Category("PARAM_BAR"), PropertyOrder(61)]
+        [DisplayName("Width")]
+        [Browsable(false)]
+        [IsCustom]
+        public float BarWidth { get; set; } = 35;
+        [Category("PARAM_BAR"), PropertyOrder(62)]
+        [DisplayName("HoleCount")]
+        [Browsable(false)]
+        [IsCustom]
+        public int BarHoleCount { get; set; }
+        [Category("PARAM_BAR"), PropertyOrder(63)]
+        [DisplayName("HoleDiameter")]
+        [Browsable(false)]
+        [IsCustom]
+        public float BarHoleDiameter { get; set; }
+        [Category("PARAM_BAR"), PropertyOrder(64)]
+        [DisplayName("HoleDistance")]
+        [Browsable(false)]
+        [IsCustom]
+        public float BarHoleDistance { get; set; }
+        [Category("PARAM_BAR"), PropertyOrder(65)]
+        [DisplayName("DOF")]
+        [Browsable(false)]
+        [IsCustom]
+        public int BarDOF { get; set; }
+        [Category("娴嬮噺鐩爣鐗╁弬鏁拌缃�"), PropertyOrder(66)]
+        [DisplayName("M")]
+        [Browsable(false)]
+        [IsCustom]
+        public int nPartitionX { get; set; }//M
+        [Category("娴嬮噺鐩爣鐗╁弬鏁拌缃�"), PropertyOrder(67)]
+        [DisplayName("N")]
+        [Browsable(false)]
+        [IsCustom]
+        public int nPartitionY { get; set; }//N
+        #endregion
+
+        #region  骞抽潰鏍囧畾
+        protected const string ROIInfo = "鏍囧畾ROI鏁版嵁";
+        protected const string CameraInfo = "鐩告満瀹夎鍙傛暟";
+        [Category(ROIInfo), PropertyOrder(80)]
+        [DisplayName("骞抽潰鍖�")]
+        [Browsable(false)]
+        [IsCustom]
+        public string Plane { get; set; } = "0,0,0,0";
+        [Category(ROIInfo), PropertyOrder(81)]
+        [DisplayName("瀛斿尯1")]
+        [Browsable(false)]
+        [IsCustom]
+        public string Hole1 { get; set; } = "0,0,0,0";
+        [Category(ROIInfo), PropertyOrder(82)]
+        [DisplayName("瀛斿尯2")]
+        [Browsable(false)]
+        [IsCustom]
+        public string Hole2 { get; set; } = "0,0,0,0";
+        [Category(ROIInfo), PropertyOrder(83)]
+        [DisplayName("瀛斿尯3")]
+        [Browsable(false)]
+        [IsCustom]
+        public string Hole3 { get; set; } = "0,0,0,0";
+        [Category(CameraInfo), PropertyOrder(84)]
+        [DisplayName("x鍊掑簭")]
+        [Browsable(false)]
+        [IsCustom]
+        public int IsReverse { get; set; } = 0;        //x鍊掑簭
+        [Category(CameraInfo), PropertyOrder(85)]
+        [DisplayName("z鐩稿")]
+        [Browsable(false)]
+        [IsCustom]
+        public int IsOpposite { get; set; } = 0;       //z鐩稿
+        [Category(CameraInfo), PropertyOrder(86)]
+        [DisplayName("鏍囧噯璺濈")]
+        [Browsable(false)]
+        [IsCustom]
+        public float fStdDistance { get; set; } = 325;
+        [Category(CameraInfo), PropertyOrder(87)]
+        [DisplayName("X杞翠腑蹇�")]
+        [Browsable(false)]
+        [IsCustom]
+        public float fXCenter { get; set; } = 215.04f;
+        [Category(CameraInfo), PropertyOrder(88)]
+        [DisplayName("X杞�")]
+        [Browsable(false)]
+        [IsCustom]
+        public float x { get; set; } = 0;
+        [Category(CameraInfo), PropertyOrder(89)]
+        [DisplayName("Y杞�")]
+        [Browsable(false)]
+        [IsCustom]
+        public float y { get; set; } = 0;
+        [Category(CameraInfo), PropertyOrder(90)]
+        [DisplayName("Z杞�")]
+        [Browsable(false)]
+        [IsCustom]
+        public float z { get; set; } = 417.75f;
+        [Category(CameraInfo), PropertyOrder(91)]
+        [DisplayName("X杞磋搴�")]
+        [Browsable(false)]
+        [IsCustom]
+        public float xAngle { get; set; } = 0;
+        [Category(CameraInfo), PropertyOrder(92)]
+        [DisplayName("Y杞磋搴�")]
+        [Browsable(false)]
+        [IsCustom]
+        public float yAngle { get; set; } = 0;
+        [Category(CameraInfo), PropertyOrder(93)]
+        [DisplayName("Z杞磋搴�")]
+        [Browsable(false)]
+        [IsCustom]
+        public float zAngle { get; set; } = 0;
+        #endregion
+    }
+    /// <summary>
+    /// IsCustomAttribute
+    /// </summary>
+    public class IsCustomAttribute : Attribute
+    {
+
+    }
+    /// <summary>
+    /// EnumDownsampling
+    /// </summary>
+    public enum EnumDownsampling
+    {
+        /// <summary>
+        /// EnumDownsampling锛歑1=1
+        /// </summary>
+        X1 = 1,
+        /// <summary>
+        /// EnumDownsampling锛歑2=2
+        /// </summary>
+        X2 = 2,
+        /// <summary>
+        /// EnumDownsampling锛歑4=4
+        /// </summary>
+        X4 = 4,
+        /// <summary>
+        /// EnumDownsampling锛歑8=8
+        /// </summary>
+        X8 = 8,
+        /// <summary>
+        /// EnumDownsampling锛歑10=10
+        /// </summary>
+        X10 = 10
+    }
+    /// <summary>
+    /// EnumFilter
+    /// </summary>
+    public enum EnumFilter
+    {
+        /// <summary>
+        /// EnumFilter锛歂one
+        /// </summary>
+        None,
+        /// <summary>
+        /// EnumFilter锛歁ean
+        /// </summary>
+        Mean,
+        /// <summary>
+        /// EnumFilter锛歁eanEdgePreserving
+        /// </summary>
+        MeanEdgePreserving,
+        /// <summary>
+        /// EnumFilter锛歁edian
+        /// </summary>
+        Median
+    }
+    /// <summary>
+    /// EnumMeanFilterWindowSize
+    /// </summary>
+    public enum EnumMeanFilterWindowSize
+    {
+        /// <summary>
+        /// EnumMeanFilterWindowSize锛歐indowSize_2
+        /// </summary>
+        WindowSize_2,
+        /// <summary>
+        /// EnumMeanFilterWindowSize锛歐indowSize_4
+        /// </summary>
+        WindowSize_4,
+        /// <summary>
+        /// EnumMeanFilterWindowSize锛歐indowSize_8
+        /// </summary>
+        WindowSize_8,
+        /// <summary>
+        /// EnumMeanFilterWindowSize锛歐indowSize_16
+        /// </summary>
+        WindowSize_16,
+        /// <summary>
+        /// EnumMeanFilterWindowSize锛歐indowSize_32
+        /// </summary>
+        WindowSize_32
+    }
+    /// <summary>
+    /// EnumMedianFilterWindowSize
+    /// </summary>
+    public enum EnumMedianFilterWindowSize
+    {
+        /// <summary>
+        /// EnumMedianFilterWindowSize锛歐indowSize_3
+        /// </summary>
+        WindowSize_3,
+        /// <summary>
+        /// EnumMedianFilterWindowSize锛歐indowSize_5
+        /// </summary>
+        WindowSize_5,
+        /// <summary>
+        /// EnumMedianFilterWindowSize锛歐indowSize_7
+        /// </summary>
+        WindowSize_7,
+        /// <summary>
+        /// EnumMedianFilterWindowSize锛歐indowSize_9
+        /// </summary>
+        WindowSize_9
+    }
+    /// <summary>
+    /// EnumResampling
+    /// </summary>
+    public enum EnumResampling
+    {
+        /// <summary>
+        /// EnumResampling锛歂earest
+        /// </summary>
+        Nearest,
+        /// <summary>
+        /// EnumResampling锛欶arthest
+        /// </summary>
+        Farthest
+    }
+    /// <summary>
+    /// EnumSpotSelection
+    /// </summary>
+    public enum EnumSpotSelection
+    {
+        /// <summary>
+        /// EnumSpotSelection锛歋trongest
+        /// </summary>
+        Strongest,
+        /// <summary>
+        /// EnumSpotSelection锛歂earest
+        /// </summary>
+        Nearest,
+        /// <summary>
+        /// EnumSpotSelection锛欶arthest
+        /// </summary>
+        Farthest,
+        /// <summary>
+        /// EnumSpotSelection锛欼nvalid
+        /// </summary>
+        Invalid
+    }
+    /// <summary>
+    /// EnumEdgeSelection
+    /// </summary>
+    public enum EnumEdgeSelection
+    {
+        /// <summary>
+        /// EnumEdgeSelection锛欳enter
+        /// </summary>
+        Center,
+        /// <summary>
+        /// EnumEdgeSelection锛歍opEdge
+        /// </summary>
+        TopEdge,
+        /// <summary>
+        /// EnumEdgeSelection锛欱ottomEdge
+        /// </summary>
+        BottomEdge
+    }
+    /// <summary>
+    /// EnumBrightnessAdjustment
+    /// </summary>
+    public enum EnumBrightnessAdjustment
+    {
+        /// <summary>
+        /// EnumBrightnessAdjustment锛歋cale_0_5_0
+        /// </summary>
+        Scale_0_5_0,
+        /// <summary>
+        /// EnumBrightnessAdjustment锛歋cale_0_7_5
+        /// </summary>
+        Scale_0_7_5,
+        /// <summary>
+        /// EnumBrightnessAdjustment锛歋cale_1_0_0
+        /// </summary>
+        Scale_1_0_0,
+        /// <summary>
+        /// EnumBrightnessAdjustment锛歋cale_1_5_0
+        /// </summary>
+        Scale_1_5_0
+    }
+    /// <summary>
+    /// EnumExposureMode
+    /// </summary>
+    public enum EnumExposureMode
+    {
+        /// <summary>
+        /// EnumExposureMode锛欻DR
+        /// </summary>
+        HDR,
+        /// <summary>
+        /// EnumExposureMode锛歍imed
+        /// </summary>
+        Timed
+    }
+    /// <summary>
+    /// EnumAnalogGain
+    /// </summary>
+    public enum EnumAnalogGain
+    {
+        /// <summary>
+        /// EnumAnalogGain锛欸ain_1_0
+        /// </summary>
+        Gain_1_0,
+        /// <summary>
+        /// EnumAnalogGain锛欸ain_1_3
+        /// </summary>
+        Gain_1_3,
+        /// <summary>
+        /// EnumAnalogGain锛欸ain_1_9
+        /// </summary>
+        Gain_1_9,
+        /// <summary>
+        /// EnumAnalogGain锛欸ain_2_8
+        /// </summary>
+        Gain_2_8,
+        /// <summary>
+        /// EnumAnalogGain锛欸ain_5_5
+        /// </summary>
+        Gain_5_5
+    }
+    /// <summary>
+    /// EnumAnalogGainFor8030
+    /// </summary>
+    public enum EnumAnalogGainFor6030
+    {
+        /// <summary>
+        /// EnumAnalogGainFor6030锛欸ain_1_0
+        /// </summary>
+        Gain_1_0,
+        /// <summary>
+        /// EnumAnalogGainFor6030锛欸ain_1_3
+        /// </summary>
+        Gain_1_3,
+        /// <summary>
+        /// EnumAnalogGainFor6030锛欸ain_2_0
+        /// </summary>
+        Gain_2_0,
+        /// <summary>
+        /// EnumAnalogGainFor6030锛欸ain_3_0
+        /// </summary>
+        Gain_3_0
+    }
+    /// <summary>
+    /// EnumZDirectionRoi
+    /// </summary>
+    public enum EnumZDirectionRoi
+    {
+        /// <summary>
+        /// EnumZDirectionRoi锛欼mageHeight_1_1
+        /// </summary>
+        ImageHeight_1_1,
+        /// <summary>
+        /// EnumZDirectionRoi锛欼mageHeight_1_2
+        /// </summary>
+        ImageHeight_1_2,
+        /// <summary>
+        /// EnumZDirectionRoi锛欼mageHeight_1_4
+        /// </summary>
+        ImageHeight_1_4,
+        /// <summary>
+        /// EnumZDirectionRoi锛欼mageHeight_1_8
+        /// </summary>
+        ImageHeight_1_8,
+        /// <summary>
+        /// EnumZDirectionRoi锛欼mageHeight_1_16
+        /// </summary>
+        ImageHeight_1_16
+    }
+    /// <summary>
+    /// EnumDataAcquisitionTriggerSource
+    /// </summary>
+    public enum EnumDataAcquisitionTriggerSource
+    {
+        /// <summary>
+        /// EnumDataAcquisitionTriggerSource锛氳蒋瑙﹀彂
+        /// </summary>
+        杞Е鍙�,
+        /// <summary>
+        /// EnumDataAcquisitionTriggerSource锛氬閮ㄨЕ鍙�
+        /// </summary>
+        澶栭儴瑙﹀彂
+    }
+    /// <summary>
+    /// EnumLineScanTriggerSource
+    /// </summary>
+    public enum EnumLineScanTriggerSource
+    {
+        /// <summary>
+        /// EnumLineScanTriggerSource锛氬浐瀹氶鐜�
+        /// </summary>
+        鍥哄畾棰戠巼,
+        /// <summary>
+        /// EnumLineScanTriggerSource锛氱紪鐮佸櫒
+        /// </summary>
+        缂栫爜鍣�
+    }
+    /// <summary>
+    /// EnumEncoderTriggerDirection
+    /// </summary>
+    public enum EnumEncoderTriggerDirection
+    {
+        /// <summary>
+        /// EnumEncoderTriggerDirection锛欰鐩稿湪鍓�
+        /// </summary>
+        A鐩稿湪鍓�,
+        /// <summary>
+        /// EnumEncoderTriggerDirection锛欱鐩稿湪鍓�
+        /// </summary>
+        B鐩稿湪鍓�,
+        /// <summary>
+        /// EnumEncoderTriggerDirection锛氬弻鍚�
+        /// </summary>
+        鍙屽悜
+    }
+    /// <summary>
+    /// EnumEncoderTriggerSignalCountingMode
+    /// </summary>
+    public enum EnumEncoderTriggerSignalCountingMode
+    {
+        /// <summary>
+        /// EnumEncoderTriggerSignalCountingMode锛歑1
+        /// </summary>
+        X1,
+        /// <summary>
+        /// EnumEncoderTriggerSignalCountingMode锛歑2
+        /// </summary>
+        X2,
+        /// <summary>
+        /// EnumEncoderTriggerSignalCountingMode锛歑4
+        /// </summary>
+        X4
+    }
+
+    /// <summary>
+    /// EnumEncoderTriggerSignalCountingMode
+    /// </summary>
+    public enum EnumNoiseRemovalIntensity
+    {
+        /// <summary>
+        /// EnumNoiseRemovalIntensity--Low
+        /// </summary>
+        Low,
+        /// <summary>
+        ///  EnumNoiseRemovalIntensity--Medium
+        /// </summary>
+        Medium,
+        /// <summary>
+        ///  EnumNoiseRemovalIntensity--High
+        /// </summary>
+        High
+    }
+    /// <summary>
+    /// EnumNameId锛屽弬鏁板悕绉板畾涔�
+    /// </summary>
+    public enum EnumNameId
+    {
+        /// <summary>
+        /// 婊ゆ尝鍣細鏋氫妇鍨嬶紝鍙栧�艰寖鍥� {None, Mean, MeanEdgePreserving, Median }
+        /// </summary>
+        Filter,
+        /// <summary>
+        /// 鍧囧�兼护娉㈠櫒绐楀彛灏哄锛氭灇涓惧瀷锛屽彇鍊艰寖鍥� {WindowSize_2, WindowSize_4, WindowSize_8, WindowSize_16, WindowSize_32}
+        /// </summary>
+        MeanFilterWindowSize,
+        /// <summary>
+        /// 涓�兼护娉㈠櫒绐楀彛灏哄锛氭灇涓惧瀷锛屽彇鍊艰寖鍥� {WindowSize_3, WindowSize_5, WindowSize_7, WindowSize_9}
+        /// </summary>
+        MedianFilterWindowSize,
+        /// <summary>
+        /// 绌虹己濉厖锛氭暣鍨�
+        /// </summary>
+        GapFilling,
+        /// <summary>
+        /// 绌虹己濉厖杈圭紭淇濇寔锛氭暣鍨�
+        /// </summary>
+        GapFillingEdgePreservation,
+        /// <summary>
+        /// 閲嶉噰鏍凤細鏋氫妇鍨嬶紝鍙栧�艰寖鍥� {Nearest, Farthest }
+        /// </summary>
+        Resampling,
+        /// <summary>
+        /// 閲嶉噰鏍疯竟缂樹繚鎸侊細鏁村瀷
+        /// </summary>
+        ResamplingEdgePreservation,
+        /// <summary>
+        /// EnableZAxisAlignment-甯冨皵鍨�
+        /// </summary>
+        EnableZAxisAlignment,
+        /// <summary>
+        /// EnableXAxisAlignment-甯冨皵鍨�
+        /// </summary>
+        EnableXAxisAlignment,
+        /// <summary>
+        /// EnableBlindSpotFiltering-甯冨皵鍨�
+        /// </summary>
+        EnableBlindSpotFiltering,
+        /// <summary>
+        /// EnableNoiseRemoval-甯冨皵鍨�
+        /// </summary>
+        EnableNoiseRemoval,
+        /// <summary>
+        /// NoiseRemovalIntensity-_Enum = {Low, Medium, High}
+        /// </summary>
+        NoiseRemovalIntensity,
+        /// <summary>
+        /// 鏈�灏忕伆搴︼細鏁村瀷
+        /// </summary>
+        MinGrayscaleValue,
+        /// <summary>
+        /// 鎻愬彇鐐规渶灏忓己搴︼細鏁村瀷
+        /// </summary>
+        MinSpotIntensity,
+        /// <summary>
+        /// 鎻愬彇鐐规渶澶у己搴︼細鏁村瀷
+        /// </summary>
+        MaxSpotIntensity,
+        /// <summary>
+        /// 婵�鍏夌嚎鏈�灏忓搴︼細鏁村瀷
+        /// </summary>
+        MinLaserLineWidth,
+        /// <summary>
+        /// 婵�鍏夌嚎鏈�澶у搴︼細鏁村瀷
+        /// </summary>
+        MaxLaserLineWidth,
+        /// <summary>
+        /// 鎻愬彇鐐归�夋嫨锛氭灇涓惧瀷锛屽彇鍊艰寖鍥� {Strongest, Nearest, Farthest, Invalid}
+        /// </summary>
+        SpotSelection,
+        /// <summary>
+        /// 鏋氫妇鍨嬶紝鍙栧�艰寖鍥� {Center, TopEdge, BottomEdge }
+        /// </summary>
+        EdgeSelection,
+        /// <summary>
+        /// MinSharpness-_Int
+        /// </summary>
+        MinSharpness,
+        /// <summary>
+        /// BrightnessAdjustment-鏋氫妇鍨嬶紝鍙栧�艰寖鍥� {Scale_0_5_0, Scale_0_7_5, Scale_1_0_0, Scale_1_5_0, Scale_1_5_0 }
+        /// </summary>
+        BrightnessAdjustment,
+        /// <summary>
+        /// 鏇濆厜妯″紡锛氭灇涓惧瀷锛屽彇鍊艰寖鍥� {HDR, Timed}
+        /// </summary>
+        ExposureMode,
+        /// <summary>
+        /// 鏇濆厜鏃堕棿锛氭暣鍨�
+        /// </summary>
+        ExposureTime,
+        /// <summary>
+        /// HDR鏇濆厜鏃堕棿1锛氭诞鐐瑰瀷
+        /// </summary>
+        HdrExposureTimeProportion1,
+        /// <summary>
+        /// HDR鏇濆厜鏃堕棿2锛氭诞鐐瑰瀷
+        /// </summary>
+        HdrExposureTimeProportion2,
+        /// <summary>
+        /// HdrFirstThreshold-娴偣鍨�
+        /// </summary>
+        HdrFirstThreshold,
+        /// <summary>
+        /// HdrSecondThreshold-娴偣鍨�
+        /// </summary>
+        HdrSecondThreshold,
+        /// <summary>
+        /// 妯℃嫙澧炵泭锛氭灇涓惧瀷锛屽彇鍊艰寖鍥� {Gain_1_0, Gain_1_3, Gain_1_9, Gain_2_8, Gain_5_5}
+        /// </summary>
+        AnalogGain,
+        /// <summary>
+        /// 妯℃嫙澧炵泭锛�6030锛夛細鏋氫妇鍨嬶紝鍙栧�艰寖鍥� {Gain_1_0, Gain_1_3, Gain_2_0, Gain_3_0}
+        /// </summary>
+        AnalogGainFor6030,
+        /// <summary>
+        /// 鏁板瓧澧炵泭锛氭暣鍨�
+        /// </summary>
+        DigitalGain,
+        /// <summary>
+        /// 婵�鍏夊姛鐜囷細鏁村瀷
+        /// </summary>
+        LaserPower,
+        /// <summary>
+        /// Z鍚戞劅鍏磋叮鍖哄煙锛氭灇涓惧瀷锛屽彇鍊艰寖鍥� {ImageHeight_1_1, ImageHeight_1_2, ImageHeight_1_4, ImageHeight_1_8, ImageHeight_1_16}
+        /// </summary>
+        ZDirectionRoi,
+        /// <summary>
+        /// 杞粨绾垮叴瓒e尯鍨�
+        /// </summary>
+        ROI,
+        /// <summary>
+        /// 鏁版嵁閲囬泦瑙﹀彂婧愶細鏋氫妇鍨嬶紝鍙栧�艰寖鍥� {Software, External}
+        /// </summary>
+        DataAcquisitionTriggerSource,
+        /// <summary>
+        /// 琛屾壂鎻忚Е鍙戞簮锛氭灇涓惧瀷锛屽彇鍊艰寖鍥� {FixedRate, Encoder}
+        /// </summary>
+        LineScanTriggerSource,
+        /// <summary>
+        /// 瑙﹀彂棰戠巼锛氭诞鐐瑰瀷
+        /// </summary>
+        SoftwareTriggerRate,
+        /// <summary>
+        /// MaxScanRate-娴偣鍨�
+        /// </summary>
+        MaxScanRate,
+        /// <summary>
+        /// TriggerDelay-_Int
+        /// </summary>
+        TriggerDelay,
+        /// <summary>
+        /// 瑙﹀彂鏂瑰悜锛氭灇涓惧瀷锛屽彇鍊艰寖鍥� {ChannelALeading, ChannelBLeading, Both}
+        /// </summary>
+        EncoderTriggerDirection,
+        /// <summary>
+        /// 瑙﹀彂淇″彿璁℃暟妯″紡锛氭灇涓惧瀷锛屽彇鍊艰寖鍥� {Multiple_1, Multiple_2, Multiple_4}
+        /// </summary>
+        EncoderTriggerSignalCountingMode,
+        /// <summary>
+        /// 瑙﹀彂闂撮殧锛氭暣鍨�
+        /// </summary>
+        EncoderTriggerInterval,
+        /// <summary>
+        /// 鎵弿琛屾暟锛氭暣鍨�
+        /// </summary>
+        ScanLineCount,
+        /// <summary>
+        /// DataPointsPerProfile-_Int
+        /// </summary>
+        DataPointsPerProfile,
+        /// <summary>
+        /// ExposureDelay-_Int
+        /// </summary>
+        ExposureDelay,
+        /// <summary>
+        /// BatchRetrievalTimeout-_Int
+        /// </summary>
+        BatchRetrievalTimeout,
+        /// <summary>
+        /// CallbackRetrievalTimeout-_Int
+        /// </summary>
+        CallbackRetrievalTimeout,
+        /// <summary>
+        /// X杞村垎杈ㄧ巼锛氭诞鐐瑰瀷
+        /// </summary>
+        XAxisResolution,
+        /// <summary>
+        /// Y杞村垎杈ㄧ巼锛氭诞鐐瑰瀷
+        /// </summary>
+        YResolution,
+        /// <summary>
+        /// 鍊炬枩鏍℃瑙掑害锛氭诞鐐瑰瀷
+        /// </summary>
+        TiltCorrectionAngle,
+        /// <summary>
+        /// 楂樺害鏍℃姣斾緥锛氭诞鐐瑰瀷
+        /// </summary>
+        HeightCorrectionRatio,
+        /// <summary>
+        /// CoordinateTransformation-娴偣鍨嬫暟缁�
+        /// </summary>
+        CoordinateTransformation,
+        /// <summary>
+        /// 鍚嶇О ID 鏈�澶у��
+        /// </summary>
+        NameIdMax
+    }
+}
diff --git a/LB_SmartVisionCameraDevice/SensorManager.cs b/LB_SmartVisionCameraDevice/SensorManager.cs
new file mode 100644
index 0000000..5e5a01a
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/SensorManager.cs
@@ -0,0 +1,145 @@
+锘縰sing LB_SmartVisionCameraDevice.Data;
+using LB_SmartVisionCameraDevice.PHM6000;
+using LB_SmartVisionCameraSDK.PHM6000;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCameraDevice
+{
+    /// <summary>
+    /// PHM6000SensorManager
+    /// </summary>
+    public class PHM6000SensorManager
+    {
+        /// <summary>
+        /// GetCameraList
+        /// </summary>
+        /// <returns>Dictionary<string, PHM6000SensorModel></returns>
+        /// <exception cref="Exception">Exception</exception>
+        #region 寰楀埌鎽勫儚澶村垪琛�
+        public static Dictionary<string, PHM6000SensorModel> GetCameraDictionary()
+        {
+            //鍒涘缓鐓х浉鏈烘帴鍙o紝杩斿洖鍏跺彞鏌�
+            IntPtr entry = PHM6000Profiler.CreateCameraEntry();
+
+            //杩斿洖鐩告満涓暟锛�-1鍒欎负鏌ュけ璐�
+            var count = PHM6000Profiler.DiscoverCameras(entry);
+            if (count == -1)
+            {
+                throw new Exception("鏌ユ壘鎽勫儚澶村け璐ワ紒");
+            }
+            byte[] bytes = new byte[16];
+            byte[] modelBytes = new byte[64];
+            byte[] serialNOBytes = new byte[64];
+            int port = 0;
+            Dictionary<string, PHM6000SensorModel> ipList = new Dictionary<string, PHM6000SensorModel>();
+            //瀵规瘡涓浉鏈鸿繘琛屾煡鎵綢P
+            for (int i = 0; i < count; i++)
+            {
+                var ipResult = PHM6000Profiler.GetCameraAddress(entry, i, bytes, ref port);
+                if (ipResult == -1)
+                {
+                    throw new Exception("鑾峰彇鎽勫儚澶碔P閿欒");
+                }
+                var infoResult = PHM6000Profiler.GetCameraInformation(entry, i, modelBytes, serialNOBytes);
+                if (infoResult == -1)
+                {
+                    throw new Exception("鑾峰彇鎽勫儚澶翠俊鎭敊璇�");
+                }
+                var ip = Encoding.ASCII.GetString(bytes);
+                var serialNo = Encoding.ASCII.GetString(serialNOBytes);
+                var model = Encoding.ASCII.GetString(modelBytes);
+                ip = ip.Replace("\0", "");
+                serialNo = serialNo.Replace("\0", "").Replace("X", "B");
+                model = model.Replace("\0", "");
+                if (model.Contains("8080"))
+                {
+                    model = "PHM6080";
+                }
+                if (model.Contains("8300"))
+                {
+                    model = "PHM6300";
+                }
+                if (model.Contains("8030"))
+                {
+                    model = "PHM6030";
+                }
+                ipList.Add(serialNo, new PHM6000SensorModel
+                {
+                    IP = ip,
+                    Port = port,
+                    Model = model,
+                    SerialNo = serialNo,
+                    State = StateIcon.DisConnect,
+                });
+            }
+            PHM6000Profiler.DestroyCameraEntry(entry);//閿�姣�
+            return ipList;
+        }
+        #endregion
+
+        #region 寰楀埌鎽勫儚澶村垪琛�
+        public static List<PHM6000SensorModel> GetCameraList()
+        {
+            //鍒涘缓鐓х浉鏈烘帴鍙o紝杩斿洖鍏跺彞鏌�
+            IntPtr entry = PHM6000Profiler.CreateCameraEntry();
+            //杩斿洖鐩告満涓暟锛�-1鍒欎负鏌ュけ璐�
+            var count = PHM6000Profiler.DiscoverCameras(entry);
+            if (count == -1)
+            {
+                throw new Exception("鏌ユ壘鎽勫儚澶村け璐ワ紒");
+            }
+            byte[] bytes = new byte[16];
+            byte[] modelBytes = new byte[64];
+            byte[] serialNOBytes = new byte[64];
+            int port = 0;
+            List<PHM6000SensorModel> ipList = new List<PHM6000SensorModel>();
+            //瀵规瘡涓浉鏈鸿繘琛屾煡鎵綢P
+            for (int i = 0; i < count; i++)
+            {
+                var ipResult = PHM6000Profiler.GetCameraAddress(entry, i, bytes, ref port);
+                if (ipResult == -1)
+                {
+                    throw new Exception("鑾峰彇鎽勫儚澶碔P閿欒");
+                }
+                var infoResult = PHM6000Profiler.GetCameraInformation(entry, i, modelBytes, serialNOBytes);
+                if (infoResult == -1)
+                {
+                    throw new Exception("鑾峰彇鎽勫儚澶翠俊鎭敊璇�");
+                }
+                var ip = Encoding.ASCII.GetString(bytes);
+                var serialNo = Encoding.ASCII.GetString(serialNOBytes);
+                var model = Encoding.ASCII.GetString(modelBytes);
+                ip = ip.Replace("\0", "");
+                serialNo = serialNo.Replace("\0", "").Replace("X", "B");
+                model = model.Replace("\0", "");
+                if (model.Contains("8080"))
+                {
+                    model = "PHM6080";
+                }
+                if (model.Contains("8300"))
+                {
+                    model = "PHM6300";
+                }
+                if (model.Contains("8030"))
+                {
+                    model = "PHM6030";
+                }
+                ipList.Add(new PHM6000SensorModel
+                {
+                    IP = ip,
+                    Port = port,
+                    Model = model,
+                    SerialNo = serialNo,
+                    State = StateIcon.DisConnect,
+                });
+            }
+            PHM6000Profiler.DestroyCameraEntry(entry);//閿�姣�
+            return ipList;
+        }
+        #endregion
+    }
+}
diff --git a/LB_SmartVisionCameraDevice/ref/PHM6000.dll b/LB_SmartVisionCameraDevice/ref/PHM6000.dll
new file mode 100644
index 0000000..63d2d22
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/ref/PHM6000.dll
Binary files differ
diff --git a/LB_SmartVisionCameraDevice/ref/PHM6000API.dll b/LB_SmartVisionCameraDevice/ref/PHM6000API.dll
new file mode 100644
index 0000000..f523ffd
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/ref/PHM6000API.dll
Binary files differ
diff --git a/LB_SmartVisionCameraDevice/ref/PHM6000API.lib b/LB_SmartVisionCameraDevice/ref/PHM6000API.lib
new file mode 100644
index 0000000..1f69ed5
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/ref/PHM6000API.lib
Binary files differ
diff --git a/LB_SmartVisionCameraDevice/ref/Pilot2D.dll b/LB_SmartVisionCameraDevice/ref/Pilot2D.dll
new file mode 100644
index 0000000..8d9ed88
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/ref/Pilot2D.dll
Binary files differ
diff --git a/LB_SmartVisionCameraDevice/ref/PointCloud3D.dll b/LB_SmartVisionCameraDevice/ref/PointCloud3D.dll
new file mode 100644
index 0000000..af08044
--- /dev/null
+++ b/LB_SmartVisionCameraDevice/ref/PointCloud3D.dll
Binary files differ
diff --git a/LB_SmartVisionCameraSDK/LB_SmartVisionCameraSDK.csproj b/LB_SmartVisionCameraSDK/LB_SmartVisionCameraSDK.csproj
new file mode 100644
index 0000000..07adf05
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/LB_SmartVisionCameraSDK.csproj
@@ -0,0 +1,16 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Library</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <Nullable>enable</Nullable>
+    <UseWindowsForms>true</UseWindowsForms>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Folder Include="ref\" />
+  </ItemGroup>
+
+</Project>
\ No newline at end of file
diff --git a/LB_SmartVisionCameraSDK/PHM6000/PHM6000Profiler.cs b/LB_SmartVisionCameraSDK/PHM6000/PHM6000Profiler.cs
new file mode 100644
index 0000000..345ff2b
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/PHM6000/PHM6000Profiler.cs
@@ -0,0 +1,951 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCameraSDK.PHM6000
+{
+    /// <summary>
+    /// 璁剧疆鍥惧儚澶у皬锛岀敤浜庨�愯娣诲姞鏄剧ず鏁版嵁
+    /// </summary>
+    /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+    /// <param name="nWidth">瀹藉害</param>
+    /// <param name="nHeight">楂樺害</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void SetImageSize_t(IntPtr pHandle, int nWidth, int nHeight);
+    /// <summary>
+    /// 娓呴櫎鏁版嵁锛屽湪鏄剧ず鏂扮殑鍥捐薄鍓嶈皟鐢�
+    /// </summary>
+    /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void ClearAllPoints_t(IntPtr pHandle);
+    /// <summary>
+    /// 鍒锋柊鏄剧ず绐楀彛锛屾鎺т欢鍦ㄤ紶鍏ユ暟鎹椂骞朵笉鏇存柊鏄剧ず锛岀洿鍒拌皟鐢ㄦ鍑芥暟銆�
+    /// </summary>
+    /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void RefreshPilot2D_t(IntPtr pHandle);
+    /// <summary>
+    /// 娣诲姞寮哄害鏁版嵁
+    /// </summary>
+    /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+    /// <param name="points">鍏板疂绾挎壂鎻忎紶鎰熷櫒杈撳嚭鐨勬暟鎹寚閽�, LBPointZA* points</param>
+    /// <param name="nCount">鎸囧畾涓婅堪鏁版嵁鐨勬寚閽堥噷鐨勭偣鐨勬暟閲�</param>
+    /// <returns>鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</returns>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate int AddIntensityData_t(IntPtr pHandle, IntPtr points, int nCount);
+    /// <summary>
+    /// 娣诲姞娣卞害鏁版嵁锛屾鍑芥暟鍏锋湁棰滆壊娓叉煋鍔熻兘
+    /// </summary>
+    /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+    /// <param name="points">鍏板疂绾挎壂鎻忎紶鎰熷櫒杈撳嚭鐨勬暟鎹寚閽�, LBPointZA* points</param>
+    /// <param name="nCount">鎸囧畾涓婅堪鏁版嵁鐨勬寚閽堥噷鐨勭偣鐨勬暟閲�</param>
+    /// <param name="nMinDepth">鎸囧畾娣卞害涓殑鏈�灏忓�硷紝鐢ㄤ簬棰滆壊娓叉煋</param>
+    /// <param name="nMaxDepth">鎸囧畾娣卞害涓殑鏈�澶у�硷紝鐢ㄤ簬棰滆壊娓叉煋</param>
+    /// <returns>鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</returns>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate int AddDepthData_t(IntPtr pHandle, IntPtr points, int nCount, short nMinDepth, short nMaxDepth);
+    /// <summary>
+    /// 娣诲姞璐ㄥ績鏁版嵁
+    /// </summary>
+    /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+    /// <param name="points">鍏板疂绾挎壂鎻忎紶鎰熷櫒杈撳嚭鐨勬暟鎹寚閽圠BPointZA*</param>
+    /// <param name="nCount">鎸囧畾涓婅堪鏁版嵁鐨勬寚閽堥噷鐨勭偣鐨勬暟閲�</param>
+    /// <param name="fMinDistance">鍏板疂绾挎壂鎻忎紶鎰熷櫒妫�娴嬬殑鏈�灏忚窛绂伙紙浠庤鏄庝功鑾峰緱锛屽彇鍊�225.0锛�</param>
+    /// <param name="fMaxDistance">鍏板疂绾挎壂鎻忎紶鎰熷櫒妫�娴嬬殑鏈�澶ц窛绂伙紙浠庤鏄庝功鑾峰緱锛屽彇鍊�473.0锛�</param>
+    /// <param name="fStdDistance">鍏板疂绾挎壂鎻忎紶鎰熷櫒妫�娴嬬殑鏍囧噯璺濈锛堜粠璇存槑涔﹁幏寰楋紝鍙栧��325.0锛�</param>
+    /// <returns>鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</returns>
+    /// <returns></returns>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate int AddBarycentreDataZA_t(IntPtr pHandle, IntPtr points, int nCount, float fMinDistance, float fMaxDistance, float fStdDistance);
+
+    /// <summary>
+    /// 娓呴櫎鐐逛簯瀹炰緥澧炲姞鏁版嵁鐐瑰唴閮ㄦ暟鎹偣
+    /// </summary>
+    /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+    /// <returns>澶辫触杩斿洖0锛屾垚鍔熻繑鍥�1銆�</returns>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate int ClearPCLPoints_t(IntPtr pInstance);
+    /// <summary>
+    /// 鍚戠偣浜戝疄渚嬪鍔犳暟鎹偣锛屽け璐ヨ繑鍥�-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��
+    /// </summary>
+    /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+    /// <param name="points">鍖呭惈娣卞害(Z)鍜屽己搴�(A)淇℃伅鐨勭偣鏁版嵁</param>
+    /// <param name="nCount">鐐圭殑鏁伴噺</param>
+    /// <param name="fStepX">x鍒嗚鲸鐜�</param>
+    /// <param name="fStepY">y鍒嗚鲸鐜�</param>
+    /// <param name="nDownSample">闄嶉噰鏍峰�嶆暟</param>
+    /// <returns>澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��</returns>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate int AddZAPoints_t(IntPtr pInstance, IntPtr points, int nCount, float fStepX, float fStepY, int nDownSample);
+    /// <summary>
+    /// 娓叉煋鐐逛簯绐楀彛锛屾棤杩斿洖
+    /// </summary>
+    /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+    /// <param name="nWidth">绐楀彛瀹藉害</param>
+    /// <param name="nHeight">绐楀彛楂樺害</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void RenderPCLWindow_t(IntPtr pInstance, int nWidth, int nHeight);
+    /// <summary>
+    /// 鏇存柊PCL鐐逛簯鏁版嵁鏄剧ず鐨勯鑹�
+    /// </summary>
+    /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+    /// <param name="szColoring">W,B,r,g,b,x,y,z 瀵瑰簲浜庣櫧榛戠孩缁胯摑鍜寈yz涓夎酱</param>
+    /// <returns>澶辫触杩斿洖0锛屾垚鍔熻繑鍥�1銆�</returns>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
+    public delegate int UpdatePCLPointColors_t(IntPtr pInstance, string szColoring);
+    /// <summary>
+    /// 鏄剧ず姝f柟浣撳潗鏍囩郴锛屾棤杩斿洖
+    /// </summary>
+    /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+    /// <param name="bInit">鏄惁鍒濆鍖�</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void ShowCubeAxes_t(IntPtr pInstance, int bInit);
+    /// <summary>
+    /// 鏄剧ず棰滆壊琛�
+    /// </summary>
+    /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+    /// <param name="x">鏄剧ず浣嶇疆锛屾暟鍊兼槸涓庣獥鍙e搴︾殑姣斿��</param>
+    /// <param name="y">鏄剧ず浣嶇疆锛屾暟鍊兼槸涓庣獥鍙i珮搴︾殑姣斿��</param>
+    /// <param name="xWide">姘村钩瀹藉害锛屾暟鍊兼槸涓庣獥鍙e搴︾殑姣斿��</param>
+    /// <param name="yWide">鍨傜洿瀹藉害锛屾暟鍊兼槸涓庣獥鍙i珮搴︾殑姣斿��</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void ShowLookUpTable_t(IntPtr pInstance, double x, double y, double xWide, double yWide);
+    /// <summary>
+    /// 鑾峰彇PCL鐐逛簯鏁版嵁鐨勮寖鍥�
+    /// </summary>
+    /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+    /// <param name="pMin">杩斿洖鏈�灏忓��</param>
+    /// <param name="pMax">杩斿洖鏈�澶у��</param>
+    /// <returns>澶辫触杩斿洖0锛屾垚鍔熻繑鍥�1銆�</returns>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate int GetPointCloudBound_t(IntPtr pInstance, ref double pMin, ref double pMax);
+    /// <summary>
+    /// 璁剧疆棰滆壊琛ㄨ寖鍥达紝鏃犺繑鍥炲��
+    /// </summary>
+    /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+    /// <param name="fMin">鏈�灏忓��</param>
+    /// <param name="fMax">鏈�澶у��</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void SetLookUpTableRange_t(IntPtr pInstance, double fMin, double fMax);
+
+    /// <summary>
+    /// 瀹氫箟涓嬮潰鐨勭粨鏋勬槸涓轰簡鍚戠浉鏈烘帴鍙e姩鎬佸簱浼犻�扨ilot2D.dll涓殑鍚屽悕鍑芥暟鎸囬拡
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct PILOT2D_FUNC
+    {
+        /// <summary>
+        /// 璁剧疆鍥惧儚澶у皬锛岀敤浜庨�愯娣诲姞鏄剧ず鏁版嵁
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public SetImageSize_t SetImageSize;
+        /// <summary>
+        /// 娓呴櫎鏁版嵁锛屽湪鏄剧ず鏂扮殑鍥捐薄鍓嶈皟鐢�
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public ClearAllPoints_t ClearAllPoints;
+        /// <summary>
+        /// 鍒锋柊鏄剧ず绐楀彛锛屾鎺т欢鍦ㄤ紶鍏ユ暟鎹椂骞朵笉鏇存柊鏄剧ず锛岀洿鍒拌皟鐢ㄦ鍑芥暟銆�
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public RefreshPilot2D_t RefreshPilot2D;
+        /// <summary>
+        /// 娣诲姞寮哄害鏁版嵁
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public AddIntensityData_t AddIntensityData;
+        /// <summary>
+        /// 娣诲姞娣卞害鏁版嵁锛屾鍑芥暟鍏锋湁棰滆壊娓叉煋鍔熻兘
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public AddDepthData_t AddDepthData;
+        /// <summary>
+        /// 娣诲姞璐ㄥ績鏁版嵁
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public AddBarycentreDataZA_t AddBarycentreDataZA;
+    }
+    /// <summary>
+    /// 瀵瑰簲浜嶱ointCloud3D.dll涓殑鍚屽悕鍑芥暟鐨勫舰寮忥紝鍏蜂綋鍑芥暟鍔熻兘鍙傝PointCloud3D.dll鐨勮皟鐢ㄨ鏄�
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct VTK3D_FUNC
+    {
+        /// <summary>
+        /// 娓呴櫎鐐逛簯瀹炰緥澧炲姞鏁版嵁鐐瑰唴閮ㄦ暟鎹偣
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public ClearPCLPoints_t ClearPCLPoints;
+        /// <summary>
+        /// 鍚戠偣浜戝疄渚嬪鍔犳暟鎹偣锛屽け璐ヨ繑鍥�-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public AddZAPoints_t AddZAPoints;
+        /// <summary>
+        /// 娓叉煋鐐逛簯绐楀彛锛屾棤杩斿洖
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public RenderPCLWindow_t RenderPCLWindow;
+        /// <summary>
+        /// 鏇存柊PCL鐐逛簯鏁版嵁鏄剧ず鐨勯鑹�
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public UpdatePCLPointColors_t UpdatePCLPointColors;
+        /// <summary>
+        /// 鏄剧ず姝f柟浣撳潗鏍囩郴锛屾棤杩斿洖
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public ShowCubeAxes_t ShowCubeAxes;
+        /// <summary>
+        /// 鏄剧ず棰滆壊琛�
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public ShowLookUpTable_t ShowLookUpTable;
+        /// <summary>
+        /// 鑾峰彇PCL鐐逛簯鏁版嵁鐨勮寖鍥�
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public GetPointCloudBound_t GetPointCloudBound;
+        /// <summary>
+        /// 璁剧疆棰滆壊琛ㄨ寖鍥达紝鏃犺繑鍥炲��
+        /// </summary>
+        [MarshalAs(UnmanagedType.FunctionPtr)]
+        public SetLookUpTableRange_t SetLookUpTableRange;
+    }
+
+    //typedef void (__stdcall* ShowDebugInfoCallback) (char* szMessage, int nLength);
+    /// <summary>
+    /// 鏄剧ず璋冭瘯淇℃伅鐨勫洖璋冨嚱鏁版牸寮忥紝鏃犺繑鍥炲��
+    /// </summary>
+    /// <param name="szMessage">娑堟伅瀛楃涓�</param>
+    /// <param name="nLength">瀛楃涓查暱搴�</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void ShowDebugInfoCallback(string szMessage, int nLength);
+
+    //typedef void (__stdcall* StartMotorCallback) (int direction, int move_steps, double move_speed);
+    /// <summary>
+    /// 鍚姩鐢垫満,姝ゅ洖璋冨嚱鏁扮敱缂栧啓鐢垫満椹卞姩鑰呮寜姝ゆ牸寮忔彁渚涜皟鐢ㄣ��
+    /// </summary>
+    /// <param name="direction">杩愬姩鏂瑰悜</param>
+    /// <param name="move_steps">绉诲姩姝ユ暟</param>
+    /// <param name="move_speed">绉诲姩閫熷害</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void StartMotorCallback(int direction, int move_steps, double move_speed);
+
+    //typedef void (__stdcall* StopMotorCallback) ();
+    /// <summary>
+    /// 鍋滄鐢垫満,姝ゅ洖璋冨嚱鏁扮敱缂栧啓鐢垫満椹卞姩鑰呮寜姝ゆ牸寮忔彁渚涜皟鐢ㄣ��
+    /// </summary>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void StopMotorCallback();
+
+    //typedef void (__stdcall* AcquisitionCallbackZA) (void* pInstance, void* buffer, int points);
+    /// <summary>
+    /// 閲囬泦鏁版嵁鐨勫洖璋冨嚱鏁�
+    /// </summary>
+    /// <param name="pInstance">鍥炶皟鍑芥暟鎻愪緵鑰呯殑鍙ユ焺</param>
+    /// <param name="buffer">LBPointZA鏍煎紡鐨勬暟鎹紦鍐插尯鎸囬拡</param>
+    /// <param name="points">鏁版嵁涓寘鍚偣鐨勬暟閲�</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void AcquisitionCallbackZA(IntPtr pInstance, IntPtr buffer, int points);
+
+    //typedef void (__stdcall* AcquisitionCompletedCallback) (void* pInstance, int nOption);
+    /// <summary>
+    /// 閲囬泦缁撴潫鐨勫洖璋冨嚱鏁帮紝鍙緵鐢ㄦ埛鍦ㄩ噰闆嗙粨鏉熷悗鍋氫簺澶勭悊
+    /// </summary>
+    /// <param name="pInstance">鍥炶皟鍑芥暟鎻愪緵鑰呯殑鍙ユ焺</param>
+    /// <param name="nOption">涓�0鏃惰〃绀轰竴鎵规暟鎹粨鏉燂紝涓�1鏃惰〃鏃跺叏閮ㄩ噰闆嗗畬鎴�</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void AcquisitionCompletedCallback(IntPtr pInstance, int nOption);
+
+    /// <summary>
+    /// 鐩告満杩炴帴鎴愬姛鍥炶皟鍑芥暟锛�
+    /// </summary>
+    /// <param name="strSN">鐩告満搴忓垪鍙�</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void AcquisitionConnectCompletedCallback(string strSN);
+
+    /// <summary>
+    /// 鐩告満鎺ュ彛绫�
+    /// </summary>
+    public class PHM6000Profiler
+    {
+        //PHM6000_API(void*) CreateCameraEntry();
+        /// <summary>
+        /// 鍒涘缓鐓х浉鏈烘帴鍙o紝
+        /// </summary>
+        /// <returns>杩斿洖鐩告満鍙ユ焺</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "CreateCameraEntry")]
+        public static extern IntPtr CreateCameraEntry();
+
+        //PHM6000_API(void) DestroyCameraEntry(void* pHandle);
+        /// <summary>
+        /// 閿�姣佺収鐩告満鎺ュ彛
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "DestroyCameraEntry")]
+        public static extern void DestroyCameraEntry(IntPtr pHandle);
+
+        //PHM6000_API(int) DiscoverCameras(void* pHandle);
+        /// <summary>
+        /// 鏌ユ壘鐓х浉鏈�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <returns>鏌ユ壘澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炵浉鏈轰釜鏁般��</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "DiscoverCameras")]
+        public static extern int DiscoverCameras(IntPtr pHandle);
+
+        //PHM6000_API(int) GetCameraInfo(void* pHandle, int nIndex, LBCameraInfo* pCameraInfo);
+        /// <summary>
+        /// 鑾峰彇鐓х浉鏈轰俊鎭�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nIndex">鐩告満搴忓彿</param>
+        /// <param name="pCameraInfo">鐩告満淇℃伅缁撴瀯鎸囬拡, LBCameraInfo* pCameraInfo</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCameraInfo")]
+        public static extern int GetCameraInfo(IntPtr pHandle, int nIndex, IntPtr pCameraInfo);
+
+        //PHM6000_API(int) GetCameraInformation(void* pHandle, int nIndex, char* szModuleType, char* szSerialNumber);
+        /// <summary>
+        /// 鑾峰彇鐓х浉鏈轰俊鎭紙鏂逛究C#璋冪敤澧炲姞鐨勶級
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nIndex">鐩告満搴忓彿</param>
+        /// <param name="szModuleType">妯″潡鍚�, char* szModuleType</param>
+        /// <param name="szSerialNumber">搴忓垪鍙�, char* szSerialNumber</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCameraInformation")]
+        public static extern int GetCameraInformation(IntPtr pHandle, int nIndex, IntPtr szModuleType, IntPtr szSerialNumber);
+        //PHM6000_API(int) GetCameraInformation(void* pHandle, int nIndex, char* szModuleType, char* szSerialNumber);
+        /// <summary>
+        /// 鑾峰彇鐓х浉鏈轰俊鎭�
+        /// </summary>
+        /// <param name="pHandle">寮�鐨勬帴鍙�</param>
+        /// <param name="nlndex">绗嚑涓�</param>
+        /// <param name="szModuleType">鍨嬪彿</param>
+        /// <param name="szSerialNumber">搴忓垪鍙�</param>
+        /// <returns></returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCameraInformation")]
+        public static extern int GetCameraInformation(IntPtr pHandle, int nlndex, byte[] szModuleType, byte[] szSerialNumber);
+
+
+        //PHM6000_API(int) GetCameraAddress(void* pHandle, int nIndex, char* szAddress, int* nPort);
+        /// <summary>
+        /// 鑾峰彇鐓х浉鏈篒P淇℃伅
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nIndex">鐩告満搴忓彿</param>
+        /// <param name="szAddress">IP鍦板潃瀛楃涓�, char* szAddress</param>
+        /// <param name="nPort">绔彛鍙�, int* nPort</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCameraAddress")]
+        public static extern int GetCameraAddress(IntPtr pHandle, int nIndex, IntPtr szAddress, IntPtr nPort);
+        //PHM6000_API(int) GetCameraAddress(void* pHandle, int nIndex, char* szAddress, int* nPort);
+        /// <summary>
+        /// 寰楀埌杩炴帴鐨処P
+        /// </summary>
+        /// <param name="pHandle">寮�鐨勬帴鍙�</param>
+        /// <param name="nlndex">绗嚑涓�</param>
+        /// <param name="szAddress">杩斿洖鐨勫湴鍧�</param>
+        /// <param name="nPort">杩斿洖鐨勭鍙�</param>
+        /// <returns>杩炴帴澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCameraAddress")]
+        public static extern int GetCameraAddress(IntPtr pHandle, int nlndex, byte[] szAddress, ref int nPort);
+
+        //PHM6000_API(int) ConnectToCamera(void* pHandle, char* szIpAddress, int nPort);
+        /// <summary>
+        /// 杩炴帴鐓х浉鏈�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="szAddress">IP鍦板潃瀛楃涓�</param>
+        /// <param name="nPort">绔彛鍙�</param>
+        /// <returns>杩炴帴澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCameraAddress")]
+        public static extern int GetCameraAddress(IntPtr pHandle, string szAddress, int nPort);
+
+        //PHM6000_API(int) ConnectToCamera(void* pHandle, char* szIpAddress, int nPort);
+        /// <summary>
+        /// 杩炴帴鐓х浉鏈�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="szAddress">IP鍦板潃瀛楃涓�</param>
+        /// <param name="nPort">绔彛鍙�</param>
+        /// <returns>杩炴帴澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "ConnectToCamera")]
+        public static extern int ConnectToCamera(IntPtr pHandle, IntPtr szAddress, int nPort);
+
+        //PHM6000_API(int) ConnectToCamera(void* pHandle, char* szIpAddress, int nPort);
+        /// <summary>
+        /// 杩炴帴鐓х浉鏈�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="szAddress">IP鍦板潃瀛楃涓�</param>
+        /// <param name="nPort">绔彛鍙�</param>
+        /// <returns>杩炴帴澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "ConnectToCamera")]
+        public static extern int ConnectToCamera(IntPtr pHandle, byte[] szAddress, int nPort);
+
+        //PHM6000_API(int) DisconnectFromCamera(void* pHandle, char* szIpAddress);
+        /// <summary>
+        /// 鏂紑鐓х浉鏈�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="szIpAddress">鎸囧畾瑕佹柇寮�鐨勭浉鏈虹殑IP鍦板潃</param>
+        /// <returns>鏂紑澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "DisconnectFromCamera")]
+        public static extern int DisconnectFromCamera(IntPtr pHandle, string szIpAddress);
+
+        //PHM6000_API(int) SetAcquisitionCallbackZA(void* pHandle, AcquisitionCallbackZA callbackZA, void* pInstance);
+        /// <summary>
+        /// 璁剧疆绱у噾鐨勯噰闆嗗洖璋冨嚱鏁�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="callbackZA">鍥炶皟鍑芥暟, AcquisitionCallbackZA callbackZA</param>
+        /// <param name="pInstance">鍥炶皟鍑芥暟鎻愪緵鑰呯殑鍙ユ焺</param>
+        /// <returns>璁剧疆澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetAcquisitionCallbackZA")]
+        public static extern int SetAcquisitionCallbackZA(IntPtr pHandle, AcquisitionCallbackZA callbackZA, IntPtr pInstance);
+
+        //PHM6000_API(int) SetAcquisitionCallbackZA(void* pHandle, AcquisitionCallbackZA callbackZA, void* pInstance);
+        /// <summary>
+        /// 璁剧疆绱у噾鐨勯噰闆嗗洖璋冨嚱鏁�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="callbackZA">鍥炶皟鍑芥暟, AcquisitionCallbackZA callbackZA</param>
+        /// <param name="pInstance">鍥炶皟鍑芥暟鎻愪緵鑰呯殑鍙ユ焺</param>
+        /// <returns>璁剧疆澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetAcquisitionCallbackZA")]
+        public static extern int SetAcquisitionCallbackZA(IntPtr pHandle, IntPtr callbackZA, IntPtr pInstance);
+
+        //PHM6000_API(int) SetMotorCallbackFunction(void* pHandle, StartMotorCallback startFunction, StopMotorCallback stopFunction);
+        /// <summary>
+        /// 璁剧疆椹揪鍥炶皟鍑芥暟锛屾病鏈夎繖涓や釜鍥炶皟鍑芥暟灏变笉璋冪敤姝ゅ嚱鏁版潵璁剧疆鍥炶皟鍔熻兘銆�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="startFunction">椹揪鍚姩鍥炶皟鍑芥暟</param>
+        /// <param name="stopFunction">椹揪鍋滄鍥炶皟鍑芥暟</param>
+        /// <returns>璁剧疆澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetMotorCallbackFunction")]
+        public static extern int SetMotorCallbackFunction(IntPtr pHandle, StartMotorCallback startFunction, StopMotorCallback stopFunction);
+
+        //PHM6000_API(int) SetAcquisitionMode(void* pHandle, int bScanMode, int bContinuedMode);
+        /// <summary>
+        /// 璁剧疆閲囬泦妯″紡
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="bScanMode">涓�1鏃舵槸鎵弿妯″紡锛屼负0鏃舵槸杞粨妯″紡</param>
+        /// <param name="bContinuedMode">涓�1鏃舵槸杩炴帴妯″紡锛屼负0鏃舵槸鍗曟妯″紡</param>
+        /// <returns>璁剧疆澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetAcquisitionMode")]
+        public static extern int SetAcquisitionMode(IntPtr pHandle, int bScanMode, int bContinuedMode);
+
+        //PHM6000_API(int) StartAcquisition(void* pHandle, int motor_direction, int move_steps, double move_speed);
+        /// <summary>
+        /// 鍚姩閲囬泦
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="motor_direction">椹揪鐨勮繍鍔ㄦ柟鍚戯紝濡傛灉娌℃湁椹揪鍥炶皟鍑芥暟锛岀疆闆跺嵆鍙��</param>
+        /// <param name="move_steps">椹揪绉诲姩姝ユ暟锛屽鏋滄病鏈夐┈杈惧洖璋冨嚱鏁帮紝缃浂鍗冲彲銆�</param>
+        /// <param name="move_speed">椹揪绉诲姩閫熷害锛屽鏋滄病鏈夐┈杈惧洖璋冨嚱鏁帮紝缃浂鍗冲彲銆�</param>
+        /// <returns>鍚姩澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "StartAcquisition")]
+        public static extern int StartAcquisition(IntPtr pHandle, int motor_direction, int move_steps, double move_speed);
+
+        //PHM6000_API(int) StopAcquisition(void* pHandle);
+        /// <summary>
+        /// 鍋滄閲囬泦
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <returns>鍋滄澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "StopAcquisition")]
+        public static extern int StopAcquisition(IntPtr pHandle);
+
+        //PHM6000_API(int) GetRawImage(void* pHandle, LBPointBGRA** image, int* w, int* h);
+        /// <summary>
+        /// 鑾峰彇鍘熷鍥惧儚鏁版嵁锛屾殏涓嶆敮鎸�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="image">鍥惧儚鏁版嵁鎸囬拡, LBPointBGRA** image</param>
+        /// <param name="w">鍥惧儚瀹藉害, int* w</param>
+        /// <param name="h">鍥惧儚楂樺害, int* h</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetRawImage")]
+        public static extern int GetRawImage(IntPtr pHandle, out IntPtr image, out int w, out int h);
+
+        //PHM6000_API(int) GetParameterGroupCount(void* pHandle);
+        /// <summary>
+        /// 鑾峰彇鍙傛暟缁勭殑涓暟
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炲弬鏁扮粍鐨勬暟閲忋��</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetParameterGroupCount")]
+        public static extern int GetParameterGroupCount(IntPtr pHandle);
+
+        //PHM6000_API(int) GetParameterGroupName(void* pHandle, int group_index, char* groupName);
+        /// <summary>
+        /// 鑾峰彇鍏ㄩ儴鍙傛暟缁勭殑鍚嶇О
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="group_index">缁勫簭鍙�</param>
+        /// <param name="groupName">缁勫悕绉帮紝UTF-8鏍煎紡鐨勫瓧绗�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炲悕绉扮殑闀垮害銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetParameterGroupName")]
+        public static extern int GetParameterGroupName(IntPtr pHandle, int group_index, byte[] groupName);
+
+        //PHM6000_API(int) GetCurrentParameterGroup(void* pHandle, char* groupName);
+        /// <summary>
+        /// 鑾峰彇褰撳墠鍙傛暟缁勭殑鍚嶇О
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="groupName">鍙傛暟鍚嶇О锛孶TF-8鏍煎紡鐨勫瓧绗�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炲悕绉扮殑闀垮害銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCurrentParameterGroup")]
+        public static extern int GetCurrentParameterGroup(IntPtr pHandle, byte[] groupName);
+
+        //PHM6000_API(int) SelectParameterGroup(void* pHandle, const char* groupName);
+        /// <summary>
+        /// 閫夋嫨鍙傛暟缁�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="groupName">鍙傛暟缁勫悕绉�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SelectParameterGroup")]
+        public static extern int SelectParameterGroup(IntPtr pHandle, byte[] groupName);
+
+        //PHM6000_API(int) AddParameterGroup(void* pHandle, const char* groupName);
+        /// <summary>
+        /// 娣诲姞鍙傛暟缁�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="groupName">鍙傛暟缁勫悕绉�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddParameterGroup")]
+        public static extern int AddParameterGroup(IntPtr pHandle, byte[] groupName);
+
+        //PHM6000_API(int) DeleteParameterGroup(void* pHandle, const char* groupName);
+        /// <summary>
+        /// 鍒犻櫎鍙傛暟缁�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="groupName">鍙傛暟缁勫悕绉�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "DeleteParameterGroup")]
+        public static extern int DeleteParameterGroup(IntPtr pHandle, byte[] groupName);
+
+        //PHM6000_API(int) RenameParameterGroup(void* pHandle, const char* newName);
+        /// <summary>
+        /// 閲嶅懡鍚嶅弬鏁扮粍
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="newName">鏂板弬鏁扮粍鍚嶇О</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "RenameParameterGroup")]
+        public static extern int RenameParameterGroup(IntPtr pHandle, byte[] newName);
+
+        //PHM6000_API(int) LoadParameters(void* pHandle, char* szJSONFileName);
+        /// <summary>
+        /// 鍔犺浇鐩告満鍙傛暟
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="szJSONFileName">json鏍煎紡鏂囦欢鍚�</param>
+        /// <returns>鍔犺浇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "LoadParameters")]
+        public static extern int LoadParameters(IntPtr pHandle, byte[] szJSONFileName);
+
+        //PHM6000_API(int) SaveParameters(void* pHandle, char* szJSONFileName);
+        /// <summary>
+        /// 淇濆瓨鐩告満鍙傛暟
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="szJSONFileName">json鏍煎紡鏂囦欢鍚�</param>
+        /// <returns>淇濆瓨澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SaveParameters")]
+        public static extern int SaveParameters(IntPtr pHandle, byte[] szJSONFileName);
+
+        //PHM6000_API(int) GetProfilerParameter(void* pHandle, int nNameId, int* intValue, double* floatValue, int* enumValue);
+        /// <summary>
+        /// 鑾峰彇绾挎壂鐩告満鍙傛暟锛屾瘡娆¤鍙栦竴绉嶅弬鏁帮紝鍙傛暟鍦ㄧ浉搴旂被鍨嬪杩斿洖锛屽叾瀹冪被鍨嬩綅缃拷鐣�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nNameId">鍙傛暟鍚嶇殑鏋氫妇鍊�</param>
+        /// <param name="intvalue">鏁村瀷鍊兼寚閽�</param>
+        /// <param name="floatValue">鍙岀簿搴﹀瀷鎸囬拡</param>
+        /// <param name="enumValue">鏋氫妇鍨嬫寚閽�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetProfilerParameter")]
+        public static extern int GetProfilerParameter(IntPtr pHandle, int nNameId, ref int intvalue, ref double floatValue, ref int enumValue);
+
+        //PHM6000_API(int) GetProfilerParameter(void* pHandle, int nNameId, int* intValue, double* floatValue, int* enumValue);
+        /// <summary>
+        /// 鑾峰彇绾挎壂鐩告満鍙傛暟锛屾瘡娆¤鍙栦竴绉嶅弬鏁帮紝鍙傛暟鍦ㄧ浉搴旂被鍨嬪杩斿洖锛屽叾瀹冪被鍨嬩綅缃拷鐣�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nNameId">鍙傛暟鍚嶇殑鏋氫妇鍊�</param>
+        /// <param name="intvalue">鏁村瀷鍊兼寚閽�</param>
+        /// <param name="floatValue">鍙岀簿搴﹀瀷鎸囬拡</param>
+        /// <param name="enumValue">鏋氫妇鍨嬫寚閽�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetProfilerParameter")]
+        public static extern int GetProfilerParameter(IntPtr pHandle, int nNameId, ref int intvalue, IntPtr floatValue, ref int enumValue);
+
+        //PHM6000_API(int) SetProfilerParameter(void* pHandle, int nNameId, int intValue, double floatValue, int enumValue);
+        /// <summary>
+        /// 璁剧疆绾挎壂鐩告満鍙傛暟锛屾瘡娆¤缃竴绉嶅弬鏁帮紝鍙傛暟鍦ㄧ浉搴旂被鍨嬪杈撳叆锛屽叾瀹冪被鍨嬩綅缃疆闆�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nNameId">鍙傛暟鍚嶇殑鏋氫妇鍊�</param>
+        /// <param name="intvalue">鏁村瀷鍊�</param>
+        /// <param name="floatValue">鍙岀簿搴﹀瀷鍊�</param>
+        /// <param name="enumValue">鏋氫妇鍨嬪��</param>
+        /// <returns>璁剧疆澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetProfilerParameter")]
+        public static extern int SetProfilerParameter(IntPtr pHandle, int nNameId, int intvalue, double floatValue, int enumValue);
+
+        //PHM6000_API(int) GetParameterNameCount(void* pHandle);
+        /// <summary>
+        /// 鑾峰彇鍙傛暟鍚嶇殑涓暟
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炲弬鏁板悕鐨勬暟閲忋��</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetParameterNameCount")]
+        public static extern int GetParameterNameCount(IntPtr pHandle);
+
+        //PHM6000_API(int) GetParameterName(void* pHandle, int param_index, char* paramName);
+        /// <summary>
+        /// 鑾峰彇鍏ㄩ儴鍙傛暟鐨勫悕绉�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="param_index">鍙傛暟鍚嶅簭鍙�</param>
+        /// <param name="paramName">鍙傛暟鍚嶇О锛孶TF-8鏍煎紡鐨勫瓧绗�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炲悕绉扮殑闀垮害銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetParameterName")]
+        public static extern int GetParameterName(IntPtr pHandle, int param_index, byte[] paramName);
+
+        //PHM6000_API(int) ResetAllParametersToDefault(void* pHandle);
+        /// <summary>
+        /// 灏嗗叏閮ㄥ弬鏁扮殑鍊煎浣嶆垚榛樿鍊�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "ResetAllParametersToDefault")]
+        public static extern int ResetAllParametersToDefault(IntPtr pHandle);
+
+        //PHM6000_API(int) SaveAllParametersToDevice(void* pHandle);
+        /// <summary>
+        /// 灏嗗叏閮ㄥ弬鏁扮殑鍊间繚瀛樺埌璁剧疆
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SaveAllParametersToDevice")]
+        public static extern int SaveAllParametersToDevice(IntPtr pHandle);
+
+        //PHM6000_API(int) SetOutputGPIO(void* pHandle, GPIOLine LineIndex, int Level);
+        /// <summary>
+        /// 璁剧疆GPIO杈撳嚭
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="LineIndex">寮曡剼搴忓彿</param>
+        /// <param name="Level">杈撳嚭鐢靛钩锛�1杈撳嚭楂樼數骞�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetOutputGPIO")]
+        public static extern int SetOutputGPIO(IntPtr pHandle, GPIOLine LineIndex, int Level);
+
+        //PHM6000_API(int) RegisterShowDebugInfoCallback(void* pHandle, ShowDebugInfoCallback callback);
+        /// <summary>
+        /// 娉ㄥ唽璋冭瘯淇℃伅鍥炶皟鍑芥暟锛岀敤浜庤皟璇�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="callback">璋冭瘯鐢ㄥ洖璋冨嚱鏁版寚閽�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "RegisterShowDebugInfoCallback")]
+        public static extern int RegisterShowDebugInfoCallback(IntPtr pHandle, ShowDebugInfoCallback callback);
+
+        //PHM6000_API(int) RegisterAcquisitionCompletedCallback(void* pHandle, AcquisitionCompletedCallback callback, void* pInstance);
+        /// <summary>
+        /// 娉ㄥ唽閲囬泦瀹屾垚鍥炶皟鍑芥暟
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="callback">閲囬泦瀹屾垚鍥炶皟鍑芥暟鎸囬拡</param>
+        /// <param name="pInstance">璋冪敤鑰呯殑鍙ユ焺</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "RegisterAcquisitionCompletedCallback")]
+        public static extern int RegisterAcquisitionCompletedCallback(IntPtr pHandle, AcquisitionCompletedCallback callback, IntPtr pInstance);
+
+        //PHM6000_API(int) LoadDataFromFile(void* pHandle, const char* szFileName);
+        /// <summary>
+        /// 浠庢枃浠跺姞杞芥暟鎹紙鍚庣紑鍚嶏細*.lb3d锛�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="szFileName">鏂囦欢鍚�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "LoadDataFromFile")]
+        public static extern int LoadDataFromFile(IntPtr pHandle, byte[] szFileName);
+
+        //PHM6000_API(int) SaveDataToFile(void* pHandle, const char* szFileName);
+        /// <summary>
+        /// 鍚戞枃浠朵繚瀛樻暟鎹紙鍚庣紑鍚嶏細*.lb3d锛�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="szFileName">鏂囦欢鍚�</param>
+        /// <returns>鑾峰彇澶辫触杩斿洖-1锛屽惁鍒欒繑鍥�0銆�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SaveDataToFile")]
+        public static extern int SaveDataToFile(IntPtr pHandle, byte[] szFileName);
+
+        //PHM6000_API(void) SetShowHandles(void* pHandle, void* pIntensityHandle, void* pDepthHandle, void* pRawHandle, void* pVTK3dHandle, void* pChartHandle = nullptr);
+        /// <summary>
+        /// 璁剧疆鏄剧ず鎺т欢鐨勫彞鏌�,鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="pIntensityHandle">寮哄害鎺т欢鍙ユ焺</param>
+        /// <param name="pDepthHandle">娣卞害鎺т欢鍙ユ焺</param>
+        /// <param name="pRawHandle">鍘熷浘鎺т欢鍙ユ焺</param>
+        /// <param name="pVTK3dHandle">涓夌淮鏄剧ず鎺т欢鍙ユ焺</param>
+        /// <param name="pChartHandle">鍥捐〃鏄炬帶浠跺彞鏌�</param>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetShowHandles")]
+        public static extern void SetShowHandles(IntPtr pHandle, IntPtr pIntensityHandle, IntPtr pDepthHandle, IntPtr pRawHandle, IntPtr pVTK3dHandle, IntPtr pChartHandle = new IntPtr());
+
+        //PHM6000_API(void) SetPilot2dFunc(void* pHandle, PILOT2D_FUNC func);
+        /// <summary>
+        /// 璁剧疆浜岀淮鏄剧ず鎺т欢鎵�闇�鐨勫姛鑳藉嚱鏁扮粨鏋勪綋,鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="func">浜岀淮鏄剧ず鎺т欢鎵�闇�鐨勫姛鑳藉嚱鏁扮粨鏋勪綋</param>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetPilot2dFunc")]
+        public static extern void SetPilot2dFunc(IntPtr pHandle, PILOT2D_FUNC func);
+
+        //PHM6000_API(void) SetVTK3dFunc(void* pHandle, VTK3D_FUNC func);
+        /// <summary>
+        /// 璁剧疆涓夌淮鏄剧ず鎺т欢鎵�闇�鐨勫姛鑳藉嚱鏁扮粨鏋勪綋,鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="func">涓夌淮鏄剧ず鎺т欢鎵�闇�鐨勫姛鑳藉嚱鏁扮粨鏋勪綋</param>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetVTK3dFunc")]
+        public static extern void SetVTK3dFunc(IntPtr pHandle, VTK3D_FUNC func);
+
+        //PHM6000_API(unsigned char*) GetIntensityData(void* pHandle, int& nWidth, int& nHeight);
+        /// <summary>
+        /// 鑾峰彇寮哄害鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nWidth">鍥炰紶寮哄害鏁版嵁鐨勫搴�</param>
+        /// <param name="nHeight">鍥炰紶寮哄害鏁版嵁鐨勯珮搴�</param>
+        /// <returns>杩斿洖寮哄害鏁版嵁鐨勬寚閽堬紝杩斿洖鍊间负NULL鏃惰〃绀鸿皟鐢ㄥけ璐ワ紝(unsigned char*)</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetIntensityData")]
+        public static extern IntPtr GetIntensityData(IntPtr pHandle, ref int nWidth, ref int nHeight);
+
+        //PHM6000_API(float*) GetDepthData(void* pHandle, int& nWidth, int& nHeight, float* fMinValue = NULL, float* fMaxValue = NULL);
+        /// <summary>
+        /// 鑾峰彇娣卞害鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nWidth">鍥炰紶娣卞害鏁版嵁鐨勫搴�</param>
+        /// <param name="nHeight">鍥炰紶娣卞害鏁版嵁鐨勯珮搴�</param>
+        /// <param name="fMinValue">鐢ㄤ簬鍥炰紶娣卞害鐨勬渶灏忓��, float* fMinValue = NULL</param>
+        /// <param name="fMaxValue">鐢ㄤ簬鍥炰紶娣卞害鐨勬渶澶у��, float* fMaxValue = NULL</param>
+        /// <returns>杩斿洖娣卞害鏁版嵁鐨勬寚閽堬紝杩斿洖鍊间负NULL鏃惰〃绀鸿皟鐢ㄥけ璐�,(float*) </returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetDepthData")]
+        public static extern IntPtr GetDepthData(IntPtr pHandle, ref int nWidth, ref int nHeight, IntPtr fMinValue = new IntPtr(), IntPtr fMaxValue = new IntPtr());
+
+        //PHM6000_API(float*) GetDepthDataInRectangle(void* pHandle, int nLeft, int nTop, int& nWidth, int& nHeight);
+        /// <summary>
+        /// 鑾峰彇鐭╁舰鍏磋叮鍖哄唴鐨勬繁搴︽暟鎹�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nLeft">鐭╁舰宸︿笂瑙掔殑x鍧愭爣</param>
+        /// <param name="nTop">鐭╁舰宸︿笂瑙掔殑y鍧愭爣</param>
+        /// <param name="nWidth">鐭╁舰鍏磋叮鍖虹殑瀹藉害</param>
+        /// <param name="nHeight">鐭╁舰鍏磋叮鍖虹殑楂樺害</param>
+        /// <returns>杩斿洖娣卞害鏁版嵁鐨勬寚閽堬紝杩斿洖鍊间负NULL鏃惰〃绀鸿皟鐢ㄥけ璐ワ紝(float*)</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetDepthDataInRectangle")]
+        public static extern IntPtr GetDepthDataInRectangle(IntPtr pHandle, int nLeft, int nTop, ref int nWidth, ref int nHeight);
+
+        //PHM6000_API(float*) GetDepthDataInCircle(void* pHandle, int& nWidth, int& nHeight, int nXPos, int nYPos, int nRadius);
+        /// <summary>
+        /// 鑾峰彇鍦嗗舰鍏磋叮鍖哄唴鐨勬繁搴︽暟鎹�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nWidth">鍥炰紶娣卞害鏁版嵁鐨勫搴�</param>
+        /// <param name="nHeight">鍥炰紶娣卞害鏁版嵁鐨勯珮搴�</param>
+        /// <param name="nXPos">鍦嗗舰涓績鐨剎鍧愭爣</param>
+        /// <param name="nYPos">鍦嗗舰涓績鐨剏鍧愭爣</param>
+        /// <param name="nRadius">鍦嗗舰鐨勫崐寰�</param>
+        /// <returns>杩斿洖娣卞害鏁版嵁鐨勬寚閽堬紝杩斿洖鍊间负NULL鏃惰〃绀鸿皟鐢ㄥけ璐�,(float*)</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetDepthDataInCircle")]
+        public static extern IntPtr GetDepthDataInCircle(IntPtr pHandle, ref int nWidth, ref int nHeight, int nXPos, int nYPos, int nRadius);
+
+        //PHM6000_API(float*) GetDepthDataInAnnulus(void* pHandle, int& nWidth, int& nHeight, int nXPos, int nYPos, int nRadius, float fRadiusRatio);
+        /// <summary>
+        /// 鑾峰彇鐜舰鍏磋叮鍖哄唴鐨勬繁搴︽暟鎹�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nWidth">鍥炰紶娣卞害鏁版嵁鐨勫搴�</param>
+        /// <param name="nHeight">鍥炰紶娣卞害鏁版嵁鐨勯珮搴�</param>
+        /// <param name="nXPos">鐜舰涓績鐨剎鍧愭爣</param>
+        /// <param name="nYPos">鐜舰涓績鐨剏鍧愭爣</param>
+        /// <param name="nRadius">鐜舰鐨勫崐寰�</param>
+        /// <param name="fRadiusRatio">鐜舰鐨勫唴澶栧崐寰勬瘮锛屽ぇ浜�1鏃跺唴澶栭鍊�</param>
+        /// <returns>杩斿洖娣卞害鏁版嵁鐨勬寚閽堬紝杩斿洖鍊间负NULL鏃惰〃绀鸿皟鐢ㄥけ璐�,(float*) </returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetDepthDataInAnnulus")]
+        public static extern IntPtr GetDepthDataInAnnulus(IntPtr pHandle, ref int nWidth, ref int nHeight, int nXPos, int nYPos, int nRadius, float fRadiusRatio);
+
+        //PHM6000_API(float*) GetDepthDataInPolygon(void* pHandle, int& nWidth, int& nHeight, void* points, int nCount);
+        /// <summary>
+        /// 鑾峰彇澶氳竟褰㈠叴瓒e尯鍐呯殑娣卞害鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nWidth">鍥炰紶娣卞害鏁版嵁鐨勫搴�</param>
+        /// <param name="nHeight">鍥炰紶娣卞害鏁版嵁鐨勯珮搴�</param>
+        /// <param name="points">澶氳竟褰㈤《鐐瑰潗鏍囨暟缁勭殑鎸囬拡</param>
+        /// <param name="nCount">澶氳竟褰㈤《鐐圭殑鏁伴噺</param>
+        /// <returns>杩斿洖娣卞害鏁版嵁鐨勬寚閽堬紝杩斿洖鍊间负NULL鏃惰〃绀鸿皟鐢ㄥけ璐ワ紝(float*) </returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetDepthDataInPolygon")]
+        public static extern IntPtr GetDepthDataInPolygon(IntPtr pHandle, ref int nWidth, ref int nHeight, IntPtr points, int nCount);
+
+        //PHM6000_API(int) InsertionSort(void* pHandle, float* pData, int nWidth, int nHeight);
+        /// <summary>
+        /// 浠庡ぇ鍒板皬鎺掑簭鍑芥暟骞跺叿鏈夋棤鏁堟繁搴︾殑杩囨护鍔熻兘
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="pData">浠庡叴瓒e尯鑾峰緱鐨勬繁搴︽暟鎹寚閽�, float* pData</param>
+        /// <param name="nWidth">浠庡叴瓒e尯鑾峰緱鐨勬繁搴︽暟鎹殑瀹藉害</param>
+        /// <param name="nHeight">浠庡叴瓒e尯鑾峰緱鐨勬繁搴︽暟鎹殑楂樺害</param>
+        /// <returns>杩斿洖鍓旈櫎鏃犳晥鏁版嵁鍚庣殑娣卞害鏁版嵁涓暟锛岃繑鍥炲�间负-1鏃惰〃绀鸿皟鐢ㄥけ璐�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "InsertionSort")]
+        public static extern int InsertionSort(IntPtr pHandle, IntPtr pData, int nWidth, int nHeight);
+
+        //PHM6000_API(int) GetEncoderValueRange(void* pHandle, int nBeginLine, int nEndLine, unsigned long* nBeginValue, unsigned long* nEndValue);
+        /// <summary>
+        /// 鑾峰彇缂栫爜鍣ㄧ殑鍊�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nBeginLine">寮�濮嬭鐨勫簭鍙�</param>
+        /// <param name="nEndLine">缁撴潫琛岀殑搴忓彿</param>
+        /// <param name="nBeginValue">鐢ㄤ簬杩斿洖寮�濮嬭鐨勭紪鐮佸櫒鍊�, unsigned long* nBeginValue</param>
+        /// <param name="nEndValue">鐢ㄤ簬杩斿洖缁撴潫琛岀殑缂栫爜鍣ㄥ��, unsigned long* nEndValue</param>
+        /// <returns>杩斿洖鍊间负-1鏃惰〃绀鸿皟鐢ㄥけ璐�</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetEncoderValueRange")]
+        public static extern int GetEncoderValueRange(IntPtr pHandle, int nBeginLine, int nEndLine, out uint nBeginValue, out uint nEndValue);
+
+        //PHM6000_API(LBLineDataZA*) GetLineDataByEncoder(void* pHandle, unsigned long nEncoderValue);
+        /// <summary>
+        /// 鑾峰彇缂栫爜鍣ㄥ�兼寚鍚戠殑鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nEncoderValue">缂栫爜鍣ㄧ殑鍊�</param>
+        /// <returns>杩斿洖鍊间负NULL鏃惰〃绀鸿皟鐢ㄥけ璐�,(LBLineDataZA*)</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetLineDataByEncoder")]
+        public static extern IntPtr GetLineDataByEncoder(IntPtr pHandle, uint nEncoderValue);
+
+        //PHM6000_API(LBLineDataZA*) GetLineDataByIndex(void* pHandle, unsigned long nIndex);
+        /// <summary>
+        /// 閫氳繃缂栫爜鍣ㄥ�艰幏鍙栨暟鎹�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nIndex">鏁版嵁鐨勮搴忓彿</param>
+        /// <returns>杩斿洖鍊间负NULL鏃惰〃绀鸿幏鍙栨暟鎹け璐�,(LBLineDataZA*)</returns>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetLineDataByIndex")]
+        public static extern IntPtr GetLineDataByIndex(IntPtr pHandle, uint nIndex);
+        //PHM6000_API(LBLineDataZA*) GetLineDataByIndex(void* pHandle, unsigned long nIndex);
+        /// <summary>
+        /// 閫氳繃缂栫爜鍣ㄥ�艰幏鍙栨暟鎹�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="nIndex">鏁版嵁鐨勮搴忓彿</param>
+        /// <returns>杩斿洖鍊间负NULL鏃惰〃绀鸿幏鍙栨暟鎹け璐�,(LBLineDataZA*)</returns>
+
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetLineDataByIndex")]
+        public static extern IntPtr GetLineDataByIndex(IntPtr pHandle, ulong nIndex);
+
+
+        //PHM6000_API(void) SetTransformParameter(void* pHandle, float fAngle, int xOffset, int yOffset, int hMirror, int vMirror, int KeepImageSize = 0);
+        /// <summary>
+        /// 璁剧疆杞崲鍙傛暟锛岀敤浜庤幏鍙栬浆鎹㈠悗鍏磋叮鍖哄唴鐨勬暟鎹�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="fAngle">鏃嬭浆瑙掑害</param>
+        /// <param name="xOffset">x鍚戝钩绉婚噺</param>
+        /// <param name="yOffset">y鍚戝钩绉婚噺</param>
+        /// <param name="hMirror">涓�1鏃舵按骞抽暅鍍忥紝涓�0鏃朵笉鍙�</param>
+        /// <param name="vMirror">涓�1鏃跺瀭鐩撮暅鍍忥紝涓�0鏃朵笉鍙�</param>
+        /// <param name="KeepImageSize">鍥惧儚澶у皬鏄惁淇濇寔</param>
+        [DllImport("PHM6000API", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetTransformParameter")]
+        public static extern void SetTransformParameter(IntPtr pHandle, float fAngle, int xOffset, int yOffset, int hMirror, int vMirror, int KeepImageSize = 0);
+        /// <summary>
+        /// 灏嗙粨鏋勪綋鎸囬拡杞崲涓篸ouble锛堟ā鎷烠++鐨�(double)(int64)&鎿嶄綔锛�
+        /// </summary>
+        /// <param name="structurePtr">IntPtr structurePtr</param>
+        /// <returns>double</returns>
+        public static double StructurePtrToDouble(IntPtr structurePtr)
+        {
+            // 灏嗘寚閽堣浆鎹负long锛岀劧鍚庤浆鎹负double
+            long ptrValue = structurePtr.ToInt64();
+            return (double)ptrValue;
+        }
+
+        /// <summary>
+        /// 灏嗙粨鏋勪綋杞崲涓篒ntPtr骞惰繑鍥炲搴旂殑double鍊�
+        /// </summary>
+        /// <typeparam name="T">T </typeparam>
+        /// <param name="structure">T structure</param>
+        /// <returns>double</returns>
+        public static double StructureToDoublePtr<T>(ref T structure)
+        {
+            IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T)));
+            Marshal.StructureToPtr(structure, ptr, false);
+
+            long ptrValue = ptr.ToInt64();
+            return (double)ptrValue;
+        }
+
+        /// <summary>
+        /// 浠巇ouble鍊兼仮澶嶄负鎸囬拡骞惰鍙栫粨鏋勪綋
+        /// </summary>
+        /// <typeparam name="T">T </typeparam>
+        /// <param name="doublePtr">double doublePtr</param>
+        /// <returns>T </returns>
+        public static T DoublePtrToStructure<T>(double doublePtr)
+        {
+            long ptrValue = (long)doublePtr;
+            IntPtr ptr = new IntPtr(ptrValue);
+            return (T)Marshal.PtrToStructure(ptr, typeof(T));
+        }
+
+        /// <summary>
+        /// 閲婃斁鐢盨tructureToDoublePtr鍒嗛厤鐨勫唴瀛�
+        /// </summary>
+        /// <param name="doublePtr">double doublePtr</param>
+        public static void FreeDoublePtr(double doublePtr)
+        {
+            long ptrValue = (long)doublePtr;
+            IntPtr ptr = new IntPtr(ptrValue);
+            Marshal.FreeHGlobal(ptr);
+        }
+        /// <summary>
+        /// IntPtr To LBLineDataZA
+        /// </summary>
+        /// <param name="ptr">IntPtr ptr</param>
+        /// <returns>LBLineDataZA</returns>
+        public static LBLineDataZA ConvertToLBLineDataZA(IntPtr ptr)
+        {
+            // 棣栧厛璇诲彇info
+            LBLineHeadInfo info = Marshal.PtrToStructure<LBLineHeadInfo>(ptr);
+
+            // 璁$畻鏁扮粍寮�濮嬬殑鎸囬拡锛歱tr鍋忕Щinfo鐨勫ぇ灏�
+            IntPtr arrayPtr = ptr + Marshal.SizeOf<LBLineHeadInfo>();
+            UInt32 pointCount = info.nPointCount;
+            LBPointZA[] points = new LBPointZA[pointCount];
+            int sizeOfPoint = Marshal.SizeOf<LBPointZA>();
+
+            for (int i = 0; i < pointCount; i++)
+            {
+                points[i] = Marshal.PtrToStructure<LBPointZA>(arrayPtr + i * sizeOfPoint);
+            }
+            //Marshal.FreeHGlobal(arrayPtr);
+            return new LBLineDataZA { info = info, data = points };
+        }
+    }
+}
\ No newline at end of file
diff --git a/LB_SmartVisionCameraSDK/PHM6000/Pilot2D.cs b/LB_SmartVisionCameraSDK/PHM6000/Pilot2D.cs
new file mode 100644
index 0000000..67741ed
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/PHM6000/Pilot2D.cs
@@ -0,0 +1,529 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCameraSDK.PHM6000
+{
+    //typedef void (__stdcall* ShowInfo) (void* pData, int nSize);
+    /// <summary>
+    /// 姝ゅ洖璋冨嚱鏁扮敤浜庢樉绀哄弬鏁颁俊鎭紝璋冭瘯鏃朵娇鐢紝鏃犺繑鍥炲��
+    /// </summary>
+    /// <param name="pData">涓哄瓧绗︿覆</param>
+    /// <param name="nSize">涓哄瓧绗︿覆闀垮害</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void ShowInfo(IntPtr pData, int nSize);
+
+    //typedef void (__stdcall* ShowRectInfo) (int left, int top, int right, int bottom);
+    /// <summary>
+    /// 姝ゅ洖璋冨嚱鏁扮敤浜庡湪鐢诲叴瓒e尯鏃舵樉绀虹煩褰㈠弬鏁帮紝鏃犺繑鍥炲��
+    /// </summary>
+    /// <param name="left">宸︿笂瑙抶鍧愭爣</param>
+    /// <param name="top">宸︿笂瑙抷鍧愭爣</param>
+    /// <param name="right">鍙充笅瑙抶鍧愭爣</param>
+    /// <param name="bottom">鍙充笅瑙抷鍧愭爣</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void ShowRectInfo(int left, int top, int right, int bottom);
+
+    //typedef void (__stdcall* ShowObjectInfo) (int nType, void* pObjectInfo, int nCount);
+    /// <summary>
+    /// 姝ゅ洖璋冨嚱鏁扮敤浜庡湪鐢诲叴瓒e尯鏃舵樉绀烘墍缁樺璞$殑鍙傛暟锛屾棤杩斿洖鍊�
+    /// </summary>
+    /// <param name="nType">瀵硅薄绫诲瀷</param>
+    /// <param name="pObjectInfo">瀵硅薄鎸囬拡</param>
+    /// <param name="nCount">瀵硅薄鏁版嵁涓暟</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void ShowObjectInfo(int nType, IntPtr pObjectInfo, int nCount);
+    /// <summary>
+    /// 鍥惧儚鐨�2D鎿嶄綔绫�
+    /// </summary>
+    public class Pilot2D
+    {
+        //PILOT2D_API(void*) CreatePilot2DEntry(void* hWnd);
+        /// <summary>
+        /// 鍒涘缓浜岀淮鍥炬樉绀烘帴鍙o紝杩斿洖鍏跺彞鏌�
+        /// </summary>
+        /// <param name="hWnd">涓哄绾充簩缁存樉绀烘帶浠剁殑瀹瑰櫒鍙ユ焺</param>
+        /// <returns>杩斿洖浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "CreatePilot2DEntry")]
+        public static extern IntPtr CreatePilot2DEntry(IntPtr hWnd);
+
+        //PILOT2D_API(void) DestroyPilot2DEntry(void* pHandle);
+        /// <summary>
+        /// 閿�姣佷簩缁村浘鏄剧ず鎺ュ彛
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DestroyPilot2DEntry")]
+        public static extern void DestroyPilot2DEntry(IntPtr pHandle);
+
+        //PILOT2D_API(void) SetImageSize(void* pHandle, int nWidth, int nHeight);
+        /// <summary>
+        /// 璁剧疆鍥惧儚澶у皬锛岀敤浜庨�愯娣诲姞鏄剧ず鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="nWidth">瀹藉害</param>
+        /// <param name="nHeight">楂樺害</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetImageSize")]
+        public static extern void SetImageSize(IntPtr pHandle, int nWidth, int nHeight);
+
+        //PILOT2D_API(void) GetImageSize(void* pHandle, int& nWidth, int& nHeight);
+        /// <summary>
+        /// 鑾峰彇鍥惧儚澶у皬
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="nWidth">瀹藉害</param>
+        /// <param name="nHeight">楂樺害</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetImageSize")]
+        public static extern void GetImageSize(IntPtr pHandle, ref int nWidth, ref int nHeight);
+
+        //PILOT2D_API(void) SetImageRotated(void* pHandle, int nIsRotated);
+        /// <summary>
+        /// 璁剧疆鍥惧儚鏃嬭浆涔濆崄搴�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="nIsRotated">涓�1鏃舵棆鏄剧ず锛屼负0鏃舵甯告樉绀�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetImageRotated")]
+        public static extern void SetImageRotated(IntPtr pHandle, int nIsRotated);
+
+        //PILOT2D_API(void) ResizePilot2D(void* pHandle, int nWidth, int nHeight);
+        /// <summary>
+        /// 璋冩暣绐楀彛澶у皬锛屽湪涓荤▼搴忕獥鍙eぇ灏忓彂鐢熷彉鍖栨椂璋冪敤
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="nWidth">瀹藉害</param>
+        /// <param name="nHeight">楂樺害</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ResizePilot2D")]
+        public static extern void ResizePilot2D(IntPtr pHandle, int nWidth, int nHeight);
+
+        //PILOT2D_API(void) RefreshPilot2D(void* pHandle);
+        /// <summary>
+        /// 鍒锋柊鏄剧ず绐楀彛锛屾鎺т欢鍦ㄤ紶鍏ユ暟鎹椂骞朵笉鏇存柊鏄剧ず锛岀洿鍒拌皟鐢ㄦ鍑芥暟銆�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ResizePilot2D")]
+        public static extern void ResizePilot2D(IntPtr pHandle);
+
+        //PILOT2D_API(void) RefreshPilot2D(void* pHandle);
+        /// <summary>
+        /// 鍒锋柊鏄剧ず绐楀彛锛屾鎺т欢鍦ㄤ紶鍏ユ暟鎹椂骞朵笉鏇存柊鏄剧ず锛岀洿鍒拌皟鐢ㄦ鍑芥暟銆�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "RefreshPilot2D")]
+        public static extern void RefreshPilot2D(IntPtr pHandle);
+
+        //PILOT2D_API(int) AddIntensityData(void* pHandle, LBPointZA* points, int nCount);
+        /// <summary>
+        /// 娣诲姞寮哄害鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="points">鍏板疂绾挎壂鎻忎紶鎰熷櫒杈撳嚭鐨勬暟鎹寚閽�, LBPointZA* points</param>
+        /// <param name="nCount">鎸囧畾涓婅堪鏁版嵁鐨勬寚閽堥噷鐨勭偣鐨勬暟閲�</param>
+        /// <returns>鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddIntensityData")]
+        public static extern int AddIntensityData(IntPtr pHandle, IntPtr points, int nCount);
+
+        //PILOT2D_API(int) AddDepthData(void* pHandle, LBPointZA* points, int nCount, short nMinDepth, short nMaxDepth);
+        /// <summary>
+        /// 娣诲姞娣卞害鏁版嵁锛屾鍑芥暟鍏锋湁棰滆壊娓叉煋鍔熻兘
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="points">鍏板疂绾挎壂鎻忎紶鎰熷櫒杈撳嚭鐨勬暟鎹寚閽�, LBPointZA* points</param>
+        /// <param name="nCount">鎸囧畾涓婅堪鏁版嵁鐨勬寚閽堥噷鐨勭偣鐨勬暟閲�</param>
+        /// <param name="nMinDepth">鎸囧畾娣卞害涓殑鏈�灏忓�硷紝鐢ㄤ簬棰滆壊娓叉煋锛屽缓璁�兼渶灏忓��-1</param>
+        /// <param name="nMaxDepth">鎸囧畾娣卞害涓殑鏈�澶у�硷紝鐢ㄤ簬棰滆壊娓叉煋锛屽缓璁�兼渶澶у��+1</param>
+        /// <returns>鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddDepthData")]
+        public static extern int AddDepthData(IntPtr pHandle, IntPtr points, int nCount, short nMinDepth, short nMaxDepth);
+
+        //PILOT2D_API(int) AddIntensityArray(void* pHandle, unsigned char* points, int nCount);
+        /// <summary>
+        /// 娣诲姞寮哄害鏁版嵁锛堟彁渚涘彟涓�绉嶆暟鎹緭鍏ユ牸寮忥紝涓嶅父鐢級
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="points">寮哄害鏁版嵁涓�8浣嶆棤绗﹀彿瀛楃鍨嬫暟鎹寚閽�, unsigned char* points</param>
+        /// <param name="nCount">鎸囧畾涓婅堪鏁版嵁鐨勬寚閽堥噷鐨勭偣鐨勬暟閲�</param>
+        /// <returns>鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddIntensityArray")]
+        public static extern int AddIntensityArray(IntPtr pHandle, IntPtr points, int nCount);
+
+        //PILOT2D_API(int) AddDepthArray(void* pHandle, float* points, int nCount, short nMinDepth, short nMaxDepth);
+        /// <summary>
+        /// 娣诲姞娣卞害鏁版嵁锛堟彁渚涘彟涓�绉嶆暟鎹緭鍏ユ牸寮忥紝涓嶅父鐢級
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="points"></param>
+        /// <param name="nCount">寮哄害鏁版嵁涓烘诞鐐瑰瀷鏁版嵁鎸囬拡, float* points</param>
+        /// <param name="nCount">鎸囧畾涓婅堪鏁版嵁鐨勬寚閽堥噷鐨勭偣鐨勬暟閲�</param>
+        /// <param name="nMinDepth">鎸囧畾娣卞害涓殑鏈�灏忓�硷紝鐢ㄤ簬棰滆壊娓叉煋锛屽缓璁�兼渶灏忓��-1</param>
+        /// <param name="nMaxDepth">鎸囧畾娣卞害涓殑鏈�澶у�硷紝鐢ㄤ簬棰滆壊娓叉煋锛屽缓璁�兼渶澶у��+1</param>
+        /// <returns>鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddDepthArray")]
+        public static extern int AddDepthArray(IntPtr pHandle, IntPtr points, int nCount, short nMinDepth, short nMaxDepth);
+
+        //PILOT2D_API(int) AddRawImagePoints(void* pHandle, LBPointBGRA* points, int nWidth, int nHeight);
+        /// <summary>
+        /// 娣诲姞鍘熷鍥惧儚鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="points">鍘熷鍥惧儚鏁版嵁鎸囬拡, LBPointBGRA* points</param>
+        /// <param name="nCount">鍘熷鍥惧儚鐨勫搴�</param>
+        /// <param name="nMinDepth">鍘熷鍥惧儚鐨勯珮搴�</param>
+        /// <param name="nMaxDepth">鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</param>
+        /// <returns></returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddRawImagePoints")]
+        public static extern int AddRawImagePoints(IntPtr pHandle, IntPtr points, int nCount, short nMinDepth, short nMaxDepth);
+
+        //PILOT2D_API(void) SetImageData(void* pHandle, LBPointBGRA* points, int nWidth, int nHeight);
+        /// <summary>
+        /// 璁剧疆鍥惧儚鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="points">鍥惧儚鏁版嵁鎸囬拡</param>
+        /// <param name="nWidth">鍥惧儚鐨勫搴�</param>
+        /// <param name="nHeight">鍥惧儚鐨勯珮搴�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetImageData")]
+        public static extern void SetImageData(IntPtr pHandle, IntPtr points, int nWidth, int nHeight);
+
+        //PILOT2D_API(void) GetImageData(void* pHandle, LBPointBGRA* points, int nWidth, int nHeight);
+        /// <summary>
+        /// 鑾峰彇鍥惧儚鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="points">鍥惧儚鏁版嵁鎸囬拡, LBPointBGRA* points</param>
+        /// <param name="nWidth">鍥惧儚鐨勫搴�</param>
+        /// <param name="nHeight">鍥惧儚鐨勯珮搴�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetImageData")]
+        public static extern void GetImageData(IntPtr pHandle, IntPtr points, int nWidth, int nHeight);
+
+        //PILOT2D_API(int) AddBarycentreDataZA(void* pHandle, LBPointZA* points, int nCount, float fMinDistance, float fMaxDistance, float fStdDistance);
+        /// <summary>
+        /// 娣诲姞璐ㄥ績鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="points">鍏板疂绾挎壂鎻忎紶鎰熷櫒杈撳嚭鐨勬暟鎹寚閽�</param>
+        /// <param name="nCount">鎸囧畾涓婅堪鏁版嵁鐨勬寚閽堥噷鐨勭偣鐨勬暟閲�</param>
+        /// <param name="fMinDistance">鍏板疂绾挎壂鎻忎紶鎰熷櫒妫�娴嬬殑鏈�灏忚窛绂伙紙浠庤鏄庝功鑾峰緱锛屽彇鍊�225.0锛�</param>
+        /// <param name="fMaxDistance">鍏板疂绾挎壂鎻忎紶鎰熷櫒妫�娴嬬殑鏈�澶ц窛绂伙紙浠庤鏄庝功鑾峰緱锛屽彇鍊�473.0锛�</param>
+        /// <param name="fStdDistance">鍏板疂绾挎壂鎻忎紶鎰熷櫒妫�娴嬬殑鏍囧噯璺濈锛堜粠璇存槑涔﹁幏寰楋紝鍙栧��325.0锛�</param>
+        /// <returns>鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddBarycentreDataZA")]
+        public static extern int AddBarycentreDataZA(IntPtr pHandle, IntPtr points, int nCount, float fMinDistance, float fMaxDistance, float fStdDistance);
+
+        //PILOT2D_API(int) AddBarycentreArray(void* pHandle, float* points, int nCount);
+        /// <summary>
+        /// 娣诲姞璐ㄥ績鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="points">璐ㄥ績鏁版嵁涓烘诞鐐瑰瀷鏁版嵁鎸囬拡, float* points</param>
+        /// <param name="nCount">鎸囧畾涓婅堪鏁版嵁鐨勬寚閽堥噷鐨勭偣鐨勬暟閲�</param>
+        /// <returns>鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddBarycentreArray")]
+        public static extern int AddBarycentreArray(IntPtr pHandle, IntPtr points, int nCount);
+
+
+        //PILOT2D_API(void) ClearBarycentreArray(void* pHandle);
+        /// <summary>
+        /// 娓呴櫎璐ㄥ績鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ClearBarycentreArray")]
+        public static extern void ClearBarycentreArray(IntPtr pHandle);
+
+        //PILOT2D_API(void) SetBarycentreColor(void* pHandle, int r, int g, int b);
+        /// <summary>
+        /// 璁剧疆璐ㄥ績棰滆壊
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="r">绾㈣壊鍒嗛噺锛屽叓浣嶆棤绗﹀彿瀛楃鍨嬫暟鍊�</param>
+        /// <param name="g">缁胯壊鍒嗛噺锛屽叓浣嶆棤绗﹀彿瀛楃鍨嬫暟鍊�</param>
+        /// <param name="b">钃濊壊鍒嗛噺锛屽叓浣嶆棤绗﹀彿瀛楃鍨嬫暟鍊�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetBarycentreColor")]
+        public static extern void SetBarycentreColor(IntPtr pHandle, int r, int g, int b);
+
+        //PILOT2D_API(void) ClearAllPoints(void* pHandle);
+        /// <summary>
+        /// 娓呴櫎鏁版嵁锛屽湪鏄剧ず鏂扮殑鍥捐薄鍓嶈皟鐢�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ClearAllPoints")]
+        public static extern void ClearAllPoints(IntPtr pHandle);
+
+        //PILOT2D_API(int) LoadPicture(void* pHandle, char* szFileName);
+        /// <summary>
+        /// 鍔犺浇鍥惧儚鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="szFileName">鏂囦欢鍚嶏紝GB2312缂栫爜瀛楃涓�, char* szFileName</param>
+        /// <returns>鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "LoadPicture")]
+        public static extern int LoadPicture(IntPtr pHandle, byte[] szFileName);
+
+        //PILOT2D_API(int) SavePicture(void* pHandle, char* szFileName);
+        /// <summary>
+        /// 淇濆瓨鍥惧儚鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="szFileName">鏂囦欢鍚嶏紝GB2312缂栫爜瀛楃涓�, char* szFileName</param>
+        /// <returns>鍑芥暟璋冪敤鎴愬姛杩斿洖1锛屽け璐ヨ繑鍥�-1</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SavePicture")]
+        public static extern int SavePicture(IntPtr pHandle, byte[] szFileName);
+
+        //PILOT2D_API(void) BeginDrawTool(void* pHandle);
+        /// <summary>
+        /// 寮�濮嬬粯鍒跺叴瓒e尯鐘舵��
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "BeginDrawTool")]
+        public static extern void BeginDrawTool(IntPtr pHandle);
+
+        //PILOT2D_API(void) EndDrawTool(void* pHandle);
+        /// <summary>
+        /// 缁撴潫缁樺埗鍏磋叮鍖虹姸鎬�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "EndDrawTool")]
+        public static extern void EndDrawTool(IntPtr pHandle);
+
+        //PILOT2D_API(void) SetDrawRect(void* pHandle);
+        /// <summary>
+        /// 璁句负缁樺埗鐭╁舰鍏磋叮鍖虹姸鎬�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetDrawRect")]
+        public static extern void SetDrawRect(IntPtr pHandle);
+
+        //PILOT2D_API(void) SetDrawPolygon(void* pHandle);
+        /// <summary>
+        /// 璁句负缁樺埗澶氳竟褰㈠叴瓒e尯鐘舵��
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetDrawPolygon")]
+        public static extern void SetDrawPolygon(IntPtr pHandle);
+
+        //PILOT2D_API(void) SetDrawCircle(void* pHandle);
+        /// <summary>
+        /// 璁句负缁樺埗鍦嗗舰鍏磋叮鍖虹姸鎬�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetDrawCircle")]
+        public static extern void SetDrawCircle(IntPtr pHandle);
+
+        //PILOT2D_API(void) SetDrawAnnulus(void* pHandle);
+        /// <summary>
+        /// 璁句负缁樺埗鐜舰鍏磋叮鍖虹姸鎬�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetDrawAnnulus")]
+        public static extern void SetDrawAnnulus(IntPtr pHandle);
+
+        //PILOT2D_API(void) SetDrawSelection(void* pHandle);
+        /// <summary>
+        /// 璁句负閫夋嫨鍏磋叮鍖虹姸鎬�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetDrawSelection")]
+        public static extern void SetDrawSelection(IntPtr pHandle);
+
+        //PILOT2D_API(void) SetRectColor(void* pHandle, int r, int g, int b);
+        /// <summary>
+        /// 璁剧疆缁樺埗鐭╁舰鍏磋叮鍖洪鑹�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="r">绾㈣壊鍒嗛噺锛屽叓浣嶆棤绗﹀彿瀛楃鍨嬫暟鍊�</param>
+        /// <param name="g">缁胯壊鍒嗛噺锛屽叓浣嶆棤绗﹀彿瀛楃鍨嬫暟鍊�</param>
+        /// <param name="b">钃濊壊鍒嗛噺锛屽叓浣嶆棤绗﹀彿瀛楃鍨嬫暟鍊�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetRectColor")]
+        public static extern void SetRectColor(IntPtr pHandle, int r, int g, int b);
+
+        //PILOT2D_API(void) AddRect(void* pHandle, int left, int top, int right, int bottom);
+        /// <summary>
+        /// 娣诲姞鐭╁舰鍏磋叮鍖�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="left">寰呮坊鍔犵殑鐭╁舰鍏磋叮鍖哄乏涓婅鐨剎鍧愭爣</param>
+        /// <param name="top">寰呮坊鍔犵殑鐭╁舰鍏磋叮鍖哄乏涓婅鐨剏鍧愭爣</param>
+        /// <param name="right">寰呮坊鍔犵殑鐭╁舰鍏磋叮鍖哄彸涓嬭鐨剎鍧愭爣</param>
+        /// <param name="bottom">寰呮坊鍔犵殑鐭╁舰鍏磋叮鍖哄彸涓嬭鐨剏鍧愭爣</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddRect")]
+        public static extern void AddRect(IntPtr pHandle, int left, int top, int right, int bottom);
+
+        //PILOT2D_API(void) AddCircle(void* pHandle, int x, int y, int radius);
+        /// <summary>
+        /// 娣诲姞鍦嗗舰鍏磋叮鍖�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="x">寰呮坊鍔犵殑鍦嗗舰鍏磋叮鍖轰腑蹇冪殑x鍧愭爣</param>
+        /// <param name="y">寰呮坊鍔犵殑鍦嗗舰鍏磋叮鍖轰腑蹇冪殑y鍧愭爣</param>
+        /// <param name="radius">寰呮坊鍔犵殑鍦嗗舰鍏磋叮鍖虹殑x鍗婂緞</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddCircle")]
+        public static extern void AddCircle(IntPtr pHandle, int x, int y, int radius);
+
+        //PILOT2D_API(void) AddAnnulus(void* pHandle, int x, int y, int radius, float fRadiusRatio);
+        /// <summary>
+        /// 娣诲姞鐜舰鍏磋叮鍖�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="x">寰呮坊鍔犵殑鐜舰鍏磋叮鍖轰腑蹇冪殑x鍧愭爣</param>
+        /// <param name="y">寰呮坊鍔犵殑鐜舰鍏磋叮鍖轰腑蹇冪殑y鍧愭爣</param>
+        /// <param name="radius">寰呮坊鍔犵殑鐜舰鍏磋叮鍖虹殑x鍗婂緞</param>
+        /// <param name="fRadiusRatio">寰呮坊鍔犵殑鐜舰鍏磋叮鍖哄唴澶栧崐寰勬瘮</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddAnnulus")]
+        public static extern void AddAnnulus(IntPtr pHandle, int x, int y, int radius, float fRadiusRatio);
+
+        //PILOT2D_API(void) AddPolygon(void* pHandle, void* points, int nCount);
+        /// <summary>
+        /// 娣诲姞澶氳竟褰㈠叴瓒e尯
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="points">寰呮坊鍔犵殑澶氳竟褰㈠叴瓒e尯鐨勯《鐐瑰潗鏍囩殑鎸囬拡</param>
+        /// <param name="nCount">寰呮坊鍔犵殑澶氳竟褰㈠叴瓒e尯鐨勯《鐐瑰潗鏍囩殑鏁伴噺</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddPolygon")]
+        public static extern void AddPolygon(IntPtr pHandle, IntPtr points, int nCount);
+
+        //PILOT2D_API(void) DeleteRect(void* pHandle);
+        /// <summary>
+        /// 鍒犻櫎鐭╁舰鍏磋叮鍖猴紙鍒犻櫎鍓嶈閫変腑锛�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DeleteRect")]
+        public static extern void DeleteRect(IntPtr pHandle);
+
+        //PILOT2D_API(void) DeleteROI(void* pHandle);
+        /// <summary>
+        /// 鍒犻櫎鍏磋叮鍖哄璞★紙鍒犻櫎鍓嶈閫変腑锛�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DeleteROI")]
+        public static extern void DeleteROI(IntPtr pHandle);
+
+        //PILOT2D_API(void) RegisterShowRectInfoCallback(void* pHandle, ShowRectInfo callback);
+        /// <summary>
+        /// 娉ㄥ唽鐢诲叴瓒e尯鏃舵樉绀虹煩褰㈠弬鏁扮殑鍥炶皟鍑芥暟
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="callback">鍥炶皟鍑芥暟鐨勬寚閽�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "RegisterShowRectInfoCallback")]
+        public static extern void RegisterShowRectInfoCallback(IntPtr pHandle, ShowRectInfo callback);
+
+        //PILOT2D_API(void) RegisterShowInfoCallback(void* pHandle, ShowInfo callback);
+        /// <summary>
+        /// 娉ㄥ唽鏄剧ず璋冭瘯淇℃伅鐨勫洖璋冨嚱鏁�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="callback">鍥炶皟鍑芥暟鐨勬寚閽�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "RegisterShowInfoCallback")]
+        public static extern void RegisterShowInfoCallback(IntPtr pHandle, ShowInfo callback);
+
+        //PILOT2D_API(void) RegisterShowObjectInfoCallback(void* pHandle, ShowObjectInfo callback);
+        /// <summary>
+        /// 娉ㄥ唽鐢诲叴瓒e尯鏃舵樉绀哄璞″弬鏁扮殑鍥炶皟鍑芥暟
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="callback">鍥炶皟鍑芥暟鐨勬寚閽�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "RegisterShowObjectInfoCallback")]
+        public static extern void RegisterShowObjectInfoCallback(IntPtr pHandle, ShowInfo callback);
+
+        #region  鍥惧儚澶勭悊鐩稿叧鎿嶄綔
+
+        //PILOT2D_API(BITMAPINFO) GetImageBITMAPINFO(void* pHandle);
+        /// <summary>
+        /// 鑾峰彇鍥惧儚鐨凚ITMAPINFO缁撴瀯浣�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <returns>杩斿洖BITMAPINFO缁撴瀯浣�</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetImageBITMAPINFO")]
+        public static extern BITMAPINFO GetImageBITMAPINFO(IntPtr pHandle);
+
+        //PILOT2D_API GetImageBufferPtr(void* pHandle);
+        /// <summary>
+        /// 鑾峰彇鍥惧儚鏁版嵁鐨勬寚閽�
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <returns>杩斿洖鍥惧儚鏁版嵁鐨勬寚閽堬紝(LBPointBGRA*)</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetImageBufferPtr")]
+        public static extern IntPtr GetImageBufferPtr(IntPtr pHandle);
+
+        //PILOT2D_API(LBPointBGRA*) RotateImage(void* pHandle, int& destWidth, int& destHeight, double angle, int keepImageSize = 0);
+        /// <summary>
+        /// 鍥惧儚鏃嬭浆鎿嶄綔
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="destWidth">鐢ㄤ簬鍥炰紶鏃嬭浆鍚庡浘鍍忕殑瀹藉害</param>
+        /// <param name="destHeight">鐢ㄤ簬鍥炰紶鏃嬭浆鍚庡浘鍍忕殑楂樺害</param>
+        /// <param name="angle">鏃嬭浆瑙掑害</param>
+        /// <param name="keepImageSize">鏄惁淇濇寔鍥惧儚灏哄</param>
+        /// <returns>杩斿洖鎿嶄綔鍚庡浘鍍忔暟鎹殑鎸囬拡,(LBPointBGRA*)</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "RotateImage")]
+        public static extern IntPtr RotateImage(IntPtr pHandle, ref int destWidth, ref int destHeight, double angle, int keepImageSize = 0);
+
+        //PILOT2D_API(LBPointBGRA*) TranslateImage(void* pHandle, int& destWidth, int& destHeight, int dx, int dy, int keepImageSize = 0);
+        /// <summary>
+        /// 鍥惧儚骞崇Щ鎿嶄綔
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="destWidth">鐢ㄤ簬鍥炰紶骞崇Щ鍚庡浘鍍忕殑瀹藉害</param>
+        /// <param name="destHeight">鐢ㄤ簬鍥炰紶骞崇Щ鍚庡浘鍍忕殑楂樺害</param>
+        /// <param name="dx">骞崇Щ鎿嶄綔鐨剎澧為噺</param>
+        /// <param name="dy">骞崇Щ鎿嶄綔鐨剏澧為噺</param>
+        /// <param name="keepImageSize">鏄惁淇濇寔鍥惧儚灏哄</param>
+        /// <returns>杩斿洖鎿嶄綔鍚庡浘鍍忔暟鎹殑鎸囬拡锛�(LBPointBGRA*)</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "RotateImage")]
+        public static extern IntPtr RotateImage(IntPtr pHandle, ref int destWidth, ref int destHeight, int dx, int dy, int keepImageSize = 0);
+
+        //PILOT2D_API(LBPointBGRA*) TransformImage(void* pHandle, int& destWidth, int& destHeight, int dx, int dy, double angle, int keepImageSize = 0);
+        /// <summary>
+        /// 鍥惧儚鏃嬭浆骞崇Щ鎿嶄綔
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="destWidth">鐢ㄤ簬鍥炰紶鏃嬭浆骞崇Щ鍚庡浘鍍忕殑瀹藉害</param>
+        /// <param name="destHeight">鐢ㄤ簬鍥炰紶鏃嬭浆骞崇Щ鍚庡浘鍍忕殑楂樺害</param>
+        /// <param name="dx">骞崇Щ鎿嶄綔鐨剎澧為噺</param>
+        /// <param name="dy">骞崇Щ鎿嶄綔鐨剏澧為噺</param>
+        /// <param name="angle">鏃嬭浆瑙掑害鐨勫閲�</param>
+        /// <param name="keepImageSize">鏄惁淇濇寔鍥惧儚灏哄</param>
+        /// <returns>杩斿洖鎿嶄綔鍚庡浘鍍忔暟鎹殑鎸囬拡锛�(LBPointBGRA*)</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "TransformImage")]
+        public static extern IntPtr TransformImage(IntPtr pHandle, ref int destWidth, ref int destHeight, int dx, int dy, double angle, int keepImageSize = 0);
+
+        //PILOT2D_API(LBPointBGRA*) MirrorImage(void* pHandle, int& destWidth, int& destHeight, int hMiiror, int vMirror);
+        /// <summary>
+        /// 鍥惧儚闀滃儚鎿嶄綔
+        /// </summary>
+        /// <param name="pHandle">浜岀淮鏄剧ず鎺т欢鐨勫彞鏌�</param>
+        /// <param name="destWidth">鐢ㄤ簬鍥炰紶鏃嬭浆骞崇Щ鍚庡浘鍍忕殑瀹藉害</param>
+        /// <param name="destHeight">鐢ㄤ簬鍥炰紶鏃嬭浆骞崇Щ鍚庡浘鍍忕殑楂樺害</param>
+        /// <param name="hMiiror">涓�1鏃讹紝姘村钩闀滃儚锛屼负0鏃舵按骞充笉闀滃儚</param>
+        /// <param name="vMirror">涓�1鏃讹紝鍨傜洿闀滃儚锛屼负0鏃跺瀭鐩翠笉闀滃儚</param>
+        /// <returns>杩斿洖鎿嶄綔鍚庡浘鍍忔暟鎹殑鎸囬拡</returns>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "MirrorImage")]
+        public static extern IntPtr MirrorImage(IntPtr pHandle, ref int destWidth, ref int destHeight, int hMiiror, int vMirror);
+
+        //PILOT2D_API(void) GetTransformParameter(void* pHandle, float& fAngle, int& xOffset, int& yOffset, int& hMirror, int& vMirror, int& KeepImageSize);
+        /// <summary>
+        /// 鑾峰彇宸叉墽琛岃繃鐨勮浆鎹㈠弬鏁�
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="fAngle">鍥炰紶鏃嬭浆瑙掑害</param>
+        /// <param name="xOffset">鍥炰紶x鍚戝钩绉婚噺</param>
+        /// <param name="yOffset">鍥炰紶y鍚戝钩绉婚噺</param>
+        /// <param name="hMirror">鍥炰紶姘村钩闀滃儚鏍囧織锛屼负1鏃舵按骞抽暅鍍忥紝涓�0鏃朵笉鍙�</param>
+        /// <param name="vMirror">鍥炰紶鍨傜洿闀滃儚鏍囧織锛屼负1鏃跺瀭鐩撮暅鍍忥紝涓�0鏃朵笉鍙�</param>
+        /// <param name="KeepImageSize">鍥炰紶淇濇寔鍥惧儚澶у皬鏍囧織</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetTransformParameter")]
+        public static extern void GetTransformParameter(IntPtr pHandle, ref float fAngle, ref int xOffset, ref int yOffset, ref int hMirror, ref int vMirror, ref int KeepImageSize);
+
+        //PILOT2D_API(void) ShowRoiHeight(void* pHandle, float* fRoiHeight, int nRow, int nCol);
+        /// <summary>
+        /// 鏄剧ずROI瀵瑰簲鐨勯珮搴﹀��
+        /// </summary>
+        /// <param name="pHandle">鐩告満鎺ュ彛鍙ユ焺</param>
+        /// <param name="fRoiHeight">鍏磋叮鍖洪珮搴︽暟缁勶紝fRoiHeight涓篘ULL锛屾垨鑰卬Row鍜宯Col涓湁涓�涓负0锛屽氨涓嶆樉绀�, float* fRoiHeight</param>
+        /// <param name="nRow">鍏磋叮鍖鸿鏁�</param>
+        /// <param name="nCol">鍏磋叮鍖哄垪鏁�</param>
+        [DllImport("Pilot2D.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ShowRoiHeight")]
+        public static extern void ShowRoiHeight(IntPtr pHandle, IntPtr fRoiHeight, int nRow, int nCol);
+        #endregion
+    }
+}
diff --git a/LB_SmartVisionCameraSDK/PHM6000/Point.cs b/LB_SmartVisionCameraSDK/PHM6000/Point.cs
new file mode 100644
index 0000000..61b17f0
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/PHM6000/Point.cs
@@ -0,0 +1,265 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCameraSDK.PHM6000
+{
+    /// <summary>
+    /// LBPointZ鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct LBPointZ
+    {
+        /// <summary>
+        /// Z鍧愭爣鍊�
+        /// </summary>
+        public float z;
+    }
+    /// <summary>
+    /// LBPointXZ鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct LBPointXZ
+    {
+        /// <summary>
+        /// X鍧愭爣鍊�
+        /// </summary>
+        public float x;
+        /// <summary>
+        /// Z鍧愭爣鍊�
+        /// </summary>
+        public float z;
+    }
+    /// <summary>
+    /// LBPointXYZ鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct LBPointXYZ
+    {
+        /// <summary>
+        /// X鍧愭爣鍊�
+        /// </summary>
+        public float x;
+        /// <summary>
+        /// Y鍧愭爣鍊�
+        /// </summary>
+        public float y;
+        /// <summary>
+        /// Z鍧愭爣鍊�
+        /// </summary>
+        public float z;
+    }
+    /// <summary>
+    /// LBPointXYZBGR鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct LBPointXYZBGR
+    {
+        /// <summary>
+        /// X鍧愭爣鍊�
+        /// </summary>
+        public float x;
+        /// <summary>
+        /// Y鍧愭爣鍊�
+        /// </summary>
+        public float y;
+        /// <summary>
+        /// Z鍧愭爣鍊�
+        /// </summary>
+        public float z;
+        /// <summary>
+        /// 钃濊壊鍒嗛噺
+        /// </summary>
+        public byte b;
+        /// <summary>
+        /// 缁胯壊鍒嗛噺
+        /// </summary>
+        public byte g;
+        /// <summary>
+        /// 绾㈣壊鍒嗛噺
+        /// </summary>
+        public byte r;
+    }
+    /// <summary>
+    /// LBPointXYZBGRA鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct LBPointXYZBGRA
+    {
+        /// <summary>
+        /// X鍧愭爣鍊�
+        /// </summary>
+        public float x;
+        /// <summary>
+        /// Y鍧愭爣鍊�
+        /// </summary>
+        public float y;
+        /// <summary>
+        /// Z鍧愭爣鍊�
+        /// </summary>
+        public float z;
+        /// <summary>
+        /// 钃濊壊鍒嗛噺
+        /// </summary>
+        public byte b;
+        /// <summary>
+        /// 缁胯壊鍒嗛噺
+        /// </summary>
+        public byte g;
+        /// <summary>
+        /// 绾㈣壊鍒嗛噺
+        /// </summary>
+        public byte r;
+        /// <summary>
+        /// 閫忔槑搴�
+        /// </summary>
+        public byte alpha;
+    }
+    /// <summary>
+    /// LBPointBGRA鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct LBPointBGRA
+    {
+        /// <summary>
+        /// 钃濊壊鍒嗛噺
+        /// </summary>
+        public byte b;
+        /// <summary>
+        /// 缁胯壊鍒嗛噺
+        /// </summary>
+        public byte g;
+        /// <summary>
+        /// 绾㈣壊鍒嗛噺
+        /// </summary>
+        public byte r;
+        /// <summary>
+        /// 閫忔槑搴�
+        /// </summary>
+        public byte alpha;
+    }
+    /// <summary>
+    /// LBPointZA鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct LBPointZA
+    {
+        /// <summary>
+        /// Z鍧愭爣鍊�
+        /// </summary>
+        public float z;
+        /// <summary>
+        /// 淇濈暀1
+        /// </summary>
+        public byte reserve1;
+        /// <summary>
+        /// 淇濈暀2
+        /// </summary>
+        public byte reserve2;
+        /// <summary>
+        /// 淇濈暀3
+        /// </summary>
+        public byte reserve3;
+        /// <summary>
+        /// 閫忔槑搴�
+        /// </summary>
+        public byte alpha;
+    }
+    /// <summary>
+    /// BITMAPINFOHEADER鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct BITMAPINFOHEADER
+    {
+        /// <summary>
+        /// 鎸囧畾缁撴瀯鎵�闇�鐨勫瓧鑺傛暟銆� 姝ゅ�间笉鍖呮嫭棰滆壊琛ㄧ殑澶у皬鎴栭鑹叉帺鐮佺殑澶у皬锛堝鏋滃畠浠拷鍔犲埌缁撴瀯鐨勬湯灏撅級銆�
+        /// </summary>
+        public uint biSize;
+        /// <summary>
+        /// 鎸囧畾浣嶅浘鐨勫搴︼紙浠ュ儚绱犱负鍗曚綅锛�
+        /// </summary>
+        public int biWidth;
+        /// <summary>
+        /// 鎸囧畾浣嶅浘鐨勯珮搴︼紙浠ュ儚绱犱负鍗曚綅锛夈��
+        /// </summary>
+        public int biHeight;
+        /// <summary>
+        /// 鎸囧畾鐩爣璁惧鐨勫钩闈㈡暟銆� 姝ゅ�煎繀椤昏缃负 1銆�
+        /// </summary>
+        public ushort biPlanes;
+        /// <summary>
+        /// 鎸囧畾姣忓儚绱� (bpp) 浣嶆暟銆� 瀵逛簬鏈帇缂╂牸寮忥紝姝ゅ�兼槸姣忓儚绱犵殑骞冲潎浣嶆暟銆� 瀵逛簬鍘嬬缉鏍煎紡锛屾鍊兼槸瑙g爜鍥惧儚鍚庢湭鍘嬬缉鍥惧儚鐨勯殣鍚綅娣卞害銆�
+        /// </summary>
+        public ushort biBitCount;
+        /// <summary>
+        /// 瀵逛簬鍘嬬缉瑙嗛鍜� YUV 鏍煎紡锛屾鎴愬憳鏄� FOURCC 浠g爜锛屼互灏忕椤哄簭鎸囧畾涓� DWORD 銆�
+        /// </summary>
+        public uint biCompression;
+        /// <summary>
+        /// 鎸囧畾鍥惧儚鐨勫ぇ灏忥紙浠ュ瓧鑺備负鍗曚綅锛夈�� 瀵逛簬鏈帇缂╃殑 RGB 浣嶅浘锛屽彲浠ュ皢鍏惰缃负 0銆�
+        /// </summary>
+        public uint biSizeImage;
+        /// <summary>
+        /// 鎸囧畾浣嶅浘鐨勭洰鏍囪澶囩殑姘村钩鍒嗚鲸鐜囷紙浠ュ儚绱�/绫充负鍗曚綅锛夈��
+        /// </summary>
+        public int biXPelsPerMeter;
+        /// <summary>
+        /// 鎸囧畾浣嶅浘鐨勭洰鏍囪澶囩殑鍨傜洿鍒嗚鲸鐜囷紙浠ユ瘡绫冲儚绱犱负鍗曚綅锛夈��
+        /// </summary>
+        public int biYPelsPerMeter;
+        /// <summary>
+        /// 鎸囧畾浣嶅浘瀹為檯浣跨敤鐨勯鑹茶〃涓殑棰滆壊绱㈠紩鏁般��
+        /// </summary>
+        public uint biClrUsed;
+        /// <summary>
+        /// 鎸囧畾琚涓哄鏄剧ず浣嶅浘寰堥噸瑕佺殑棰滆壊绱㈠紩鏁般��
+        /// </summary>
+        public uint biClrImportant;
+    }
+    /// <summary>
+    /// RGBQUAD鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct RGBQUAD
+    {
+        /// <summary>
+        /// 钃濊壊鐨勫己搴︺��
+        /// </summary>
+        public byte rgbBlue;
+        /// <summary>
+        /// 缁胯壊鐨勯鑹插己搴︺��
+        /// </summary>
+        public byte rgbGreen;
+        /// <summary>
+        /// 绾㈣壊鐨勫己搴︺��
+        /// </summary>
+        public byte rgbRed;
+        /// <summary>
+        /// 姝ゆ垚鍛樹负淇濈暀鎴愬憳锛屽繀椤讳负闆躲��
+        /// </summary>
+        public byte rgbReserved;
+    }
+
+    // 姝g‘瀹炵幇 BITMAPINFO 缁撴瀯浣�
+    /// <summary>
+    ///  BITMAPINFO鏁版嵁缁撴瀯浣�
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct BITMAPINFO
+    {
+        /// <summary>
+        /// 涓�涓� BITMAPINFOHEADER 缁撴瀯锛屽叾涓寘鍚湁鍏抽鑹叉牸寮忕淮搴︾殑淇℃伅銆�
+        /// </summary>
+        public BITMAPINFOHEADER bmiHeader;
+
+        // 浣跨敤 InlineArray 鐗规�у鐞嗗彲鍙橀暱搴﹂鑹茶〃
+        /// <summary>
+        /// RGBQUAD 鏁扮粍銆� 鏋勬垚棰滆壊琛ㄧ殑鏁扮粍鐨勫厓绱犮��
+        /// </summary>
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
+        public RGBQUAD[] bmiColors;
+    }
+}
diff --git a/LB_SmartVisionCameraSDK/PHM6000/ProfilerData.cs b/LB_SmartVisionCameraSDK/PHM6000/ProfilerData.cs
new file mode 100644
index 0000000..fe35c75
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/PHM6000/ProfilerData.cs
@@ -0,0 +1,771 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCameraSDK.PHM6000
+{
+    /// <summary>
+    /// 甯搁噺绫�
+    /// </summary>
+    public class Constants
+    {
+        /// <summary>
+        /// 鏈�澶т紶鎰熷櫒鏁伴噺
+        /// </summary>
+        public const int SYS_SENSORS_MAX = 8;
+        /// <summary>
+        /// 杞粨鐐圭殑鏁伴噺
+        /// </summary>
+        public const int MAX_POINTS_PER_LINE = 4096;
+        /// <summary>
+        /// 鏈�澶ф壂鎻忚鏁�
+        /// </summary>
+        public const int MAX_LINES_PER_CLOUD = 50000;
+        /// <summary>
+        /// 鍥哄畾鏂瑰紡
+        /// </summary>
+        public const int TYPE_STATIONARY = 0;
+        /// <summary>
+        /// 杩愬姩鏂瑰紡
+        /// </summary>
+        public const int TYPE_MOVING = 1;
+        /// <summary>
+        /// 鐩爣骞抽潰琛ㄩ潰
+        /// </summary>
+        public const int TARGET_FLAT_SURFACE = 0;
+        /// <summary>
+        /// 鐩爣鐨勮竟缂�
+        /// </summary>
+        public const int TARGET_BAR = 1;
+        /// <summary>
+        /// 鐩爣鐨勫杈瑰舰
+        /// </summary>
+        public const int TARGET_POLYGON = 2;
+        /// <summary>
+        /// 鐩爣鍒嗗壊
+        /// </summary>
+        public const int TARGET_DISK = 3;
+        /// <summary>
+        /// 鐩爣閲戝瓧濉�
+        /// </summary>
+        public const int TARGET_PYRAMID = 4;
+        /// <summary>
+        /// 鐩爣鍙岄噾瀛楀
+        /// </summary>
+        public const int TARGET_DUAL_PYRAMIDS = 5;
+        /// <summary>
+        /// XZ-YA鏅繁
+        /// </summary>
+        public const int DOF_XZ_YA = 1;
+        /// <summary>
+        /// XYZ-YA鏅繁
+        /// </summary>
+        public const int DOF_XYZ_YA = 2;
+        /// <summary>
+        /// XYZ-YZA鏅繁
+        /// </summary>
+        public const int DOF_XYZ_YZA = 3;
+    }
+    /// <summary>
+    /// LBLineHeadInfo鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct LBLineHeadInfo
+    {
+        /// <summary>
+        /// 琛屽彿
+        /// </summary>
+        public UInt32 nLineIndex;
+        /// <summary>
+        /// 缂栫爜鍣ㄥ��
+        /// </summary>
+        public UInt32 nCoderValue;
+        /// <summary>
+        /// 姝よ鏁版嵁涓寘鍚偣鐨勬暟閲�
+        /// </summary>
+        public UInt32 nPointCount;
+        /// <summary>
+        /// 鏁版嵁琛屼俊鎭ご缁撴瀯鍜岀偣鏁版嵁鎬讳綋瀛楄妭鏁�
+        /// </summary>
+        public UInt32 nDataSize;
+        /// <summary>
+        /// X鍚戞瘮渚�
+        /// </summary>
+        public float fPitchX;
+        /// <summary>
+        /// X鍚戞渶灏忔杩涘崟浣�
+        /// </summary>
+        public float fUnitX;
+        /// <summary>
+        /// Y鍚戞瘮渚�
+        /// </summary>
+        public float fPitchY;
+        /// <summary>
+        /// Y鍚戞渶灏忔杩涘崟浣�
+        /// </summary>
+        public float fUnitY;
+    }
+    /// <summary>
+    /// LB3dFileHeadInfo鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct LB3dFileHeadInfo
+    {
+        /// <summary>
+        /// 鏁版嵁澶у皬
+        /// </summary>
+        public uint nDataSize;
+        /// <summary>
+        /// 杞粨绾跨殑琛屾暟閲�
+        /// </summary>
+        public uint nLineCount;
+        /// <summary>
+        /// 鏄惁浣跨敤缂栫爜鍣�
+        /// </summary>
+        public uint bUseCoder;
+        /// <summary>
+        /// 鏄惁鐧界棿
+        /// </summary>
+        public uint nReserve;
+    }
+    /// <summary>
+    /// LBLineDataZA鍏板疂绾挎壂鎻忎紶鎰熷櫒杈撳嚭琛屾暟鎹畾涔夛紙鍖呭惈娣卞害鍊�(z)鍜屽己搴﹀��(alpha)锛�
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct LBLineDataZA
+    {
+        /// <summary>
+        /// 琛屼俊鎭ご
+        /// </summary>
+        public LBLineHeadInfo info;
+        /// <summary>
+        /// 琛屾暟鎹紙鍖呭惈娣卞害鍊�(z)鍜屽己搴﹀��(alpha)锛�
+        /// </summary>
+        public LBPointZA[] data;
+    }
+    /// <summary>
+    /// LBLineDataXYZ鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct LBLineDataXYZ
+    {
+        /// <summary>
+        /// 鐐规暟
+        /// </summary>
+        public uint nPointCount;
+        /// <summary>
+        /// LBPointXYZ鏁扮粍鏁版嵁
+        /// </summary>
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.MAX_POINTS_PER_LINE)]
+        public LBPointXYZ[] data;
+    }
+    /// <summary>
+    /// LBLineDataXZ鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct LBLineDataXZ
+    {
+        /// <summary>
+        /// 鐐规暟
+        /// </summary>
+        public uint nPointCount;
+        /// <summary>
+        /// LBPointXZ鏁扮粍鏁版嵁
+        /// </summary>
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.MAX_POINTS_PER_LINE)]
+        public LBPointXZ[] data;
+    }
+    /// <summary>
+    /// LB3dFileData鏁版嵁缁撴瀯
+    /// </summary>
+    public struct LB3dFileData
+    {
+        /// <summary>
+        /// LB3dFileHeadInfo鏁版嵁
+        /// </summary>
+        public LB3dFileHeadInfo info;
+        /// <summary>
+        /// LBLineDataZA鏁扮粍鏁版嵁
+        /// </summary>
+        public LBLineDataZA[] lines;
+    }
+    /// <summary>
+    /// LBPointCloudData鏁版嵁缁撴瀯
+    /// </summary>
+    public struct LBPointCloudData
+    {
+        /// <summary>
+        /// 杞粨绾挎暟閲�
+        /// </summary>
+        public int nLineCount;
+        /// <summary>
+        /// LBLineDataXYZ鏁扮粍鏁版嵁
+        /// </summary>
+        public LBLineDataXYZ[] data;
+    }
+    /// <summary>
+    /// LBPointCloudDataXYZ鏁版嵁缁撴瀯
+    /// </summary>
+    public struct LBPointCloudDataXYZ
+    {
+        /// <summary>
+        /// 鐐逛簯鏁伴噺
+        /// </summary>
+        public int nPointCount;
+        /// <summary>
+        /// LBPointXYZ*鏁版嵁鎸囬拡
+        /// </summary>
+        public IntPtr points;
+    }
+    /// <summary>
+    /// LB鏍囧畾鏁版嵁
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct LBCalibrationData
+    {
+        /// <summary>
+        /// 鐐规暟
+        /// </summary>
+        public int nCount;
+        /// <summary>
+        /// LB 杞粨绾挎暟鎹� XYZ
+        /// </summary>
+        public LBLineDataXYZ LineData;
+    }
+    /// <summary>
+    /// 浼犳劅鍣ㄤ俊鎭�
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct SENSOR_INFO
+    {
+        /// <summary>
+        /// 鏈�灏忔按骞宠鍦�
+        /// </summary>
+        public float XMinFOV;
+        /// <summary>
+        /// 鏈�澶ф按骞宠鍦�
+        /// </summary>
+        public float xMaxFOV;
+        /// <summary>
+        /// 鏈�灏忓�艰寖鍥�
+        /// </summary>
+        public float minMRange;
+        /// <summary>
+        /// 鏈�澶у�艰寖鍥�
+        /// </summary>
+        public float maxMRange;
+        /// <summary>
+        /// 鏍囧噯璺濈
+        /// </summary>
+        public float stdDistance;
+        /// <summary>
+        /// 鏍囧噯瑙嗗満
+        /// </summary>
+        public float stdFOV;
+        /// <summary>
+        /// X璧峰
+        /// </summary>
+        public float xStart;
+        /// <summary>
+        /// Z璧峰
+        /// </summary>
+        public float zStart;
+    }
+    /// <summary>
+    /// 娲诲姩鍖哄煙淇℃伅
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct ACTIVE_AREA_INFO
+    {
+        /// <summary>
+        /// X璧风偣
+        /// </summary>
+        public float xOrigin;
+        /// <summary>
+        /// Y璧风偣
+        /// </summary>
+        public float yOrigin;
+        /// <summary>
+        /// X鍋忕Щ
+        /// </summary>
+        public float xOffset;
+        /// <summary>
+        /// 姘村钩瑙嗗満
+        /// </summary>
+        public float xFOV;
+        /// <summary>
+        /// X璧峰
+        /// </summary>
+        public float xStart;
+    }
+    /// <summary>
+    /// 浼犳劅鍣ㄤ綅缃俊鎭�
+    /// </summary>
+    public struct SENSOR_POSITION
+    {
+        /// <summary>
+        /// X鏄惁鍊掑簭
+        /// </summary>
+        public int IsReverse;
+        /// <summary>
+        /// Z鏄惁鐩稿
+        /// </summary>
+        public int IsOpposite;
+        /// <summary>
+        /// 鏍囧噯璺濈
+        /// </summary>
+        public float fStdDistance;
+        /// <summary>
+        /// X 涓績
+        /// </summary>
+        public float fXCenter;
+        /// <summary>
+        /// X鍧愭爣
+        /// </summary>
+        public float x;
+        /// <summary>
+        /// Y鍧愭爣
+        /// </summary>
+        public float y;
+        /// <summary>
+        /// Z鍧愭爣
+        /// </summary>
+        public float z;
+        /// <summary>
+        /// X杞磋搴�
+        /// </summary>
+        public float xAngle;
+        /// <summary>
+        /// Y杞磋搴�
+        /// </summary>
+        public float yAngle;
+        /// <summary>
+        /// Z杞磋搴�
+        /// </summary>
+        public float zAngle;
+    }
+    /// <summary>
+    /// 鍋忕Щ淇℃伅
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct OFFSET_INFO
+    {
+        /// <summary>
+        /// X鍧愭爣
+        /// </summary>
+        public float x;
+        /// <summary>
+        /// Y鍧愭爣
+        /// </summary>
+        public float y;
+        /// <summary>
+        /// Z鍧愭爣
+        /// </summary>
+        public float z;
+        /// <summary>
+        /// X杞磋搴�
+        /// </summary>
+        public float xAngle;
+        /// <summary>
+        /// Y杞磋搴�
+        /// </summary>
+        public float yAngle;
+        /// <summary>
+        /// Z杞磋搴�
+        /// </summary>
+        public float zAngle;
+    }
+    /// <summary>
+    /// 杞粨绾挎爣瀹氭暟鎹粨鏋�
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct PARAM_BAR
+    {
+        /// <summary>
+        /// 楂樺害鎴栬�呭帤搴﹀��
+        /// </summary>
+        public float Height;
+        /// <summary>
+        /// 瀹藉害鍊�
+        /// </summary>
+        public float Width;
+        /// <summary>
+        /// 瀛旂殑鏁伴噺
+        /// </summary>
+        public int HoleCount;
+        /// <summary>
+        /// 瀛旂殑鐩村緞
+        /// </summary>
+        public float HoleDiameter;
+        /// <summary>
+        /// 瀛旂殑璺濈
+        /// </summary>
+        public float HoleDistance;
+        /// <summary>
+        /// 鏅繁
+        /// </summary>
+        public int DOF;
+    }
+    /// <summary>
+    /// 瑙掔偣鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct PARAM_CORNER
+    {
+        /// <summary>
+        /// X鍧愭爣
+        /// </summary>
+        public float x;
+        /// <summary>
+        /// Z鍧愭爣
+        /// </summary>
+        public float z;
+    }
+    /// <summary>
+    /// 澶氳竟褰㈡暟鎹粨鏋�
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct PARAM_POLYGON
+    {
+        /// <summary>
+        /// 鎬荤偣鏁�
+        /// </summary>
+        public int nCorners;
+        /// <summary>
+        /// 瑙掔偣鏁版嵁缁�
+        /// </summary>
+        public unsafe PARAM_CORNER* pCornerInfo;
+    }
+    /// <summary>
+    /// 缃戞牸鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct PARAM_BOARD
+    {
+        /// <summary>
+        /// 鍒濆鍖栧弬鏁�
+        /// </summary>
+        public void Initialize()
+        {
+            Height = 73.76f;
+            Width = 218;
+            HoleDiameter = 20;
+            HoleDistance = 98;
+            LocationHoleX1 = 60;
+            LocationHoleY1 = 73;
+            LocationHoleX2 = 60;
+            LocationHoleY2 = 213;
+        }
+        /// <summary>
+        /// 楂樺害鍊�
+        /// </summary>
+        public float Height;
+        /// <summary>
+        /// 瀹藉害鍊�
+        /// </summary>
+        public float Width;
+        /// <summary>
+        /// 瀛旂洿寰�
+        /// </summary>
+        public float HoleDiameter;
+        /// <summary>
+        /// 瀛旇窛绂�
+        /// </summary>
+        public float HoleDistance;
+        /// <summary>
+        /// 瀛�1X
+        /// </summary>
+        public float LocationHoleX1;
+        /// <summary>
+        /// 瀛�2Y
+        /// </summary>
+        public float LocationHoleY1;
+        /// <summary>
+        /// 瀛�2X
+        /// </summary>
+        public float LocationHoleX2;
+        /// <summary>
+        /// 瀛�2Y
+        /// </summary>
+        public float LocationHoleY2;
+    }
+    /// <summary>
+    /// LB-ROI
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct LB_ROI
+    {
+        /// <summary>
+        /// ROI-Left鍧愭爣
+        /// </summary>
+        public float left;
+        /// <summary>
+        /// ROI-Top鍧愭爣
+        /// </summary>
+        public float top;
+        /// <summary>
+        /// ROI-Right鍧愭爣
+        /// </summary>
+        public float right;
+        /// <summary>
+        /// ROI-Bottom鍧愭爣
+        /// </summary>
+        public float bottom;
+    }
+    /// <summary>
+    /// LB-ROI-INTEGER
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct LB_ROI_INTEGER
+    {
+        /// <summary>
+        /// LB-ROI-INTEGER-Left鍧愭爣
+        /// </summary>
+        public float left;
+        /// <summary>
+        /// LB-ROI-INTEGER-Top鍧愭爣
+        /// </summary>
+        public float top;
+        /// <summary>
+        /// LB-ROI-INTEGER-Right鍧愭爣
+        /// </summary>
+        public float right;
+        /// <summary>
+        /// LB-ROI-INTEGER-Bottom鍧愭爣
+        /// </summary>
+        public float bottom;
+    }
+    /// <summary>
+    /// LB 棰滆壊鏄犲皠琛�
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct LBColorMap
+    {
+        /// <summary>
+        /// 楂�
+        /// </summary>
+        public int nHeight;
+        /// <summary>
+        /// 瀹�
+        /// </summary>
+        public int nWidth;
+        /// <summary>
+        /// LBPointBGRA鏁版嵁
+        /// </summary>
+        public unsafe LBPointBGRA* pMap;
+    }
+    /// <summary>
+    /// 鐩爣淇℃伅鏁版嵁缁撴瀯
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct TARGET_INFO
+    {
+        /// <summary>
+        /// 瀹藉害鍊�
+        /// </summary>
+        public float fWidth;
+        /// <summary>
+        /// 楂樺害鍊�
+        /// </summary>
+        public float fHeight;
+        /// <summary>
+        /// 鏅繁
+        /// </summary>
+        public float fDepth;
+        /// <summary>
+        /// XL
+        /// </summary>
+        public float fMarginX;
+        /// <summary>
+        /// XROI
+        /// </summary>
+        public float fMarginRangeX;
+        /// <summary>
+        /// YL
+        /// </summary>
+        public float fMarginY;
+        /// <summary>
+        /// YROI
+        /// </summary>
+        public float fMarginRangeY;
+        /// <summary>
+        /// M
+        /// </summary>
+        public int nPartitionX;
+        /// <summary>
+        /// N
+        /// </summary>
+        public int nPartitionY;
+    }
+    /// <summary>
+    /// TRANS_INFO鏁版嵁缁撴瀯
+    /// </summary>
+    public struct TRANS_INFO
+    {
+        /// <summary>
+        /// x鍋忕Щ
+        /// </summary>
+        public float x;
+        /// <summary>
+        /// y鍋忕Щ
+        /// </summary>
+        public float y;
+        /// <summary>
+        /// z鍋忕Щ
+        /// </summary>
+        public float z;
+        /// <summary>
+        /// x鍋忚
+        /// </summary>
+        public float xAngle;
+        /// <summary>
+        /// y鍋忚
+        /// </summary>
+        public float yAngle;
+        /// <summary>
+        /// z鍋忚
+        /// </summary>
+        public float zAngle;
+    }
+    /// <summary>
+    /// 鍊肩被鍨�
+    /// </summary>
+    enum ValueType
+    {
+        /// <summary>
+        /// 鏁村瀷
+        /// </summary>
+        _Int,
+        /// <summary>
+        /// 娴偣鍨�
+        /// </summary>
+        _Float,
+        /// <summary>
+        /// 甯冨皵绫诲瀷
+        /// </summary>
+        _Bool,
+        /// <summary>
+        /// 鏋氫妇绫诲瀷
+        /// </summary>
+        _Enum,
+        /// <summary>
+        /// ROI绫诲瀷
+        /// </summary>
+        _Roi,
+        /// <summary>
+        /// 鑼冨洿
+        /// </summary>
+        _Range,
+        /// <summary>
+        /// 娴偣鍨嬫暟缁�
+        /// </summary>
+        _FloatArray,
+    };
+
+    #region  鍏板疂PHM6000浼犳劅鍣�
+
+    /// <summary>
+    /// 鍏板疂绾挎壂鎻忎紶鎰熷櫒鍏磋叮鍖虹粨鏋勫畾涔�
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential/*, Pack = 1*/)]  // 淇濊瘉鍐呭瓨甯冨眬椤哄簭
+    public struct LBProfileROI
+    {
+        /// <summary>
+        /// 鍏磋叮鍖篨鍚戜腑蹇冧綅缃� (鍗曚綅锛歮m)
+        /// </summary>
+        [DisplayName("xAxisCenter")]
+        [Category("LBProfileROI")]
+        [Description("鍏磋叮鍖篨鍚戜腑蹇冧綅缃� (鍗曚綅锛歮m)")]
+        public double xAxisCenter { get; set; }
+
+        /// <summary>
+        /// 鍏磋叮鍖篨鍚戝搴� (鍗曚綅锛歮m)
+        /// </summary>
+        [DisplayName("width")]
+        [Category("LBProfileROI")]
+        [Description("鍏磋叮鍖篨鍚戝搴� (鍗曚綅锛歮m)")]
+        public double width { get; set; }
+
+        /// <summary>
+        /// 鍏磋叮鍖篫鍚戦珮搴� (鍗曚綅锛歮m)
+        /// </summary>
+        [DisplayName("height")]
+        [Category("LBProfileROI")]
+        [Description("鍏磋叮鍖篫鍚戦珮搴� (鍗曚綅锛歮m)")]
+        public double height { get; set; }
+    }
+    /// <summary>
+    /// 鍏板疂绾挎壂鎻忎紶鎰熷櫒淇℃伅缁撴瀯瀹氫箟
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+    public struct LBCameraInfo
+    {
+        /// <summary>
+        /// 妯″潡鍨嬪彿
+        /// </summary>
+        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
+        public string szModuleType;
+
+        /// <summary>
+        /// 妯″潡搴忓垪鍙�
+        /// </summary>
+        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
+        public string szSerialNumber;
+
+        /// <summary>
+        /// 缃戠粶鍦板潃
+        /// </summary>
+        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
+        public string szIpAddress;
+
+        /// <summary>
+        /// 鐩戝惉绔彛
+        /// </summary>
+        public int nPort;
+    }
+
+    /// <summary>
+    /// 閫氱敤杈撳叆杈撳嚭绔彛(GPIO)鏋氫妇鍊�
+    /// </summary>
+    public enum GPIOLine
+    {
+        /// <summary>
+        /// 鎺у埗鐩掍笂鎺ユ彃浠跺紩绾跨紪鍙稬ine21
+        /// </summary>
+        Line21 = 0,
+        /// <summary>
+        /// 鎺у埗鐩掍笂鎺ユ彃浠跺紩绾跨紪鍙稬ine22
+        /// </summary>
+        Line22,
+        /// <summary>
+        /// 鎺у埗鐩掍笂鎺ユ彃浠跺紩绾跨紪鍙稬ine23
+        /// </summary>
+        Line23,
+        /// <summary>
+        /// 鎺у埗鐩掍笂鎺ユ彃浠跺紩绾跨紪鍙稬ine24
+        /// </summary>
+        Line24,
+        /// <summary>
+        /// 鎺у埗鐩掍笂鎺ユ彃浠跺紩绾跨紪鍙稬ine25
+        /// </summary>
+        Line25,
+        /// <summary>
+        /// 鎺у埗鐩掍笂鎺ユ彃浠跺紩绾跨紪鍙稬ine26
+        /// </summary>
+        Line26,
+        /// <summary>
+        /// 鎺у埗鐩掍笂鎺ユ彃浠跺紩绾跨紪鍙稬ine27
+        /// </summary>
+        Line27,
+        /// <summary>
+        /// 鎺у埗鐩掍笂鎺ユ彃浠跺紩绾跨紪鍙稬ine28
+        /// </summary>
+        Line28,
+    };
+
+    #endregion
+}
diff --git a/LB_SmartVisionCameraSDK/PHM6000/SysCalibration.cs b/LB_SmartVisionCameraSDK/PHM6000/SysCalibration.cs
new file mode 100644
index 0000000..1754486
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/PHM6000/SysCalibration.cs
@@ -0,0 +1,761 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCameraSDK.PHM6000
+{
+    /// <summary>
+    /// 鏍囧畾绫�
+    /// </summary>
+    public class SysCalibration
+    {
+        //SYS_CALIBRATION_API(void*) CreateSysCalibrationEntry();
+        /// <summary>
+        ///鍒涘缓绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀疄渚嬶紝杩斿洖鍏跺彞鏌�
+        /// </summary>
+        /// <returns>杩斿洖鍏跺彞鏌�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "CreateSysCalibrationEntry")]
+        public static extern IntPtr CreateSysCalibrationEntry();
+
+        //SYS_CALIBRATION_API(void) DestroySysCalibrationEntry(void* pHandle);
+        /// <summary>
+        /// 閿�姣佺郴缁熸爣瀹氫笌娴嬮噺妯″潡瀹炰緥
+        /// </summary>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DestroySysCalibrationEntry")]
+        public static extern void DestroySysCalibrationEntry();
+
+        //SYS_CALIBRATION_API(void) SetSensorInfo(void* pHandle, int nSensorIndex, SENSOR_INFO stInfo);
+        /// <summary>
+        /// 璁剧疆浼犳劅鍣ㄤ俊鎭紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stInfo">浼犳劅鍣ㄤ俊鎭�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetSensorInfo")]
+        public static extern void SetSensorInfo(IntPtr pHandle, int nSensorIndex, SENSOR_INFO stInfo);
+
+        //SYS_CALIBRATION_API(void) GetSensorInfo(void* pHandle, int nSensorIndex, SENSOR_INFO& stInfo);
+        /// <summary>
+        /// 鑾峰彇浼犳劅鍣ㄤ俊鎭紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stInfo">杩斿洖浼犳劅鍣ㄤ俊鎭�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetSensorInfo")]
+        public static extern void GetSensorInfo(IntPtr pHandle, int nSensorIndex, ref SENSOR_INFO stInfo);
+
+        //SYS_CALIBRATION_API(void) SetActiveAreaInfo(void* pHandle, int nSensorIndex, ACTIVE_AREA_INFO stInfo);
+        /// <summary>
+        /// 璁剧疆娲诲姩鍖轰俊鎭紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stInfo">娲诲姩鍖轰俊鎭�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetActiveAreaInfo")]
+        public static extern void SetActiveAreaInfo(IntPtr pHandle, int nSensorIndex, ACTIVE_AREA_INFO stInfo);
+
+        //SYS_CALIBRATION_API(void) GetActiveAreaInfo(void* pHandle, int nSensorIndex, ACTIVE_AREA_INFO& stInfo);
+        /// <summary>
+        /// 鑾峰彇娲诲姩鍖轰俊鎭紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stInfo">杩斿洖娲诲姩鍖轰俊鎭�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetActiveAreaInfo")]
+        public static extern void GetActiveAreaInfo(IntPtr pHandle, int nSensorIndex, ref ACTIVE_AREA_INFO stInfo);
+
+        //SYS_CALIBRATION_API(void) SetTransInfo(void* pHandle, int nSensorIndex, TRANS_INFO stInfo);
+        /// <summary>
+        /// 璁剧疆鍧愭爣绯昏浆鎹俊鎭紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stInfo">鍧愭爣绯昏浆鎹俊鎭�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetTransInfo")]
+        public static extern void SetTransInfo(IntPtr pHandle, int nSensorIndex, TRANS_INFO stInfo);
+
+        //SYS_CALIBRATION_API(void) GetTransInfo(void* pHandle, int nSensorIndex, TRANS_INFO& stInfo);
+        /// <summary>
+        /// 鑾峰彇鍧愭爣绯昏浆鎹俊鎭紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stInfo">杩斿洖鍧愭爣绯昏浆鎹俊鎭�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetTransInfo")]
+        public static extern void GetTransInfo(IntPtr pHandle, int nSensorIndex, ref TRANS_INFO stInfo);
+
+        //SYS_CALIBRATION_API(void) SetSensorPosition(void* pHandle, int nSensorIndex, SENSOR_POSITION stPosition);
+        /// <summary>
+        /// 璁剧疆浼犳劅鍣ㄤ綅缃俊鎭紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stPosition">浼犳劅鍣ㄤ綅缃俊鎭�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetSensorPosition")]
+        public static extern void SetSensorPosition(IntPtr pHandle, int nSensorIndex, SENSOR_POSITION stPosition);
+
+        //SYS_CALIBRATION_API(void) GetSensorPosition(void* pHandle, int nSensorIndex, SENSOR_POSITION* stPosition);
+        /// <summary>
+        /// 鑾峰彇浼犳劅鍣ㄤ綅缃俊鎭紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stPosition">杩斿洖浼犳劅鍣ㄤ綅缃俊鎭�, SENSOR_POSITION* stPosition</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetSensorPosition")]
+        public static extern void GetSensorPosition(IntPtr pHandle, int nSensorIndex, IntPtr stPosition);
+
+        //SYS_CALIBRATION_API(void) CalcTransInfo(void* pHandle, int nTotal);
+        /// <summary>
+        /// 璁$畻鍧愭爣绯昏浆鎹俊鎭紝鏃犺繑鍥炲�硷紝姝ゅ嚱鏁颁笉鐢�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nTotal">浼犳劅鍣ㄦ暟閲�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "CalcTransInfo")]
+        public static extern void CalcTransInfo(IntPtr pHandle, int nTotal);
+
+        //SYS_CALIBRATION_API(void) GetTransInfoPtr(void* pHandle, int nSensorIndex, TRANS_INFO* stInfo);
+        /// <summary>
+        /// 鑾峰彇鍧愭爣绯昏浆鎹俊鎭紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stInfo">杩斿洖鍧愭爣绯昏浆鎹俊鎭粨鏋勪綋鐨勬寚閽�, TRANS_INFO* stInfo</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetTransInfoPtr")]
+        public static extern void GetTransInfoPtr(IntPtr pHandle, int nSensorIndex, IntPtr stInfo);
+
+        //SYS_CALIBRATION_API(void) SetBoardParameter(void* pHandle, PARAM_BOARD stBoardParam);
+        /// <summary>
+        /// 璁剧疆鏍囧畾鐗╀俊鎭紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="stBoardParam">鏍囧畾鐗╀俊鎭�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetBoardParameter")]
+        public static extern void SetBoardParameter(IntPtr pHandle, PARAM_BOARD stBoardParam);
+
+        //SYS_CALIBRATION_API(void) SetTargetParameter(void* pHandle, TARGET_INFO stTargetInfo);
+        /// <summary>
+        /// 璁剧疆琚祴鐗╀俊鎭紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="stTargetInfo">琚祴鐗╀俊鎭�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetTargetParameter")]
+        public static extern void SetTargetParameter(IntPtr pHandle, TARGET_INFO stTargetInfo);
+
+        //SYS_CALIBRATION_API(void) SetRate(void* pHandle, int nSensorIndex, float xRate, float yRate);
+        /// <summary>
+        /// 璁剧疆x鍜寉鍧愭爣杞崲姣斾緥锛屾棤杩斿洖鍊�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="xRate">x鍚戣浆鎹㈡瘮渚�</param>
+        /// <param name="yRate">y鍚戣浆鎹㈡瘮渚�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetRate")]
+        public static extern void SetRate(IntPtr pHandle, int nSensorIndex, float xRate, float yRate);
+
+        //SYS_CALIBRATION_API(void) SetHoleROI(void* pHandle, int nSensorIndex, int nIndex, LB_ROI stRoi, bool IsFloatValue);
+        /// <summary>
+        /// 璁剧疆鍦嗗瓟鍏磋叮鍖猴紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="nIndex">瀛斿簭鍙�</param>
+        /// <param name="stRoi">鍦嗗瓟鍏磋叮鍖�</param>
+        /// <param name="IsFloatValue">鏁板�兼槸鍚︿负娴偣鏁�</param>
+
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetHoleROI")]
+        public static extern void SetHoleROI(IntPtr pHandle, int nSensorIndex, int nIndex, LB_ROI stRoi, bool IsFloatValue);
+
+        //SYS_CALIBRATION_API(void) SetFlatROI(void* pHandle, int nSensorIndex, LB_ROI stRoi, bool IsFloatValue);
+        /// <summary>
+        /// 璁剧疆骞抽潰鍏磋叮鍖猴紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stRoi">骞抽潰鍏磋叮鍖�</param>
+        /// <param name="IsFloatValue">鏁板�兼槸鍚︿负娴偣鏁�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetFlatROI")]
+        public static extern void SetFlatROI(IntPtr pHandle, int nSensorIndex, LB_ROI stRoi, bool IsFloatValue);
+
+        //SYS_CALIBRATION_API(void) SetLineROI(void* pHandle, int nSensorIndex, LB_ROI stRoi, bool IsFloatValue);
+        /// <summary>
+        /// 璁剧疆鐩寸嚎鍏磋叮鍖猴紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stRoi">鐩寸嚎鍏磋叮鍖�</param>
+        /// <param name="IsFloatValue">鏁板�兼槸鍚︿负娴偣鏁�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetLineROI")]
+        public static extern void SetLineROI(IntPtr pHandle, int nSensorIndex, LB_ROI stRoi, bool IsFloatValue);
+
+        //SYS_CALIBRATION_API(void) SetTestROI(void* pHandle, int nSensorIndex, LB_ROI stRoi, bool IsFloatValue);
+        /// <summary>
+        /// 璁剧疆娴嬮噺鍏磋叮鍖猴紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stRoi">娴嬮噺鍏磋叮鍖�</param>
+        /// <param name="IsFloatValue">鏁板�兼槸鍚︿负娴偣鏁�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetTestROI")]
+        public static extern void SetTestROI(IntPtr pHandle, int nSensorIndex, LB_ROI stRoi, bool IsFloatValue);
+
+        //SYS_CALIBRATION_API(void) RemovePointsRatio(void* pHandle, int nSensorIndex, float fRatio);
+        /// <summary>
+        /// 璁剧疆鍓旈櫎鏁版嵁涓暟鐨勬瘮渚嬶紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="fRatio">鍓旈櫎鏁版嵁涓暟鐨勬瘮渚�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "RemovePointsRatio")]
+        public static extern void RemovePointsRatio(IntPtr pHandle, int nSensorIndex, float fRatio);
+
+        //SYS_CALIBRATION_API(void) GetLineROI(void* pHandle, int nSensorIndex, LB_ROI* stRoi);
+        /// <summary>
+        /// 鑾峰緱鐩寸嚎鍏磋叮鍖猴紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stRoi">杩斿洖鐩寸嚎鍏磋叮鍖�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetLineROI")]
+        public static extern void GetLineROI(IntPtr pHandle, int nSensorIndex, IntPtr stRoi);
+
+        //SYS_CALIBRATION_API(void) SetSysSensors(void* pHandle, int nCount);
+        /// <summary>
+        /// 璁剧疆绯荤粺涓紶鎰熷櫒鐨勬暟閲忥紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nCount">浼犳劅鍣ㄦ暟閲�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetSysSensors")]
+        public static extern void SetSysSensors(IntPtr pHandle, int nCount);
+
+        //SYS_CALIBRATION_API(void) SetLineData(void* pHandle, int nSensorIndex, LBLineDataXYZ* pData);
+        /// <summary>
+        /// 璁剧疆琛屾暟鎹紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="pData">鍚玐YZ淇℃伅鐨勮鏁版嵁, LBLineDataXYZ* pData</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetSysSensors")]
+        public static extern void SetSysSensors(IntPtr pHandle, int nSensorIndex, IntPtr pData);
+
+        //SYS_CALIBRATION_API(void) AddLineData(void* pHandle, int nSensorIndex, LBLineDataXYZ* pData);
+        /// <summary>
+        /// 娣诲姞琛屾暟鎹紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="pData">鍚玐YZ淇℃伅鐨勮鏁版嵁, LBLineDataXYZ* pData</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddLineData")]
+        public static extern void AddLineData(IntPtr pHandle, int nSensorIndex, IntPtr pData);
+
+        //SYS_CALIBRATION_API(void) ClearData(void* pHandle, int nSensorIndex);
+        /// <summary>
+        /// 娓呴櫎鏁版嵁锛屾棤杩斿洖鍊�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ClearData")]
+        public static extern void ClearData(IntPtr pHandle, int nSensorIndex);
+
+        //SYS_CALIBRATION_API(void) SetLineDataArray(void* pHandle, int nSensorIndex, LBLineDataZA* pData);
+        /// <summary>
+        /// 璁剧疆琛屾暟鎹紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="pData">鍚玐YZ淇℃伅鐨勮鏁版嵁, LBLineDataZA* pData</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetLineDataArray")]
+        public static extern void SetLineDataArray(IntPtr pHandle, int nSensorIndex, IntPtr pData);
+
+        //SYS_CALIBRATION_API(void) AddLineDataArray(void* pHandle, int nSensorIndex, LBLineDataZA* pData, bool bUseEncoder, int nCountingMode);
+        /// <summary>
+        /// 娣诲姞琛屾暟鎹紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="pData">鍚玐YZ淇℃伅鐨勮鏁版嵁, LBLineDataZA* pData</param>
+        /// <param name="bUseEncoder">鏄惁浣跨敤缂栫爜鍣�</param>
+        /// <param name="nCountingMode">璁℃暟妯″紡锛屽缓璁�间负1</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddLineDataArray")]
+        public static extern void AddLineDataArray(IntPtr pHandle, int nSensorIndex, IntPtr pData, bool bUseEncoder, int nCountingMode);
+
+        //SYS_CALIBRATION_API(LBLineDataXYZ*) GetLineData(void* pHandle, int nSensorIndex);
+        /// <summary>
+        /// 鑾峰彇琛屾暟鎹�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <returns>杩斿洖鍚玐YZ淇℃伅鐨勮鏁版嵁锛�(LBLineDataXYZ*)</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetLineData")]
+        public static extern IntPtr GetLineData(IntPtr pHandle, int nSensorIndex);
+
+        //SYS_CALIBRATION_API(LBPointCloudData*) GetCloudData(void* pHandle, int nSensorIndex);
+        /// <summary>
+        /// 鑾峰彇鐐逛簯鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <returns>杩斿洖鐐逛簯鏁版嵁锛�(LBPointCloudData*)</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCloudData")]
+        public static extern IntPtr GetCloudData(IntPtr pHandle, int nSensorIndex);
+
+        //SYS_CALIBRATION_API(LBPointCloudDataXYZ*) GetCloudDataXYZ(void* pHandle, int nSensorIndex, int nDownsample);
+        /// <summary>
+        /// 鑾峰彇鐐逛簯鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="nDownsample">闄嶉噰鏍峰�嶆暟</param>
+        /// <returns>杩斿洖鍚玐YZ淇℃伅鐨勭偣浜戞暟鎹紝(LBPointCloudDataXYZ*)</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCloudDataXYZ")]
+        public static extern IntPtr GetCloudDataXYZ(IntPtr pHandle, int nSensorIndex, int nDownsample);
+
+        //SYS_CALIBRATION_API(LBPointCloudDataXYZ*) GetFlatDataXYZ(void* pHandle, int nSensorIndex, int nDownsample, float fThreshold);
+        /// <summary>
+        /// 鑾峰彇骞抽潰鐐逛簯鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="nDownsample">闄嶉噰鏍峰�嶆暟</param>
+        /// <param name="fThreshold">涓庡钩闈㈢殑鍋忓樊鍩熷��</param>
+        /// <returns>杩斿洖鍚玐YZ淇℃伅鐨勫钩闈㈢偣浜戞暟鎹紝(LBPointCloudDataXYZ*) </returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetFlatDataXYZ")]
+        public static extern IntPtr GetFlatDataXYZ(IntPtr pHandle, int nSensorIndex, int nDownsample, float fThreshold);
+
+        //SYS_CALIBRATION_API(bool) AlignmentMovingFlat(void* pHandle, int nSensorIndex);
+        /// <summary>
+        /// 绉诲姩骞抽潰鍨嬫牎鍑�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <returns>璁剧疆澶辫触杩斿洖false锛屽惁鍒欒繑鍥瀟rue銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AlignmentMovingFlat")]
+        public static extern bool AlignmentMovingFlat(IntPtr pHandle, int nSensorIndex);
+
+        //SYS_CALIBRATION_API(bool) AlignmentFlatSurface(void* pHandle, int nSensorIndex, int nType);
+        /// <summary>
+        /// 骞抽潰鍨嬫牎鍑�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="nType">绫诲瀷锛屾湭浣跨敤</param>
+        /// <returns>璁剧疆澶辫触杩斿洖false锛屽惁鍒欒繑鍥瀟rue銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AlignmentFlatSurface")]
+        public static extern bool AlignmentFlatSurface(IntPtr pHandle, int nSensorIndex, int nType);
+
+        //SYS_CALIBRATION_API(bool) AlignmentBar(void* pHandle, int nSensorIndex, int nType, PARAM_BAR stBarInfo);
+        /// <summary>
+        /// 鏉$姸鐗╁瀷鏍″噯
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="nType">绫诲瀷锛堢Щ鍔ㄥ瀷鎴栧浐瀹氬瀷锛�</param>
+        /// <param name="stBarInfo">鏉$姸鐗╀俊鎭�</param>
+        /// <returns>璁剧疆澶辫触杩斿洖false锛屽惁鍒欒繑鍥瀟rue銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AlignmentBar")]
+        public static extern bool AlignmentBar(IntPtr pHandle, int nSensorIndex, int nType, PARAM_BAR stBarInfo);
+
+        //SYS_CALIBRATION_API(bool) AlignmentPolygon(void* pHandle, int nSensorIndex, int nType, PARAM_POLYGON stInfo);
+        /// <summary>
+        /// 澶氳竟褰㈠瀷鏍″噯
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="nType">绫诲瀷锛堢Щ鍔ㄥ瀷鎴栧浐瀹氬瀷锛�</param>
+        /// <param name="stInfo">澶氳竟褰俊鎭�</param>
+        /// <returns>璁剧疆澶辫触杩斿洖false锛屽惁鍒欒繑鍥瀟rue銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AlignmentPolygon")]
+        public static extern bool AlignmentPolygon(IntPtr pHandle, int nSensorIndex, int nType, PARAM_POLYGON stInfo);
+
+        //SYS_CALIBRATION_API(bool) PointsRotationAndTranslation(void* pHandle, int nSensorIndex, LBLineDataXYZ Input, LBLineDataXYZ Output);
+        /// <summary>
+        /// 鐐归泦鍏堟棆杞啀骞崇Щ鍑芥暟
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="Input">杈撳叆鐐归泦</param>
+        /// <param name="Output">杈撳嚭鐐归泦</param>
+        /// <returns>璁剧疆澶辫触杩斿洖false锛屽惁鍒欒繑鍥瀟rue銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "PointsRotationAndTranslation")]
+        public static extern bool PointsRotationAndTranslation(IntPtr pHandle, int nSensorIndex, LBLineDataXYZ Input, LBLineDataXYZ Output);
+
+        //SYS_CALIBRATION_API(bool) PointsResampling(void* pHandle, LBCalibrationData Input, LBCalibrationData Output);
+        /// <summary>
+        /// 鐐归泦閲嶉噰鏍峰嚱鏁�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="Input">杈撳叆鐐归泦</param>
+        /// <param name="Output">杈撳嚭鐐归泦</param>
+        /// <returns>璁剧疆澶辫触杩斿洖false锛屽惁鍒欒繑鍥瀟rue銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "PointsResampling")]
+        public static extern bool PointsResampling(IntPtr pHandle, LBCalibrationData Input, LBCalibrationData Output);
+
+        //SYS_CALIBRATION_API(bool) PointsRotationAndTranslation2D(void* pHandle, int nSensorIndex, LBLineDataXYZ* pInput, LBLineDataXYZ* pOutput);
+        /// <summary>
+        /// 浜岀淮鐐归泦鍏堟棆杞啀骞崇Щ鍑芥暟
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="pInput">杈撳叆鐐归泦, LBLineDataXYZ* pInput</param>
+        /// <param name="pOutput">杈撳嚭鐐归泦, LBLineDataXYZ* pOutput</param>
+        /// <returns>璁剧疆澶辫触杩斿洖false锛屽惁鍒欒繑鍥瀟rue銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "PointsRotationAndTranslation2D")]
+        public static extern bool PointsRotationAndTranslation2D(IntPtr pHandle, int nSensorIndex, IntPtr pInput, IntPtr pOutput);
+
+        //SYS_CALIBRATION_API(bool) PointsTranslationAndRotation2D(void* pHandle, int nSensorIndex, LBLineDataXYZ* pInput, LBLineDataXYZ* pOutput);
+        /// <summary>
+        /// 浜岀淮鐐归泦鍏堝钩绉诲啀鏃嬭浆鍑芥暟
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="pInput">杈撳叆鐐归泦, LBLineDataXYZ* pInput</param>
+        /// <param name="pOutput">杈撳嚭鐐归泦, LBLineDataXYZ* pOutput</param>
+        /// <returns>璁剧疆澶辫触杩斿洖false锛屽惁鍒欒繑鍥瀟rue銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "PointsTranslationAndRotation2D")]
+        public static extern bool PointsTranslationAndRotation2D(IntPtr pHandle, int nSensorIndex, IntPtr pInput, IntPtr pOutput);
+
+        //SYS_CALIBRATION_API(LBLineDataXZ*) GetInlierDataXZ(void* pHandle);
+        /// <summary>
+        /// 鑾峰彇鍚玐Z淇℃伅鐨勫唴鐐规暟鎹�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <returns>杩斿洖鍚玐Z淇℃伅鐨勫唴鐐规暟鎹�,(LBLineDataXZ*)</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetInlierDataXZ")]
+        public static extern IntPtr GetInlierDataXZ(IntPtr pHandle);
+
+        //SYS_CALIBRATION_API(LBPointCloudDataXYZ*) GetInlierDataXYZ(void* pHandle);
+        /// <summary>
+        /// 鑾峰彇鍚玐YZ淇℃伅鐨勫唴鐐规暟鎹�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <returns>杩斿洖鍚玐YZ淇℃伅鐨勫唴鐐规暟鎹�,(LBPointCloudDataXYZ*)</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetInlierDataXYZ")]
+        public static extern IntPtr GetInlierDataXYZ(IntPtr pHandle);
+
+        //SYS_CALIBRATION_API(LBPointCloudDataXYZ*) GetSourceDataXYZ(void* pHandle);
+        /// <summary>
+        /// 鑾峰彇鍚玐YZ淇℃伅鐨勬簮鐐规暟鎹�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <returns>杩斿洖鍚玐YZ淇℃伅鐨勬簮鐐规暟鎹�,(LBPointCloudDataXYZ*)</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetSourceDataXYZ")]
+        public static extern IntPtr GetSourceDataXYZ(IntPtr pHandle);
+
+        //SYS_CALIBRATION_API(void) GetLineParameter(void* pHandle, double& k, double& b);
+        /// <summary>
+        /// 鑾峰彇鐩寸嚎鍙傛暟锛屾棤杩斿洖
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="k">鏂滅巼</param>
+        /// <param name="b">鎴窛</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetLineParameter")]
+        public static extern void GetLineParameter(IntPtr pHandle, ref double k, ref double b);
+
+        //SYS_CALIBRATION_API(void) GetFlatParameter(void* pHandle, int nSensorIndex, double& A, double& B, double &C, double &D);
+        /// <summary>
+        /// 鑾峰彇骞抽潰鍙傛暟锛屾棤杩斿洖
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="A">x鍒嗛噺</param>
+        /// <param name="B">y鍒嗛噺</param>
+        /// <param name="C">z鍒嗛噺</param>
+        /// <param name="D">鎴窛</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetFlatParameter")]
+        public static extern void GetFlatParameter(IntPtr pHandle, int nSensorIndex, ref double A, ref double B, ref double C, ref double D);
+
+        //SYS_CALIBRATION_API(void) GetCircleParameter(void* pHandle, int nSensorIndex, int nIndex, double& x, double& y, double &r);
+        /// <summary>
+        /// 鑾峰彇鍦嗗弬鏁帮紝鏃犺繑鍥�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="nIndex">鍦嗙殑绱㈠紩</param>
+        /// <param name="x">x鍧愭爣</param>
+        /// <param name="y">y鍧愭爣</param>
+        /// <param name="r">鍗婂緞</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCircleParameter")]
+        public static extern void GetCircleParameter(IntPtr pHandle, int nSensorIndex, int nIndex, ref double x, ref double y, ref double r);
+
+        //SYS_CALIBRATION_API(void) GetLineParam(void* pHandle, double* k, double* b);
+        /// <summary>
+        /// 鑾峰彇鐩寸嚎鍙傛暟锛屾棤杩斿洖
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="k">鏂滅巼</param>
+        /// <param name="b">鎴窛</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetLineParam")]
+        public static extern void GetLineParam(IntPtr pHandle, ref double k, ref double b);
+
+        //SYS_CALIBRATION_API(void) GetLineParamInfo(void* pHandle, char* szParamInfo);
+        /// <summary>
+        /// 鑾峰彇鐩寸嚎鍙傛暟淇℃伅锛屾棤杩斿洖
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="szParamInfo">鐩寸嚎鐢ㄦ枃瀛楄〃杈剧殑淇℃伅, char* szParamInfo</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetLineParamInfo")]
+        public static extern void GetLineParamInfo(IntPtr pHandle, IntPtr szParamInfo);
+
+        //SYS_CALIBRATION_API(void) GetLineModel(void* pHandle, double* cos_theta, double* sin_theta, double* rho);
+        /// <summary>
+        /// 鑾峰彇鐩寸嚎鐨勬ā鍨嬪弬鏁帮紝鏃犺繑鍥�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="cos_theta">瑙掍綑寮﹀��</param>
+        /// <param name="sin_theta">瑙掓寮﹀��</param>
+        /// <param name="rho">妯¢暱</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetLineModel")]
+        public static extern void GetLineModel(IntPtr pHandle, ref double cos_theta, ref double sin_theta, ref double rho);
+
+        //SYS_CALIBRATION_API(void) ConvertZA2XYZ(void* pHandle, LBLineDataZA* Input, LBLineDataXYZ* Output, bool bUseEncoder, int nCountingMode, int nDownSample);
+        /// <summary>
+        /// 杞崲ZA鏍煎紡鏁版嵁鍒癤YZ鏍煎紡鏁版嵁锛屾棤杩斿洖
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="Input">杈撳叆鏁版嵁鎸囬拡, LBLineDataZA* Input</param>
+        /// <param name="Output">杈撳嚭鏁版嵁鎸囬拡, LBLineDataXYZ* Output</param>
+        /// <param name="bUseEncoder">鏄惁浣跨敤缂栫爜鍣�</param>
+        /// <param name="nCountingMode">璁℃暟妯″紡</param>
+        /// <param name="nDownSample">闄嶉噰鏍峰�嶇巼</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ConvertZA2XYZ")]
+        public static extern void ConvertZA2XYZ(IntPtr pHandle, IntPtr Input, IntPtr Output, bool bUseEncoder, int nCountingMode, int nDownSample);
+
+        //SYS_CALIBRATION_API(int) CvtZA2XYZ(void* pHandle, LBLineDataZA* Input, float* x, float* y, float* z, bool bUseEncoder, int nCountingMode, int nDownSample);
+        /// <summary>
+        /// 杞崲XYZ鏍煎紡鏁版嵁鍒癦A鏍煎紡鏁版嵁
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="Input">杈撳叆鏁版嵁鎸囬拡, LBLineDataZA* Input</param>
+        /// <param name="x">x鏁版嵁鎸囬拡, float* x</param>
+        /// <param name="y">y鏁版嵁鎸囬拡, float* y</param>
+        /// <param name="z">z鏁版嵁鎸囬拡, float* z</param>
+        /// <param name="bUseEncoder">鏄惁浣跨敤缂栫爜鍣�</param>
+        /// <param name="nCountingMode">璁℃暟妯″紡</param>
+        /// <param name="nDownSample">闄嶉噰鏍峰�嶇巼</param>
+        /// <returns>杩斿洖杞崲鍚庣殑鏁版嵁鏁伴噺</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "CvtZA2XYZ")]
+        public static extern int CvtZA2XYZ(IntPtr pHandle, IntPtr Input, IntPtr x, IntPtr y, IntPtr z, bool bUseEncoder, int nCountingMode, int nDownSample);
+
+        //SYS_CALIBRATION_API(int) SetOffsetInfo(void* pHandle, int nSensorIndex, OFFSET_INFO stInfo);
+        /// <summary>
+        /// 璁剧疆琛屾暟鎹�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stInfo">鍋忕Щ淇℃伅</param>
+        /// <returns>杩斿洖鍊�0琛ㄧず澶辫触锛�1琛ㄦ槸鎴愬姛</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetOffsetInfo")]
+        public static extern int SetOffsetInfo(IntPtr pHandle, int nSensorIndex, OFFSET_INFO stInfo);
+
+        //SYS_CALIBRATION_API(int) PointsRotateAndTrans2D(void* pHandle, int nSensorIndex, LBLineDataXYZ* pInput, LBLineDataXYZ* pOutput, int RemoveNAN);
+        /// <summary>
+        /// 浜岀淮鐐归泦鍏堟棆杞啀骞崇Щ鍑芥暟
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="pInput">杈撳叆鐐归泦, LBLineDataXYZ* pInput</param>
+        /// <param name="pOutput">杈撳嚭鐐归泦, LBLineDataXYZ* pOutput</param>
+        /// <param name="RemoveNAN">鏄惁鍒犻櫎NAN锛�1鍒犻櫎锛�0淇濈暀</param>
+        /// <returns>璁剧疆澶辫触杩斿洖0锛屽惁鍒欒繑鍥�1銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "PointsRotateAndTrans2D")]
+        public static extern int PointsRotateAndTrans2D(IntPtr pHandle, int nSensorIndex, IntPtr pInput, IntPtr pOutput, int RemoveNAN);
+
+        //SYS_CALIBRATION_API(int) PointsRotateAndMove2D(void* pHandle, int nSensorIndex, LBPointXYZ* pInput, LBPointXYZ* pOutput, int nInputSize, int RemoveNAN);
+        /// <summary>
+        /// 浜岀淮鐐归泦鍏堟棆杞啀骞崇Щ鍑芥暟锛屼笌涓婇潰鐨勪竴涓嚱鏁拌緭鍏ヨ緭鍑轰笉鍚�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="pInput">杈撳叆鐐归泦, LBPointXYZ* pInput</param>
+        /// <param name="pOutput">杈撳嚭鐐归泦, LBPointXYZ* pOutput</param>
+        /// <param name="nInputSize">杈撳叆鏁版嵁闆嗙殑澶у皬</param>
+        /// <param name="RemoveNAN">鏄惁鍒犻櫎NAN锛�1鍒犻櫎锛�0淇濈暀</param>
+        /// <returns>璁剧疆澶辫触杩斿洖0锛屽惁鍒欒繑鍥�1銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "PointsRotateAndMove2D")]
+        public static extern int PointsRotateAndMove2D(IntPtr pHandle, int nSensorIndex, IntPtr pInput, IntPtr pOutput, int nInputSize, int RemoveNAN);
+
+        //SYS_CALIBRATION_API(int) PointsRotateAroundPt2D(void* pHandle, LBLineDataXYZ* pInput, LBLineDataXYZ* pOutput, LBPointXZ pt, float theta, int IsOpposite);
+        /// <summary>
+        /// 浜岀淮鐐归泦缁曠偣鏃嬭浆
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="pInput">杈撳叆鐐归泦, LBLineDataXYZ* pInput</param>
+        /// <param name="pOutput">杈撳嚭鐐归泦, LBLineDataXYZ* pOutput</param>
+        /// <param name="pt">瑕佺粫鐨勭偣</param>
+        /// <param name="theta">瑕佽浆鐨勫姬搴�</param>
+        /// <param name="IsOpposite">鏄惁鐩稿瀹夎</param>
+        /// <returns>璁剧疆澶辫触杩斿洖0锛屽惁鍒欒繑鍥�1銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "PointsRotateAroundPt2D")]
+        public static extern int PointsRotateAroundPt2D(IntPtr pHandle, IntPtr pInput, IntPtr pOutput, LBPointXZ pt, float theta, int IsOpposite);
+
+        //SYS_CALIBRATION_API(int) PointsMove2D(void* pHandle, LBLineDataXYZ* pInput, LBLineDataXYZ* pOutput, const float fDeltaX, const float fDeltaZ);
+        /// <summary>
+        /// 浜岀淮鐐归泦骞崇Щ
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="pInput">杈撳叆鐐归泦, LBLineDataXYZ* pInput</param>
+        /// <param name="pOutput">杈撳嚭鐐归泦, LBLineDataXYZ* pOutput</param>
+        /// <param name="fDeltaX">x鍋忕Щ閲�</param>
+        /// <param name="fDeltaZ">y鍋忕Щ閲�</param>
+        /// <returns>璁剧疆澶辫触杩斿洖0锛屽惁鍒欒繑鍥�1銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "PointsMove2D")]
+        public static extern int PointsMove2D(IntPtr pHandle, IntPtr pInput, IntPtr pOutput, float fDeltaX, float fDeltaZ);
+
+        //SYS_CALIBRATION_API(int) PointsMerge(void* pHandle, LBPointXYZ* pInput1, int nCount1, LBPointXYZ* pInput2, int nCount2, LBPointXYZ* pOutput, int nSize);
+        /// <summary>
+        /// 涓ょ粍涓夌淮鐐归泦鍚堝苟鍑芥暟
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="pInput1">杈撳叆鐐归泦1, LBPointXYZ* pInput1</param>
+        /// <param name="nCount1">杈撳叆鐐归泦1鐨勬暟閲�</param>
+        /// <param name="pInput2">杈撳叆鐐归泦2, LBPointXYZ* pInput2</param>
+        /// <param name="nCount2">杈撳叆鐐归泦2鐨勬暟閲�</param>
+        /// <param name="pOutput">杈撳嚭鐐归泦, LBPointXYZ* pOutput</param>
+        /// <param name="nSize">杈撳嚭鐐归泦鏁伴噺</param>
+        /// <returns>杩斿洖鍚堝苟鍚庣殑鐐归泦澶у皬銆�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "PointsMerge")]
+        public static extern int PointsMerge(IntPtr pHandle, IntPtr pInput1, int nCount1, IntPtr pInput2, int nCount2, IntPtr pOutput, int nSize);
+
+        //SYS_CALIBRATION_API(void) CalibratePointCloud(void* pHandle, int nSensorIndex);
+        /// <summary>
+        /// 鏍″噯鐐逛簯锛屾棤杩斿洖鍊�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex"></param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "CalibratePointCloud")]
+        public static extern void CalibratePointCloud(IntPtr pHandle, int nSensorIndex);
+
+        //SYS_CALIBRATION_API(void) SystemCalibration(void* pHandle);
+        /// <summary>
+        /// 绯荤粺鏍囧畾锛屾棤杩斿洖鍊�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "SystemCalibration")]
+        public static extern void SystemCalibration(IntPtr pHandle);
+
+        //SYS_CALIBRATION_API(float) MeasureDistance(void* pHandle);
+        /// <summary>
+        /// 娴嬮噺璺濈锛屼笉浣跨敤
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <returns>杩斿洖琚祴璺濈</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "MeasureDistance")]
+        public static extern float MeasureDistance(IntPtr pHandle);
+
+        //SYS_CALIBRATION_API(float) MeasureMaxDistance(void* pHandle);
+        /// <summary>
+        /// 娴嬮噺鏈�澶ц窛绂伙紝涓嶄娇鐢�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <returns>杩斿洖琚祴鏈�澶ц窛绂�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "MeasureMaxDistance")]
+        public static extern float MeasureMaxDistance(IntPtr pHandle);
+
+        //SYS_CALIBRATION_API(float) ComputeConcavity(void* pHandle, int nSensorIndex);
+        /// <summary>
+        /// 璁$畻鍑瑰嚫搴︼紝涓嶄娇鐢�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <returns>杩斿洖鍑瑰嚫搴﹀��</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ComputeConcavity")]
+        public static extern float ComputeConcavity(IntPtr pHandle, int nSensorIndex);
+
+        //SYS_CALIBRATION_API(float) MeasureFlatHigh(void* pHandle, int nSensorIndex, LB_ROI stRoi);
+        /// <summary>
+        /// 娴嬮噺骞抽潰楂樺害锛屼笉浣跨敤
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="stRoi">鎸囧畾鐨勫叴瓒e尯</param>
+        /// <returns>杩斿洖琚祴璺濆钩闈㈢殑楂樺害</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "MeasureFlatHigh")]
+        public static extern float MeasureFlatHigh(IntPtr pHandle, int nSensorIndex, LB_ROI stRoi);
+
+        //SYS_CALIBRATION_API(float) MeasureTargetHigh(void* pHandle, int nSensorIndex);
+        /// <summary>
+        /// 娴嬮噺鐩爣鐗╅珮搴�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <returns>杩斿洖琚祴鐩爣鐗╃殑楂樺害</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "MeasureTargetHigh")]
+        public static extern float MeasureTargetHigh(IntPtr pHandle, int nSensorIndex);
+
+        //SYS_CALIBRATION_API(float) MeasureRoiHigh(void* pHandle, int nSensorIndex, int nRoiIndex);
+        /// <summary>
+        /// 娴嬮噺鍏磋叮鍖虹墿楂樺害
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="nRoiIndex">鍏磋叮鍖虹殑绱㈠彿锛屽�间粠1璧�</param>
+        /// <returns>杩斿洖琚祴鍏磋叮鍖虹殑楂樺害</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "MeasureRoiHigh")]
+        public static extern float MeasureRoiHigh(IntPtr pHandle, int nSensorIndex, int nRoiIndex);
+
+        //SYS_CALIBRATION_API(float) MeasureLineHigh(void* pHandle, int nSensorIndex);
+        /// <summary>
+        /// 娴嬮噺杞粨绾块珮搴�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <returns>杩斿洖琚祴杞粨绾跨殑楂樺害</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "MeasureLineHigh")]
+        public static extern float MeasureLineHigh(IntPtr pHandle, int nSensorIndex);
+
+        //SYS_CALIBRATION_API(void) EdgeDetection(void* pHandle, int nSensorIndex);
+        /// <summary>
+        /// 杈圭紭妫�娴嬶紝鏃犺繑鍥烇紝涓嶄娇鐢�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "EdgeDetection")]
+        public static extern void EdgeDetection(IntPtr pHandle, int nSensorIndex);
+
+        //SYS_CALIBRATION_API(float) CalcIntercept(void* pHandle, int nSensorIndex, float& theta);
+        /// <summary>
+        /// 璁$畻鑻ュ共鐩歌繎鐨勮疆寤撶嚎鎷熷悎鐩寸嚎涓嶻杞寸殑浜ょ偣锛屼笉浣跨敤
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="theta">杩斿洖澶硅</param>
+        /// <returns>杩斿洖Y杞翠笂鐨勬埅璺�</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "CalcIntercept")]
+        public static extern float CalcIntercept(IntPtr pHandle, int nSensorIndex, ref float theta);
+
+        //SYS_CALIBRATION_API(LBColorMap*) GetDepthMap(void* pHandle, int nSensorIndex, int nOption);
+        /// <summary>
+        /// 鑾峰彇娣卞害鍥�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="nOption">鐢�4鏉ヨ幏鍙栧ぇ鍏磋叮鐨勬繁搴﹀浘</param>
+        /// <returns>杩斿洖娣卞害鍥剧粨鏋勪綋锛�(LBColorMap*)</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetDepthMap")]
+        public static extern IntPtr GetDepthMap(IntPtr pHandle, int nSensorIndex, int nOption);
+
+        //SYS_CALIBRATION_API(LBColorMap*) GetBinaryMap(void* pHandle, int nSensorIndex, int nOption);
+        /// <summary>
+        /// 鑾峰彇榛戠櫧鍥撅紝涓嶄娇鐢�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="nOption">閫夐」</param>
+        /// <returns>杩斿洖榛戠櫧鍥剧粨鏋勪綋锛�(LBColorMap*)</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetBinaryMap")]
+        public static extern IntPtr GetBinaryMap(IntPtr pHandle, int nSensorIndex, int nOption);
+
+        //SYS_CALIBRATION_API(LBColorMap*) GetResultMap(void* pHandle, int nSensorIndex, int nOption);
+        /// <summary>
+        /// 鑾峰彇缁撴灉鍥撅紝浠呰皟璇曚娇鐢紝涓嶅澶栧紑鏀�
+        /// </summary>
+        /// <param name="pHandle">绯荤粺鏍囧畾涓庢祴閲忔ā鍧楀彞鏌�</param>
+        /// <param name="nSensorIndex">浼犳劅鍣ㄥ簭鍙�</param>
+        /// <param name="nOption">閫夐」</param>
+        /// <returns>杩斿洖缁撴灉鍥剧粨鏋勪綋锛�(LBColorMap*)</returns>
+        [DllImport("SysCalibration.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetResultMap")]
+        public static extern IntPtr GetResultMap(IntPtr pHandle, int nSensorIndex, int nOption);
+    }
+}
diff --git a/LB_SmartVisionCameraSDK/PclEntry.cs b/LB_SmartVisionCameraSDK/PclEntry.cs
new file mode 100644
index 0000000..93a3805
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/PclEntry.cs
@@ -0,0 +1,356 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCameraSDK
+{
+    //typedef void(__stdcall* PCLPointPickCallback)(double x, double y, double z);
+    /// <summary>
+    /// 鑾峰彇鐐逛簯涓偣鐨勫洖璋冨嚱鏁�
+    /// </summary>
+    /// <param name="x">x鍧愭爣</param>
+    /// <param name="y">y鍧愭爣</param>
+    /// <param name="z">z鍧愭爣</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void PCLPointPickCallback(double x, double y, double z);
+
+    //typedef void (__stdcall* ShowParameterCallback) (void* pData, int nSize);
+    /// <summary>
+    /// 鏄剧ず鍙傛暟淇℃伅鐨勫洖璋冨嚱鏁版牸寮忥紝鏃犺繑鍥炲��
+    /// </summary>
+    /// <param name="pData">娑堟伅瀛楃涓�</param>
+    /// <param name="nSize">瀛楃涓查暱搴�</param>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void ShowParameterCallback(IntPtr pData, int nSize);
+
+    public class PclEntry
+    {
+        /// <summary>
+        /// 鐩稿搴旂獥浣撳彂閫佷俊鎭�
+        /// </summary>
+        /// <param name="hWnd">瀵瑰簲绐椾綋鍙ユ焺</param>
+        /// <param name="Msg">鎸囧畾琚瘎閫佺殑娑堟伅</param>
+        /// <param name="wParam">鎸囧畾闄勫姞鐨勬秷鎭壒瀹氱殑淇℃伅</param>
+        /// <param name="lParam">鎸囧畾闄勫姞鐨勬秷鎭壒瀹氱殑淇℃伅</param>
+        /// <returns>濡傛灉鍑芥暟璋冪敤鎴愬姛锛岃繑鍥為潪闆跺�硷細濡傛灉鍑芥暟璋冪敤澶辫触锛岃繑鍥炲�兼槸闆躲��</returns>
+        [DllImport("user32.dll")]
+        public static extern bool PostMessage(IntPtr hWnd, uint Msg, ushort wParam, ulong lParam);
+
+        //PCLAPI(void*) CreatePCLWindow(void* hWnd);
+        /// <summary>
+        /// 鍒涘缓PCL鏄剧ず瀹炰緥锛岃繑鍥炲叾鍙ユ焺
+        /// </summary>
+        /// <param name="hWnd">涓哄绾充簩缁存樉绀烘帶浠剁殑瀹瑰櫒鍙ユ焺</param>
+        /// <returns>杩斿洖PCL鏄剧ず瀹炰緥鍙ユ焺</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "CreatePCLWindow")]
+        public static extern IntPtr CreatePCLWindow(IntPtr hWnd);
+
+        //PCLAPI(void) DestroyPCLWindow(void* pInstance);
+        /// <summary>
+        /// 閿�姣丳CL鏄剧ず瀹炰緥锛屾棤杩斿洖鍊�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "DestroyPCLWindow")]
+        public static extern void DestroyPCLWindow(IntPtr pInstance);
+
+        //PCLAPI(void) ShowPCLWindow(void* pInstance);
+        /// <summary>
+        /// 鏄剧ずPCL瀹炰緥绐楀彛锛屾棤杩斿洖鍊硷紙涓嶄娇鐢級
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "ShowPCLWindow")]
+        public static extern void ShowPCLWindow(IntPtr pInstance);
+
+        //PCLAPI(void) HidePCLWindow(void* pInstance);
+        /// <summary>
+        /// 闅愯棌PCL瀹炰緥绐楀彛锛屾棤杩斿洖鍊硷紙涓嶄娇鐢級
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "HidePCLWindow")]
+        public static extern void HidePCLWindow(IntPtr pInstance);
+
+        //PCLAPI(int) LoadPointsFromFile(void* pInstance, const char* szFilename);
+        /// <summary>
+        /// 鎵撳紑鐐逛簯鏂囦欢锛屼互pcd銆乸ly鎴朿sv涓烘墿灞曞悕锛屽姞杞芥垚鍔熻繑鍥炵偣鐨勪釜鏁帮紙涓嶅皬浜�0锛夈��
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="szFilename">寰呮墦寮�鐨勬枃浠跺悕</param>
+        /// <returns>杩斿洖鎵撳紑鐨勬枃浠朵腑鍖呭惈鐨勭偣鐨勪釜鏁�</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "LoadPointsFromFile")]
+        public static extern int LoadPointsFromFile(IntPtr pInstance, byte[] szFilename);
+
+        //PCLAPI(int) SavePointsToFile(void* pInstance, const char* szFilename);
+        /// <summary>
+        /// 瀛樺偍鐐逛簯鏂囦欢锛屼互pcd銆乸ly鎴朿sv涓烘墿灞曞悕锛屼繚瀛樻垚鍔熻繑鍥炵偣鐨勪釜鏁帮紙涓嶅皬浜�0锛夈��
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="szFilename">寰呬繚瀛樼殑鏂囦欢鍚�</param>
+        /// <returns>杩斿洖淇濆瓨鐨勬枃浠朵腑鍖呭惈鐨勭偣鐨勪釜鏁�</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "SavePointsToFile")]
+        public static extern int SavePointsToFile(IntPtr pInstance, byte[] szFilename);
+
+        //        /***********************************************************************
+        //        * 涓嶄娇鐢�
+        //        ************************************************************************/
+        //        PCLAPI(int) PointCloudToMemery(void* pInstance, unsigned char** buffer, unsigned int* size);
+
+        //        /***********************************************************************
+        //        * 涓嶄娇鐢�
+        //        ************************************************************************/
+        //        PCLAPI(int) MemeryToPointCloud(void* pInstance, unsigned char** buffer, unsigned int* size);
+
+        //        /***********************************************************************
+        //        * 涓嶄娇鐢�
+        //        ************************************************************************/
+        //        PCLAPI(int) PointCloudToArray(void* pInstance, void* PointsArray);
+
+        //        /***********************************************************************
+        //        * 涓嶄娇鐢�
+        //        ************************************************************************/
+        //        PCLAPI(int) ArrayToPointCloud(void* pInstance, void* PointsArray);
+
+        //PCLAPI(int) AddZPoints(void* pInstance, LBPointZ* points, int nCount);
+        /// <summary>
+        /// 鍚戠偣浜戝疄渚嬪鍔犳暟鎹偣锛屽け璐ヨ繑鍥�-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="points">鍖呭惈Z淇℃伅鐨勭偣鏁版嵁, LBPointZ* points</param>
+        /// <param name="nCount">鐐圭殑鏁伴噺</param>
+        /// <returns>澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddZPoints")]
+        public static extern int AddZPoints(IntPtr pInstance, IntPtr points, int nCount);
+
+        //PCLAPI(int) AddXZPoints(void* pInstance, LBPointXZ* points, int nCount);
+        /// <summary>
+        /// 鍚戠偣浜戝疄渚嬪鍔犳暟鎹偣锛屽け璐ヨ繑鍥�-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="points">鍖呭惈X鍜孼淇℃伅鐨勭偣鏁版嵁, LBPointXZ* points</param>
+        /// <param name="nCount">鐐圭殑鏁伴噺</param>
+        /// <returns>澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddXZPoints")]
+        public static extern int AddXZPoints(IntPtr pInstance, IntPtr points, int nCount);
+
+        //PCLAPI(int) AddZAPoints(void* pInstance, LBPointZA* points, int nCount, float fStepX, float fStepY, int nDownSample);
+        /// <summary>
+        /// 鍚戠偣浜戝疄渚嬪鍔犳暟鎹偣锛屽け璐ヨ繑鍥�-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="points">鍖呭惈娣卞害(Z)鍜屽己搴�(A)淇℃伅鐨勭偣鏁版嵁, LBPointZA* points</param>
+        /// <param name="nCount">鐐圭殑鏁伴噺</param>
+        /// <param name="fStepX">x鍒嗚鲸鐜�</param>
+        /// <param name="fStepY">y鍒嗚鲸鐜�</param>
+        /// <param name="nDownSample">闄嶉噰鏍峰�嶆暟</param>
+        /// <returns>澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddZAPoints")]
+        public static extern int AddZAPoints(IntPtr pInstance, IntPtr points, int nCount, float fStepX, float fStepY, int nDownSample);
+
+        //PCLAPI(int) AddXYZPoints(void* pInstance, LBPointXYZ* points, int nCount);
+        /// <summary>
+        /// 鍚戠偣浜戝疄渚嬪鍔犳暟鎹偣锛屽け璐ヨ繑鍥�-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="points">鍖呭惈X銆乊鍜孼淇℃伅鐨勭偣鏁版嵁, LBPointXYZ* points</param>
+        /// <param name="nCount">鐐圭殑鏁伴噺</param>
+        /// <returns>澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddXYZPoints")]
+        public static extern int AddXYZPoints(IntPtr pInstance, IntPtr points, int nCount);
+
+        //PCLAPI(int) AddXYZBGRAPoints(void* pInstance, LBPointXYZBGRA* points, int nCount);
+        /// <summary>
+        /// 鍚戠偣浜戝疄渚嬪鍔犳暟鎹偣锛屽け璐ヨ繑鍥�-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="points">鍖呭惈X銆乊鍜孼浠ュ強B銆丟銆丷鍜孉淇℃伅鐨勭偣鏁版嵁, LBPointXYZBGRA* points</param>
+        /// <param name="nCount">鐐圭殑鏁伴噺</param>
+        /// <returns>澶辫触杩斿洖-1锛屽惁鍒欒繑鍥炲綋鍓嶇偣浜戜腑鐐圭殑涓暟锛堜笉灏忎簬0锛夈��</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "AddXYZBGRAPoints")]
+        public static extern int AddXYZBGRAPoints(IntPtr pInstance, IntPtr points, int nCount);
+
+        //PCLAPI(int) ClearPCLPoints(void* pInstance);
+        /// <summary>
+        /// 娓呴櫎鐐逛簯瀹炰緥澧炲姞鏁版嵁鐐瑰唴閮ㄦ暟鎹偣
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <returns>澶辫触杩斿洖0锛屾垚鍔熻繑鍥�1銆�</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "ClearPCLPoints")]
+        public static extern int ClearPCLPoints(IntPtr pInstance);
+
+        //PCLAPI(int) UpdatePCLPointColors(void* pInstance, const char* szColoring = "z");
+        /// <summary>
+        /// 鏇存柊PCL鐐逛簯鏁版嵁鏄剧ず鐨勯鑹�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="szColoring">W,B,r,g,b,x,y,z 瀵瑰簲浜庣櫧榛戠孩缁胯摑鍜寈yz涓夎酱</param>
+        /// <returns>澶辫触杩斿洖0锛屾垚鍔熻繑鍥�1銆�</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "UpdatePCLPointColors", CharSet = CharSet.Ansi)]
+        public static extern int UpdatePCLPointColors(IntPtr pInstance, string szColoring = "z");
+
+        //PCLAPI(int) GetPointCloudBound(void* pInstance, double* pMin, double* pMax);
+        /// <summary>
+        /// 鑾峰彇PCL鐐逛簯鏁版嵁鐨勮寖鍥�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="pMin">杩斿洖鏈�灏忓��</param>
+        /// <param name="pMax">杩斿洖鏈�澶у��</param>
+        /// <returns>澶辫触杩斿洖0锛屾垚鍔熻繑鍥�1銆�</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetPointCloudBound")]
+        public static extern int GetPointCloudBound(IntPtr pInstance, ref double pMin, ref double pMax);
+
+        //PCLAPI(int) SetPointCloudBound(void* pInstance, double* pMin, double* pMax);
+        /// <summary>
+        /// 璁剧疆PCL鐐逛簯鏁版嵁鐨勮寖鍥�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="pMin">杈撳叆鏈�灏忓��, double* pMin</param>
+        /// <param name="pMax">杈撳叆鏈�澶у��, double* pMax</param>
+        /// <returns>澶辫触杩斿洖0锛屾垚鍔熻繑鍥�1銆�</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetPointCloudBound")]
+        public static extern int SetPointCloudBound(IntPtr pInstance, IntPtr pMin, IntPtr pMax);
+
+        //PCLAPI(int) ResizePCLWindow(void* pInstance, int nWidth, int nHeight);
+        /// <summary>
+        /// 璋冩暣鏄剧ず鐐逛簯绐楀彛鐨勫ぇ灏�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="nWidth">绐楀彛瀹藉害</param>
+        /// <param name="nHeight">绐楀彛楂樺害</param>
+        /// <returns>澶辫触杩斿洖0锛屾垚鍔熻繑鍥�1銆�</returns>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "ResizePCLWindow")]
+        public static extern int ResizePCLWindow(IntPtr pInstance, int nWidth, int nHeight);
+
+        //PCLAPI(void) RenderPCLWindow(void* pInstance, int nWidth, int nHeight);
+        /// <summary>
+        /// 娓叉煋鐐逛簯绐楀彛锛屾棤杩斿洖
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="nWidth">绐楀彛瀹藉害</param>
+        /// <param name="nHeight">绐楀彛楂樺害</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "RenderPCLWindow")]
+        public static extern void RenderPCLWindow(IntPtr pInstance, int nWidth, int nHeight);
+
+        //PCLAPI(void) ShowCubeAxes(void* pInstance, int bInit = 0);
+        /// <summary>
+        /// 鏄剧ず姝f柟浣撳潗鏍囩郴锛屾棤杩斿洖
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="bInit">鏄惁鍒濆鍖�</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "ShowCubeAxes")]
+        public static extern void ShowCubeAxes(IntPtr pInstance, int bInit = 0);
+
+        //PCLAPI(void) HideCubeAxes(void* pInstance);
+        /// <summary>
+        /// 闅愯棌姝f柟浣撳潗鏍囩郴锛屾棤杩斿洖
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "HideCubeAxes")]
+        public static extern void HideCubeAxes(IntPtr pInstance);
+
+        //PCLAPI(void) ShowAxes(void* pInstance);
+        /// <summary>
+        /// 鍦ㄥ乏涓嬭鏄剧ず鍧愭爣绯伙紝鏃犺繑鍥�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "ShowAxes")]
+        public static extern void ShowAxes(IntPtr pInstance);
+
+        //PCLAPI(void) HideAxes(void* pInstance);
+        /// <summary>
+        /// 闅愯棌鍦ㄥ乏涓嬭鍧愭爣绯伙紝鏃犺繑鍥�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "HideAxes")]
+        public static extern void HideAxes(IntPtr pInstance);
+
+        //PCLAPI(void) ShowLookUpTable(void* pInstance, double x = 0.9, double y = 0.0, double xWide = 0.08, double yWide = 0.35);
+        /// <summary>
+        /// 鏄剧ず棰滆壊琛�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="x">鏄剧ず浣嶇疆锛屾暟鍊兼槸涓庣獥鍙e搴︾殑姣斿��</param>
+        /// <param name="y">鏄剧ず浣嶇疆锛屾暟鍊兼槸涓庣獥鍙i珮搴︾殑姣斿��</param>
+        /// <param name="xWide">姘村钩瀹藉害锛屾暟鍊兼槸涓庣獥鍙e搴︾殑姣斿��</param>
+        /// <param name="yWide">鍨傜洿瀹藉害锛屾暟鍊兼槸涓庣獥鍙i珮搴︾殑姣斿��</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "ShowLookUpTable")]
+        public static extern void ShowLookUpTable(IntPtr pInstance, double x = 0.9, double y = 0.0, double xWide = 0.08, double yWide = 0.35);
+
+        //PCLAPI(void) HideLookUpTable(void* pInstance);
+        /// <summary>
+        /// 闅愯棌棰滆壊琛紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "HideLookUpTable")]
+        public static extern void HideLookUpTable(IntPtr pInstance);
+
+        //PCLAPI(void) SetLookUpTableRange(void* pInstance, double fMin, double fMax);
+        /// <summary>
+        /// 璁剧疆棰滆壊琛ㄨ寖鍥达紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="fMin">鏈�灏忓��</param>
+        /// <param name="fMax">鏈�澶у��</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "SetLookUpTableRange")]
+        public static extern void SetLookUpTableRange(IntPtr pInstance, double fMin, double fMax);
+
+        //PCLAPI(void) InsertBox(void* pInstance);
+        /// <summary>
+        /// 鎻掑叆鐩掑瓙锛屾棤杩斿洖鍊�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "InsertBox")]
+        public static extern void InsertBox(IntPtr pInstance);
+
+        //PCLAPI(void) InsertSphere(void* pInstance);
+        /// <summary>
+        /// 鎻掑叆鐞冧綋锛屾棤杩斿洖鍊�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "InsertSphere")]
+        public static extern void InsertSphere(IntPtr pInstance);
+
+        //PCLAPI(void) InsertRule(void* pInstance);
+        /// <summary>
+        /// 鎻掑叆鏍囧昂锛屾棤杩斿洖鍊�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "InsertRule")]
+        public static extern void InsertRule(IntPtr pInstance);
+
+        //PCLAPI(void) InsertPlane(void* pInstance);
+        /// <summary>
+        /// 鎻掑叆骞抽潰锛屾棤杩斿洖鍊�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "InsertPlane")]
+        public static extern void InsertPlane(IntPtr pInstance);
+
+        //PCLAPI(void) InsertText(void* pInstance, char* szText);
+        /// <summary>
+        /// 鎻掑叆鏂囧瓧锛屾棤杩斿洖鍊�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="szText">鎻掑叆鏂囧瓧</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "InsertText", CharSet = CharSet.Ansi)]
+        public static extern void InsertText(IntPtr pInstance, string szText);
+
+        //PCLAPI(void) DeleteWidget(void* pInstance);
+        /// <summary>
+        /// 鍒犻櫎閮ㄤ欢锛岀洅瀛愩�佺悆浣撶瓑閮芥槸閮ㄤ欢锛屾棤杩斿洖鍊�
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "DeleteWidget")]
+        public static extern void DeleteWidget(IntPtr pInstance);
+
+        //PCLAPI(void) RegisterShowParameter(void* pInstance, ShowParameterCallback callback);
+        /// <summary>
+        /// 娉ㄥ唽鏄剧ず鍙傛暟鐨勫嚱鏁帮紝鏃犺繑鍥炲��
+        /// </summary>
+        /// <param name="pInstance">PCL鏄剧ず瀹炰緥鍙ユ焺</param>
+        /// <param name="callback">寰呮敞鍐岀殑鍥炶皟鍑芥暟</param>
+        [DllImport("PointCloud3D", CallingConvention = CallingConvention.StdCall, EntryPoint = "RegisterShowParameter")]
+        public static extern void RegisterShowParameter(IntPtr pInstance, ShowParameterCallback callback);
+    }
+}
diff --git a/LB_SmartVisionCameraSDK/ref/PHM6000.dll b/LB_SmartVisionCameraSDK/ref/PHM6000.dll
new file mode 100644
index 0000000..63d2d22
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/ref/PHM6000.dll
Binary files differ
diff --git a/LB_SmartVisionCameraSDK/ref/PHM6000API.dll b/LB_SmartVisionCameraSDK/ref/PHM6000API.dll
new file mode 100644
index 0000000..f523ffd
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/ref/PHM6000API.dll
Binary files differ
diff --git a/LB_SmartVisionCameraSDK/ref/PHM6000API.lib b/LB_SmartVisionCameraSDK/ref/PHM6000API.lib
new file mode 100644
index 0000000..1f69ed5
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/ref/PHM6000API.lib
Binary files differ
diff --git a/LB_SmartVisionCameraSDK/ref/Pilot2D.dll b/LB_SmartVisionCameraSDK/ref/Pilot2D.dll
new file mode 100644
index 0000000..8d9ed88
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/ref/Pilot2D.dll
Binary files differ
diff --git a/LB_SmartVisionCameraSDK/ref/PointCloud3D.dll b/LB_SmartVisionCameraSDK/ref/PointCloud3D.dll
new file mode 100644
index 0000000..af08044
--- /dev/null
+++ b/LB_SmartVisionCameraSDK/ref/PointCloud3D.dll
Binary files differ
diff --git a/LB_SmartVisionCommon/AESHelper.cs b/LB_SmartVisionCommon/AESHelper.cs
new file mode 100644
index 0000000..9b35afe
--- /dev/null
+++ b/LB_SmartVisionCommon/AESHelper.cs
@@ -0,0 +1,62 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    /// <summary>
+    /// AES鍔犲瘑/瑙e瘑
+    /// </summary>
+    public class AESHelper
+    {
+        private static readonly byte[] Key = Encoding.UTF8.GetBytes("SHANGHAILANBAOSHANGHAILANBAO1234"); // 32瀛楄妭
+        private static readonly byte[] IV = Encoding.UTF8.GetBytes("LANBAO1234567890"); // 16瀛楄妭
+        /// <summary>
+        /// AES鍔犲瘑
+        /// </summary>
+        /// <param name="plainText">寰呭姞瀵嗘枃瀛�</param>
+        /// <returns>鍔犲瘑鍚庢枃瀛�</returns>
+        public static string Encrypt(string plainText)
+        {
+            using (Aes aes = Aes.Create())
+            {
+                aes.Key = Key;
+                aes.IV = IV;
+                ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
+                using (MemoryStream ms = new MemoryStream())
+                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
+                {
+                    using (StreamWriter sw = new StreamWriter(cs))
+                    {
+                        sw.Write(plainText);
+                    }
+                    return Convert.ToBase64String(ms.ToArray());
+                }
+            }
+        }
+
+        /// <summary>
+        /// AES瑙e瘑
+        /// </summary>
+        /// <param name="cipherText">寰呰В瀵嗘枃瀛�</param>
+        /// <returns>瑙e瘑鍚庢枃瀛�</returns>
+        public static string Decrypt(string cipherText)
+        {
+            using (Aes aes = Aes.Create())
+            {
+                aes.Key = Key;
+                aes.IV = IV;
+                ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
+                using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(cipherText)))
+                using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
+                using (StreamReader sr = new StreamReader(cs))
+                {
+                    return sr.ReadToEnd();
+                }
+            }
+        }
+    }
+}
diff --git a/LB_SmartVisionCommon/AsyncLogHelper.cs b/LB_SmartVisionCommon/AsyncLogHelper.cs
new file mode 100644
index 0000000..6eb14e0
--- /dev/null
+++ b/LB_SmartVisionCommon/AsyncLogHelper.cs
@@ -0,0 +1,177 @@
+锘縰sing log4net;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    /// <summary>
+    /// 寮傛璁板綍鏃ュ織绫�
+    /// </summary>
+    public static class AsyncLogHelper
+    {
+        private static readonly BlockingCollection<LogItem> _logQueue = new BlockingCollection<LogItem>(2000);
+        private static readonly Task _backgroundTask;
+        private static readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
+
+        static string LineT = "璁板綍淇℃伅锛�";
+        static readonly ILog _logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+
+        static AsyncLogHelper()
+        {
+            // 鍚姩鍚庡彴鏃ュ織澶勭悊浠诲姟
+            _backgroundTask = Task.Factory.StartNew(
+                ProcessLogQueue,
+                _cancellationTokenSource.Token,
+                TaskCreationOptions.LongRunning,
+                TaskScheduler.Default);
+
+            // 娉ㄥ唽搴旂敤绋嬪簭閫�鍑烘椂鐨勬竻鐞�
+            AppDomain.CurrentDomain.ProcessExit += (s, e) => Dispose();
+            AppDomain.CurrentDomain.DomainUnload += (s, e) => Dispose();
+        }
+
+        /// <summary>
+        /// Info绫诲瀷 - 寮傛璁板綍
+        /// </summary>
+        public static void Info(string message)
+        {
+            EnqueueLog(LogLevel.Info, message);
+        }
+
+        /// <summary>
+        /// Debug绫诲瀷 - 寮傛璁板綍
+        /// </summary>
+        public static void Debug(string message)
+        {
+            EnqueueLog(LogLevel.Debug, message);
+        }
+
+        /// <summary>
+        /// Warn绫诲瀷 - 寮傛璁板綍
+        /// </summary>
+        public static void Warn(string message)
+        {
+            EnqueueLog(LogLevel.Warn, message);
+        }
+
+        /// <summary>
+        /// Error绫诲瀷 - 寮傛璁板綍
+        /// </summary>
+        public static void Error(string message)
+        {
+            EnqueueLog(LogLevel.Error, message);
+        }
+
+        /// <summary>
+        /// Error绫诲瀷 - 寮傛璁板綍寮傚父
+        /// </summary>
+        public static void Error(string message, Exception exception)
+        {
+            EnqueueLog(LogLevel.Error, message, exception);
+        }
+
+        private static void EnqueueLog(LogLevel level, string message, Exception exception = null)
+        {
+            if (!_logQueue.IsAddingCompleted)
+            {
+                var logItem = new LogItem
+                {
+                    Level = level,
+                    Message = LineT + message,
+                    Exception = exception,
+                    Timestamp = DateTime.Now
+                };
+
+                // 濡傛灉闃熷垪宸叉弧锛岀瓑寰呬竴娈垫椂闂�
+                if (!_logQueue.TryAdd(logItem, 100))
+                {
+                    // 闃熷垪婊℃椂鐨勯檷绾у鐞嗭細鍚屾璁板綍鎴栦涪寮�
+                    try
+                    {
+                        WriteLogSync(logItem);
+                    }
+                    catch
+                    {
+                        // 蹇界暐鍚屾璁板綍鏃剁殑寮傚父
+                    }
+                }
+            }
+        }
+
+        private static void ProcessLogQueue()
+        {
+            foreach (var logItem in _logQueue.GetConsumingEnumerable(_cancellationTokenSource.Token))
+            {
+                try
+                {
+                    WriteLogSync(logItem);
+                }
+                catch (Exception ex)
+                {
+                    System.Diagnostics.Debug.WriteLine($"寮傛鏃ュ織璁板綍澶辫触: {ex.Message}");
+                }
+            }
+        }
+
+        private static void WriteLogSync(LogItem logItem)
+        {
+            switch (logItem.Level)
+            {
+                case LogLevel.Debug:
+                    _logger.Debug(logItem.Message, logItem.Exception);
+                    break;
+                case LogLevel.Info:
+                    _logger.Info(logItem.Message, logItem.Exception);
+                    break;
+                case LogLevel.Warn:
+                    _logger.Warn(logItem.Message, logItem.Exception);
+                    break;
+                case LogLevel.Error:
+                    _logger.Error(logItem.Message, logItem.Exception);
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// 閲婃斁璧勬簮锛岀‘淇濇墍鏈夋棩蹇楅兘琚鐞�
+        /// </summary>
+        public static void Dispose()
+        {
+            try
+            {
+                _logQueue.CompleteAdding();
+                _cancellationTokenSource.CancelAfter(5000); // 5绉掑悗寮哄埗鍙栨秷
+
+                // 绛夊緟浠诲姟瀹屾垚锛屾渶澶氱瓑寰�10绉�
+                if (!_backgroundTask.Wait(10000))
+                {
+                    System.Diagnostics.Debug.WriteLine("鏃ュ織浠诲姟鏈湪瓒呮椂鏃堕棿鍐呭畬鎴�");
+                }
+            }
+            catch (Exception ex)
+            {
+                System.Diagnostics.Debug.WriteLine($"閲婃斁鏃ュ織璧勬簮鏃跺嚭閿�: {ex.Message}");
+            }
+        }
+    }
+
+    internal enum LogLevel
+    {
+        Debug,
+        Info,
+        Warn,
+        Error
+    }
+
+    internal class LogItem
+    {
+        public LogLevel Level { get; set; }
+        public string Message { get; set; }
+        public Exception Exception { get; set; }
+        public DateTime Timestamp { get; set; }
+    }
+}
diff --git a/LB_SmartVisionCommon/CommonVar.cs b/LB_SmartVisionCommon/CommonVar.cs
new file mode 100644
index 0000000..7b0483f
--- /dev/null
+++ b/LB_SmartVisionCommon/CommonVar.cs
@@ -0,0 +1,18 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    public static class CommonVar
+    {
+        public const uint WM_RENDER_VTK = 50276;
+        // 澹版槑 Windows API 鍑芥暟
+        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        public static extern uint RegisterWindowMessage(string lpString);
+
+    }
+}
diff --git a/LB_SmartVisionCommon/ConfigManager.cs b/LB_SmartVisionCommon/ConfigManager.cs
new file mode 100644
index 0000000..9815212
--- /dev/null
+++ b/LB_SmartVisionCommon/ConfigManager.cs
@@ -0,0 +1,44 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    /// <summary>
+    /// T绫诲瀷-JSON--Serialize鍜孌eserialize
+    /// </summary>
+    /// <typeparam name="T">T绫诲瀷</typeparam>
+    public static class ConfigManager<T>
+    {
+        /// <summary>
+        /// 淇濆瓨閰嶇疆
+        /// </summary>
+        /// <typeparam name="T">T绫诲瀷</typeparam>
+        /// <param name="config">T绫诲瀷鐨勫��</param>
+        /// <param name="filePath">鏂囦欢瀛樺偍璺緞浠ュ強鍚嶇О</param>
+        public static void SaveConfig<T>(T config, string filePath)
+        {
+            var json = JsonConvert.SerializeObject(config, Newtonsoft.Json.Formatting.Indented);
+            File.WriteAllText(filePath, json);
+        }
+        /// <summary>
+        /// 鍔犺浇閰嶇疆鏂囦欢
+        /// </summary>
+        /// <typeparam name="T">T绫诲瀷</typeparam>
+        /// <param name="filePath">鏂囦欢瀛樺偍璺緞浠ュ強鍚嶇О</param>
+        /// <returns>T绫诲瀷鐨勫��</returns>
+        public static T LoadConfig<T>(string filePath) where T : new()
+        {
+            if (!File.Exists(filePath))
+            {
+                return new T();
+            }
+
+            var json = File.ReadAllText(filePath);
+            return JsonConvert.DeserializeObject<T>(json);
+        }
+    }
+}
diff --git a/LB_SmartVisionCommon/DiskInfoHelper.cs b/LB_SmartVisionCommon/DiskInfoHelper.cs
new file mode 100644
index 0000000..dd9fd44
--- /dev/null
+++ b/LB_SmartVisionCommon/DiskInfoHelper.cs
@@ -0,0 +1,49 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    public class DiskInfoHelper
+    {
+        public static double GetFreeSpaceGB(string driveName)
+        {
+            try
+            {
+                DriveInfo drive = new DriveInfo(driveName);
+                return drive.IsReady ? Math.Round((double)drive.AvailableFreeSpace / (1024 * 1024 * 1024), 2) : -1;
+            }
+            catch
+            {
+                return -1;
+            }
+        }
+
+        public static Dictionary<string, object> GetDiskDetails(string driveName)
+        {
+            var result = new Dictionary<string, object>();
+
+            try
+            {
+                DriveInfo drive = new DriveInfo(driveName);
+
+                if (drive.IsReady)
+                {
+                    result["DriveName"] = drive.Name;
+                    result["TotalSizeGB"] = Math.Round((double)drive.TotalSize / (1024 * 1024 * 1024), 2);
+                    result["FreeSpaceGB"] = Math.Round((double)drive.AvailableFreeSpace / (1024 * 1024 * 1024), 2);
+                    result["DriveFormat"] = drive.DriveFormat;
+                    result["DriveType"] = drive.DriveType.ToString();
+                }
+            }
+            catch (Exception ex)
+            {
+                result["Error"] = ex.Message;
+            }
+
+            return result;
+        }
+    }
+}
diff --git a/LB_SmartVisionCommon/DynamicPermissionObject.cs b/LB_SmartVisionCommon/DynamicPermissionObject.cs
new file mode 100644
index 0000000..460cb3d
--- /dev/null
+++ b/LB_SmartVisionCommon/DynamicPermissionObject.cs
@@ -0,0 +1,197 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Security.Permissions;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    /// <summary>
+    /// 鍔ㄦ�佹潈闄愬璞″寘瑁呭櫒
+    /// </summary>
+    public class DynamicPermissionObject : ICustomTypeDescriptor
+    {
+        private readonly object _target;
+        private readonly object _currentRole;
+        private readonly Type _roleType;
+        private readonly object[] _roles;
+
+        /// <summary>
+        /// 鍔ㄦ�佹潈闄愬璞★紝鍙互鎺ュ彈澶氫釜瑙掕壊
+        /// </summary>
+        /// <param name="target">鐩爣</param>
+        /// <param name="roles">瑙掕壊</param>
+        /// <exception cref="ArgumentException">寮傚父淇℃伅</exception>
+        public DynamicPermissionObject(object target, params object[] roles)
+        {
+            _target = target;
+            _roles = roles;
+
+            // 楠岃瘉鎵�鏈夎鑹查兘鏄灇涓剧被鍨�
+            foreach (var role in _roles)
+            {
+                if (role != null && !role.GetType().IsEnum)
+                    throw new ArgumentException("鎵�鏈夎鑹插繀椤绘槸鏋氫妇鍊�", nameof(roles));
+            }
+        }
+
+        /// <summary>
+        /// 鍦ㄥ睘鎬ц繃婊ゆ椂妫�鏌ユ墍鏈夎鑹�
+        /// </summary>
+        /// <param name="attr">鏉冮檺灞炴��</param>
+        /// <returns>楂樻槸true,浣庢槸false</returns>
+        private bool CheckPermissions(PermissionAttribute attr)
+        {
+            foreach (var role in _roles)
+            {
+                if (role != null && role.GetType() == attr.RoleType)
+                {
+                    int roleValue = (int)Convert.ChangeType(role, typeof(int));
+                    int requiredValue = (int)Convert.ChangeType(attr.MinimumRole, typeof(int));
+
+                    if (roleValue >= requiredValue)
+                        return true;
+                }
+            }
+            return false;
+        }
+        /// <summary>
+        /// 鍔ㄦ�佹潈闄愬璞★紝鍗曚釜瑙掕壊
+        /// </summary>
+        /// <param name="target">鐩爣</param>
+        /// <param name="currentRole">褰撳墠瑙掕壊</param>
+        /// <exception cref="ArgumentException">寮傚父淇℃伅</exception>
+
+        public DynamicPermissionObject(object target, object currentRole)
+        {
+            _target = target;
+            _currentRole = currentRole;
+
+            if (currentRole != null)
+                _roleType = currentRole.GetType();
+
+            if (!_roleType.IsEnum)
+                throw new ArgumentException("currentRole 蹇呴』鏄灇涓惧��", nameof(currentRole));
+        }
+        /// <summary>
+        /// 鑾峰彇灞炴�ф弿杩扮闆嗗悎
+        /// </summary>
+        /// <returns>杩斿洖灞炴�ф弿杩扮闆嗗悎</returns>
+        public PropertyDescriptorCollection GetProperties()
+        {
+            return GetProperties(null);
+        }
+        /// <summary>
+        /// 鑾峰彇灞炴�ф弿杩扮闆嗗悎
+        /// </summary>
+        /// <param name="attributes">鑷畾涔夊睘鎬ч泦鍚�</param>
+        /// <returns>杩斿洖灞炴�ф弿杩扮闆嗗悎</returns>
+        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
+        {
+            var originalProperties = TypeDescriptor.GetProperties(_target, attributes, true);
+            var filteredProperties = new List<PropertyDescriptor>();
+            foreach (PropertyDescriptor pd in originalProperties)
+            {
+                var attrs = pd.Attributes.OfType<PermissionAttribute>().ToArray();
+                bool hasPermission = true;
+                bool isReadOnly = false;
+                // 妫�鏌ユ墍鏈夋潈闄愮壒鎬�
+                foreach (var attr in attrs)
+                {
+                    // 鍙鐞嗕笌褰撳墠瑙掕壊绫诲瀷鍖归厤鐨勭壒鎬�
+                    if (attr.RoleType == _roleType)
+                    {
+                        if (!HasPermission(attr.MinimumRole))
+                        {
+                            hasPermission = false;
+                            break;
+                        }
+                        else
+                        {
+                            // 鏈夋潈闄愪絾鍙兘鍙
+                            isReadOnly = !HasPermission(attr.MinimumRole);
+                        }
+                    }
+                }
+                if (hasPermission)
+                {
+                    filteredProperties.Add(new PermissionPropertyDescriptor(pd, isReadOnly));
+                }
+            }
+            return new PropertyDescriptorCollection(filteredProperties.ToArray());
+        }
+        /// <summary>
+        /// 鏉冮檺妫�娴�
+        /// </summary>
+        /// <param name="requiredRole">妫�娴嬭鑹�</param>
+        /// <returns>鏄惁鏈夋潈闄�</returns>
+        private bool HasPermission(object requiredRole)
+        {
+            if (_currentRole == null)
+            {
+                return false;
+            }
+            // 灏嗘灇涓惧�艰浆鎹负鏁存暟杩涜姣旇緝
+            int currentRoleValue = (int)Convert.ChangeType(_currentRole, typeof(int));
+            int requiredRoleValue = (int)Convert.ChangeType(requiredRole, typeof(int));
+            return currentRoleValue >= requiredRoleValue;
+        }
+
+        // ICustomTypeDescriptor 鐨勫叾浠栨柟娉曞疄鐜�...
+        /// <summary>
+        /// 鑾峰彇灞炴��
+        /// </summary>
+        /// <returns>杩斿洖灞炴�ч泦鍚�</returns>
+        public AttributeCollection GetAttributes() => TypeDescriptor.GetAttributes(_target);
+        /// <summary>
+        /// 鑾峰彇绫诲悕绉�
+        /// </summary>
+        /// <returns>杩斿洖绫诲悕绉�</returns>
+        public string GetClassName() => TypeDescriptor.GetClassName(_target);
+        /// <summary>
+        /// 鑾峰彇缁勪欢鍚嶇О
+        /// </summary>
+        /// <returns>杩斿洖鑾峰彇缁勪欢鍚嶇О</returns>
+        public string GetComponentName() => TypeDescriptor.GetComponentName(_target);
+        /// <summary>
+        /// 鑾峰彇杞崲
+        /// </summary>
+        /// <returns>杩斿洖瀵瑰簲绫诲瀷鐨勮浆鎹�</returns>
+        public TypeConverter GetConverter() => TypeDescriptor.GetConverter(_target);
+        /// <summary>
+        /// 鑾峰彇榛樿浜嬩欢
+        /// </summary>
+        /// <returns>杩斿洖榛樿浜嬩欢</returns>
+        public EventDescriptor GetDefaultEvent() => TypeDescriptor.GetDefaultEvent(_target);
+        /// <summary>
+        /// 鑾峰彇榛樿灞炴��
+        /// </summary>
+        /// <returns>杩斿洖榛樿灞炴��</returns>
+        public PropertyDescriptor GetDefaultProperty() => TypeDescriptor.GetDefaultProperty(_target);
+        /// <summary>
+        /// 鑾峰彇鎸囧畾缁勪欢鐨勫叿鏈夋寚瀹氬熀绫诲瀷鐨勭紪杈戝櫒
+        /// </summary>
+        /// <param name="editorBaseType">琛ㄧず瑕佹煡鎵剧殑缂栬緫鍣ㄧ殑鍩虹被鍨嬬殑 Type銆�</param>
+        /// <returns>鍙浆鎹负鎸囧畾缂栬緫鍣ㄧ被鍨嬬殑缂栬緫鍣ㄧ殑涓�涓疄渚嬶紝濡傛灉鎵句笉鍒拌姹傜被鍨嬬殑缂栬緫鍣紝鍒欎负 null銆�</returns>
+        public object GetEditor(Type editorBaseType) => TypeDescriptor.GetEditor(_target, editorBaseType);
+        /// <summary>
+        /// 杩斿洖缁勪欢鎴栫被鍨嬬殑浜嬩欢鐨勯泦鍚堛��
+        /// </summary>
+        /// <returns>鍏锋湁姝ょ粍浠剁殑浜嬩欢鐨� EventDescriptorCollection銆�</returns>
+        public EventDescriptorCollection GetEvents() => TypeDescriptor.GetEvents(_target);
+        /// <summary>
+        /// 杩斿洖缁勪欢鎴栫被鍨嬬殑浜嬩欢鐨勯泦鍚堛��
+        /// </summary>
+        /// <param name="attributes">鍙互鐢ㄤ綔绛涢�夊櫒鐨勭被鍨� Attribute 鐨勬暟缁勩��</param>
+        /// <returns>鍏锋湁鍖归厤姝ょ粍浠舵寚瀹氬睘鎬х殑浜嬩欢鐨� EventDescriptorCollection銆�</returns>
+        public EventDescriptorCollection GetEvents(Attribute[] attributes) => TypeDescriptor.GetEvents(_target, attributes);
+        /// <summary>
+        /// 杩斿洖涓�涓璞★紝璇ュ璞″寘鍚寚瀹氱殑灞炴�ф弿杩扮鎵�鎻忚堪鐨勫睘鎬с��
+        /// </summary>
+        /// <param name="pd">瑕佹绱㈠叾鎵�灞炲璞$殑灞炴�ф弿杩扮銆�</param>
+        /// <returns>涓�涓� Object锛屾嫢鏈夎绫诲瀷璇存槑绗︽寚瀹氱殑缁欏畾灞炴�с�� 榛樿鍊间负 null銆�</returns>
+        public object GetPropertyOwner(PropertyDescriptor pd) => _target;
+    }
+}
diff --git a/LB_SmartVisionCommon/DynamicPropertyDescriptor.cs b/LB_SmartVisionCommon/DynamicPropertyDescriptor.cs
new file mode 100644
index 0000000..047f5eb
--- /dev/null
+++ b/LB_SmartVisionCommon/DynamicPropertyDescriptor.cs
@@ -0,0 +1,70 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    /// <summary>
+    /// 鍔ㄦ�佸睘鎬ф弿杩扮
+    /// </summary>
+    public class DynamicPropertyDescriptor : PropertyDescriptor
+    {
+        private readonly PropertyDescriptor _original;
+        private readonly bool _isReadOnly;
+        /// <summary>
+        /// 鍔ㄦ�佸睘鎬ф弿杩扮
+        /// </summary>
+        /// <param name="original">灞炴�ф弿杩�</param>
+        /// <param name="isReadOnly">鏄惁鍙</param>
+        public DynamicPropertyDescriptor(PropertyDescriptor original, bool isReadOnly)
+            : base(original)
+        {
+            _original = original;
+            _isReadOnly = isReadOnly;
+        }
+        /// <summary>
+        /// 鏄惁鍙
+        /// </summary>
+        public override bool IsReadOnly => _isReadOnly;
+        /// <summary>
+        /// 褰撳墠缁勪欢绫诲瀷
+        /// </summary>
+        public override Type ComponentType => _original.ComponentType;
+        /// <summary>
+        /// 灞炴�х被鍨�
+        /// </summary>
+        public override Type PropertyType => _original.PropertyType;
+        /// <summary>
+        /// 杩斿洖閲嶇疆瀵硅薄鏃舵槸鍚︽洿鏀瑰叾鍊笺��
+        /// </summary>
+        /// <param name="component">瑕佹祴璇曢噸缃姛鑳界殑缁勪欢銆�</param>
+        /// <returns>濡傛灉閲嶇疆缁勪欢鏇存敼鍏跺�硷紝鍒欎负 true锛涘惁鍒欎负 false銆�</returns>
+        public override bool CanResetValue(object component) => _original.CanResetValue(component);
+        /// <summary>
+        /// 杩斿洖缁欏畾瀵硅薄鏀寔鐨勫瓧娈电殑鍊笺��
+        /// </summary>
+        /// <param name="component">灏嗚繑鍥炲叾瀛楁鍊肩殑瀵硅薄銆�</param>
+        /// <returns>涓�涓璞★紝鍖呭惈姝ゅ疄渚嬪弽鏄犵殑瀛楁鐨勫�笺��</returns>
+        public override object GetValue(object component) => _original.GetValue(component);
+        /// <summary>
+        /// 灏嗙粍浠剁殑姝ゅ睘鎬х殑鍊奸噸缃负榛樿鍊笺��
+        /// </summary>
+        /// <param name="component">鍏锋湁瑕侀噸缃负榛樿鍊肩殑灞炴�у�肩殑缁勪欢銆�</param>
+        public override void ResetValue(object component) => _original.ResetValue(component);
+        /// <summary>
+        /// 璁剧疆鎸囧畾瀵硅薄鐨勫睘鎬у�笺��
+        /// </summary>
+        /// <param name="component">灏嗚缃叾灞炴�у�肩殑瀵硅薄銆�</param>
+        /// <param name="value">鏂扮殑灞炴�у�笺��</param>
+        public override void SetValue(object component, object value) => _original.SetValue(component, value);
+        /// <summary>
+        /// 纭畾涓�涓�硷紝璇ュ�兼寚绀烘槸鍚﹂渶瑕佹案涔呬繚瀛樻灞炴�х殑鍊笺��
+        /// </summary>
+        /// <param name="component">鍏锋湁瑕佹鏌ュ叾鎸佷箙鎬х殑灞炴�х殑缁勪欢銆�</param>
+        /// <returns>濡傛灉灞炴�у簲璇ヨ姘镐箙淇濆瓨锛屽垯涓� true锛涘惁鍒欎负 false銆�</returns>
+        public override bool ShouldSerializeValue(object component) => _original.ShouldSerializeValue(component);
+    }
+}
diff --git a/LB_SmartVisionCommon/Fun.cs b/LB_SmartVisionCommon/Fun.cs
new file mode 100644
index 0000000..85d781b
--- /dev/null
+++ b/LB_SmartVisionCommon/Fun.cs
@@ -0,0 +1,59 @@
+锘縰sing LB_SmartVisionCameraSDK.PHM6000;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    public class Fun
+    {
+        public static readonly object waitFormLock = new object();
+        public static readonly object resetLock = new object();
+        public static string GetOrAddDirPath()
+        {
+            var basedir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+            var path = Path.Combine(basedir, "LB_SmartVision");
+            if (!Directory.Exists(path))
+            {
+                Directory.CreateDirectory(path);
+            }
+            return path;
+        }
+
+        public static void SetImageSize_t(IntPtr pHandle, int nWidth, int nHeight) { }
+
+        public static void ClearAllPoints_t(IntPtr pHandle) { }
+
+        public static void RefreshPilot2D_t(IntPtr pHandle) { }
+
+        public static int AddIntensityData_t(IntPtr pHandle, ref LBPointZA points, int nCount) { return default; }
+
+        public static int AddDepthData_t(IntPtr pHandle, ref LBPointZA points, int nCount, short nMinDepth, short nMaxDepth)
+        {
+            return default;
+        }
+
+        //public static int AddBarycentreDataZA_t(IntPtr pHandle, ref LBPointZA points, int nCount, float fMinDistance, float fMaxDistance, float fStdDistance) {
+
+        //    Pilot2D.AddBarycentreDataZA(pHandle,points,nCount,fMinDistance,fMaxDistance,fStdDistance);
+        //}
+
+        public static int ClearPCLPoints_t(IntPtr pInstance) { return default; }
+
+        public static int AddZAPoints_t(IntPtr pInstance, ref LBPointZA points, int nCount, float fStepX, float fStepY, int nDownSample) { return default; }
+
+        public static void RenderPCLWindow_t(IntPtr pInstance, int nWidth, int nHeight) { }
+
+        public static int UpdatePCLPointColors_t(IntPtr pInstance, string szColoring) { return default; }
+
+        public static void ShowCubeAxes_t(IntPtr pInstance, int bInit) { }
+
+        public static void ShowLookUpTable_t(IntPtr pInstance, double x, double y, double xWide, double yWide) { }
+
+        public static int GetPointCloudBound_t(IntPtr pInstance, ref double pMin, ref double pMax) { return default; }
+
+        public static void SetLookUpTableRange_t(IntPtr pInstance, double fMin, double fMax) { }
+    }
+}
diff --git a/LB_SmartVisionCommon/LB_SmartVisionCommon.csproj b/LB_SmartVisionCommon/LB_SmartVisionCommon.csproj
new file mode 100644
index 0000000..bc9e494
--- /dev/null
+++ b/LB_SmartVisionCommon/LB_SmartVisionCommon.csproj
@@ -0,0 +1,20 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Library</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <Nullable>enable</Nullable>
+    <UseWindowsForms>true</UseWindowsForms>
+    <ImplicitUsings>enable</ImplicitUsings>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="log4net" Version="3.2.0" />
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\LB_SmartVisionCameraSDK\LB_SmartVisionCameraSDK.csproj" />
+  </ItemGroup>
+
+</Project>
\ No newline at end of file
diff --git a/LB_SmartVisionCommon/LogHelper.cs b/LB_SmartVisionCommon/LogHelper.cs
new file mode 100644
index 0000000..2f99dd7
--- /dev/null
+++ b/LB_SmartVisionCommon/LogHelper.cs
@@ -0,0 +1,115 @@
+锘縰sing log4net;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    /// <summary>
+    /// 鍚屾璁板綍鏃ュ織绫�
+    /// </summary>
+    public static class LogHelper
+    {
+        static string LineT = "璁板綍淇℃伅锛�";
+        static readonly ILog _logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+
+        /// <summary>
+        /// Info绫诲瀷 - 寮傛璁板綍
+        /// </summary>
+        /// <param name="message">璁板綍淇℃伅</param>
+        public static void Info(string message)
+        {
+            Task.Factory.StartNew(() =>
+            {
+                try
+                {
+                    _logger.Info(LineT + message);
+                }
+                catch (Exception ex)
+                {
+                    // 寮傛鏃ュ織璁板綍澶辫触鏃剁殑澶勭悊
+                    System.Diagnostics.Debug.WriteLine($"鏃ュ織璁板綍澶辫触: {ex.Message}");
+                }
+            }, TaskCreationOptions.LongRunning);
+        }
+
+        /// <summary>
+        /// Debug绫诲瀷 - 寮傛璁板綍
+        /// </summary>
+        /// <param name="message">璁板綍淇℃伅</param>
+        public static void Debug(string message)
+        {
+            Task.Factory.StartNew(() =>
+            {
+                try
+                {
+                    _logger.Debug(LineT + message);
+                }
+                catch (Exception ex)
+                {
+                    System.Diagnostics.Debug.WriteLine($"鏃ュ織璁板綍澶辫触: {ex.Message}");
+                }
+            }, TaskCreationOptions.LongRunning);
+        }
+
+        /// <summary>
+        /// Warn绫诲瀷 - 寮傛璁板綍
+        /// </summary>
+        /// <param name="message">璁板綍淇℃伅</param>
+        public static void Warn(string message)
+        {
+            Task.Factory.StartNew(() =>
+            {
+                try
+                {
+                    _logger.Warn(LineT + message);
+                }
+                catch (Exception ex)
+                {
+                    System.Diagnostics.Debug.WriteLine($"鏃ュ織璁板綍澶辫触: {ex.Message}");
+                }
+            }, TaskCreationOptions.LongRunning);
+        }
+
+        /// <summary>
+        /// Error绫诲瀷 - 寮傛璁板綍
+        /// </summary>
+        /// <param name="message">璁板綍淇℃伅</param>
+        public static void Error(string message)
+        {
+            Task.Factory.StartNew(() =>
+            {
+                try
+                {
+                    _logger.Error(LineT + message);
+                }
+                catch (Exception ex)
+                {
+                    System.Diagnostics.Debug.WriteLine($"鏃ュ織璁板綍澶辫触: {ex.Message}");
+                }
+            }, TaskCreationOptions.LongRunning);
+        }
+
+        /// <summary>
+        /// Error绫诲瀷 - 寮傛璁板綍寮傚父
+        /// </summary>
+        /// <param name="message">璁板綍淇℃伅</param>
+        /// <param name="exception">寮傚父瀵硅薄</param>
+        public static void Error(string message, Exception exception)
+        {
+            Task.Factory.StartNew(() =>
+            {
+                try
+                {
+                    _logger.Error(LineT + message, exception);
+                }
+                catch (Exception ex)
+                {
+                    System.Diagnostics.Debug.WriteLine($"鏃ュ織璁板綍澶辫触: {ex.Message}");
+                }
+            }, TaskCreationOptions.LongRunning);
+        }
+    }
+}
diff --git a/LB_SmartVisionCommon/NetworkDiagnostics.cs b/LB_SmartVisionCommon/NetworkDiagnostics.cs
new file mode 100644
index 0000000..5e6e0f0
--- /dev/null
+++ b/LB_SmartVisionCommon/NetworkDiagnostics.cs
@@ -0,0 +1,117 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.NetworkInformation;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    public class NetworkDiagnostics
+    {
+        public static async Task<NetworkStatus> CheckNetworkStatusAsync(string host = "www.google.com")
+        {
+            var status = new NetworkStatus();
+
+            // 娴嬭瘯Ping
+            status.CanPing = await TestPingAsync(host);
+
+            // 娴嬭瘯HTTP
+            status.CanAccessHttp = await TestHttpAsync($"https://{host}");
+
+            // 娴嬭瘯甯哥敤绔彛
+            status.CanAccessPort80 = await TestTcpPortAsync(host, 80);
+            status.CanAccessPort443 = await TestTcpPortAsync(host, 443);
+
+            status.IsNetworkAvailable = NetworkInterface.GetIsNetworkAvailable();
+
+            return status;
+        }
+
+        public static async Task<NetworkStatus> CheckNetworkCanPingStatusAsync(string host = "www.google.com")
+        {
+            var status = new NetworkStatus();
+
+            // 娴嬭瘯Ping
+            status.CanPing = await TestPingAsync(host);
+
+            //// 娴嬭瘯HTTP
+            //status.CanAccessHttp = await TestHttpAsync($"https://{host}");
+
+            //// 娴嬭瘯甯哥敤绔彛
+            //status.CanAccessPort80 = await TestTcpPortAsync(host, 80);
+            //status.CanAccessPort443 = await TestTcpPortAsync(host, 443);
+
+            status.IsNetworkAvailable = NetworkInterface.GetIsNetworkAvailable();
+
+            return status;
+        }
+
+        private static async Task<bool> TestPingAsync(string host)
+        {
+            try
+            {
+                using (var ping = new Ping())
+                {
+                    var reply = await ping.SendPingAsync(host, 3000);
+                    return reply.Status == IPStatus.Success;
+                }
+            }
+            catch
+            {
+                return false;
+            }
+        }
+
+        private static async Task<bool> TestHttpAsync(string url)
+        {
+            try
+            {
+                using (var client = new HttpClient { Timeout = TimeSpan.FromSeconds(10) })
+                {
+                    var response = await client.GetAsync(url);
+                    return response.IsSuccessStatusCode;
+                }
+            }
+            catch
+            {
+                return false;
+            }
+        }
+
+        private static async Task<bool> TestTcpPortAsync(string host, int port)
+        {
+            try
+            {
+                using (var client = new TcpClient())
+                {
+                    var task = client.ConnectAsync(host, port);
+                    return await Task.WhenAny(task, Task.Delay(3000)) == task && client.Connected;
+                }
+            }
+            catch
+            {
+                return false;
+            }
+        }
+    }
+
+    public class NetworkStatus
+    {
+        public bool IsNetworkAvailable { get; set; }
+        public bool CanPing { get; set; }
+        public bool CanAccessHttp { get; set; }
+        public bool CanAccessPort80 { get; set; }
+        public bool CanAccessPort443 { get; set; }
+
+        public void PrintStatus()
+        {
+            Console.WriteLine($"缃戠粶鎺ュ彛鍙敤: {IsNetworkAvailable}");
+            Console.WriteLine($"Ping娴嬭瘯: {CanPing}");
+            Console.WriteLine($"HTTP璁块棶: {CanAccessHttp}");
+            Console.WriteLine($"绔彛80: {CanAccessPort80}");
+            Console.WriteLine($"绔彛443: {CanAccessPort443}");
+        }
+    }
+}
diff --git a/LB_SmartVisionCommon/NetworkMonitor.cs b/LB_SmartVisionCommon/NetworkMonitor.cs
new file mode 100644
index 0000000..d96d35d
--- /dev/null
+++ b/LB_SmartVisionCommon/NetworkMonitor.cs
@@ -0,0 +1,34 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    public class NetworkMonitor
+    {
+        private System.Timers.Timer _timer;
+
+        public event Action<bool> NetworkStatusChanged;
+
+        public void StartMonitoring(int intervalSeconds = 30, string ip = "www.google.com")
+        {
+            _timer = new System.Timers.Timer(intervalSeconds * 1000);
+            _timer.Elapsed += async (s, e) => await CheckNetworkAsync(ip);
+            _timer.Start();
+        }
+
+        public void StopMonitoring()
+        {
+            _timer?.Stop();
+            _timer?.Dispose();
+        }
+
+        private async Task CheckNetworkAsync(string ip = "www.google.com")
+        {
+            var isConnected = await NetworkTester.TestConnectionAsync(ip);
+            NetworkStatusChanged?.Invoke(isConnected);
+        }
+    }
+}
diff --git a/LB_SmartVisionCommon/NetworkTester.cs b/LB_SmartVisionCommon/NetworkTester.cs
new file mode 100644
index 0000000..9d5c8a0
--- /dev/null
+++ b/LB_SmartVisionCommon/NetworkTester.cs
@@ -0,0 +1,46 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.NetworkInformation;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    public class NetworkTester
+    {
+        public static async Task<bool> TestConnectionAsync(string host, int timeout = 3000)
+        {
+            try
+            {
+                using (var ping = new Ping())
+                {
+                    var reply = await ping.SendPingAsync(host, timeout);
+                    AsyncLogHelper.Warn("鐩告満IP锛�" + host + "閫氳姝e父锛�");
+                    return reply.Status == IPStatus.Success;
+                }
+            }
+            catch
+            {
+                AsyncLogHelper.Warn("鐩告満IP锛�" + host + "閫氳寮傚父锛�");
+                return false;
+            }
+        }
+
+        public static bool TestConnection(string host, int timeout = 3000)
+        {
+            try
+            {
+                using (var ping = new Ping())
+                {
+                    var reply = ping.Send(host, timeout);
+                    return reply.Status == IPStatus.Success;
+                }
+            }
+            catch
+            {
+                return false;
+            }
+        }
+    }
+}
diff --git a/LB_SmartVisionCommon/PermissionAttribute.cs b/LB_SmartVisionCommon/PermissionAttribute.cs
new file mode 100644
index 0000000..f7f8cdb
--- /dev/null
+++ b/LB_SmartVisionCommon/PermissionAttribute.cs
@@ -0,0 +1,38 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    /// <summary>
+    /// 娉涘瀷鏉冮檺鎺у埗鐗规��
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
+    public class PermissionAttribute : Attribute
+    {
+        /// <summary>
+        /// 瑙掕壊
+        /// </summary>
+        public Type RoleType { get; }
+        /// <summary>
+        /// 鏈�灏忔潈闄�
+        /// </summary>
+        public object MinimumRole { get; }
+        /// <summary>
+        /// 娉涘瀷鏉冮檺鎺у埗鐗规��
+        /// </summary>
+        /// <param name="roleType">瑙掕壊</param>
+        /// <param name="minimumRole">鏈�灏忔潈闄�</param>
+        /// <exception cref="ArgumentException"></exception>
+        public PermissionAttribute(Type roleType, object minimumRole)
+        {
+            if (!roleType.IsEnum)
+                throw new ArgumentException("roleType 蹇呴』鏄灇涓剧被鍨�", nameof(roleType));
+
+            RoleType = roleType;
+            MinimumRole = minimumRole;
+        }
+    }
+}
diff --git a/LB_SmartVisionCommon/PermissionPropertyDescriptor.cs b/LB_SmartVisionCommon/PermissionPropertyDescriptor.cs
new file mode 100644
index 0000000..3668f14
--- /dev/null
+++ b/LB_SmartVisionCommon/PermissionPropertyDescriptor.cs
@@ -0,0 +1,70 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    /// <summary>
+    /// 鏉冮檺灞炴�ф弿杩扮
+    /// </summary>
+    public class PermissionPropertyDescriptor : PropertyDescriptor
+    {
+        private readonly PropertyDescriptor _original;
+        private readonly bool _isReadOnly;
+        /// <summary>
+        /// 鏉冮檺灞炴�ф弿杩扮
+        /// </summary>
+        /// <param name="original">灞炴�ф弿杩扮</param>
+        /// <param name="isReadOnly">鏄惁鍙</param>
+        public PermissionPropertyDescriptor(PropertyDescriptor original, bool isReadOnly)
+            : base(original)
+        {
+            _original = original;
+            _isReadOnly = isReadOnly;
+        }
+        /// <summary>
+        /// 鏄惁鍙
+        /// </summary>
+        public override bool IsReadOnly => _isReadOnly;
+        /// <summary>
+        /// 褰撳墠缁勪欢绫诲瀷
+        /// </summary>
+        public override Type ComponentType => _original.ComponentType;
+        /// <summary>
+        /// 灞炴�х被鍨�
+        /// </summary>
+        public override Type PropertyType => _original.PropertyType;
+        /// <summary>
+        /// 杩斿洖閲嶇疆瀵硅薄鏃舵槸鍚︽洿鏀瑰叾鍊笺��
+        /// </summary>
+        /// <param name="component">瑕佹祴璇曢噸缃姛鑳界殑缁勪欢銆�</param>
+        /// <returns>濡傛灉閲嶇疆缁勪欢鏇存敼鍏跺�硷紝鍒欎负 true锛涘惁鍒欎负 false銆�</returns>
+        public override bool CanResetValue(object component) => _original.CanResetValue(component);
+        /// <summary>
+        /// 杩斿洖缁欏畾瀵硅薄鏀寔鐨勫瓧娈电殑鍊笺��
+        /// </summary>
+        /// <param name="component">灏嗚繑鍥炲叾瀛楁鍊肩殑瀵硅薄銆�</param>
+        /// <returns>涓�涓璞★紝鍖呭惈姝ゅ疄渚嬪弽鏄犵殑瀛楁鐨勫�笺��</returns>
+        public override object GetValue(object component) => _original.GetValue(component);
+        /// <summary>
+        /// 灏嗙粍浠剁殑姝ゅ睘鎬х殑鍊奸噸缃负榛樿鍊笺��
+        /// </summary>
+        /// <param name="component">鍏锋湁瑕侀噸缃负榛樿鍊肩殑灞炴�у�肩殑缁勪欢銆�</param>
+        public override void ResetValue(object component) => _original.ResetValue(component);
+        /// <summary>
+        /// 璁剧疆鎸囧畾瀵硅薄鐨勫睘鎬у�笺��
+        /// </summary>
+        /// <param name="component">灏嗚缃叾灞炴�у�肩殑瀵硅薄銆�</param>
+        /// <param name="value">鏂扮殑灞炴�у�笺��</param>
+        public override void SetValue(object component, object value) => _original.SetValue(component, value);
+        /// <summary>
+        /// 纭畾涓�涓�硷紝璇ュ�兼寚绀烘槸鍚﹂渶瑕佹案涔呬繚瀛樻灞炴�х殑鍊笺��
+        /// </summary>
+        /// <param name="component">鍏锋湁瑕佹鏌ュ叾鎸佷箙鎬х殑灞炴�х殑缁勪欢銆�</param>
+        /// <returns>濡傛灉灞炴�у簲璇ヨ姘镐箙淇濆瓨锛屽垯涓� true锛涘惁鍒欎负 false銆�</returns>
+        public override bool ShouldSerializeValue(object component) => _original.ShouldSerializeValue(component);
+    }
+}
diff --git a/LB_SmartVisionCommon/PropertySorter.cs b/LB_SmartVisionCommon/PropertySorter.cs
new file mode 100644
index 0000000..db55702
--- /dev/null
+++ b/LB_SmartVisionCommon/PropertySorter.cs
@@ -0,0 +1,134 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    /// <summary>
+    /// 灞炴�ф帓搴�
+    /// </summary>
+    public class PropertySorter : ExpandableObjectConverter
+    {
+        /// <summary>
+        /// 鑾峰彇鏀寔鐨勫睘鎬�
+        /// </summary>
+        /// <param name="context">鎻愪緵鏈夊叧缁勪欢锛堜緥濡傚叾瀹瑰櫒鍜屽睘鎬ф弿杩扮锛夌殑涓婁笅鏂囦俊鎭��</param>
+        /// <returns>鎵ц鏄惁鎴愬姛</returns>
+        public override bool GetPropertiesSupported(ITypeDescriptorContext context)
+        {
+            return true;
+        }
+        /// <summary>
+        /// 鑾峰彇灞炴�ф弿杩扮闆嗗悎
+        /// </summary>
+        /// <param name="context">鎻愪緵鏈夊叧缁勪欢锛堜緥濡傚叾瀹瑰櫒鍜屽睘鎬ф弿杩扮锛夌殑涓婁笅鏂囦俊鎭��</param>
+        /// <param name="value">鍊�</param>
+        /// <param name="attributes">鑷畾涔夌壒鎬�</param>
+        /// <returns>杩斿洖灞炴�ф弿杩扮闆嗗悎</returns>
+        public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
+        {
+            PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(value, attributes);
+            ArrayList orderedProperties = new ArrayList();
+            foreach (PropertyDescriptor pd in pdc)
+            {
+                Attribute attribute = pd.Attributes[typeof(PropertyOrderAttribute)];
+                if (attribute != null)
+                {
+                    PropertyOrderAttribute poa = (PropertyOrderAttribute)attribute;
+                    orderedProperties.Add(new PropertyOrderPair(pd.Name, poa.Order));
+                }
+                else
+                {
+                    orderedProperties.Add(new PropertyOrderPair(pd.Name, 0));
+                }
+            }
+            orderedProperties.Sort();
+            ArrayList propertyNames = new ArrayList();
+            foreach (PropertyOrderPair pop in orderedProperties)
+            {
+                propertyNames.Add(pop.Name);
+            }
+            return pdc.Sort((string[])propertyNames.ToArray(typeof(string)));
+        }
+    }
+    /// <summary>
+    /// 灞炴�ф帓搴忓睘鎬х被
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Property)]
+    public class PropertyOrderAttribute : Attribute
+    {
+        /// <summary>
+        /// 搴忓彿
+        /// </summary>
+        private int _order;
+        /// <summary>
+        /// 灞炴�ф帓搴忓睘鎬�
+        /// </summary>
+        /// <param name="order">搴忓彿</param>
+        public PropertyOrderAttribute(int order)
+        {
+            _order = order;
+        }
+        /// <summary>
+        /// 灞炴�у簭鍙�
+        /// </summary>
+        public int Order
+        {
+            get
+            {
+                return _order;
+            }
+        }
+    }
+    /// <summary>
+    /// 灞炴�ч『搴忓绫�
+    /// </summary>
+    public class PropertyOrderPair : IComparable
+    {
+        private int _order;
+        private string _name;
+        /// <summary>
+        /// 鍚嶇О
+        /// </summary>
+        public string Name
+        {
+            get
+            {
+                return _name;
+            }
+        }
+        /// <summary>
+        /// 灞炴�ч『搴忓
+        /// </summary>
+        /// <param name="name">鍚嶇О</param>
+        /// <param name="order">搴忓彿</param>
+        public PropertyOrderPair(string name, int order)
+        {
+            _order = order;
+            _name = name;
+        }
+        /// <summary>
+        /// 姣斿鎺掑簭
+        /// </summary>
+        /// <param name="obj">鑷畾涔夊睘鎬�</param>
+        /// <returns></returns>
+        public int CompareTo(object obj)
+        {
+            int otherOrder = ((PropertyOrderPair)obj)._order;
+            if (otherOrder == _order)
+            {
+                string otherName = ((PropertyOrderPair)obj)._name;
+                return string.Compare(_name, otherName);
+            }
+            else if (otherOrder > _order)
+            {
+                return -1;
+            }
+            return 1;
+        }
+    }
+}
diff --git a/LB_SmartVisionCommon/UserData.cs b/LB_SmartVisionCommon/UserData.cs
new file mode 100644
index 0000000..c89d9e3
--- /dev/null
+++ b/LB_SmartVisionCommon/UserData.cs
@@ -0,0 +1,81 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    /// <summary>
+    /// 璁板綍鐢ㄦ埛淇℃伅鏁版嵁
+    /// </summary>
+    [JsonObject(MemberSerialization.OptOut)]
+    [TypeConverter(typeof(PropertySorter))]
+    public class RecordUserData
+    {
+        /// <summary>
+        /// 鍛樺伐缂栧彿
+        /// </summary>
+        [Category("RecordUserData"), PropertyOrder(1)]
+        [DisplayName("鍛樺伐鍙�")]
+        [Browsable(true)]
+        public string EmployeeNumber { get; set; }
+        /// <summary>
+        /// 鍛樺伐鍚嶇О
+        /// </summary>
+        [Category("RecordUserData"), PropertyOrder(2)]
+        [DisplayName("濮撳悕")]
+        [Browsable(true)]
+        public string EmployeeName { get; set; }
+        /// <summary>
+        /// 鍛樺伐璐﹀彿
+        /// </summary>
+        [Category("RecordUserData"), PropertyOrder(3)]
+        [DisplayName("璐﹀彿")]
+        [Browsable(true)]
+        public string EmployeeAccount { get; set; }
+        /// <summary>
+        /// 鍛樺伐瀵嗙爜
+        /// </summary>
+        [Browsable(false)]
+        public string EmployeePassword { get; set; }
+        /// <summary>
+        /// 鍛樺伐鏉冮檺
+        /// </summary>
+        [Category("RecordUserData"), PropertyOrder(5)]
+        [DisplayName("鏉冮檺")]
+        [Browsable(true)]
+        public UserPermission EmployeePermission { get; set; } = UserPermission.Operator;
+
+        /// <summary>
+        /// 澶嶅埗鐢ㄦ埛鏁版嵁
+        /// </summary>
+        public RecordUserData Clone()
+        {
+            return new RecordUserData
+            {
+                EmployeeNumber = this.EmployeeNumber,
+                EmployeeName = this.EmployeeName,
+                EmployeeAccount = this.EmployeeAccount,
+                EmployeePassword = this.EmployeePassword,
+                EmployeePermission = this.EmployeePermission
+            };
+        }
+    }
+    /// <summary>
+    /// UserPermission
+    /// </summary>
+    public enum UserPermission
+    {
+        /// <summary>
+        /// UserPermission锛歄perator
+        /// </summary>
+        Operator,
+        /// <summary>
+        /// UserPermission锛欰dministrator
+        /// </summary>
+        Administrator
+    }
+}
diff --git a/LB_SmartVisionCommon/UserManager.cs b/LB_SmartVisionCommon/UserManager.cs
new file mode 100644
index 0000000..22bef7d
--- /dev/null
+++ b/LB_SmartVisionCommon/UserManager.cs
@@ -0,0 +1,311 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionCommon
+{
+    public class UserManager
+    {
+        private Dictionary<string, RecordUserData> _users;
+        private readonly string _dataFilePath;
+        private RecordUserData _currentUser;
+        private static UserManager _instance;
+        /// <summary>
+        /// 绾跨▼閿�
+        /// </summary>
+        private static readonly object _lock = new object();
+        private UserManager(string dataFilePath = "users.json")
+        {
+            _dataFilePath = dataFilePath;
+            _users = new Dictionary<string, RecordUserData>();
+            _currentUser = null;
+            LoadUsers();
+        }
+
+        public static UserManager Instance
+        {
+            get
+            {
+                // 鍙岄噸妫�鏌ラ攣瀹氱‘淇濈嚎绋嬪畨鍏�
+                if (_instance == null)
+                {
+                    lock (_lock)
+                    {
+                        if (_instance == null)
+                        {
+                            _instance = new UserManager();
+                        }
+                    }
+                }
+                return _instance;
+            }
+        }
+
+        /// <summary>
+        /// 褰撳墠鐧诲綍鐢ㄦ埛
+        /// </summary>
+        public RecordUserData CurrentUser => _currentUser;
+
+        /// <summary>
+        /// 鐢ㄦ埛鍒楄〃锛堝彧璇伙級
+        /// </summary>
+        public Dictionary<string, RecordUserData> Users
+        {
+            get { return _users; }
+        }
+        /// <summary>
+        /// 鐢ㄦ埛鏁伴噺
+        /// </summary>
+        public int UserCount => _users.Count;
+
+        /// <summary>
+        /// 鐢ㄦ埛鐧诲綍
+        /// </summary>
+        /// <param name="account">璐︽埛</param>
+        /// <param name="password">瀵嗙爜</param>
+        /// <returns></returns>
+        public bool Login(string account, string password)
+        {
+            var user = _users.FirstOrDefault(u =>
+                u.Value.EmployeeAccount == account && AESHelper.Decrypt(u.Value.EmployeePassword) == password);
+
+            if (user.Value != null && user.Value != null)
+            {
+                _currentUser = user.Value;
+                return true;
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// 鐢ㄦ埛鐧诲嚭
+        /// </summary>
+        public void Logout()
+        {
+            _currentUser = null;
+        }
+
+        /// <summary>
+        /// 妫�鏌ュ綋鍓嶇敤鎴锋潈闄�
+        /// </summary>
+        /// <param name="requireAdmin">鏄惁鏄鐞嗗憳锛�</param>
+        /// <returns>杩斿洖鏉冮檺</returns>
+        private bool CheckPermission(bool requireAdmin = false)
+        {
+            if (_currentUser == null) return false;
+
+            if (requireAdmin)
+                return _currentUser.EmployeePermission == UserPermission.Administrator;
+
+            return true;
+        }
+
+        /// <summary>
+        /// 娣诲姞鐢ㄦ埛锛堥渶瑕佺鐞嗗憳鏉冮檺锛�
+        /// </summary>
+        /// <param name="user">RecordUserData user</param>
+        /// <returns>鏄惁娣诲姞鎴愬姛锛�</returns>
+        public bool AddUser(RecordUserData user)
+        {
+            if (_currentUser == null)
+            {
+                _currentUser = user;
+            }
+            if (!CheckPermission(true))
+            {
+                MessageBox.Show("闇�瑕佺鐞嗗憳鏉冮檺鎵嶈兘娣诲姞鐢ㄦ埛锛�", "鏉冮檺涓嶈冻", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+                return false;
+            }
+
+            if (_users.Any(u => u.Value.EmployeeNumber == user.EmployeeNumber ||
+                               u.Value.EmployeeAccount == user.EmployeeAccount))
+            {
+                MessageBox.Show("鍛樺伐鍙锋垨璐﹀彿宸插瓨鍦紒", "娣诲姞澶辫触", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+                return false;
+            }
+            RecordUserData recordUserData = new RecordUserData();
+            recordUserData.EmployeeNumber = user.EmployeeNumber;
+            recordUserData.EmployeeAccount = user.EmployeeAccount;
+            recordUserData.EmployeePassword = AESHelper.Encrypt(user.EmployeePassword);
+            recordUserData.EmployeeName = user.EmployeeName;
+            recordUserData.EmployeePermission = user.EmployeePermission;
+            _users.Add(recordUserData.EmployeeNumber, recordUserData);
+            SaveUsers();
+            return true;
+        }
+
+        /// <summary>
+        /// 鍒犻櫎鐢ㄦ埛锛堥渶瑕佺鐞嗗憳鏉冮檺锛�
+        /// </summary>
+        /// <param name="employeeNumber">string employeeNumber</param>
+        /// <returns>鏄惁鍒犻櫎鎴愬姛</returns>
+        public bool DeleteUser(string employeeNumber)
+        {
+            if (!CheckPermission(true))
+            {
+                MessageBox.Show("闇�瑕佺鐞嗗憳鏉冮檺鎵嶈兘鍒犻櫎鐢ㄦ埛锛�", "鏉冮檺涓嶈冻", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+                return false;
+            }
+
+            // 绠$悊鍛樹笉鑳藉垹闄よ嚜宸�
+            if (_currentUser.EmployeeNumber == employeeNumber)
+            {
+                MessageBox.Show("涓嶈兘鍒犻櫎褰撳墠鐧诲綍鐨勭敤鎴凤紒", "鍒犻櫎澶辫触", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+                return false;
+            }
+
+            var user = _users.FirstOrDefault(u => u.Value.EmployeeNumber == employeeNumber);
+            if (user.Value != null)
+            {
+                _users.Remove(user.Key);
+                SaveUsers();
+                return true;
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// 鏇存柊鐢ㄦ埛淇℃伅
+        /// </summary>
+        /// <param name="updatedUser">RecordUserData updatedUser</param>
+        /// <returns>鏄惁鏇存柊鎴愬姛</returns>
+        public bool UpdateUser(RecordUserData updatedUser)
+        {
+            // 鏅�氱敤鎴峰彧鑳戒慨鏀硅嚜宸辩殑淇℃伅锛岀鐞嗗憳鍙互淇敼鎵�鏈夌敤鎴蜂俊鎭�
+            bool canModify = _currentUser.EmployeePermission == UserPermission.Administrator ||
+                            _currentUser.EmployeeNumber == updatedUser.EmployeeNumber;
+
+            if (!canModify)
+            {
+                MessageBox.Show("娌℃湁鏉冮檺淇敼姝ょ敤鎴蜂俊鎭紒", "鏉冮檺涓嶈冻", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+                return false;
+            }
+
+            var existingUser = _users.FirstOrDefault(u => u.Value.EmployeeNumber == updatedUser.EmployeeNumber);
+            if (existingUser.Value != null)
+            {
+                // 妫�鏌ヨ处鍙锋槸鍚﹂噸澶嶏紙鎺掗櫎鑷繁锛�
+                if (_users.Any(u => u.Value.EmployeeAccount == updatedUser.EmployeeAccount &&
+                                   u.Value.EmployeeNumber != updatedUser.EmployeeNumber))
+                {
+                    MessageBox.Show("璐﹀彿宸插瓨鍦紒", "鏇存柊澶辫触", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+                    return false;
+                }
+
+                // 鏇存柊鐢ㄦ埛淇℃伅
+                existingUser.Value.EmployeeName = updatedUser.EmployeeName;
+                existingUser.Value.EmployeeAccount = updatedUser.EmployeeAccount;
+                existingUser.Value.EmployeePassword = AESHelper.Encrypt(updatedUser.EmployeePassword);
+
+                // 鍙湁绠$悊鍛樺彲浠ヤ慨鏀规潈闄�
+                if (_currentUser.EmployeePermission == UserPermission.Administrator)
+                {
+                    existingUser.Value.EmployeePermission = updatedUser.EmployeePermission;
+                }
+                SaveUsers();
+                return true;
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// 鏍规嵁鍛樺伐鍙锋煡璇㈢敤鎴�
+        /// </summary>
+        /// <param name="employeeNumber">string employeeNumber</param>
+        /// <returns>RecordUserData</returns>
+        public RecordUserData GetUserByNumber(string employeeNumber)
+        {
+            return _users.FirstOrDefault(u => u.Value.EmployeeNumber == employeeNumber).Value.Clone();
+        }
+
+        /// <summary>
+        /// 鏍规嵁璐﹀彿鏌ヨ鐢ㄦ埛
+        /// </summary>
+        /// <param name="account">string account</param>
+        /// <returns>RecordUserData</returns>
+        public RecordUserData GetUserByAccount(string account)
+        {
+            return _users.FirstOrDefault(u => u.Value.EmployeeAccount == account).Value.Clone();
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎵�鏈夌敤鎴峰垪琛�
+        /// </summary>
+        /// <returns>List<RecordUserData></returns>
+        public List<RecordUserData> GetAllUsers()
+        {
+            return _users.Select(u => u.Value.Clone()).ToList();
+        }
+
+        /// <summary>
+        /// 鏍规嵁鏉冮檺绛涢�夌敤鎴�
+        /// </summary>
+        /// <param name="permission">UserPermission permission</param>
+        /// <returns>List<RecordUserData></returns>
+        public List<RecordUserData> GetUsersByPermission(UserPermission permission)
+        {
+            return _users.Where(u => u.Value.EmployeePermission == permission)
+                        .Select(u => u.Value.Clone()).ToList();
+        }
+
+        /// <summary>
+        /// 淇濆瓨鐢ㄦ埛鏁版嵁鍒癑SON鏂囦欢
+        /// </summary>
+        private void SaveUsers()
+        {
+            try
+            {
+                ConfigManager<Dictionary<string, RecordUserData>>.SaveConfig<Dictionary<string, RecordUserData>>(_users, _dataFilePath);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show($"淇濆瓨鐢ㄦ埛鏁版嵁澶辫触锛歿ex.Message}", "閿欒", MessageBoxButtons.OK, MessageBoxIcon.Error);
+            }
+        }
+
+        /// <summary>
+        /// 浠嶫SON鏂囦欢鍔犺浇鐢ㄦ埛鏁版嵁
+        /// </summary>
+        private void LoadUsers()
+        {
+            try
+            {
+                if (File.Exists(_dataFilePath))
+                {
+                    _users = ConfigManager<Dictionary<string, RecordUserData>>.LoadConfig<Dictionary<string, RecordUserData>>(_dataFilePath) ?? new Dictionary<string, RecordUserData>();
+                }
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show($"鍔犺浇鐢ㄦ埛鏁版嵁澶辫触锛歿ex.Message}", "閿欒", MessageBoxButtons.OK, MessageBoxIcon.Error);
+                _users = new Dictionary<string, RecordUserData>();
+            }
+        }
+
+        /// <summary>
+        /// 楠岃瘉鍛樺伐鍙锋槸鍚﹀敮涓�
+        /// </summary>
+        /// <param name="employeeNumber">string employeeNumber</param>
+        /// <param name="excludeEmployeeNumber">string excludeEmployeeNumber = null</param>
+        /// <returns>鍛樺伐鍙锋槸鍚﹀敮涓�锛�</returns>
+        public bool IsEmployeeNumberUnique(string employeeNumber, string excludeEmployeeNumber = null)
+        {
+            return !_users.Any(u => u.Value.EmployeeNumber == employeeNumber &&
+                                   u.Value.EmployeeNumber != excludeEmployeeNumber);
+        }
+
+        /// <summary>
+        /// 楠岃瘉璐﹀彿鏄惁鍞竴
+        /// </summary>
+        /// <param name="account">string account</param>
+        /// <param name="excludeEmployeeNumber">string excludeEmployeeNumber = null</param>
+        /// <returns>璐﹀彿鏄惁鍞竴锛�</returns>
+        public bool IsAccountUnique(string account, string excludeEmployeeNumber = null)
+        {
+            return !_users.Any(u => u.Value.EmployeeAccount == account &&
+                                   u.Value.EmployeeNumber != excludeEmployeeNumber);
+        }
+    }
+}
diff --git a/LB_SmartVisionLoginUI/App.config b/LB_SmartVisionLoginUI/App.config
new file mode 100644
index 0000000..ecdcf8a
--- /dev/null
+++ b/LB_SmartVisionLoginUI/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
+    </startup>
+</configuration>
diff --git a/LB_SmartVisionLoginUI/App.xaml b/LB_SmartVisionLoginUI/App.xaml
new file mode 100644
index 0000000..8e14309
--- /dev/null
+++ b/LB_SmartVisionLoginUI/App.xaml
@@ -0,0 +1,9 @@
+锘�<Application x:Class="LB_SmartVisionLoginUI.App"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:local="clr-namespace:VideojetLiongUi"
+             StartupUri="MainWindow.xaml">
+    <Application.Resources>
+         
+    </Application.Resources>
+</Application>
diff --git a/LB_SmartVisionLoginUI/App.xaml.cs b/LB_SmartVisionLoginUI/App.xaml.cs
new file mode 100644
index 0000000..0309187
--- /dev/null
+++ b/LB_SmartVisionLoginUI/App.xaml.cs
@@ -0,0 +1,17 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace VideojetLiongUi
+{
+    /// <summary>
+    /// App.xaml 鐨勪氦浜掗�昏緫
+    /// </summary>
+    public partial class App : Application
+    {
+    }
+}
diff --git a/LB_SmartVisionLoginUI/AssemblyInfo.cs b/LB_SmartVisionLoginUI/AssemblyInfo.cs
new file mode 100644
index 0000000..b0ec827
--- /dev/null
+++ b/LB_SmartVisionLoginUI/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+    ResourceDictionaryLocation.None,            //where theme specific resource dictionaries are located
+                                                //(used if a resource is not found in the page,
+                                                // or application resource dictionaries)
+    ResourceDictionaryLocation.SourceAssembly   //where the generic resource dictionary is located
+                                                //(used if a resource is not found in the page,
+                                                // app, or any theme specific resource dictionaries)
+)]
diff --git a/LB_SmartVisionLoginUI/ICommonData_Loading.cs b/LB_SmartVisionLoginUI/ICommonData_Loading.cs
new file mode 100644
index 0000000..30d06c8
--- /dev/null
+++ b/LB_SmartVisionLoginUI/ICommonData_Loading.cs
@@ -0,0 +1,16 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_SmartVisionLoginUI
+{
+    public interface ICommonData_Loading
+    {
+        string applicationName { get; }
+        string appdesignerName { get; }
+        string logoFile { get; }
+        string strKey { get; }
+    }
+}
diff --git a/LB_SmartVisionLoginUI/LB_SmartVisionLoginUI.csproj b/LB_SmartVisionLoginUI/LB_SmartVisionLoginUI.csproj
new file mode 100644
index 0000000..40a464c
--- /dev/null
+++ b/LB_SmartVisionLoginUI/LB_SmartVisionLoginUI.csproj
@@ -0,0 +1,15 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>WinExe</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <Nullable>enable</Nullable>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <UseWPF>true</UseWPF>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\LB_SmartVisionCommon\LB_SmartVisionCommon.csproj" />
+  </ItemGroup>
+
+</Project>
diff --git a/LB_SmartVisionLoginUI/MainWindow.xaml b/LB_SmartVisionLoginUI/MainWindow.xaml
new file mode 100644
index 0000000..911a04d
--- /dev/null
+++ b/LB_SmartVisionLoginUI/MainWindow.xaml
@@ -0,0 +1,79 @@
+锘�<Window x:Class="LB_SmartVisionLoginUI.MainWindow"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:local="clr-namespace:LB_SmartVisionLoginUI"
+        WindowStartupLocation="CenterScreen"
+        WindowStyle="None"
+        Background="Transparent"
+        AllowsTransparency="True"
+        mc:Ignorable="d"
+        Title="MainWindow" Height="420" Width="800" Closing="Window_Closing">
+
+    <Grid x:Name="test" Width="800" Height="460" Opacity="1.0">
+        <Grid.Background>
+            <ImageBrush ImageSource="./images/lanbao.jpg" 
+                   Stretch="UniformToFill"/>
+        </Grid.Background>
+        <!--鏍囬-->
+        <Border BorderBrush="LightBlue" BorderThickness="3" Height="60" VerticalAlignment="Top" CornerRadius="30" Margin="116,2,102,0" Background="#72F5DEB3">
+            <Label x:Name="Lbl_Title" BorderBrush="Red"  Background="Transparent" Content="杞儙澶栬瑙嗚妫�娴嬬郴缁�" HorizontalAlignment="Center" Foreground="Black" FontFamily="妤蜂綋" FontSize="36" Margin="31,2,91,-2" Width="454"></Label>
+        </Border>
+
+        <!--鍏抽棴绯荤粺-->
+        <Image Source="./images/05.png" Height="30" MouseDown="test_Close" Margin="644,15,116,415" ToolTip="鍏抽棴绯荤粺" />
+        <!--鏈�灏忓寲绯荤粺-->
+        <Image Source="./images/06.png" Height="30" Margin="603,15,157,415" MouseDown="test_Min" ToolTip="鏈�灏忓寲"/>
+
+        <Border BorderBrush="LightBlue" Width="700" Height="325" Background="Transparent" BorderThickness="3" CornerRadius="80" Padding="13" >
+
+            <Border Width="655" BorderThickness="3" CornerRadius="80" BorderBrush="LightBlue"  Padding="23" >
+                <!--<Border.Background>
+                    <ImageBrush ImageSource="./images/lanbao.jpg" Stretch="UniformToFill"/>
+                </Border.Background>-->
+                <!--<Image Height="161" Width="162" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="-5,40,0,0" RenderTransformOrigin="0.5,0.5" Stretch="Fill" Source="./images/logo.ico"/>-->
+                <!--<Image Source="/images/logo_h.png" Height="161" Width="162" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="-5,40,0,0" RenderTransformOrigin="0.5,0.5" Stretch="Fill" Visibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Auto" StretchDirection="DownOnly">-->
+                    <!--<Image.RenderTransform>
+                        <TransformGroup>
+                            <ScaleTransform/>
+                            <SkewTransform AngleX="0.149"/>
+                            <RotateTransform/>
+                            <TranslateTransform X="-0.469"/>
+                        </TransformGroup>
+                    </Image.RenderTransform>
+                </Image>-->
+
+            </Border>
+        </Border>
+        <Border Background="#72F5DEB3" BorderThickness="3" CornerRadius="80" BorderBrush="LightBlue" Padding="23" Margin="277,116,95,111" RenderTransformOrigin="0.5,0.5" >
+            <Border.RenderTransform>
+                <TransformGroup>
+                    <ScaleTransform/>
+                    <SkewTransform AngleY="0.351"/>
+                    <RotateTransform/>
+                    <TranslateTransform Y="1.312"/>
+                </TransformGroup>
+            </Border.RenderTransform>
+            <Button x:Name="Btn_KeyBoard"  Margin="283,67,-16,67" Content="" FontFamily="妤蜂綋" FontSize="36" Foreground="Black" Click="Btn_KeyBoard_Click" Visibility="Hidden" >
+                <Button.Background>
+                    <ImageBrush ImageSource="images/閿洏.ico"/>
+                </Button.Background>
+            </Button>
+        </Border>
+        <!--鐢ㄦ埛瀵嗙爜鏍囩鍔犳枃鏈-->
+        <Label x:Name="Lbl_UserName" Content="鐢ㄦ埛鍚嶏細"  FontFamily="妤蜂綋" FontSize="22" Height="35" Width="83" HorizontalAlignment="Left" Margin="316,177,0,250" FontWeight="Bold"  />
+        <TextBox x:Name="Txt_UserName" TextBlock.FontStyle="Normal"  FontStretch="Normal"   HorizontalScrollBarVisibility="Hidden" Height="30" FontSize="15" Margin="404,185,229,250"/>
+
+        <Label x:Name="Lbl_PassWord"   Content="瀵嗙爜锛�"  FontFamily="妤蜂綋" FontSize="22"  Height="35" Width="63" HorizontalAlignment="Left" Margin="337,217,0,213" RenderTransformOrigin="0.597,0.559" FontWeight="Bold"  ></Label>
+        <!--璇疯緭鍏ュ瘑鐮�-->
+        <PasswordBox x:Name="Txt_UserPassWord"   TextBlock.FontStyle="Normal"   Height="30" Margin="405,224,230,211" FontSize="15" KeyDown="Txt_UserPassWord_KeyDown"/>
+        <!--鐧诲綍鎸夐挳-->
+        <Button x:Name="Btn_Login"  Margin="378,275,336,138" Content="鐧诲綍" FontFamily="妤蜂綋" FontSize="36" Foreground="Black"  Background="Wheat" Click="Btn_Login_Click" FontWeight="Bold" />
+        <Button x:Name="Btn_Cancel" Margin="511,275,203,138" Content="鍙栨秷" FontFamily="妤蜂綋" FontSize="36" Foreground="Black"   Background="Wheat" Click="Btn_Cancel_Click" FontWeight="Bold" />
+
+
+
+    </Grid>
+
+</Window>
diff --git a/LB_SmartVisionLoginUI/MainWindow.xaml.cs b/LB_SmartVisionLoginUI/MainWindow.xaml.cs
new file mode 100644
index 0000000..1a1db16
--- /dev/null
+++ b/LB_SmartVisionLoginUI/MainWindow.xaml.cs
@@ -0,0 +1,197 @@
+锘�
+using LB_SmartVisionCommon;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Forms;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using MessageBox = System.Windows.Forms.MessageBox;
+
+namespace LB_SmartVisionLoginUI
+{
+    /// <summary>
+    /// MainWindow.xaml 鐨勪氦浜掗�昏緫
+    /// </summary>
+    public partial class MainWindow : Window
+    {
+        /// <summary>
+        /// 璋冪敤Windows鐨凙PI搴搖ser32.dll涓殑娑堟伅鍙戦�佹満鍒讹紝鍙疄鐜拌法绋嬪簭鏁版嵁鍙戦��
+        /// </summary>
+        /// <param name="hwnd"></param>
+        /// <param name="wMsg"></param>
+        /// <param name="wParam"></param>
+        /// <param name="lParam"></param>
+        /// <returns></returns>
+        [DllImport("user32.dll", EntryPoint = "SendMessageA")]
+        public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
+        /// <summary>
+        /// 褰撳墠鐧诲綍鐨勭敤鎴峰悕锛屼篃闇�瑕佸叡浜粰鏁翠釜宸ョ▼
+        /// </summary>
+        public static string userName;//
+        /// <summary>
+        /// 鐢ㄦ埛瀵嗙爜
+        /// </summary>
+        private static string userPassword;
+        /// <summary>
+        /// 鏄惁閫�鍑�
+        /// </summary>
+        public bool isQuit = false;
+        /// <summary>
+        /// 褰撳墠鐢ㄦ埛
+        /// </summary>
+        public  bool correctUser = false;
+        /// <summary>
+        /// 鏄惁鐧诲嚭
+        /// </summary>
+        public bool login_on_off = false;
+
+
+        private MainWindow()
+        {
+            InitializeComponent();
+            correctUser = false;
+        }
+
+        private static MainWindow instanceLoginandConfirmation = null;
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public static MainWindow InstanceLoginandConfirmation()
+        {
+            if (instanceLoginandConfirmation == null)
+            {
+                instanceLoginandConfirmation = new MainWindow();
+            }
+            return instanceLoginandConfirmation;
+        }
+
+        /// <summary>
+        /// 鍏抽棴
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void test_Close(object sender, MouseButtonEventArgs e)
+        {
+            correctUser = false;
+            isQuit = true;
+            this.Close();
+        }
+
+        /// <summary>
+        /// 鏈�灏忓寲
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void test_Min(object sender, MouseButtonEventArgs e)
+        {
+            this.WindowState = WindowState.Minimized;
+        }
+
+        private void Btn_Cancel_Click(object sender, RoutedEventArgs e)
+        {
+            this.Close();
+            try
+            {
+                Process[] processes = System.Diagnostics.Process.GetProcesses(); //鑾峰緱鎵�鏈夎繘绋�
+                foreach (Process p in processes)
+                {
+                    if (p.ProcessName == "ShockPadMeasurementSystem" && p.StartTime < DateTime.Now.AddMilliseconds(-300))
+                    {
+                        p.Kill();
+                    }
+                }
+            }
+            catch { }
+        }
+
+        private void Btn_KeyBoard_Click(object sender, RoutedEventArgs e)
+        {
+            System.Diagnostics.Process.Start(@"C:\WINDOWS\system32\osk.exe");
+        }
+
+        private void Btn_Login_Click(object sender, RoutedEventArgs e)
+        {
+            login_on_off = true;
+            loginon();
+            // 鍦ㄦ澶勬坊鍔犱簨浠跺鐞嗙▼搴忓疄鐜般��
+            if (correctUser)//濡傛灉鐢ㄦ埛鍚嶅瘑鐮佹纭紝鍚堟硶鐧诲綍锛屽垯鑾峰緱褰撳墠鐢ㄦ埛鍚嶅拰绾у埆銆傚悓鏃跺叧闂櫥褰曠獥浣�
+            {
+                userName = this.Txt_UserName.Text.Trim().ToLower();
+                userPassword = this.Txt_UserPassWord.Password;
+                //closeLoginFrm();
+                this.Hide();
+            }
+        }
+
+        private void loginon()
+        {
+            if (!UserManager.Instance.Login(this.Txt_UserName.Text.Trim(), this.Txt_UserPassWord.Password))
+            {
+                MessageBox.Show("璇疯緭鍏ユ纭殑鐢ㄦ埛鍚嶅拰瀵嗙爜.",
+                    "鐧诲綍澶辫触!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+                correctUser = false;
+                return;
+            }
+            else// Valid user, pass the authentication
+            {
+                userName = this.Txt_UserName.Text.Trim();
+                userPassword = this.Txt_UserPassWord.Password;
+                correctUser = true;
+                isQuit = false;
+            }
+        }
+        /// <summary>
+        /// 鍏抽棴
+        /// </summary>
+        public void closeLoginFrm()
+        {
+            this.ShowInTaskbar = false;//鐐瑰嚮鐧诲綍鍚庡幓鎺変换鍔℃爮鍥炬爣
+            instanceLoginandConfirmation = null;
+            this.Close();
+        }
+
+        private void Txt_UserPassWord_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
+        {
+            if (e.Key== Key.Enter)
+            {
+                login_on_off = true;
+                loginon();
+                // 鍦ㄦ澶勬坊鍔犱簨浠跺鐞嗙▼搴忓疄鐜般��
+                if (correctUser)
+                {
+                    userName = this.Txt_UserName.Text.Trim().ToLower();
+                    userPassword = this.Txt_UserPassWord.Password;
+                    isQuit = false;
+                    //closeLoginFrm();
+                }
+            }
+            else if (e.Key == Key.Escape)
+            {
+                correctUser = false;
+                isQuit = true;
+                this.Close();
+            }
+        }
+
+        private void Window_Closing(object sender, CancelEventArgs e)
+        {
+            this.Txt_UserName.Text = "";
+            this.Txt_UserPassWord.Password = "";
+        }
+    }
+}
diff --git a/LB_SmartVisionLoginUI/favicon.ico b/LB_SmartVisionLoginUI/favicon.ico
new file mode 100644
index 0000000..cd4ac1c
--- /dev/null
+++ b/LB_SmartVisionLoginUI/favicon.ico
Binary files differ
diff --git a/LB_SmartVisionLoginUI/images/01.JPG b/LB_SmartVisionLoginUI/images/01.JPG
new file mode 100644
index 0000000..8e0a603
--- /dev/null
+++ b/LB_SmartVisionLoginUI/images/01.JPG
Binary files differ
diff --git a/LB_SmartVisionLoginUI/images/02.png b/LB_SmartVisionLoginUI/images/02.png
new file mode 100644
index 0000000..442c206
--- /dev/null
+++ b/LB_SmartVisionLoginUI/images/02.png
Binary files differ
diff --git a/LB_SmartVisionLoginUI/images/03.png b/LB_SmartVisionLoginUI/images/03.png
new file mode 100644
index 0000000..04b53b8
--- /dev/null
+++ b/LB_SmartVisionLoginUI/images/03.png
Binary files differ
diff --git a/LB_SmartVisionLoginUI/images/04.png b/LB_SmartVisionLoginUI/images/04.png
new file mode 100644
index 0000000..2f29be3
--- /dev/null
+++ b/LB_SmartVisionLoginUI/images/04.png
Binary files differ
diff --git a/LB_SmartVisionLoginUI/images/05.png b/LB_SmartVisionLoginUI/images/05.png
new file mode 100644
index 0000000..f72676c
--- /dev/null
+++ b/LB_SmartVisionLoginUI/images/05.png
Binary files differ
diff --git a/LB_SmartVisionLoginUI/images/06.png b/LB_SmartVisionLoginUI/images/06.png
new file mode 100644
index 0000000..73dfbce
--- /dev/null
+++ b/LB_SmartVisionLoginUI/images/06.png
Binary files differ
diff --git a/LB_SmartVisionLoginUI/images/07.png b/LB_SmartVisionLoginUI/images/07.png
new file mode 100644
index 0000000..c75e5bc
--- /dev/null
+++ b/LB_SmartVisionLoginUI/images/07.png
Binary files differ
diff --git a/LB_SmartVisionLoginUI/images/favicon.ico b/LB_SmartVisionLoginUI/images/favicon.ico
new file mode 100644
index 0000000..cd4ac1c
--- /dev/null
+++ b/LB_SmartVisionLoginUI/images/favicon.ico
Binary files differ
diff --git a/LB_SmartVisionLoginUI/images/lanbao.jpg b/LB_SmartVisionLoginUI/images/lanbao.jpg
new file mode 100644
index 0000000..159cab2
--- /dev/null
+++ b/LB_SmartVisionLoginUI/images/lanbao.jpg
Binary files differ
diff --git a/LB_SmartVisionLoginUI/images/logo.ico b/LB_SmartVisionLoginUI/images/logo.ico
new file mode 100644
index 0000000..5887476
--- /dev/null
+++ b/LB_SmartVisionLoginUI/images/logo.ico
Binary files differ
diff --git a/LB_SmartVisionLoginUI/images/logo_h.png b/LB_SmartVisionLoginUI/images/logo_h.png
new file mode 100644
index 0000000..dd1d0b6
--- /dev/null
+++ b/LB_SmartVisionLoginUI/images/logo_h.png
Binary files differ
diff --git "a/LB_SmartVisionLoginUI/images/\351\224\256\347\233\230.ico" "b/LB_SmartVisionLoginUI/images/\351\224\256\347\233\230.ico"
new file mode 100644
index 0000000..135f336
--- /dev/null
+++ "b/LB_SmartVisionLoginUI/images/\351\224\256\347\233\230.ico"
Binary files differ
diff --git a/LB_SmartVisionLoginUI/lanbao.jpg b/LB_SmartVisionLoginUI/lanbao.jpg
new file mode 100644
index 0000000..159cab2
--- /dev/null
+++ b/LB_SmartVisionLoginUI/lanbao.jpg
Binary files differ
diff --git a/LB_SmartVisionLoginUI/logo.ico b/LB_SmartVisionLoginUI/logo.ico
new file mode 100644
index 0000000..5887476
--- /dev/null
+++ b/LB_SmartVisionLoginUI/logo.ico
Binary files differ
diff --git a/LB_SmartVisionLoginUI/logo_h.png b/LB_SmartVisionLoginUI/logo_h.png
new file mode 100644
index 0000000..dd1d0b6
--- /dev/null
+++ b/LB_SmartVisionLoginUI/logo_h.png
Binary files differ
diff --git a/LB_VisionControl/Form1.Designer.cs b/LB_VisionControl/Form1.Designer.cs
new file mode 100644
index 0000000..f1c2844
--- /dev/null
+++ b/LB_VisionControl/Form1.Designer.cs
@@ -0,0 +1,39 @@
+锘縩amespace LB_VisionControl
+{
+    partial class Form1
+    {
+        /// <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.components = new System.ComponentModel.Container();
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(800, 450);
+            this.Text = "Form1";
+        }
+
+        #endregion
+    }
+}
diff --git a/LB_VisionControl/Form1.cs b/LB_VisionControl/Form1.cs
new file mode 100644
index 0000000..44349da
--- /dev/null
+++ b/LB_VisionControl/Form1.cs
@@ -0,0 +1,10 @@
+namespace LB_VisionControl
+{
+    public partial class Form1 : Form
+    {
+        public Form1()
+        {
+            InitializeComponent();
+        }
+    }
+}
diff --git a/LB_VisionControl/Form1.resx b/LB_VisionControl/Form1.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/LB_VisionControl/Form1.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/LB_VisionControl/Forms/RenameForm.Designer.cs b/LB_VisionControl/Forms/RenameForm.Designer.cs
new file mode 100644
index 0000000..b7b570e
--- /dev/null
+++ b/LB_VisionControl/Forms/RenameForm.Designer.cs
@@ -0,0 +1,262 @@
+锘縩amespace VisionControl.Forms
+{
+    partial class RenameForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RenameForm));
+            theme_RenameForm = new ReaLTaiizor.Forms.ThemeForm();
+            tlp_RennameMain = new Sunny.UI.UITableLayoutPanel();
+            tlp_RennameInput = new Sunny.UI.UITableLayoutPanel();
+            lb_OriginalName = new ReaLTaiizor.Controls.BigLabel();
+            bl_NewName = new ReaLTaiizor.Controls.BigLabel();
+            txt_OriginalName = new ReaLTaiizor.Controls.AloneTextBox();
+            txt_NewName = new ReaLTaiizor.Controls.AloneTextBox();
+            tlp_RennameOperator = new Sunny.UI.UITableLayoutPanel();
+            btn_Rename = new ReaLTaiizor.Controls.Button();
+            btn_Cancel = new ReaLTaiizor.Controls.Button();
+            theme_RenameForm.SuspendLayout();
+            tlp_RennameMain.SuspendLayout();
+            tlp_RennameInput.SuspendLayout();
+            tlp_RennameOperator.SuspendLayout();
+            SuspendLayout();
+            // 
+            // theme_RenameForm
+            // 
+            theme_RenameForm.BackColor = Color.FromArgb(32, 41, 50);
+            theme_RenameForm.Controls.Add(tlp_RennameMain);
+            theme_RenameForm.Dock = DockStyle.Fill;
+            theme_RenameForm.Font = new Font("Microsoft Sans Serif", 9F);
+            theme_RenameForm.Image = (Image)resources.GetObject("theme_RenameForm.Image");
+            theme_RenameForm.Location = new Point(0, 0);
+            theme_RenameForm.Name = "theme_RenameForm";
+            theme_RenameForm.Padding = new Padding(10, 70, 10, 9);
+            theme_RenameForm.RoundCorners = true;
+            theme_RenameForm.Sizable = true;
+            theme_RenameForm.Size = new Size(461, 260);
+            theme_RenameForm.SmartBounds = true;
+            theme_RenameForm.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            theme_RenameForm.TabIndex = 0;
+            theme_RenameForm.Text = "閲嶅懡鍚嶈缃�";
+            // 
+            // tlp_RennameMain
+            // 
+            tlp_RennameMain.ColumnCount = 1;
+            tlp_RennameMain.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tlp_RennameMain.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tlp_RennameMain.Controls.Add(tlp_RennameInput, 0, 0);
+            tlp_RennameMain.Controls.Add(tlp_RennameOperator, 0, 1);
+            tlp_RennameMain.Dock = DockStyle.Fill;
+            tlp_RennameMain.Location = new Point(10, 70);
+            tlp_RennameMain.Name = "tlp_RennameMain";
+            tlp_RennameMain.RowCount = 2;
+            tlp_RennameMain.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tlp_RennameMain.RowStyles.Add(new RowStyle(SizeType.Absolute, 60F));
+            tlp_RennameMain.Size = new Size(441, 181);
+            tlp_RennameMain.TabIndex = 0;
+            tlp_RennameMain.TagString = null;
+            // 
+            // tlp_RennameInput
+            // 
+            tlp_RennameInput.ColumnCount = 4;
+            tlp_RennameInput.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tlp_RennameInput.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tlp_RennameInput.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tlp_RennameInput.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tlp_RennameInput.Controls.Add(lb_OriginalName, 1, 0);
+            tlp_RennameInput.Controls.Add(bl_NewName, 1, 1);
+            tlp_RennameInput.Controls.Add(txt_OriginalName, 2, 0);
+            tlp_RennameInput.Controls.Add(txt_NewName, 2, 1);
+            tlp_RennameInput.Dock = DockStyle.Fill;
+            tlp_RennameInput.Location = new Point(3, 3);
+            tlp_RennameInput.Name = "tlp_RennameInput";
+            tlp_RennameInput.RowCount = 2;
+            tlp_RennameInput.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+            tlp_RennameInput.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+            tlp_RennameInput.Size = new Size(435, 115);
+            tlp_RennameInput.TabIndex = 0;
+            tlp_RennameInput.TagString = null;
+            // 
+            // lb_OriginalName
+            // 
+            lb_OriginalName.AutoSize = true;
+            lb_OriginalName.BackColor = Color.Transparent;
+            lb_OriginalName.Dock = DockStyle.Fill;
+            lb_OriginalName.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            lb_OriginalName.ForeColor = SystemColors.Control;
+            lb_OriginalName.Location = new Point(103, 0);
+            lb_OriginalName.Name = "lb_OriginalName";
+            lb_OriginalName.Size = new Size(94, 57);
+            lb_OriginalName.TabIndex = 0;
+            lb_OriginalName.Text = "鍘熷悕绉帮細";
+            lb_OriginalName.TextAlign = ContentAlignment.MiddleRight;
+            // 
+            // bl_NewName
+            // 
+            bl_NewName.AutoSize = true;
+            bl_NewName.BackColor = Color.Transparent;
+            bl_NewName.Dock = DockStyle.Fill;
+            bl_NewName.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            bl_NewName.ForeColor = SystemColors.Control;
+            bl_NewName.Location = new Point(103, 57);
+            bl_NewName.Name = "bl_NewName";
+            bl_NewName.Size = new Size(94, 58);
+            bl_NewName.TabIndex = 1;
+            bl_NewName.Text = "鏂板悕绉帮細";
+            bl_NewName.TextAlign = ContentAlignment.MiddleRight;
+            // 
+            // txt_OriginalName
+            // 
+            txt_OriginalName.BackColor = Color.FromArgb(32, 41, 50);
+            txt_OriginalName.Dock = DockStyle.Fill;
+            txt_OriginalName.EnabledCalc = true;
+            txt_OriginalName.Font = new Font("Microsoft YaHei UI", 12F);
+            txt_OriginalName.ForeColor = SystemColors.WindowText;
+            txt_OriginalName.Location = new Point(203, 3);
+            txt_OriginalName.MaxLength = 32767;
+            txt_OriginalName.MultiLine = false;
+            txt_OriginalName.Name = "txt_OriginalName";
+            txt_OriginalName.ReadOnly = true;
+            txt_OriginalName.Size = new Size(129, 51);
+            txt_OriginalName.TabIndex = 2;
+            txt_OriginalName.TextAlign = HorizontalAlignment.Center;
+            txt_OriginalName.UseSystemPasswordChar = false;
+            // 
+            // txt_NewName
+            // 
+            txt_NewName.BackColor = Color.FromArgb(32, 41, 50);
+            txt_NewName.Dock = DockStyle.Fill;
+            txt_NewName.EnabledCalc = true;
+            txt_NewName.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            txt_NewName.ForeColor = Color.FromArgb(124, 133, 142);
+            txt_NewName.Location = new Point(203, 60);
+            txt_NewName.MaxLength = 32767;
+            txt_NewName.MultiLine = false;
+            txt_NewName.Name = "txt_NewName";
+            txt_NewName.ReadOnly = false;
+            txt_NewName.Size = new Size(129, 52);
+            txt_NewName.TabIndex = 3;
+            txt_NewName.TextAlign = HorizontalAlignment.Center;
+            txt_NewName.UseSystemPasswordChar = false;
+            // 
+            // tlp_RennameOperator
+            // 
+            tlp_RennameOperator.ColumnCount = 5;
+            tlp_RennameOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tlp_RennameOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tlp_RennameOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
+            tlp_RennameOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tlp_RennameOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 101F));
+            tlp_RennameOperator.Controls.Add(btn_Rename, 1, 0);
+            tlp_RennameOperator.Controls.Add(btn_Cancel, 3, 0);
+            tlp_RennameOperator.Dock = DockStyle.Fill;
+            tlp_RennameOperator.Location = new Point(3, 124);
+            tlp_RennameOperator.Name = "tlp_RennameOperator";
+            tlp_RennameOperator.RowCount = 1;
+            tlp_RennameOperator.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tlp_RennameOperator.Size = new Size(435, 54);
+            tlp_RennameOperator.TabIndex = 1;
+            tlp_RennameOperator.TagString = null;
+            // 
+            // btn_Rename
+            // 
+            btn_Rename.BackColor = Color.Transparent;
+            btn_Rename.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_Rename.Cursor = Cursors.Hand;
+            btn_Rename.Dock = DockStyle.Fill;
+            btn_Rename.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Rename.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_Rename.Font = new Font("Microsoft Sans Serif", 12F);
+            btn_Rename.Image = null;
+            btn_Rename.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_Rename.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_Rename.Location = new Point(103, 3);
+            btn_Rename.Name = "btn_Rename";
+            btn_Rename.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Rename.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_Rename.Size = new Size(86, 48);
+            btn_Rename.TabIndex = 0;
+            btn_Rename.Text = "閲嶅懡鍚�";
+            btn_Rename.TextAlignment = StringAlignment.Center;
+            btn_Rename.Click += btn_Rename_Click;
+            // 
+            // btn_Cancel
+            // 
+            btn_Cancel.BackColor = Color.Transparent;
+            btn_Cancel.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_Cancel.Cursor = Cursors.Hand;
+            btn_Cancel.Dock = DockStyle.Fill;
+            btn_Cancel.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Cancel.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_Cancel.Font = new Font("Microsoft Sans Serif", 12F);
+            btn_Cancel.Image = null;
+            btn_Cancel.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_Cancel.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_Cancel.Location = new Point(245, 3);
+            btn_Cancel.Name = "btn_Cancel";
+            btn_Cancel.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Cancel.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_Cancel.Size = new Size(86, 48);
+            btn_Cancel.TabIndex = 1;
+            btn_Cancel.Text = "鍙栨秷";
+            btn_Cancel.TextAlignment = StringAlignment.Center;
+            btn_Cancel.Click += btn_Cancel_Click;
+            // 
+            // RenameForm
+            // 
+            AutoScaleDimensions = new SizeF(96F, 96F);
+            AutoScaleMode = AutoScaleMode.Dpi;
+            ClientSize = new Size(461, 260);
+            Controls.Add(theme_RenameForm);
+            FormBorderStyle = FormBorderStyle.None;
+            MinimumSize = new Size(261, 61);
+            Name = "RenameForm";
+            Text = "閲嶅懡鍚嶈缃�";
+            TransparencyKey = Color.Fuchsia;
+            theme_RenameForm.ResumeLayout(false);
+            tlp_RennameMain.ResumeLayout(false);
+            tlp_RennameInput.ResumeLayout(false);
+            tlp_RennameInput.PerformLayout();
+            tlp_RennameOperator.ResumeLayout(false);
+            ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private ReaLTaiizor.Forms.ThemeForm theme_RenameForm;
+        private Sunny.UI.UITableLayoutPanel tlp_RennameMain;
+        private Sunny.UI.UITableLayoutPanel tlp_RennameInput;
+        private Sunny.UI.UITableLayoutPanel tlp_RennameOperator;
+        private ReaLTaiizor.Controls.BigLabel lb_OriginalName;
+        private ReaLTaiizor.Controls.BigLabel bl_NewName;
+        private ReaLTaiizor.Controls.Button btn_Rename;
+        private ReaLTaiizor.Controls.Button btn_Cancel;
+        private ReaLTaiizor.Controls.AloneTextBox txt_OriginalName;
+        private ReaLTaiizor.Controls.AloneTextBox txt_NewName;
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionControl/Forms/RenameForm.cs b/LB_VisionControl/Forms/RenameForm.cs
new file mode 100644
index 0000000..6bfc53f
--- /dev/null
+++ b/LB_VisionControl/Forms/RenameForm.cs
@@ -0,0 +1,69 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace VisionControl.Forms
+{
+    public partial class RenameForm : Form
+    {
+        // 瀹氫箟涓�涓鎵樺拰浜嬩欢
+        public delegate void UpdateStringHandler(string oriString, string newString);
+        public event UpdateStringHandler UpdateStringEvent;
+        public bool bRename = false;
+        public string strOriName { get; set; }
+        public string strNewName { get; set; }
+
+        public bool bCheckBan = true;
+
+        public RenameForm(string strOrigin = "", bool bCheckBan = true)
+        {
+            InitializeComponent();
+            // 绂佹淇敼绐楀彛澶у皬
+            this.FormBorderStyle = FormBorderStyle.FixedDialog;
+            this.txt_OriginalName.Text = strOrigin;
+            this.txt_NewName.Text = strOrigin;
+            this.bCheckBan = bCheckBan;
+        }
+
+        private void btn_Cancel_Click(object sender, EventArgs e)
+        {
+            this.Close();
+        }
+        List<string> banStr = new List<string>() { ",", ".", "\\", "/", ":", "*", "?", "\"", "<", ">", "|", "\0" };
+
+        private void btn_Rename_Click(object sender, EventArgs e)
+        {
+            if (string.IsNullOrEmpty(this.txt_NewName.Text.Trim()))
+            {
+                MessageBox.Show("鍚嶇О涓嶅厑璁镐负绌�", "寮傚父");
+                return;
+            }
+
+            if (bCheckBan)
+            {
+                foreach (string str in banStr)
+                {
+                    if (this.txt_NewName.Text.Contains(str))
+                    {
+                        MessageBox.Show("鍚嶇О涓嶅厑璁稿嚭鐜�, . \\ / : * ? \" < > | 绛夊瓧绗�", "寮傚父");
+                        return;
+                    }
+                }
+            }
+
+            // 瑙﹀彂浜嬩欢锛岄�氱煡鐖剁獥浣撴洿鏂皊tring
+            UpdateStringEvent?.Invoke(this.txt_OriginalName.Text, this.txt_NewName.Text);
+            bRename = true;
+            strOriName = this.txt_OriginalName.Text;
+            strNewName = this.txt_NewName.Text;
+            this.Close();
+
+        }
+    }
+}
diff --git a/LB_VisionControl/Forms/RenameForm.resx b/LB_VisionControl/Forms/RenameForm.resx
new file mode 100644
index 0000000..0ffce30
--- /dev/null
+++ b/LB_VisionControl/Forms/RenameForm.resx
@@ -0,0 +1,139 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="theme_RenameForm.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        vwAADr8BOAVTJAAAAt9JREFUSEvtVc9rU0EQflGrUqtVa0l2J01siGZ3XpoKKQgqVr3oxYuK4KH0UFDB
+        P0Dx4g8UxJsHbz2LeCiCF0ElatWa7E4SoVLoQa+iUkS0Vq2tzEuiyctre9CDBwe+03zvm9lvZ+c5zv/4
+        k7DZbMtYKrzZutH9FuUp0nCBUF4uIpwpaBigNGRuOc5y/3dLRi4eX21c2GNRDlsUk6Tgs0X4QQjzDIMw
+        ZxBeWy2P2qzTQjoSH8fONr9OUITKmXA3IVwnhPc1wXqwOGmwFmFfrt9ZYVzYaxWUrIYbeR125x0n5Bf1
+        ghOUjvSRhiemrtsGKPhOGu6QG9HnHGdZMSV3GAUva4W5UFFF+wOLFFQ0TQjW69AvjDBvUcywZUbFBPOL
+        LvQSAvl5XsFUV1+D+GhPbAOhHFlInO+AEK4yj/nlTKybtMgF8SsWyruPk5HOmn7IoBwkFNN+crWjTzw9
+        tUvMK9lhEG4uaGP1tEbLk55VE6mOtRbhnp9UgZgmDRfLmfAaFp9MJlfxmBolvjZzG2FQPir1xtc7PMuk
+        4I2fQEp8I5TXuAEW526KCEesElNN3GC8IyWyDrnyoEEx01idvZUjxTofC1tiCZ6SAKFAFLhBFw45Rolj
+        3vjVEzRMlFU0XRPnebdaXiGEWb/QIpglFwa8E/Cl/E6IL4RwnOe8VuBFj0xZhFcBIgujcoLDTgnlNoPw
+        tpYwCM/qreEwWgw1nXIJGCWmjIbtjs0m2i3Kh1XxOavhrP8lWoRLfoEloUTebhWbKisC4YRnkxbTeYwe
+        qBfnMDo6VJmqAKEg8GkVnP5lM1vCr48QPpKO7PYX4E54TRCKD0Gv1w+2ueDKrgYRSnf1ecsK5WBDoho5
+        7GzjDUoazvNLJiUeWA1PCcUYKRg1CPctwm2LMFxyxU6/zZ5VZRS7eC08T25c15BsjBD/A2xWtDLPJhLt
+        3jbIitZxxJWL/oC8+9CROKW6pD/3t6N5n/+r8RMPp2HDn8xmcgAAAABJRU5ErkJggg==
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionControl/LB_VisionControl.csproj b/LB_VisionControl/LB_VisionControl.csproj
new file mode 100644
index 0000000..8e982c6
--- /dev/null
+++ b/LB_VisionControl/LB_VisionControl.csproj
@@ -0,0 +1,54 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Library</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <Nullable>enable</Nullable>
+    <UseWindowsForms>true</UseWindowsForms>
+    <ImplicitUsings>enable</ImplicitUsings>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Compile Remove="Form1.cs" />
+    <Compile Remove="Form1.Designer.cs" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <EmbeddedResource Remove="Form1.resx" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
+    <PackageReference Include="OpenCvSharp4" Version="4.11.0.20250507" />
+    <PackageReference Include="OpenCvSharp4.Extensions" Version="4.11.0.20250507" />
+    <PackageReference Include="OpenCvSharp4.runtime.win" Version="4.11.0.20250507" />
+    <PackageReference Include="ReaLTaiizor" Version="3.8.1.4" />
+    <PackageReference Include="SunnyUI" Version="3.9.0" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\LB_SmartVisionCommon\LB_SmartVisionCommon.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Reference Include="halcondotnet">
+      <HintPath>ref\halcondotnet.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Update="Properties\Resources.Designer.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <EmbeddedResource Update="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+
+</Project>
\ No newline at end of file
diff --git a/LB_VisionControl/Program.cs b/LB_VisionControl/Program.cs
new file mode 100644
index 0000000..82ea03e
--- /dev/null
+++ b/LB_VisionControl/Program.cs
@@ -0,0 +1,18 @@
+锘縰sing LB_VisionControl.ScriptEditControl;
+
+namespace LB_VisionControl
+{
+    internal static class Program
+    {
+        /// <summary>
+        /// 搴旂敤绋嬪簭鐨勪富鍏ュ彛鐐广��
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            Application.EnableVisualStyles();
+            Application.SetCompatibleTextRenderingDefault(false);
+            Application.Run(new ScriptEditForm());
+        }
+    }
+}
diff --git a/LB_VisionControl/Properties/Resources.Designer.cs b/LB_VisionControl/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..b013dd7
--- /dev/null
+++ b/LB_VisionControl/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+锘�//------------------------------------------------------------------------------
+// <auto-generated>
+//     姝や唬鐮佺敱宸ュ叿鐢熸垚銆�
+//     杩愯鏃剁増鏈�:4.0.30319.42000
+//
+//     瀵规鏂囦欢鐨勬洿鏀瑰彲鑳戒細瀵艰嚧涓嶆纭殑琛屼负锛屽苟涓斿鏋�
+//     閲嶆柊鐢熸垚浠g爜锛岃繖浜涙洿鏀瑰皢浼氫涪澶便��
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace LB_VisionControl.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   涓�涓己绫诲瀷鐨勮祫婧愮被锛岀敤浜庢煡鎵炬湰鍦板寲鐨勫瓧绗︿覆绛夈��
+    /// </summary>
+    // 姝ょ被鏄敱 StronglyTypedResourceBuilder
+    // 绫婚�氳繃绫讳技浜� ResGen 鎴� Visual Studio 鐨勫伐鍏疯嚜鍔ㄧ敓鎴愮殑銆�
+    // 鑻ヨ娣诲姞鎴栫Щ闄ゆ垚鍛橈紝璇风紪杈� .ResX 鏂囦欢锛岀劧鍚庨噸鏂拌繍琛� ResGen
+    // (浠� /str 浣滀负鍛戒护閫夐」)锛屾垨閲嶆柊鐢熸垚 VS 椤圭洰銆�
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.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 (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LB_VisionControl.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/LB_VisionControl/Properties/Resources.resx b/LB_VisionControl/Properties/Resources.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/LB_VisionControl/Properties/Resources.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/LB_VisionControl/ROI.cs b/LB_VisionControl/ROI.cs
new file mode 100644
index 0000000..119c7bf
--- /dev/null
+++ b/LB_VisionControl/ROI.cs
@@ -0,0 +1,580 @@
+锘縰sing HalconDotNet;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using OpenCvSharp;
+using System;
+using System.Collections.Generic;
+using System.Data.Common;
+using System.Diagnostics;
+using System.Formats.Asn1;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static System.Windows.Forms.AxHost;
+
+namespace LB_VisionControl
+{
+    public enum RoiType { None, Rectangle2, Circle, Ellipse, Segment };
+
+    public class ROI
+    {
+        // 浣犲彲浠ュ湪鐖剁被涓畾涔変竴浜涘叕鍏卞睘鎬ф垨鏂规硶
+        public string Type = "ROI";  // 绫诲瀷鏍囪瘑绗�
+
+        public double Z = 0;
+
+        public double Column = 0;
+        public double X
+        {
+            get { return Column; }
+            set
+            {
+                double result = 0;
+                value = double.TryParse(value.ToString(), out result) ? result : 0;
+                Column = value;
+            }
+        }
+
+        public double Row = 0;
+        public double Y
+        {
+            get { return Row; }
+            set
+            {
+                double result = 0;
+                value = double.TryParse(value.ToString(), out result) ? result : 0;
+                Row = value;
+            }
+        }
+
+        public double Phi = 0;
+        public double Angle
+        {
+            get { return Phi * 180 / Math.PI; }
+            set
+            {
+                double result = 0;
+                value = double.TryParse(value.ToString(), out result) ? result : 0;
+                Phi = (value / 180 * Math.PI);
+            }
+        }
+        public double Rotation
+        {
+            get { return Phi; }
+            set
+            {
+                double result = 0;
+                value = double.TryParse(value.ToString(), out result) ? result : 0;
+                Phi = value;
+            }
+        }
+
+        public object Clone()
+        { return MemberwiseClone(); }
+    }
+    [Serializable]
+    public class HRectangle2 : ROI
+    {
+        public HRectangle2() { Type = "HRectangle2"; }
+
+        //public HRectangle2(HTuple row, HTuple column, HTuple phi, HTuple length1, HTuple length2)
+        //{
+        //    Type = "HRectangle2";
+        //    this.Row = row.TupleReal();
+        //    this.Column = column.TupleReal();
+        //    this.Phi = phi.TupleReal();
+        //    this.SemiLength1 = length1.TupleReal();
+        //    this.SemiLength2 = length2.TupleReal();
+        //}
+
+        // 甯︾鏈夊弬鏁扮殑鏋勯�犲嚱鏁�
+        [JsonConstructor]  // 鏍囪涓虹敤浜庡弽搴忓垪鍖�
+        public HRectangle2(double X = 0, double Y = 0, double rotation = 0, double width = 800, double height = 800)
+        {
+            Type = "HRectangle2";
+            this.X = X;
+            this.Y = Y;
+            Rotation = rotation;
+            Width = width;
+            Height = height;
+        }
+
+        public HObject GetHObject()
+        {
+            HOperatorSet.GenRectangle2(out HObject hObject, (HTuple)Row, (HTuple)Column, (HTuple)Phi, (HTuple)SemiLength1, (HTuple)SemiLength2);
+            return hObject;
+        }
+
+        /// <summary>
+        /// 鐭╁舰瀹藉害鐨勪竴鍗�
+        /// </summary>
+        public double SemiLength1 = 200;
+        /// <summary>
+        /// 鐭╁舰瀹藉害
+        /// </summary>
+        public double Width
+        {
+            get { return SemiLength1 * 2; }
+            set
+            {
+                double result = 0;
+                value = double.TryParse(value.ToString(), out result) ? result : 0;
+                SemiLength1 = (value / 2.0);
+            }
+        }
+
+        /// <summary>
+        /// 鐭╁舰楂樺害鐨勪竴鍗�
+        /// </summary>
+        public double SemiLength2 = 200;
+        public double Height
+        {
+            get { return SemiLength2 * 2; }
+            set
+            {
+                double result = 0;
+                value = double.TryParse(value.ToString(), out result) ? result : 0;
+                SemiLength2 = (value / 2.0);
+            }
+        }
+
+        public HPoint[] Corners
+        {
+            get
+            {
+                // 璁$畻鏈棆杞煩褰㈢殑瑙掔偣鐩稿浜庝腑蹇冪殑鍧愭爣
+                var corners = new HPoint[]
+                {
+                    new HPoint(-Width / 2, -Height / 2), // 宸︿笂瑙�
+                    new HPoint(Width / 2, -Height / 2),  // 鍙充笂瑙�
+                    new HPoint(Width / 2, Height / 2),   // 鍙充笅瑙�
+                    new HPoint(-Width / 2, Height / 2)   // 宸︿笅瑙�
+                };
+
+                // 鏃嬭浆鐭╁舰鐨勮鐐�
+                for (int i = 0; i < corners.Length; i++)
+                {
+                    double x = corners[i].X;
+                    double y = corners[i].Y;
+
+                    // 鏃嬭浆鐭╅樀搴旂敤
+                    double rotatedX = x * Math.Cos(Rotation) - y * Math.Sin(Rotation);
+                    double rotatedY = x * Math.Sin(Rotation) + y * Math.Cos(Rotation);
+
+                    // 绉诲姩鍒板疄闄呬綅缃�
+                    corners[i] = new HPoint(rotatedX + X, rotatedY + Y);
+                }
+
+                return corners;
+            }
+        }
+    }
+
+    [Serializable]
+    public class HCircle : ROI
+    {
+        public HCircle() { Type = "HCircle"; }
+
+        //public HCircle(HTuple row, HTuple column, HTuple radius)
+        //{
+        //    Type = "HCircle";
+        //    this.Row = row.TupleReal();
+        //    this.Column = column.TupleReal();
+        //    this.Radius = radius.TupleReal();
+        //}
+
+        // 甯︾鏈夊弬鏁扮殑鏋勯�犲嚱鏁�
+        [JsonConstructor]  // 鏍囪涓虹敤浜庡弽搴忓垪鍖�
+        public HCircle(double X = 0, double Y = 0, double radius = 100)
+        {
+            Type = "HCircle";
+            this.X = X;
+            this.Y = Y;
+            Radius = radius;
+        }
+
+        public double Radius = 100;
+        public double Diameter
+        {
+            get { return Radius * 2; }
+            set
+            {
+                double result = 0;
+                value = double.TryParse(value.ToString(), out result) ? result : 0;
+                Radius = value / 2.0;
+            }
+        }
+    }
+
+    public class HEllipse : ROI
+    {
+        public HEllipse() { Type = "HEllipse"; }
+
+        // 甯︾鏈夊弬鏁扮殑鏋勯�犲嚱鏁�
+        [JsonConstructor]  // 鏍囪涓虹敤浜庡弽搴忓垪鍖�
+        public HEllipse(double x, double y, double phi, double radius1, double radius2, double start_angle = 0, double end_angle = Math.PI)
+        {
+            Type = "HEllipse";
+            this.X = x;
+            this.Y = y;
+            this.Phi = phi;
+            Radius1 = radius1;
+            Radius2 = radius2;
+            StartAngle = start_angle;
+            EndAngle = end_angle;
+        }
+
+        public double Radius1 = 100;
+        public double Radius2 = 100;
+        public double StartAngle = 0;
+        public double EndAngle = Math.PI;
+    }
+
+    [Serializable]
+    public class HSegment : ROI
+    {
+        public HSegment() { Type = "HSegment"; }
+
+        // 甯︾鏈夊弬鏁扮殑鏋勯�犲嚱鏁�
+        [JsonConstructor]  // 鏍囪涓虹敤浜庡弽搴忓垪鍖�
+        public HSegment(double startX = 0, double startY = 0, double endX = 0, double endY = 0)
+        {
+            Type = "HSegment";
+            StartX = startX;
+            StartY = startY;
+            EndX = endX;
+            EndY = endY;
+        }
+
+        public HSegment(HPoint startPoint, HPoint endPoint)
+        {
+            Type = "HSegment";
+            BeginRow = startPoint.Row;
+            BeginColumn = startPoint.Column;
+            EndRow = endPoint.Row;
+            EndColumn = endPoint.Column;
+        }
+
+        public HObject GetHObject()
+        {
+            HOperatorSet.GenRegionLine(out HObject hObject, (HTuple)BeginRow, (HTuple)BeginColumn, (HTuple)EndRow, (HTuple)EndColumn);
+            return hObject;
+        }
+
+        public HPoint StartPoint
+        {
+            get { return new HPoint(BeginColumn, BeginRow); }
+            set { BeginRow = value.Row; BeginColumn = value.Column; }
+        }
+
+        public HPoint EndPoint
+        {
+            get { return new HPoint(EndColumn, EndRow); }
+            set { EndRow = value.Row; EndColumn = value.Column; }
+        }
+
+        public double BeginColumn = 0;
+        public double StartX
+        {
+            get { return BeginColumn; }
+            set
+            {
+                double result = 0;
+                value = double.TryParse(value.ToString(), out result) ? result : 0;
+                BeginColumn = value;
+            }
+        }
+
+        public double BeginRow = 0;
+        public double StartY
+        {
+            get { return BeginRow; }
+            set
+            {
+                double result = 0;
+                value = double.TryParse(value.ToString(), out result) ? result : 0;
+                BeginRow = value;
+            }
+        }
+
+        public double EndColumn = 100;
+        public double EndX
+        {
+            get { return EndColumn; }
+            set
+            {
+                double result = 0;
+                value = double.TryParse(value.ToString(), out result) ? result : 0;
+                EndColumn = value;
+            }
+        }
+
+        public double EndRow = 100;
+        public double EndY
+        {
+            get
+            {
+                return EndRow;
+            }
+            set
+            {
+                double result = 0;
+                value = double.TryParse(value.ToString(), out result) ? result : 0;
+                EndRow = value;
+            }
+        }
+
+        public double MidX
+        {
+            get { return (StartX + EndX) / 2; }
+        }
+
+        public double MidY
+        {
+            get { return (StartY + EndY) / 2; }
+        }
+
+        public double Length
+        {
+            get { return Math.Sqrt(Math.Pow(StartX - EndX, 2) + Math.Pow(StartX - EndY, 2)); }
+        }
+    }
+
+    [Serializable]
+    public class HLine : ROI
+    {
+        public HLine() { Type = "HLine"; }
+
+        // 甯︾鏈夊弬鏁扮殑鏋勯�犲嚱鏁�
+        [JsonConstructor]  // 鏍囪涓虹敤浜庡弽搴忓垪鍖�
+        public HLine(double x = 0, double y = 0, double phi = 0)
+        {
+            Type = "HLine";
+            X = x;
+            Y = y;
+            Phi = phi;
+        }
+
+        public HLine(HPoint point, double phi = 0)
+        {
+            Type = "HLine";
+            X = point.Row;
+            Y = point.Column;
+            Phi = phi;
+        }
+    }
+
+    [Serializable]
+    public class HPoint : ROI
+    {
+        public HPoint() { Type = "HPoint"; }
+
+        // 甯︾鏈夊弬鏁扮殑鏋勯�犲嚱鏁�
+        [JsonConstructor]  // 鏍囪涓虹敤浜庡弽搴忓垪鍖�
+        public HPoint(double x, double y, double z = 0)
+        {
+            Type = "HPoint";
+            X = x;
+            Y = y;
+            Z = z;
+        }
+
+        public HPoint(OpenCvSharp.Point point)
+        {
+            Type = "HPoint";
+            X = point.X;
+            Y = point.Y;
+        }
+
+        public HPoint(HPoint point)
+        {
+            Type = "HPoint";
+            X = point.X;
+            Y = point.Y;
+        }
+
+        public HObject GetHObject()
+        {
+            HOperatorSet.GenRegionPoints(out HObject hObject, (HTuple)Row, (HTuple)Column);
+            return hObject;
+        }
+
+        public Point2d ToPoint2d() { return new Point2d(X, Y); }
+    }
+
+    public class ROIConverter : JsonConverter
+    {
+        public override bool CanConvert(Type objectType)
+        {
+            return objectType == typeof(ROI);
+        }
+
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            JObject jo = JObject.Load(reader);  // 鍙皟鐢ㄤ竴娆� Load(reader)
+            if (jo != null)
+            {
+                var type = jo["Type"]?.ToString();  // 鑾峰彇绫诲瀷鏍囪瘑绗�
+
+                // 鏍规嵁绫诲瀷鏍囪瘑绗﹀弽搴忓垪鍖栦负鍏蜂綋绫诲瀷
+                switch (type)
+                {
+                    case "ROI":
+                        return jo.ToObject<ROI>();
+                    case "HRectangle2":
+                        return jo.ToObject<HRectangle2>();
+                    case "HCircle":
+                        return jo.ToObject<HCircle>();
+                    case "HSegment":
+                        return jo.ToObject<HSegment>();
+                    case "HLine":
+                        return jo.ToObject<HLine>();
+                    case "HPoint":
+                        return jo.ToObject<HPoint>();
+                    default:
+                        // 鍏朵粬绫诲瀷鐨勫鐞嗘柟寮�
+                        throw new JsonSerializationException($"Unknown type: {type}");
+                }
+            }
+            return null;
+        }
+
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            try
+            {
+                if (value != null)
+                {
+                    // 鍒涘缓涓�涓� JObject 鏉ュ簭鍒楀寲 ROI 瀵硅薄
+                    JObject jo = JObject.FromObject(value, serializer);
+                    var type = value.GetType().Name;
+                    // 鏍规嵁绫诲瀷鏍囪瘑绗﹀弽搴忓垪鍖栦负鍏蜂綋绫诲瀷
+                    switch (type)
+                    {
+                        case "ROI":
+                            ROI roi = value as ROI;
+                            if (roi == null)
+                                throw new JsonSerializationException($"Convert {type} to null");
+
+                            // 寮�濮嬪啓鍏� JSON 瀵硅薄
+                            writer.WriteStartObject();
+
+                            writer.WritePropertyName("Type");
+                            writer.WriteValue(roi.Type);
+
+                            // 缁撴潫瀵硅薄
+                            writer.WriteEndObject();
+                            break;
+                        case "HRectangle2":
+                            HRectangle2 hRectangle2 = value as HRectangle2;
+                            if (hRectangle2 == null)
+                                throw new JsonSerializationException($"Convert {type} to null");
+
+                            // 寮�濮嬪啓鍏� JSON 瀵硅薄
+                            writer.WriteStartObject();
+
+                            writer.WritePropertyName("Type");
+                            writer.WriteValue(hRectangle2.Type);
+
+                            writer.WritePropertyName("X");
+                            writer.WriteValue(hRectangle2.X);
+
+                            writer.WritePropertyName("Y");
+                            writer.WriteValue(hRectangle2.Y);
+
+                            writer.WritePropertyName("Rotation");
+                            writer.WriteValue(hRectangle2.Rotation);
+
+                            writer.WritePropertyName("Width");
+                            writer.WriteValue(hRectangle2.Width);
+
+                            writer.WritePropertyName("Height");
+                            writer.WriteValue(hRectangle2.Height);
+
+                            // 缁撴潫瀵硅薄
+                            writer.WriteEndObject();
+                            break;
+                        case "HCircle":
+                            HCircle hCircle = value as HCircle;
+                            if (hCircle == null)
+                                throw new JsonSerializationException($"Convert {type} to null");
+
+                            // 寮�濮嬪啓鍏� JSON 瀵硅薄
+                            writer.WriteStartObject();
+
+                            writer.WritePropertyName("Type");
+                            writer.WriteValue(hCircle.Type);
+
+                            writer.WritePropertyName("X");
+                            writer.WriteValue(hCircle.X);
+
+                            writer.WritePropertyName("Y");
+                            writer.WriteValue(hCircle.Y);
+
+                            writer.WritePropertyName("Radius");
+                            writer.WriteValue(hCircle.Radius);
+
+                            // 缁撴潫瀵硅薄
+                            writer.WriteEndObject();
+                            break;
+                        case "HPoint":
+                            HPoint hPoint = value as HPoint;
+                            if (hPoint == null)
+                                throw new JsonSerializationException($"Convert {type} to null");
+
+                            // 寮�濮嬪啓鍏� JSON 瀵硅薄
+                            writer.WriteStartObject();
+
+                            writer.WritePropertyName("Type");
+                            writer.WriteValue(hPoint.Type);
+
+                            writer.WritePropertyName("X");
+                            writer.WriteValue(hPoint.X);
+
+                            writer.WritePropertyName("Y");
+                            writer.WriteValue(hPoint.Y);
+
+                            // 缁撴潫瀵硅薄
+                            writer.WriteEndObject();
+                            break;
+                        case "HSegment":
+                            HSegment hSegment = value as HSegment;
+                            if (hSegment == null)
+                                throw new JsonSerializationException($"Convert {type} to null");
+
+                            // 寮�濮嬪啓鍏� JSON 瀵硅薄
+                            writer.WriteStartObject();
+
+                            writer.WritePropertyName("Type");
+                            writer.WriteValue(hSegment.Type);
+
+                            writer.WritePropertyName("StartX");
+                            writer.WriteValue(hSegment.StartX);
+
+                            writer.WritePropertyName("StartY");
+                            writer.WriteValue(hSegment.StartY);
+
+                            writer.WritePropertyName("EndX");
+                            writer.WriteValue(hSegment.EndX);
+
+                            writer.WritePropertyName("EndY");
+                            writer.WriteValue(hSegment.EndY);
+
+                            // 缁撴潫瀵硅薄
+                            writer.WriteEndObject();
+                            break;
+                        case "HLine":
+                        default:
+                            // 鍏朵粬绫诲瀷鐨勫鐞嗘柟寮�
+                            throw new JsonSerializationException($"Unsupport convert {type}");
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                // 杈撳嚭寮傚父淇℃伅杩涜璋冭瘯
+                Debug.WriteLine($"Error: {ex.Message}");
+            }
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/ClassFileList.Designer.cs b/LB_VisionControl/ScriptEditControl/ClassFileList.Designer.cs
new file mode 100644
index 0000000..df4b91b
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ClassFileList.Designer.cs
@@ -0,0 +1,86 @@
+锘縩amespace LB_VisionControl.ScriptEditControl
+{
+    partial class ClassFileList
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.listBox1 = new System.Windows.Forms.ListBox();
+            this.textBox1 = new System.Windows.Forms.TextBox();
+            this.SuspendLayout();
+            // 
+            // listBox1
+            // 
+            this.listBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.listBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(17)))), ((int)(((byte)(18)))));
+            this.listBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
+            this.listBox1.Font = new System.Drawing.Font("寰蒋闆呴粦", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.listBox1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(128)))));
+            this.listBox1.FormattingEnabled = true;
+            this.listBox1.ItemHeight = 17;
+            this.listBox1.Location = new System.Drawing.Point(0, 14);
+            this.listBox1.Name = "listBox1";
+            this.listBox1.Size = new System.Drawing.Size(483, 85);
+            this.listBox1.TabIndex = 0;
+            this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
+            this.listBox1.DoubleClick += new System.EventHandler(this.listBox1_DoubleClick);
+            // 
+            // textBox1
+            // 
+            this.textBox1.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.textBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(17)))), ((int)(((byte)(18)))));
+            this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+            this.textBox1.Font = new System.Drawing.Font("寰蒋闆呴粦", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.textBox1.ForeColor = System.Drawing.Color.Green;
+            this.textBox1.Location = new System.Drawing.Point(0, 100);
+            this.textBox1.Multiline = true;
+            this.textBox1.Name = "textBox1";
+            this.textBox1.Size = new System.Drawing.Size(483, 105);
+            this.textBox1.TabIndex = 1;
+            this.textBox1.Text = "鏂囦欢绯荤粺";
+            // 
+            // ClassFileList
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.textBox1);
+            this.Controls.Add(this.listBox1);
+            this.Name = "ClassFileList";
+            this.Size = new System.Drawing.Size(483, 208);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.ListBox listBox1;
+        private System.Windows.Forms.TextBox textBox1;
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/ClassFileList.cs b/LB_VisionControl/ScriptEditControl/ClassFileList.cs
new file mode 100644
index 0000000..1c7f99c
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ClassFileList.cs
@@ -0,0 +1,59 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.IO;
+using System.Text.RegularExpressions;
+using LB_VisionControl.ScriptEditControl.FastColorTextBox;
+namespace LB_VisionControl.ScriptEditControl
+{
+    public partial class ClassFileList : UserControl
+    {
+        public ClassFileList()
+        {
+            InitializeComponent();
+            LoadFile();
+        }
+        public FastColoredTextBox fctb { get; set; }
+        public void LoadFile()
+        {
+            if (!Directory.Exists(CommConfig.ClassLibPath))
+            {
+                textBox1.Text = "鏃犲彲鐢ㄦ枃浠讹紒";
+                return;
+
+            }
+            foreach (var i in Directory.GetFiles(CommConfig.ClassLibPath))
+            {
+                listBox1.Items.Add(i);
+            }
+        }
+
+        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            string s = File.ReadAllText(listBox1.Text);
+            Regex reg = new Regex(@"(?<!/)/\*([^*/]|\*(?!/)|/(?<!\*))*((?=\*/))(\*/)");
+            Match m = reg.Match(s, 0);
+            if (m.Success)
+            {
+                textBox1.Text = m.Value;
+            }
+            else
+            {
+                textBox1.Text = "鏃犲彲鐢ㄦ暟鎹�";
+            }
+        }
+
+        private void listBox1_DoubleClick(object sender, EventArgs e)
+        {
+            if (fctb != null)
+            {
+                fctb.Text = File.ReadAllText(listBox1.Text);
+            }
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/ClassFileList.resx b/LB_VisionControl/ScriptEditControl/ClassFileList.resx
new file mode 100644
index 0000000..758fd19
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ClassFileList.resx
@@ -0,0 +1,129 @@
+锘�<?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=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>
+  <metadata name="listBox1.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="textBox1.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionControl/ScriptEditControl/CommConfig.cs b/LB_VisionControl/ScriptEditControl/CommConfig.cs
new file mode 100644
index 0000000..eb06de4
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/CommConfig.cs
@@ -0,0 +1,40 @@
+锘縰sing LB_VisionControl.ScriptEditControl.FastColorTextBox;
+using System.Text;
+//|5|1|a|s|p|x
+namespace LB_VisionControl.ScriptEditControl
+{
+    class CommConfig
+    {
+        public static string AppLocationPath;//闇�瑕佽缃�
+
+
+        public static Brush ErrorMake = Brushes.Red;
+        public static MarkerStyle RedStyle = new MarkerStyle(new SolidBrush(Color.FromArgb(180, Color.Red)));
+        public static string ClassLibPath { get { return AppLocationPath + "\\ClassLib"; } }
+        public static string BinPath { get { return AppLocationPath + "\\bin"; } }
+        public static string ExeFilePath { get { return BinPath + "\\tmp.exe"; } }
+        public static string DllFilePath { get { return BinPath + "\\tmp.dll"; } }
+        public static string SrcFilePath { get { return BinPath + "\\tmp.cs"; } }
+        public static string CscPath
+        {
+            get
+            {
+                return Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.System)) + @"\Microsoft.NET\Framework\v3.5";
+            }
+        }
+        public static string fileName
+        {
+            get
+            {
+                StringBuilder sbr = new StringBuilder();
+                sbr.Append(DateTime.Now.ToLocalTime().ToString("yyyyMMdd"));
+                sbr.Append(DateTime.Now.Hour.ToString());
+                sbr.Append(DateTime.Now.Minute.ToString());
+                sbr.Append(DateTime.Now.Second.ToString());
+                return ClassLibPath + "\\" + sbr.ToString() + ".cs";
+            }
+        }
+
+
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/CommandRun.cs b/LB_VisionControl/ScriptEditControl/CommandRun.cs
new file mode 100644
index 0000000..edae8bb
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/CommandRun.cs
@@ -0,0 +1,91 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Drawing;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    class CommandRun
+    {
+        //public CommandRun(Form1 Tmpform)
+        //{
+        //    this.Tmpform = Tmpform;
+        //}
+        //Form1 Tmpform;
+        ////澶勭悊Csc鍛戒护
+        //public string RunCsc(string cscCommand)
+        //{
+        //    cscCommand = cscCommand.ToLower();
+        //    Regex reg = new Regex(@"\s+");
+        //    string[] strArrys = reg.Split(cscCommand);
+
+        //    ComplieBuilder cp = new ComplieBuilder();
+        //    string srcStr = Tmpform.fctb.Text;
+        //    string comm = "";
+        //    ComplieType cpType = ComplieType.exe;
+        //    bool isWindow = false;
+
+        //    //
+        //    foreach (var i in strArrys)
+        //    {
+        //        if (i == "?" || i == "help")
+        //        {
+        //            return "CSC 缂栬瘧甯姪\n" +
+        //                   "exe        鐢熸垚鏅�歟xe绋嬪簭\n" +
+        //                   "winexe     鐢熸垚绐椾綋exe绋嬪簭\n" +
+        //                   "dll        鐢熸垚绫诲簱绋嬪簭\n" +
+        //                   "wd         浣跨敤绐楀彛鍚姩(鏅�歟xe绋嬪簭鏈夋晥)\n" +
+        //                   "arg:hello  璁剧疆鍙傛暟涓篽ello(鏅�歟xe绋嬪簭鏈夋晥,涓嶈兘鍑虹幇绗﹀彿'鈭�',瑕佽緭鍑虹┖鏍硷細\\s)\n";
+
+        //        }
+        //        if (i == "show")
+        //        {
+        //            Tmpform.AddCsc();
+        //            if (Tmpform.isShow)
+        //                Tmpform.StartMeun();
+        //            return "";
+        //        }
+        //        switch (i)
+        //        {
+        //            case "exe":
+        //                cpType = ComplieType.exe;
+        //                break;
+        //            case "winexe":
+        //                cpType = ComplieType.winexe;
+        //                break;
+        //            case "dll":
+        //                cpType = ComplieType.dll;
+        //                break;
+        //            case "wd":
+        //                isWindow = true;
+        //                break;
+        //        }
+        //        if (i.StartsWith("arg:"))
+        //        {
+        //            string tmp = i;
+        //            tmp = tmp.Replace(@"\\", @"\");
+        //            tmp = tmp.Replace(@"\s", " ");
+        //            comm += tmp.Replace("arg:", "鈭�");
+        //        }
+
+        //    }
+        //    CompliReslut.OutPutStr = cp.Creat(srcStr, comm, cpType, isWindow);
+        //    CompliReslut.isError = cp.isError;
+        //    CompliReslut.isHasErrorRow = cp.isHasErrorRows;
+        //    CompliReslut.RowErrorNumber = cp.RowErrorNumber;
+        //    ErrorMake();
+        //    return CompliReslut.OutPutStr;
+        //}
+
+        //private void ErrorMake()
+        //{
+        //    if (CompliReslut.isError && CompliReslut.isHasErrorRow && CompliReslut.RowErrorNumber != -1)
+        //    {
+        //        Tmpform.fctb[CompliReslut.RowErrorNumber - 1].BackgroundBrush = CommConfig.ErrorMake;
+        //        Tmpform.fctb.Invalidate();
+        //    }
+        //}
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/CompliReslut.cs b/LB_VisionControl/ScriptEditControl/CompliReslut.cs
new file mode 100644
index 0000000..79c7651
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/CompliReslut.cs
@@ -0,0 +1,15 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    class CompliReslut
+    {
+        public static bool isError = false;
+        public static bool isHasErrorRow = false;
+        public static int RowErrorNumber = -1;
+        public static string OutPutStr = "";
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/ComplieBuilder.cs b/LB_VisionControl/ScriptEditControl/ComplieBuilder.cs
new file mode 100644
index 0000000..474dcc4
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ComplieBuilder.cs
@@ -0,0 +1,144 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Threading;
+using System.Text.RegularExpressions;
+namespace LB_VisionControl.ScriptEditControl
+{
+    class ComplieBuilder
+    {
+
+        public string SrcString;
+        public string Command;
+        public ComplieType cpType=ComplieType.exe;
+        public bool isWindow = false;
+        public int RowErrorNumber { get; private set; }
+        public bool isHasErrorRows { get; private set; }
+        public bool isError { get; private set; }
+        public string Creat(string srcString, string Command, ComplieType cpType=ComplieType.exe, bool isStartByWindow=false)
+        {
+            this.SrcString = srcString;
+            this.Command = Command;
+            this.cpType = cpType;
+            this.isWindow = isStartByWindow;
+            this.isHasErrorRows = false;
+            this.RowErrorNumber = -1;
+            isError = false;
+            CreatFile();//
+            StringBuilder sbr = new StringBuilder();
+            sbr.AppendLine(runStringCSC(MakeCommond()));//缂栬瘧
+            if (File.Exists(CommConfig.ExeFilePath) || File.Exists(CommConfig.DllFilePath))
+            {
+                sbr = new StringBuilder();
+                sbr.AppendLine("-------缂栬瘧鎴愬姛--------------------------------");
+                if (cpType == ComplieType.exe || cpType == ComplieType.winexe)//娴嬭瘯*.exe鏂囦欢
+                {
+                    if (isWindow || cpType == ComplieType.winexe)//鍒ゆ柇鏄惁浣跨敤CMD
+                    {
+                        System.Diagnostics.Process.Start(CommConfig.ExeFilePath);
+                    }
+                    else
+                    {
+                        sbr.AppendLine("\n" + runStringTemp(this.Command));
+                    }
+                }
+            }
+            else
+            {
+                isError = true;
+                sbr.AppendLine("-------缂栬瘧澶辫触--------------------------------");
+
+                try
+                {
+                    Regex reg = new Regex(@"\((\d+)\,\d+\)", RegexOptions.Multiline);
+                    Match m = reg.Match(sbr.ToString());
+                    
+                    if (m.Success)
+                    {
+                        isHasErrorRows = true;
+                        RowErrorNumber = int.Parse(m.Groups[1].Value);
+                    }
+                }
+                catch (Exception e)
+                {
+                    isHasErrorRows = false;
+                    RowErrorNumber = -1;
+                }
+            }
+
+            return sbr.ToString();
+        }
+
+        //鏋勫缓鍛戒护
+        private string MakeCommond()
+        {
+            StringBuilder sb = new StringBuilder();
+            switch (cpType)
+            {
+                case ComplieType.exe:
+                    sb.Append("/target:exe /out:"+ CommConfig.ExeFilePath + " " + CommConfig.SrcFilePath);//鏅�歟xe
+                    break;
+                case ComplieType.winexe:
+                    sb.Append("/target:winexe /out:"+ CommConfig.ExeFilePath + " " + CommConfig.SrcFilePath);//Winexe
+                    break;
+                case ComplieType.dll:
+                    sb.Append("/target:library /out:"+ CommConfig.DllFilePath + " " + CommConfig.SrcFilePath);//dll
+                    break;
+                default:
+                    throw new Exception("鏃犳晥鐨勮緭鍏�!");
+            }
+            return sb.ToString();
+        }
+        //娴嬭瘯鐢熸垚鏂囦欢
+        private string runStringTemp(string commond)
+        {
+            System.Diagnostics.Process p = new System.Diagnostics.Process();
+            p.StartInfo.FileName = CommConfig.ExeFilePath;
+            p.StartInfo.UseShellExecute = false;
+            p.StartInfo.RedirectStandardError = true;
+            p.StartInfo.RedirectStandardInput = true;
+            p.StartInfo.RedirectStandardOutput = true;
+            p.StartInfo.CreateNoWindow = true;
+            p.Start();
+            string[] sp = commond.Split('鈭�');
+            foreach (string i in sp)
+            {
+                if (string.IsNullOrEmpty(i))
+                    continue;
+                p.StandardInput.WriteLine(i);
+            }
+            // p.StandardInput.WriteLine(commond);
+            return p.StandardOutput.ReadToEnd();
+
+        }
+        //缂栬瘧鍑芥暟
+        private string runStringCSC(string commond)
+        {
+            System.Diagnostics.Process p = new System.Diagnostics.Process();
+            p.StartInfo.FileName = CommConfig.CscPath + "\\csc.exe";
+            p.StartInfo.Arguments = commond;
+            p.StartInfo.UseShellExecute = false;
+            p.StartInfo.RedirectStandardError = true;
+            p.StartInfo.RedirectStandardInput = true;
+            p.StartInfo.RedirectStandardOutput = true;
+            p.StartInfo.CreateNoWindow = true;
+            p.Start();
+            p.StandardInput.WriteLine(commond);
+            return p.StandardOutput.ReadToEnd();
+
+        }
+        //鐢熸垚鏂囦欢
+        private void CreatFile()
+        {
+            if (Directory.Exists(CommConfig.BinPath))
+                Directory.Delete(CommConfig.BinPath, true);
+            Directory.CreateDirectory(CommConfig.BinPath);
+            Thread.Sleep(500);
+            StreamWriter strCode = new StreamWriter(File.OpenWrite(CommConfig.SrcFilePath), System.Text.Encoding.Default);
+            strCode.WriteLine(SrcString);
+            strCode.Close();
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/ComplieType.cs b/LB_VisionControl/ScriptEditControl/ComplieType.cs
new file mode 100644
index 0000000..de06f98
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ComplieType.cs
@@ -0,0 +1,14 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    enum ComplieType
+    {
+        exe,
+        winexe,
+        dll
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/ComplieUI.Designer.cs b/LB_VisionControl/ScriptEditControl/ComplieUI.Designer.cs
new file mode 100644
index 0000000..b8dcae0
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ComplieUI.Designer.cs
@@ -0,0 +1,217 @@
+锘縩amespace LB_VisionControl.ScriptEditControl
+{
+    partial class ComplieUI
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.btnCsc = new System.Windows.Forms.Button();
+            this.chkCmd = new System.Windows.Forms.CheckBox();
+            this.radDll = new System.Windows.Forms.RadioButton();
+            this.radWinexe = new System.Windows.Forms.RadioButton();
+            this.radExe = new System.Windows.Forms.RadioButton();
+            this.txtArgs = new System.Windows.Forms.TextBox();
+            this.label2 = new System.Windows.Forms.Label();
+            this.txtOutput = new System.Windows.Forms.TextBox();
+            this.contextMenuStripEx1 = new ContextMenuStripEx();
+            this.澶嶅埗ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
+            this.娓呴櫎ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.contextMenuStripEx1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // btnCsc
+            // 
+            this.btnCsc.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+            this.btnCsc.Font = new System.Drawing.Font("寰蒋闆呴粦", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.btnCsc.ForeColor = System.Drawing.Color.White;
+            this.btnCsc.Location = new System.Drawing.Point(356, 3);
+            this.btnCsc.Name = "btnCsc";
+            this.btnCsc.Size = new System.Drawing.Size(44, 23);
+            this.btnCsc.TabIndex = 16;
+            this.btnCsc.Text = "CSC";
+            this.btnCsc.UseVisualStyleBackColor = true;
+            this.btnCsc.Click += new System.EventHandler(this.btnCsc_Click);
+            // 
+            // chkCmd
+            // 
+            this.chkCmd.AutoSize = true;
+            this.chkCmd.Font = new System.Drawing.Font("寰蒋闆呴粦", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.chkCmd.ForeColor = System.Drawing.Color.White;
+            this.chkCmd.Location = new System.Drawing.Point(304, 6);
+            this.chkCmd.Name = "chkCmd";
+            this.chkCmd.Size = new System.Drawing.Size(57, 21);
+            this.chkCmd.TabIndex = 13;
+            this.chkCmd.Text = "CMD";
+            this.chkCmd.UseVisualStyleBackColor = true;
+            // 
+            // radDll
+            // 
+            this.radDll.AutoSize = true;
+            this.radDll.Font = new System.Drawing.Font("寰蒋闆呴粦", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.radDll.ForeColor = System.Drawing.Color.White;
+            this.radDll.Location = new System.Drawing.Point(256, 5);
+            this.radDll.Name = "radDll";
+            this.radDll.Size = new System.Drawing.Size(42, 21);
+            this.radDll.TabIndex = 12;
+            this.radDll.Text = "dll";
+            this.radDll.UseVisualStyleBackColor = true;
+            // 
+            // radWinexe
+            // 
+            this.radWinexe.AutoSize = true;
+            this.radWinexe.Font = new System.Drawing.Font("寰蒋闆呴粦", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.radWinexe.ForeColor = System.Drawing.Color.White;
+            this.radWinexe.Location = new System.Drawing.Point(185, 5);
+            this.radWinexe.Name = "radWinexe";
+            this.radWinexe.Size = new System.Drawing.Size(69, 21);
+            this.radWinexe.TabIndex = 10;
+            this.radWinexe.Text = "winexe";
+            this.radWinexe.UseVisualStyleBackColor = true;
+            // 
+            // radExe
+            // 
+            this.radExe.AutoSize = true;
+            this.radExe.BackColor = System.Drawing.Color.Transparent;
+            this.radExe.Checked = true;
+            this.radExe.Font = new System.Drawing.Font("寰蒋闆呴粦", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.radExe.ForeColor = System.Drawing.Color.White;
+            this.radExe.Location = new System.Drawing.Point(137, 5);
+            this.radExe.Name = "radExe";
+            this.radExe.Size = new System.Drawing.Size(47, 21);
+            this.radExe.TabIndex = 11;
+            this.radExe.TabStop = true;
+            this.radExe.Text = "exe";
+            this.radExe.UseVisualStyleBackColor = false;
+            // 
+            // txtArgs
+            // 
+            this.txtArgs.BackColor = System.Drawing.Color.White;
+            this.txtArgs.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+            this.txtArgs.Font = new System.Drawing.Font("寰蒋闆呴粦", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.txtArgs.Location = new System.Drawing.Point(45, 3);
+            this.txtArgs.Name = "txtArgs";
+            this.txtArgs.Size = new System.Drawing.Size(86, 23);
+            this.txtArgs.TabIndex = 8;
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+            this.label2.Font = new System.Drawing.Font("寰蒋闆呴粦", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.label2.ForeColor = System.Drawing.Color.White;
+            this.label2.Location = new System.Drawing.Point(3, 7);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(44, 17);
+            this.label2.TabIndex = 9;
+            this.label2.Text = "鍙傛暟锛�";
+            // 
+            // txtOutput
+            // 
+            this.txtOutput.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.txtOutput.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(17)))), ((int)(((byte)(18)))));
+            this.txtOutput.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+            this.txtOutput.ContextMenuStrip = this.contextMenuStripEx1;
+            this.txtOutput.Font = new System.Drawing.Font("寰蒋闆呴粦", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.txtOutput.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(128)))));
+            this.txtOutput.Location = new System.Drawing.Point(0, 29);
+            this.txtOutput.Multiline = true;
+            this.txtOutput.Name = "txtOutput";
+            this.txtOutput.ReadOnly = true;
+            this.txtOutput.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+            this.txtOutput.Size = new System.Drawing.Size(492, 162);
+            this.txtOutput.TabIndex = 7;
+            // 
+            // contextMenuStripEx1
+            // 
+            this.contextMenuStripEx1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.澶嶅埗ToolStripMenuItem,
+            this.toolStripMenuItem1,
+            this.娓呴櫎ToolStripMenuItem});
+            this.contextMenuStripEx1.Name = "contextMenuStripEx1";
+            this.contextMenuStripEx1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System;
+            this.contextMenuStripEx1.Size = new System.Drawing.Size(101, 54);
+            // 
+            // 澶嶅埗ToolStripMenuItem
+            // 
+            this.澶嶅埗ToolStripMenuItem.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(128)))));
+            this.澶嶅埗ToolStripMenuItem.Name = "澶嶅埗ToolStripMenuItem";
+            this.澶嶅埗ToolStripMenuItem.Size = new System.Drawing.Size(100, 22);
+            this.澶嶅埗ToolStripMenuItem.Text = "澶嶅埗";
+            this.澶嶅埗ToolStripMenuItem.Click += new System.EventHandler(this.texstToolStripMenuItem_Click);
+            // 
+            // toolStripMenuItem1
+            // 
+            this.toolStripMenuItem1.Name = "toolStripMenuItem1";
+            this.toolStripMenuItem1.Size = new System.Drawing.Size(97, 6);
+            // 
+            // 娓呴櫎ToolStripMenuItem
+            // 
+            this.娓呴櫎ToolStripMenuItem.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(128)))));
+            this.娓呴櫎ToolStripMenuItem.Name = "娓呴櫎ToolStripMenuItem";
+            this.娓呴櫎ToolStripMenuItem.Size = new System.Drawing.Size(100, 22);
+            this.娓呴櫎ToolStripMenuItem.Text = "娓呴櫎";
+            this.娓呴櫎ToolStripMenuItem.Click += new System.EventHandler(this.娓呮ToolStripMenuItem_Click);
+            // 
+            // ComplieUI
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.BackColor = System.Drawing.Color.Black;
+            this.Controls.Add(this.radDll);
+            this.Controls.Add(this.btnCsc);
+            this.Controls.Add(this.chkCmd);
+            this.Controls.Add(this.radWinexe);
+            this.Controls.Add(this.radExe);
+            this.Controls.Add(this.txtOutput);
+            this.Controls.Add(this.txtArgs);
+            this.Controls.Add(this.label2);
+            this.Name = "ComplieUI";
+            this.Size = new System.Drawing.Size(492, 192);
+            this.contextMenuStripEx1.ResumeLayout(false);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Button btnCsc;
+        private System.Windows.Forms.CheckBox chkCmd;
+        private System.Windows.Forms.RadioButton radDll;
+        private System.Windows.Forms.RadioButton radWinexe;
+        private System.Windows.Forms.RadioButton radExe;
+        private System.Windows.Forms.TextBox txtArgs;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.TextBox txtOutput;
+        private ContextMenuStripEx contextMenuStripEx1;
+        private System.Windows.Forms.ToolStripMenuItem 澶嶅埗ToolStripMenuItem;
+        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
+        private System.Windows.Forms.ToolStripMenuItem 娓呴櫎ToolStripMenuItem;
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/ComplieUI.cs b/LB_VisionControl/ScriptEditControl/ComplieUI.cs
new file mode 100644
index 0000000..d19a3e4
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ComplieUI.cs
@@ -0,0 +1,126 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+using System.IO;
+using System.Threading;
+using System.Drawing.Drawing2D;
+using LB_VisionControl.ScriptEditControl.FastColorTextBox;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    public partial class ComplieUI : UserControl
+    {
+        public ComplieUI()
+        {
+            InitializeComponent();
+        }
+        public FastColoredTextBox fctb { get; set; }
+
+        private void btnCsc_Click(object sender, EventArgs e)
+        {
+            UIConfig(false);
+            CreatFile();
+
+            txtOutput.Text = runStringCSC(MakeCommond());//缂栬瘧
+
+            if (File.Exists(CommConfig.ExeFilePath) || File.Exists(CommConfig.DllFilePath))
+            {
+                txtOutput.Text = "====================缂栬瘧鎴愬姛==================\r\n";
+                if (radExe.Checked || radWinexe.Checked)//娴嬭瘯*.exe鏂囦欢
+                {
+                    if (chkCmd.Checked || radWinexe.Checked)//鍒ゆ柇鏄惁浣跨敤CMD
+                    {
+                        System.Diagnostics.Process.Start(CommConfig.ExeFilePath);
+                    }
+                    else
+                    {
+                        txtOutput.Text += "\r\n" + runStringTemp(txtArgs.Text);
+                    }
+                }
+            }
+            else
+                txtOutput.Text += "==================缂栬瘧澶辫触!!=======================";
+
+            UIConfig(true);
+        }
+        public void UIConfig(bool isLock)
+        {
+            fctb.ReadOnly = !isLock;
+            txtArgs.Enabled = isLock;
+            radExe.Enabled = isLock;
+            radWinexe.Enabled = isLock;
+            radDll.Enabled = isLock;
+            chkCmd.Enabled = isLock;
+        }
+        private string MakeCommond()
+        {
+            StringBuilder sb = new StringBuilder();
+
+            if (radExe.Checked)
+                sb.Append("/target:exe  /out:" + CommConfig.ExeFilePath + " " + CommConfig.SrcFilePath);
+            else if (radWinexe.Checked)
+                sb.Append("/target:winexe  /out:" + CommConfig.ExeFilePath + " " + CommConfig.SrcFilePath);
+            else
+                sb.Append("/target:library /out:" + CommConfig.DllFilePath + " " + CommConfig.SrcFilePath);
+            return sb.ToString();
+        }
+        //娴嬭瘯鐢熸垚鏂囦欢
+        private string runStringTemp(string commond)
+        {
+            System.Diagnostics.Process p = new System.Diagnostics.Process();
+            p.StartInfo.FileName = CommConfig.ExeFilePath;
+            p.StartInfo.Arguments = commond;
+            p.StartInfo.UseShellExecute = false;
+            p.StartInfo.RedirectStandardError = true;
+            p.StartInfo.RedirectStandardInput = true;
+            p.StartInfo.RedirectStandardOutput = true;
+            p.StartInfo.CreateNoWindow = true;
+            p.Start();
+            p.StandardInput.WriteLine(commond);
+            return p.StandardOutput.ReadToEnd();
+
+        }
+        //缂栬瘧鍑芥暟
+        private string runStringCSC(string commond)
+        {
+            System.Diagnostics.Process p = new System.Diagnostics.Process();
+            p.StartInfo.FileName = CommConfig.CscPath + "\\csc.exe";
+            p.StartInfo.Arguments = commond;
+            p.StartInfo.UseShellExecute = false;
+            p.StartInfo.RedirectStandardError = true;
+            p.StartInfo.RedirectStandardInput = true;
+            p.StartInfo.RedirectStandardOutput = true;
+            p.StartInfo.CreateNoWindow = true;
+            p.Start();
+            p.StandardInput.WriteLine(commond);
+            // p.StandardInput.WriteLine("exit");
+            return p.StandardOutput.ReadToEnd();
+
+        }
+        private void CreatFile()
+        {
+            if (Directory.Exists(CommConfig.BinPath))
+                Directory.Delete(CommConfig.BinPath, true);
+            Directory.CreateDirectory(CommConfig.BinPath);
+            Thread.Sleep(500);
+            StreamWriter strCode = new StreamWriter(File.OpenWrite(CommConfig.SrcFilePath), System.Text.Encoding.Default);
+            strCode.WriteLine(fctb.Text);
+            strCode.Close();
+        }
+
+        private void texstToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            txtOutput.Copy();
+        }
+
+        private void 娓呮ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            txtOutput.Clear();
+        }
+
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/ComplieUI.resx b/LB_VisionControl/ScriptEditControl/ComplieUI.resx
new file mode 100644
index 0000000..d7fa7ca
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ComplieUI.resx
@@ -0,0 +1,150 @@
+锘�<?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=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>
+  <metadata name="btnCsc.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="chkCmd.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="radDll.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="radWinexe.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="radExe.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="txtArgs.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="label2.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="txtOutput.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="contextMenuStripEx1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>182, 17</value>
+  </metadata>
+  <metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionControl/ScriptEditControl/ConsoleTextBox.cs b/LB_VisionControl/ScriptEditControl/ConsoleTextBox.cs
new file mode 100644
index 0000000..82a5e17
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ConsoleTextBox.cs
@@ -0,0 +1,120 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Threading;
+using LB_VisionControl.ScriptEditControl.FastColorTextBox;
+using Range = LB_VisionControl.ScriptEditControl.FastColorTextBox.Range;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    /// <summary>
+    /// Debug emulator.
+    /// </summary>
+    public class DebugTextBox : FastColoredTextBox
+    {
+        private volatile bool isReadLineMode;
+        private volatile bool isUpdating;
+        private Place StartReadPlace { get; set; }
+        /// <summary>
+        /// Control is waiting for line entering. 
+        /// </summary>
+        public bool IsReadLineMode
+        {
+            get { return isReadLineMode; }
+            set { isReadLineMode = value; }
+        }
+
+        /// <summary>
+        /// Append line to end of text.
+        /// </summary>
+        /// <param name="text"></param>
+        public void WriteLine(string text)
+        {
+            IsReadLineMode = false;
+            isUpdating = true;
+            try
+            {
+                AppendText(text);
+                GoEnd();
+            }
+            finally
+            {
+                isUpdating = false;
+                ClearUndo();
+            }
+        }
+
+        /// <summary>
+        /// Wait for line entering.
+        /// Set IsReadLineMode to false for break of waiting.
+        /// </summary>
+        /// <returns></returns>
+        public string ReadLine()
+        {
+            GoEnd();
+            StartReadPlace = Range.End;
+            IsReadLineMode = true;
+            try
+            {
+                while (IsReadLineMode)
+                {
+                    Application.DoEvents();
+                    Thread.Sleep(5);
+                }
+            }
+            finally
+            {
+                IsReadLineMode = false;
+                ClearUndo();
+            }
+
+            return new Range(this, StartReadPlace, Range.End).Text.TrimEnd('\r', '\n');
+        }
+
+        public override void OnTextChanging(ref string text)
+        {
+            if (!IsReadLineMode && !isUpdating)
+            {
+                text = ""; //cancel changing
+                return;
+            }
+
+            if (IsReadLineMode)
+            {
+                if (Selection.Start < StartReadPlace || Selection.End < StartReadPlace)
+                    GoEnd();//move caret to entering position
+
+                if (Selection.Start == StartReadPlace || Selection.End == StartReadPlace)
+                    if (text == "\b") //backspace
+                    {
+                        text = ""; //cancel deleting of last char of readonly text
+                        return;
+                    }
+
+                if (text != null && text.Contains('\n'))
+                {
+                    text = text.Substring(0, text.IndexOf('\n') + 1);
+                    IsReadLineMode = false;
+                }
+            }
+
+            base.OnTextChanging(ref text);
+        }
+
+        private void InitializeComponent()
+        {
+            this.SuspendLayout();
+            // 
+            // DebugTextBox
+            // 
+            this.AutoScrollMinSize = new System.Drawing.Size(27, 14);
+            this.BackColor = System.Drawing.SystemColors.Control;
+            this.Name = "DebugTextBox";
+            this.ResumeLayout(false);
+
+        }
+
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/ConsoleTextBox.resx b/LB_VisionControl/ScriptEditControl/ConsoleTextBox.resx
new file mode 100644
index 0000000..7080a7d
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ConsoleTextBox.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=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/LB_VisionControl/ScriptEditControl/ContextMenuStripEx.cs b/LB_VisionControl/ScriptEditControl/ContextMenuStripEx.cs
new file mode 100644
index 0000000..d10d835
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ContextMenuStripEx.cs
@@ -0,0 +1,26 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Drawing.Drawing2D;
+using System.Drawing;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    class ContextMenuStripEx : ContextMenuStrip
+    {
+        public ContextMenuStripEx()
+            : base()
+        {
+            this.RenderMode = ToolStripRenderMode.System;
+        }
+        protected override void OnPaint(PaintEventArgs e)
+        {
+            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
+            e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(50, 37, 38)), new Rectangle(-1, -1, this.ClientRectangle.Width + 2, this.ClientRectangle.Height + 2));
+            base.OnPaint(e);
+            e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.FromArgb(50, 37, 38)), 1.0f), new Rectangle(0, 0, this.ClientRectangle.Width - 1, this.ClientRectangle.Height - 1));
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/EditHeightLight.cs b/LB_VisionControl/ScriptEditControl/EditHeightLight.cs
new file mode 100644
index 0000000..d443a64
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/EditHeightLight.cs
@@ -0,0 +1,51 @@
+锘縰sing LB_VisionControl.ScriptEditControl.FastColorTextBox;
+using System.Text.RegularExpressions;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    class EditHeightLight
+    {
+        //styles
+        public static TextStyle KeyWordsStyle = new TextStyle(Brushes.RoyalBlue, null, FontStyle.Regular);//鍏抽敭瀛�
+        public static TextStyle ClassNameStyle = new TextStyle(Brushes.Orange, null, FontStyle.Bold);//绫诲悕,缁撴瀯浣撳悕绉�
+        public static TextStyle GrayStyle = new TextStyle(Brushes.Gray, null, FontStyle.Regular);
+        public static TextStyle NumberStyle = new TextStyle(Brushes.Magenta, null, FontStyle.Regular);
+        public static TextStyle NoteStyle = new TextStyle(Brushes.DarkGreen, null, FontStyle.Regular);//娉ㄩ噴
+        public static TextStyle StringStyle = new TextStyle(Brushes.Lime, null, FontStyle.Regular);//瀛楃涓插紩鍙�
+        public static TextStyle MaroonStyle = new TextStyle(Brushes.Maroon, null, FontStyle.Regular);
+        public static MarkerStyle SameWordsStyle = new MarkerStyle(new SolidBrush(Color.FromArgb(40, Color.Gray)));
+
+        public static void CSharpSyntaxHighlight(FastColoredTextBox fctb, TextChangedEventArgs e)
+        {
+            fctb.LeftBracket = '(';
+            fctb.RightBracket = ')';
+            fctb.LeftBracket2 = '\x0';
+            fctb.RightBracket2 = '\x0';
+            //clear style of changed range
+            e.ChangedRange.ClearStyle(KeyWordsStyle, ClassNameStyle, GrayStyle, NumberStyle, NoteStyle, StringStyle);
+
+            //string highlighting
+            e.ChangedRange.SetStyle(StringStyle, @"""""|@""""|''|@"".*?""|(?<!@)(?<range>"".*?[^\\]"")|'.*?[^\\]'");
+            //comment highlighting
+            e.ChangedRange.SetStyle(NoteStyle, @"//.*$", RegexOptions.Multiline);
+            e.ChangedRange.SetStyle(NoteStyle, @"(/\*.*?\*/)|(/\*.*)", RegexOptions.Singleline);
+            e.ChangedRange.SetStyle(NoteStyle, @"(/\*.*?\*/)|(.*\*/)", RegexOptions.Singleline | RegexOptions.RightToLeft);
+            //number highlighting
+            e.ChangedRange.SetStyle(NumberStyle, @"\b\d+[\.]?\d*([eE]\-?\d+)?[lLdDfF]?\b|\b0x[a-fA-F\d]+\b");
+            //attribute highlighting
+            e.ChangedRange.SetStyle(GrayStyle, @"^\s*(?<range>\[.+?\])\s*$", RegexOptions.Multiline);
+            //class name highlighting
+            e.ChangedRange.SetStyle(ClassNameStyle, @"\b(class|struct|enum|interface)\s+(?<range>\w+?)\b");
+            //keyword highlighting
+            e.ChangedRange.SetStyle(KeyWordsStyle, @"\b(abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while|add|alias|ascending|descending|dynamic|from|get|global|group|into|join|let|orderby|partial|remove|select|set|value|var|where|yield)\b|#region\b|#endregion\b");
+
+            //clear folding markers
+            e.ChangedRange.ClearFoldingMarkers();
+            //set folding markers
+            e.ChangedRange.SetFoldingMarkers("{", "}");//allow to collapse brackets block
+            e.ChangedRange.SetFoldingMarkers(@"#region\b", @"#endregion\b");//allow to collapse #region blocks
+            e.ChangedRange.SetFoldingMarkers(@"/\*", @"\*/");//allow to collapse comment block
+        }
+    }
+
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/AutocompleteItem.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/AutocompleteItem.cs
new file mode 100644
index 0000000..b1f98b2
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/AutocompleteItem.cs
@@ -0,0 +1,234 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// Item of autocomplete menu
+    /// </summary>
+    public class AutocompleteItem
+    {
+        public string Text;
+        public int ImageIndex = -1;
+        public object Tag;
+        string toolTipTitle;
+        string toolTipText;
+        string menuText;
+        public AutocompleteMenu Parent { get; internal set; }
+
+
+        public AutocompleteItem()
+        {
+        }
+
+        public AutocompleteItem(string text)
+        {
+            Text = text;
+        }
+
+        public AutocompleteItem(string text, int imageIndex)
+            : this(text)
+        {
+            this.ImageIndex = imageIndex;
+        }
+
+        public AutocompleteItem(string text, int imageIndex, string menuText)
+            : this(text, imageIndex)
+        {
+            this.menuText = menuText;
+        }
+
+        public AutocompleteItem(string text, int imageIndex, string menuText, string toolTipTitle, string toolTipText)
+            : this(text, imageIndex, menuText)
+        {
+            this.toolTipTitle = toolTipTitle;
+            this.toolTipText = toolTipText;
+        }
+
+        /// <summary>
+        /// Returns text for inserting into Textbox
+        /// </summary>
+        public virtual string GetTextForReplace()
+        {
+            return Text;
+        }
+
+        /// <summary>
+        /// Compares fragment text with this item
+        /// </summary>
+        public virtual CompareResult Compare(string fragmentText)
+        {
+            if (Text.StartsWith(fragmentText, StringComparison.InvariantCultureIgnoreCase) &&
+                   Text != fragmentText)
+                return CompareResult.VisibleAndSelected;
+
+            return CompareResult.Hidden;
+        }
+
+        /// <summary>
+        /// Returns text for display into popup menu
+        /// </summary>
+        public override string ToString()
+        {
+            return menuText ?? Text;
+        }
+
+        /// <summary>
+        /// This method is called after item inserted into text
+        /// </summary>
+        public virtual void OnSelected(AutocompleteMenu popupMenu, SelectedEventArgs e)
+        {
+            ;
+        }
+
+        /// <summary>
+        /// Title for tooltip.
+        /// </summary>
+        /// <remarks>Return null for disable tooltip for this item</remarks>
+        public virtual string ToolTipTitle
+        {
+            get { return toolTipTitle; }
+            set { toolTipTitle = value; }
+        }
+
+        /// <summary>
+        /// Tooltip text.
+        /// </summary>
+        /// <remarks>For display tooltip text, ToolTipTitle must be not null</remarks>
+        public virtual string ToolTipText
+        {
+            get { return toolTipText; }
+            set { toolTipText = value; }
+        }
+
+        /// <summary>
+        /// Menu text. This text is displayed in the drop-down menu.
+        /// </summary>
+        public virtual string MenuText
+        {
+            get { return menuText; }
+            set { menuText = value; }
+        }
+    }
+
+    public enum CompareResult
+    {
+        /// <summary>
+        /// Item do not appears
+        /// </summary>
+        Hidden,
+        /// <summary>
+        /// Item appears
+        /// </summary>
+        Visible,
+        /// <summary>
+        /// Item appears and will selected
+        /// </summary>
+        VisibleAndSelected
+    }
+
+    /// <summary>
+    /// Autocomplete item for code snippets
+    /// </summary>
+    /// <remarks>Snippet can contain special char ^ for caret position.</remarks>
+    public class SnippetAutocompleteItem : AutocompleteItem
+    {
+        public SnippetAutocompleteItem(string snippet)
+        {
+            Text = snippet.Replace("\r", "");
+            ToolTipTitle = "Code snippet:";
+            ToolTipText = Text;
+        }
+
+        public override string ToString()
+        {
+            return MenuText ?? Text.Replace("\n", " ").Replace("^", "");
+        }
+
+        public override string GetTextForReplace()
+        {
+            return Text;
+        }
+
+        public override void OnSelected(AutocompleteMenu popupMenu, SelectedEventArgs e)
+        {
+            e.Tb.BeginUpdate();
+            e.Tb.Selection.BeginUpdate();
+            //remember places
+            var p1 = popupMenu.Fragment.Start;
+            var p2 = e.Tb.Selection.Start;
+            //do auto indent
+            if (e.Tb.AutoIndent)
+            {
+                for (int iLine = p1.iLine + 1; iLine <= p2.iLine; iLine++)
+                {
+                    e.Tb.Selection.Start = new Place(0, iLine);
+                    e.Tb.DoAutoIndent(iLine);
+                }
+            }
+            e.Tb.Selection.Start = p1;
+            //move caret position right and find char ^
+            while (e.Tb.Selection.CharBeforeStart != '^')
+                if (!e.Tb.Selection.GoRightThroughFolded())
+                    break;
+            //remove char ^
+            e.Tb.Selection.GoLeft(true);
+            e.Tb.InsertText("");
+            //
+            e.Tb.Selection.EndUpdate();
+            e.Tb.EndUpdate();
+        }
+
+        /// <summary>
+        /// Compares fragment text with this item
+        /// </summary>
+        public override CompareResult Compare(string fragmentText)
+        {
+            if (Text.StartsWith(fragmentText, StringComparison.InvariantCultureIgnoreCase) &&
+                   Text != fragmentText)
+                return CompareResult.Visible;
+
+            return CompareResult.Hidden;
+        }
+    }
+
+    /// <summary>
+    /// This autocomplete item appears after dot
+    /// </summary>
+    public class MethodAutocompleteItem : AutocompleteItem
+    {
+        string firstPart;
+        string lowercaseText;
+
+        public MethodAutocompleteItem(string text)
+            : base(text)
+        {
+            lowercaseText = Text.ToLower();
+        }
+
+        public override CompareResult Compare(string fragmentText)
+        {
+            int i = fragmentText.LastIndexOf('.');
+            if (i < 0)
+                return CompareResult.Hidden;
+            string lastPart = fragmentText.Substring(i + 1);
+            firstPart = fragmentText.Substring(0, i);
+
+            if (lastPart == "") return CompareResult.Visible;
+            if (Text.StartsWith(lastPart, StringComparison.InvariantCultureIgnoreCase))
+                return CompareResult.VisibleAndSelected;
+            if (lowercaseText.Contains(lastPart.ToLower()))
+                return CompareResult.Visible;
+
+            return CompareResult.Hidden;
+        }
+
+        public override string GetTextForReplace()
+        {
+            return firstPart + "." + Text;
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/AutocompleteMenu.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/AutocompleteMenu.cs
new file mode 100644
index 0000000..3bf8af2
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/AutocompleteMenu.cs
@@ -0,0 +1,597 @@
+锘縰sing Sunny.UI;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// Popup menu for autocomplete
+    /// </summary>
+    [Browsable(false)]
+    public class AutocompleteMenu : ToolStripDropDown
+    {
+        AutocompleteListView listView;
+        public ToolStripControlHost host;
+        public Range Fragment { get; internal set; }
+
+        /// <summary>
+        /// Regex pattern for serach fragment around caret
+        /// </summary>
+        public string SearchPattern { get; set; }
+        /// <summary>
+        /// Minimum fragment length for popup
+        /// </summary>
+        public int MinFragmentLength { get; set; }
+        /// <summary>
+        /// User selects item
+        /// </summary>
+        public event EventHandler<SelectingEventArgs> Selecting;
+        /// <summary>
+        /// It fires after item inserting
+        /// </summary>
+        public event EventHandler<SelectedEventArgs> Selected;
+        /// <summary>
+        /// Occurs when popup menu is opening
+        /// </summary>
+        public event EventHandler<CancelEventArgs> Opening;
+        /// <summary>
+        /// Allow TAB for select menu item
+        /// </summary>
+        public bool AllowTabKey { get { return listView.AllowTabKey; } set { listView.AllowTabKey = value; } }
+        /// <summary>
+        /// Interval of menu appear (ms)
+        /// </summary>
+        public int AppearInterval { get { return listView.AppearInterval; } set { listView.AppearInterval = value; } }
+
+        protected override void OnPaint(PaintEventArgs e)
+        {
+            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
+            e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(50, 37, 38)), new Rectangle(-1, -1, this.ClientRectangle.Width + 2, this.ClientRectangle.Height + 2));
+            //base.OnPaint(e);
+        }
+        public AutocompleteMenu(FastColoredTextBox tb)
+        {
+            // create a new popup and add the list view to it 
+            AutoClose = false;
+            AutoSize = false;
+            Margin = Padding.Empty;
+            Padding = Padding.Empty;
+            listView = new AutocompleteListView(tb);
+            host = new ToolStripControlHost(listView);
+            host.Margin = new Padding(1, 1, 1, 1);
+            host.Padding = Padding.Empty;
+            host.AutoSize = false;
+            host.AutoToolTip = false;
+            CalcSize();
+            base.Items.Add(host);
+            listView.Parent = this;
+            SearchPattern = @"[\w\.]";
+            MinFragmentLength = 2;
+        }
+
+        internal void OnOpening(CancelEventArgs args)
+        {
+            if (Opening != null)
+                Opening(this, args);
+        }
+
+        public new void Close()
+        {
+            listView.toolTip.Hide(listView);
+            base.Close();
+        }
+
+        internal void CalcSize()
+        {
+            host.Size = listView.Size;
+            Size = new System.Drawing.Size(listView.Size.Width, listView.Size.Height);
+        }
+
+        public virtual void OnSelecting()
+        {
+            listView.OnSelecting();
+        }
+
+        public void SelectNext(int shift)
+        {
+            listView.SelectNext(shift);
+        }
+
+        internal void OnSelecting(SelectingEventArgs args)
+        {
+            if (Selecting != null)
+                Selecting(this, args);
+        }
+
+        public void OnSelected(SelectedEventArgs args)
+        {
+            if (Selected != null)
+                Selected(this, args);
+        }
+
+        public new AutocompleteListView Items
+        {
+            get { return listView; }
+        }
+
+        /// <summary>
+        /// Shows popup menu immediately
+        /// </summary>
+        /// <param name="forced">If True - MinFragmentLength will be ignored</param>
+        public void Show(bool forced)
+        {
+            Items.DoAutocomplete(forced);
+        }
+    }
+
+    public class AutocompleteListView : UserControl
+    {
+        internal List<AutocompleteItem> visibleItems;
+        IEnumerable<AutocompleteItem> sourceItems = new List<AutocompleteItem>();
+        int selectedItemIndex = 0;
+        int hoveredItemIndex = -1;
+        int itemHeight;
+        AutocompleteMenu Menu { get { return Parent as AutocompleteMenu; } }
+        int oldItemCount = 0;
+        FastColoredTextBox tb;
+        internal ToolTip toolTip = new ToolTip();
+        System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
+
+        internal bool AllowTabKey { get; set; }
+        public ImageList ImageList { get; set; }
+        internal int AppearInterval { get { return timer.Interval; } set { timer.Interval = value; } }
+
+        internal AutocompleteListView(FastColoredTextBox tb)
+        {
+            this.Width = 210;
+            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);
+            base.Font = new Font(FontFamily.GenericSansSerif, 9);
+            visibleItems = new List<AutocompleteItem>();
+            itemHeight = Font.Height + 2;
+            VerticalScroll.SmallChange = itemHeight;
+            this.BackColor = Color.Transparent; //Color.FromArgb(255, 255, 17, 18);
+            BorderStyle = BorderStyle.None;
+            MaximumSize = new Size(Size.Width, 180);
+            toolTip.ShowAlways = false;
+            AppearInterval = 500;
+
+            timer.Tick += new EventHandler(timer_Tick);
+
+            this.tb = tb;
+
+            tb.KeyDown += new KeyEventHandler(tb_KeyDown);
+            tb.SelectionChanged += new EventHandler(tb_SelectionChanged);
+            tb.KeyPressed += new KeyPressEventHandler(tb_KeyPressed);
+
+            Form form = tb.FindForm();
+            if (form != null)
+            {
+                form.LocationChanged += (o, e) => Menu.Close();
+                form.ResizeBegin += (o, e) => Menu.Close();
+                form.FormClosing += (o, e) => Menu.Close();
+                form.LostFocus += (o, e) => Menu.Close();
+            }
+
+            tb.LostFocus += (o, e) =>
+            {
+                if (!Menu.Focused) Menu.Close();
+            };
+
+            tb.Scroll += (o, e) => Menu.Close();
+        }
+
+        void tb_KeyPressed(object sender, KeyPressEventArgs e)
+        {
+            bool backspaceORdel = e.KeyChar == '\b' || e.KeyChar == 0xff;
+
+            /*
+            if (backspaceORdel)
+                prevSelection = tb.Selection.Start;*/
+
+            if (Menu.Visible && !backspaceORdel)
+                DoAutocomplete(false);
+            else
+                ResetTimer(timer);
+        }
+
+        void timer_Tick(object sender, EventArgs e)
+        {
+            timer.Stop();
+            DoAutocomplete(false);
+        }
+
+        void ResetTimer(System.Windows.Forms.Timer timer)
+        {
+            timer.Stop();
+            timer.Start();
+        }
+
+        internal void DoAutocomplete()
+        {
+            DoAutocomplete(false);
+        }
+
+        internal void DoAutocomplete(bool forced)
+        {
+            if (!Menu.Enabled)
+            {
+                Menu.Close();
+                return;
+            }
+
+            visibleItems.Clear();
+            selectedItemIndex = 0;
+            VerticalScroll.Value = 0;
+            //get fragment around caret
+            Range fragment = tb.Selection.GetFragment(Menu.SearchPattern);
+            string text = fragment.Text;
+            //calc screen point for popup menu
+            Point point = tb.PlaceToPoint(fragment.End);
+            point.Offset(2, tb.CharHeight);
+            //
+            if (forced ||
+                (text.Length >= Menu.MinFragmentLength && tb.Selection.IsEmpty))
+            {
+                Menu.Fragment = fragment;
+                bool foundSelected = false;
+                //build popup menu
+                foreach (var item in sourceItems)
+                {
+                    item.Parent = Menu;
+                    CompareResult res = item.Compare(text);
+                    if (res != CompareResult.Hidden)
+                        visibleItems.Add(item);
+                    if (res == CompareResult.VisibleAndSelected && !foundSelected)
+                    {
+                        foundSelected = true;
+                        selectedItemIndex = visibleItems.Count - 1;
+                    }
+                }
+
+                if (foundSelected)
+                {
+                    AdjustScroll();
+                    DoSelectedVisible();
+                }
+            }
+
+            //show popup menu
+            if (Count > 0)
+            {
+                if (!Menu.Visible)
+                {
+                    CancelEventArgs args = new CancelEventArgs();
+                    Menu.OnOpening(args);
+                    if (!args.Cancel)
+                        Menu.Show(tb, point);
+                }
+                else
+                    Invalidate();
+            }
+            else
+                Menu.Close();
+        }
+
+        void tb_SelectionChanged(object sender, EventArgs e)
+        {
+            /*
+            FastColoredTextBox tb = sender as FastColoredTextBox;
+            
+            if (Math.Abs(prevSelection.iChar - tb.Selection.Start.iChar) > 1 ||
+                        prevSelection.iLine != tb.Selection.Start.iLine)
+                Menu.Close();
+            prevSelection = tb.Selection.Start;*/
+            if (Menu.Visible)
+            {
+                bool needClose = false;
+
+                if (!tb.Selection.IsEmpty)
+                    needClose = true;
+                else
+                    if (!Menu.Fragment.Contains(tb.Selection.Start))
+                {
+                    if (tb.Selection.Start.iLine == Menu.Fragment.End.iLine && tb.Selection.Start.iChar == Menu.Fragment.End.iChar + 1)
+                    {
+                        //user press key at end of fragment
+                        char c = tb.Selection.CharBeforeStart;
+                        if (!Regex.IsMatch(c.ToString(), Menu.SearchPattern))//check char
+                            needClose = true;
+                    }
+                    else
+                        needClose = true;
+                }
+
+                if (needClose)
+                    Menu.Close();
+            }
+
+        }
+
+        void tb_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (Menu.Visible)
+                if (ProcessKey(e.KeyCode, e.Modifiers))
+                    e.Handled = true;
+
+            if (!Menu.Visible)
+                if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Space)
+                {
+                    DoAutocomplete();
+                    e.Handled = true;
+                }
+        }
+
+        void AdjustScroll()
+        {
+            if (oldItemCount == visibleItems.Count)
+                return;
+
+            int needHeight = itemHeight * visibleItems.Count + 1;
+            Height = Math.Min(needHeight, MaximumSize.Height);
+            Menu.CalcSize();
+
+            AutoScrollMinSize = new Size(0, needHeight);
+            oldItemCount = visibleItems.Count;
+        }
+
+        protected override void OnPaint(PaintEventArgs e)
+        {
+            AdjustScroll();
+            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
+            e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
+            int startI = VerticalScroll.Value / itemHeight - 1;
+            int finishI = (VerticalScroll.Value + ClientSize.Height) / itemHeight + 1;
+            startI = Math.Max(startI, 0);
+            finishI = Math.Min(finishI, visibleItems.Count);
+            int y = 0;
+            int leftPadding = 20;
+            for (int i = startI; i < finishI; i++)
+            {
+                y = i * itemHeight - VerticalScroll.Value;
+
+                //if (ImageList != null && visibleItems[i].ImageIndex >= 0)
+                //    e.Graphics.DrawImage(ImageList.Images[visibleItems[i].ImageIndex], 1, y);
+
+                if (i == selectedItemIndex)
+                {
+                    Brush selectedBrush = new SolidBrush(Color.Yellow);//new LinearGradientBrush(new Point(0, y - 3), new Point(0, y + itemHeight), Color.GreenYellow, Color.Green);
+                    e.Graphics.FillRectangle(selectedBrush, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1);
+                    e.Graphics.DrawRectangle(Pens.Yellow, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1);
+                    e.Graphics.DrawString(visibleItems[i].ToString(), Font, Brushes.Black, leftPadding, y);
+                }
+                else
+                {
+                    e.Graphics.DrawString(visibleItems[i].ToString(), Font, Brushes.LightSkyBlue, leftPadding, y);
+                }
+                if (i == hoveredItemIndex)
+                    e.Graphics.DrawRectangle(Pens.Red, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1);
+            }
+        }
+
+        protected override void OnScroll(ScrollEventArgs se)
+        {
+            base.OnScroll(se);
+            Invalidate();
+        }
+
+        protected override void OnMouseClick(MouseEventArgs e)
+        {
+            base.OnMouseClick(e);
+
+            if (e.Button == System.Windows.Forms.MouseButtons.Left)
+            {
+                selectedItemIndex = PointToItemIndex(e.Location);
+                DoSelectedVisible();
+                Invalidate();
+            }
+        }
+
+        protected override void OnMouseDoubleClick(MouseEventArgs e)
+        {
+            base.OnMouseDoubleClick(e);
+            selectedItemIndex = PointToItemIndex(e.Location);
+            Invalidate();
+            OnSelecting();
+        }
+
+        internal virtual void OnSelecting()
+        {
+            if (selectedItemIndex < 0 || selectedItemIndex >= visibleItems.Count)
+                return;
+            tb.TextSource.Manager.BeginAutoUndoCommands();
+            try
+            {
+                AutocompleteItem item = visibleItems[selectedItemIndex];
+                SelectingEventArgs args = new SelectingEventArgs()
+                {
+                    Item = item,
+                    SelectedIndex = selectedItemIndex
+                };
+
+                Menu.OnSelecting(args);
+
+                if (args.Cancel)
+                {
+                    selectedItemIndex = args.SelectedIndex;
+                    Invalidate();
+                    return;
+                }
+
+                if (!args.Handled)
+                {
+                    var fragment = Menu.Fragment;
+                    DoAutocomplete(item, fragment);
+                }
+
+                Menu.Close();
+                //
+                SelectedEventArgs args2 = new SelectedEventArgs()
+                {
+                    Item = item,
+                    Tb = Menu.Fragment.tb
+                };
+                item.OnSelected(Menu, args2);
+                Menu.OnSelected(args2);
+            }
+            finally
+            {
+                tb.TextSource.Manager.EndAutoUndoCommands();
+            }
+        }
+
+        private void DoAutocomplete(AutocompleteItem item, Range fragment)
+        {
+            string newText = item.GetTextForReplace();
+            //replace text of fragment
+            var tb = fragment.tb;
+            if (tb.Selection.ColumnSelectionMode)
+            {
+                var start = tb.Selection.Start;
+                var end = tb.Selection.End;
+                start.iChar = fragment.Start.iChar;
+                end.iChar = fragment.End.iChar;
+                tb.Selection.Start = start;
+                tb.Selection.End = end;
+            }
+            else
+            {
+                tb.Selection.Start = fragment.Start;
+                tb.Selection.End = fragment.End;
+            }
+            tb.InsertText(newText);
+            tb.Focus();
+        }
+
+        int PointToItemIndex(Point p)
+        {
+            return (p.Y + VerticalScroll.Value) / itemHeight;
+        }
+
+        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+        {
+            ProcessKey(keyData, Keys.None);
+
+            return base.ProcessCmdKey(ref msg, keyData);
+        }
+
+        private bool ProcessKey(Keys keyData, Keys keyModifiers)
+        {
+            if (keyModifiers == Keys.None)
+                switch (keyData)
+                {
+                    case Keys.Down:
+                        SelectNext(+1);
+                        return true;
+                    case Keys.PageDown:
+                        SelectNext(+10);
+                        return true;
+                    case Keys.Up:
+                        SelectNext(-1);
+                        return true;
+                    case Keys.PageUp:
+                        SelectNext(-10);
+                        return true;
+                    case Keys.Enter:
+                    case Keys.Space:
+                        OnSelecting();
+                        return true;
+                    case Keys.Tab:
+                        if (!AllowTabKey)
+                            break;
+                        OnSelecting();
+                        return true;
+                    case Keys.Escape:
+                        Menu.Close();
+                        return true;
+                }
+
+            return false;
+        }
+
+        public void SelectNext(int shift)
+        {
+            selectedItemIndex = Math.Max(0, Math.Min(selectedItemIndex + shift, visibleItems.Count - 1));
+            DoSelectedVisible();
+            //
+            Invalidate();
+        }
+
+        private void DoSelectedVisible()
+        {
+            if (selectedItemIndex >= 0 && selectedItemIndex < visibleItems.Count)
+                SetToolTip(visibleItems[selectedItemIndex]);
+
+            var y = selectedItemIndex * itemHeight - VerticalScroll.Value;
+            if (y < 0)
+                VerticalScroll.Value = selectedItemIndex * itemHeight;
+            if (y > ClientSize.Height - itemHeight)
+                VerticalScroll.Value = Math.Min(VerticalScroll.Maximum, selectedItemIndex * itemHeight - ClientSize.Height + itemHeight);
+            //some magic for update scrolls
+            AutoScrollMinSize -= new Size(1, 0);
+            AutoScrollMinSize += new Size(1, 0);
+        }
+
+        private void SetToolTip(AutocompleteItem autocompleteItem)
+        {
+            var title = visibleItems[selectedItemIndex].ToolTipTitle;
+            var text = visibleItems[selectedItemIndex].ToolTipText;
+
+            if (string.IsNullOrEmpty(title))
+            {
+                toolTip.ToolTipTitle = null;
+                toolTip.SetToolTip(this, null);
+                return;
+            }
+
+            if (string.IsNullOrEmpty(text))
+            {
+                toolTip.ToolTipTitle = null;
+                toolTip.Show(title, this, Width + 3, 0, 3000);
+            }
+            else
+            {
+                toolTip.ToolTipTitle = title;
+                toolTip.Show(text, this, Width + 3, 0, 3000);
+            }
+        }
+
+        public int Count
+        {
+            get { return visibleItems.Count; }
+        }
+
+        public void SetAutocompleteItems(ICollection<string> items)
+        {
+            List<AutocompleteItem> list = new List<AutocompleteItem>(items.Count);
+            foreach (var item in items)
+                list.Add(new AutocompleteItem(item));
+            SetAutocompleteItems(list);
+        }
+
+        public void SetAutocompleteItems(ICollection<AutocompleteItem> items)
+        {
+            sourceItems = items;
+        }
+    }
+
+    public class SelectingEventArgs : EventArgs
+    {
+        public AutocompleteItem Item { get; internal set; }
+        public bool Cancel { get; set; }
+        public int SelectedIndex { get; set; }
+        public bool Handled { get; set; }
+    }
+
+    public class SelectedEventArgs : EventArgs
+    {
+        public AutocompleteItem Item { get; internal set; }
+        public FastColoredTextBox Tb { get; set; }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/Char.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Char.cs
new file mode 100644
index 0000000..14edf45
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Char.cs
@@ -0,0 +1,56 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// Char and style
+    /// </summary>
+    public struct Char
+    {
+        /// <summary>
+        /// Unicode character
+        /// </summary>
+        public char c;
+        /// <summary>
+        /// Style bit mask
+        /// </summary>
+        /// <remarks>Bit 1 in position n means that this char will rendering by FastColoredTextBox.Styles[n]</remarks>
+        public StyleIndex style;
+
+        public Char(char c)
+        {
+            this.c = c;
+            style = StyleIndex.None;
+        }
+    }
+
+    /// <summary>
+    /// Style index mask
+    /// </summary>
+    [Flags]
+    public enum StyleIndex : ushort
+    {
+        None = 0,
+        Style0 = 0x1,
+        Style1 = 0x2,
+        Style2 = 0x4,
+        Style3 = 0x8,
+        Style4 = 0x10,
+        Style5 = 0x20,
+        Style6 = 0x40,
+        Style7 = 0x80,
+        Style8 = 0x100,
+        Style9 = 0x200,
+        Style10 = 0x400,
+        Style11 = 0x800,
+        Style12 = 0x1000,
+        Style13 = 0x2000,
+        Style14 = 0x4000,
+        Style15 = 0x8000,
+        All = 0xffff
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/CommandManager.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/CommandManager.cs
new file mode 100644
index 0000000..44a401f
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/CommandManager.cs
@@ -0,0 +1,236 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    internal class CommandManager
+    {
+        readonly int maxHistoryLength = 200;
+        LimitedStack<UndoableCommand> history;
+        Stack<UndoableCommand> redoStack = new Stack<UndoableCommand>();
+        public TextSource TextSource { get; private set; }
+
+        public CommandManager(TextSource ts)
+        {
+            history = new LimitedStack<UndoableCommand>(maxHistoryLength);
+            TextSource = ts;
+        }
+
+        public void ExecuteCommand(Command cmd)
+        {
+            if (disabledCommands > 0)
+                return;
+
+            //multirange ?
+            if (cmd.ts.CurrentTB.Selection.ColumnSelectionMode)
+                if (cmd is UndoableCommand)
+                    //make wrapper
+                    cmd = new MultiRangeCommand((UndoableCommand)cmd);
+
+
+            if (cmd is UndoableCommand)
+            {
+                //if range is ColumnRange, then create wrapper
+                (cmd as UndoableCommand).autoUndo = autoUndoCommands > 0;
+                history.Push(cmd as UndoableCommand);
+            }
+            try
+            {
+                cmd.Execute();
+            }
+            catch (ArgumentOutOfRangeException)
+            {
+                //OnTextChanging cancels enter of the text
+                if (cmd is UndoableCommand)
+                    history.Pop();
+            }
+            //
+            redoStack.Clear();
+            //
+            TextSource.CurrentTB.OnUndoRedoStateChanged();
+        }
+
+        public void Undo()
+        {
+            if (history.Count > 0)
+            {
+                var cmd = history.Pop();
+                //
+                BeginDisableCommands();//prevent text changing into handlers
+                try
+                {
+                    cmd.Undo();
+                }
+                finally
+                {
+                    EndDisableCommands();
+                }
+                //
+                redoStack.Push(cmd);
+            }
+
+            //undo next autoUndo command
+            if (history.Count > 0)
+            {
+                if (history.Peek().autoUndo)
+                    Undo();
+            }
+
+            TextSource.CurrentTB.OnUndoRedoStateChanged();
+        }
+
+        int disabledCommands = 0;
+
+        private void EndDisableCommands()
+        {
+            disabledCommands--;
+        }
+
+        private void BeginDisableCommands()
+        {
+            disabledCommands++;
+        }
+
+        int autoUndoCommands = 0;
+
+        public void EndAutoUndoCommands()
+        {
+            autoUndoCommands--;
+            if (autoUndoCommands == 0)
+                if (history.Count > 0)
+                    history.Peek().autoUndo = false;
+        }
+
+        public void BeginAutoUndoCommands()
+        {
+            autoUndoCommands++;
+        }
+
+        internal void ClearHistory()
+        {
+            history.Clear();
+            redoStack.Clear();
+            TextSource.CurrentTB.OnUndoRedoStateChanged();
+        }
+
+        internal void Redo()
+        {
+            if (redoStack.Count == 0)
+                return;
+            UndoableCommand cmd;
+            BeginDisableCommands();//prevent text changing into handlers
+            try
+            {
+                cmd = redoStack.Pop();
+                if (TextSource.CurrentTB.Selection.ColumnSelectionMode)
+                    TextSource.CurrentTB.Selection.ColumnSelectionMode = false;
+                TextSource.CurrentTB.Selection.Start = cmd.sel.Start;
+                TextSource.CurrentTB.Selection.End = cmd.sel.End;
+                cmd.Execute();
+                history.Push(cmd);
+            }
+            finally
+            {
+                EndDisableCommands();
+            }
+
+            //redo command after autoUndoable command
+            if (cmd.autoUndo)
+                Redo();
+
+            TextSource.CurrentTB.OnUndoRedoStateChanged();
+        }
+
+        public bool UndoEnabled
+        {
+            get
+            {
+                return history.Count > 0;
+            }
+        }
+
+        public bool RedoEnabled
+        {
+            get
+            {
+                return redoStack.Count > 0;
+            }
+        }
+    }
+
+    internal abstract class Command
+    {
+        internal TextSource ts;
+        public abstract void Execute();
+    }
+
+    internal class RangeInfo
+    {
+        public Place Start { get; set; }
+        public Place End { get; set; }
+
+        public RangeInfo(Range r)
+        {
+            Start = r.Start;
+            End = r.End;
+        }
+
+        internal int FromX
+        {
+            get
+            {
+                if (End.iLine < Start.iLine) return End.iChar;
+                if (End.iLine > Start.iLine) return Start.iChar;
+                return Math.Min(End.iChar, Start.iChar);
+            }
+        }
+    }
+
+    internal abstract class UndoableCommand : Command
+    {
+        internal RangeInfo sel;
+        internal RangeInfo lastSel;
+        internal bool autoUndo;
+
+        public UndoableCommand(TextSource ts)
+        {
+            this.ts = ts;
+            sel = new RangeInfo(ts.CurrentTB.Selection);
+        }
+
+        public virtual void Undo()
+        {
+            OnTextChanged(true);
+        }
+
+        public override void Execute()
+        {
+            lastSel = new RangeInfo(ts.CurrentTB.Selection);
+            OnTextChanged(false);
+        }
+
+        protected virtual void OnTextChanged(bool invert)
+        {
+            bool b = sel.Start.iLine < lastSel.Start.iLine;
+            if (invert)
+            {
+                if (b)
+                    ts.OnTextChanged(sel.Start.iLine, sel.Start.iLine);
+                else
+                    ts.OnTextChanged(sel.Start.iLine, lastSel.Start.iLine);
+            }
+            else
+            {
+                if (b)
+                    ts.OnTextChanged(sel.Start.iLine, lastSel.Start.iLine);
+                else
+                    ts.OnTextChanged(lastSel.Start.iLine, lastSel.Start.iLine);
+            }
+        }
+
+        public abstract UndoableCommand Clone();
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/Commands.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Commands.cs
new file mode 100644
index 0000000..ea6655d
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Commands.cs
@@ -0,0 +1,724 @@
+锘縰sing Sunny.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// Insert single char
+    /// </summary>
+    /// <remarks>This operation includes also insertion of new line and removing char by backspace</remarks>
+    internal class InsertCharCommand : UndoableCommand
+    {
+        internal char c;
+        char deletedChar = '\x0';
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="tb">Underlaying textbox</param>
+        /// <param name="c">Inserting char</param>
+        public InsertCharCommand(TextSource ts, char c) : base(ts)
+        {
+            this.c = c;
+        }
+
+        /// <summary>
+        /// Undo operation
+        /// </summary>
+        public override void Undo()
+        {
+            ts.OnTextChanging();
+            switch (c)
+            {
+                case '\n': MergeLines(sel.Start.iLine, ts); break;
+                case '\r': break;
+                case '\b':
+                    ts.CurrentTB.Selection.Start = lastSel.Start;
+                    char cc = '\x0';
+                    if (deletedChar != '\x0')
+                    {
+                        ts.CurrentTB.ExpandBlock(ts.CurrentTB.Selection.Start.iLine);
+                        InsertChar(deletedChar, ref cc, ts);
+                    }
+                    break;
+                default:
+                    ts.CurrentTB.ExpandBlock(sel.Start.iLine);
+                    ts[sel.Start.iLine].RemoveAt(sel.Start.iChar);
+                    ts.CurrentTB.Selection.Start = sel.Start;
+                    break;
+            }
+
+            ts.NeedRecalc(new TextSource.TextChangedEventArgs(sel.Start.iLine, sel.Start.iLine));
+
+            base.Undo();
+        }
+
+        /// <summary>
+        /// Execute operation
+        /// </summary>
+        public override void Execute()
+        {
+            ts.CurrentTB.ExpandBlock(ts.CurrentTB.Selection.Start.iLine);
+            string s = c.ToString();
+            ts.OnTextChanging(ref s);
+            if (s.Length == 1)
+                c = s[0];
+
+            if (String.IsNullOrEmpty(s))
+                throw new ArgumentOutOfRangeException();
+
+
+            if (ts.Count == 0)
+                InsertLine(ts);
+            InsertChar(c, ref deletedChar, ts);
+
+            ts.NeedRecalc(new TextSource.TextChangedEventArgs(ts.CurrentTB.Selection.Start.iLine, ts.CurrentTB.Selection.Start.iLine));
+            base.Execute();
+        }
+
+        internal static void InsertChar(char c, ref char deletedChar, TextSource ts)
+        {
+            var tb = ts.CurrentTB;
+
+            switch (c)
+            {
+                case '\n':
+                    if (!ts.CurrentTB.allowInsertRemoveLines)
+                        throw new ArgumentOutOfRangeException("Cant insert this char in ColumnRange mode");
+                    if (ts.Count == 0)
+                        InsertLine(ts);
+                    InsertLine(ts);
+                    break;
+                case '\r': break;
+                case '\b'://backspace
+                    if (tb.Selection.Start.iChar == 0 && tb.Selection.Start.iLine == 0)
+                        return;
+                    if (tb.Selection.Start.iChar == 0)
+                    {
+                        if (!ts.CurrentTB.allowInsertRemoveLines)
+                            throw new ArgumentOutOfRangeException("Cant insert this char in ColumnRange mode");
+                        if (tb.lineInfos[tb.Selection.Start.iLine - 1].VisibleState != VisibleState.Visible)
+                            tb.ExpandBlock(tb.Selection.Start.iLine - 1);
+                        deletedChar = '\n';
+                        MergeLines(tb.Selection.Start.iLine - 1, ts);
+                    }
+                    else
+                    {
+                        deletedChar = ts[tb.Selection.Start.iLine][tb.Selection.Start.iChar - 1].c;
+                        ts[tb.Selection.Start.iLine].RemoveAt(tb.Selection.Start.iChar - 1);
+                        tb.Selection.Start = new Place(tb.Selection.Start.iChar - 1, tb.Selection.Start.iLine);
+                    }
+                    break;
+                case '\t':
+                    for (int i = 0; i < tb.TabLength; i++)
+                        ts[tb.Selection.Start.iLine].Insert(tb.Selection.Start.iChar, new Char(' '));
+                    tb.Selection.Start = new Place(tb.Selection.Start.iChar + tb.TabLength, tb.Selection.Start.iLine);
+                    break;
+                default:
+                    ts[tb.Selection.Start.iLine].Insert(tb.Selection.Start.iChar, new Char(c));
+                    tb.Selection.Start = new Place(tb.Selection.Start.iChar + 1, tb.Selection.Start.iLine);
+                    break;
+            }
+        }
+
+        internal static void InsertLine(TextSource ts)
+        {
+            var tb = ts.CurrentTB;
+
+            if (!tb.Multiline && tb.LinesCount > 0)
+                return;
+
+            if (ts.Count == 0)
+                ts.InsertLine(0, ts.CreateLine());
+            else
+                BreakLines(tb.Selection.Start.iLine, tb.Selection.Start.iChar, ts);
+
+            tb.Selection.Start = new Place(0, tb.Selection.Start.iLine + 1);
+            ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1));
+        }
+
+        /// <summary>
+        /// Merge lines i and i+1
+        /// </summary>
+        internal static void MergeLines(int i, TextSource ts)
+        {
+            var tb = ts.CurrentTB;
+
+            if (i + 1 >= ts.Count)
+                return;
+            tb.ExpandBlock(i);
+            tb.ExpandBlock(i + 1);
+            int pos = ts[i].Count;
+            //
+            if (ts[i].Count == 0)
+                ts.RemoveLine(i);
+            else
+            if (ts[i + 1].Count == 0)
+                ts.RemoveLine(i + 1);
+            else
+            {
+                ts[i].AddRange(ts[i + 1]);
+                ts.RemoveLine(i + 1);
+            }
+            tb.Selection.Start = new Place(pos, i);
+            ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1));
+        }
+
+        internal static void BreakLines(int iLine, int pos, TextSource ts)
+        {
+            Line newLine = ts.CreateLine();
+            for (int i = pos; i < ts[iLine].Count; i++)
+                newLine.Add(ts[iLine][i]);
+            ts[iLine].RemoveRange(pos, ts[iLine].Count - pos);
+            //
+            ts.InsertLine(iLine + 1, newLine);
+        }
+
+        public override UndoableCommand Clone()
+        {
+            return new InsertCharCommand(ts, c);
+        }
+    }
+
+    /// <summary>
+    /// Insert text
+    /// </summary>
+    internal class InsertTextCommand : UndoableCommand
+    {
+        internal string insertedText;
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="tb">Underlaying textbox</param>
+        /// <param name="insertedText">Text for inserting</param>
+        public InsertTextCommand(TextSource ts, string insertedText) : base(ts)
+        {
+            this.insertedText = insertedText;
+        }
+
+        /// <summary>
+        /// Undo operation
+        /// </summary>
+        public override void Undo()
+        {
+            ts.CurrentTB.Selection.Start = sel.Start;
+            ts.CurrentTB.Selection.End = lastSel.Start;
+            ts.OnTextChanging();
+            ClearSelectedCommand.ClearSelected(ts);
+            base.Undo();
+        }
+
+        /// <summary>
+        /// Execute operation
+        /// </summary>
+        public override void Execute()
+        {
+            ts.OnTextChanging(ref insertedText);
+            InsertText(insertedText, ts);
+            base.Execute();
+        }
+
+        internal static void InsertText(string insertedText, TextSource ts)
+        {
+            var tb = ts.CurrentTB;
+            try
+            {
+                tb.Selection.BeginUpdate();
+                char cc = '\x0';
+                if (ts.Count == 0)
+                    InsertCharCommand.InsertLine(ts);
+                tb.ExpandBlock(tb.Selection.Start.iLine);
+                foreach (char c in insertedText)
+                    InsertCharCommand.InsertChar(c, ref cc, ts);
+                ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1));
+            }
+            finally
+            {
+                tb.Selection.EndUpdate();
+            }
+        }
+
+        public override UndoableCommand Clone()
+        {
+            return new InsertTextCommand(ts, insertedText);
+        }
+    }
+
+    /// <summary>
+    /// Insert text into given ranges
+    /// </summary>
+    internal class ReplaceTextCommand : UndoableCommand
+    {
+        string insertedText;
+        List<Range> ranges;
+        List<string> prevText = new List<string>();
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="tb">Underlaying textbox</param>
+        /// <param name="ranges">List of ranges for replace</param>
+        /// <param name="insertedText">Text for inserting</param>
+        public ReplaceTextCommand(TextSource ts, List<Range> ranges, string insertedText)
+            : base(ts)
+        {
+            //sort ranges by place
+            ranges.Sort((r1, r2) =>
+            {
+                if (r1.Start.iLine == r2.Start.iLine)
+                    return r1.Start.iChar.CompareTo(r2.Start.iChar);
+                return r1.Start.iLine.CompareTo(r2.Start.iLine);
+            });
+            //
+            this.ranges = ranges;
+            this.insertedText = insertedText;
+            lastSel = sel = new RangeInfo(ts.CurrentTB.Selection);
+        }
+
+        /// <summary>
+        /// Undo operation
+        /// </summary>
+        public override void Undo()
+        {
+            var tb = ts.CurrentTB;
+
+            ts.OnTextChanging();
+
+            tb.Selection.BeginUpdate();
+            for (int i = 0; i < ranges.Count; i++)
+            {
+                tb.Selection.Start = ranges[i].Start;
+                for (int j = 0; j < insertedText.Length; j++)
+                    tb.Selection.GoRight(true);
+                ClearSelectedCommand.ClearSelected(ts);
+                InsertTextCommand.InsertText(prevText[prevText.Count - i - 1], ts);
+                ts.OnTextChanged(ranges[i].Start.iLine, ranges[i].Start.iLine);
+            }
+            tb.Selection.EndUpdate();
+
+            ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1));
+        }
+
+        /// <summary>
+        /// Execute operation
+        /// </summary>
+        public override void Execute()
+        {
+            var tb = ts.CurrentTB;
+            prevText.Clear();
+
+            ts.OnTextChanging(ref insertedText);
+
+            tb.Selection.BeginUpdate();
+            for (int i = ranges.Count - 1; i >= 0; i--)
+            {
+                tb.Selection.Start = ranges[i].Start;
+                tb.Selection.End = ranges[i].End;
+                prevText.Add(tb.Selection.Text);
+                ClearSelectedCommand.ClearSelected(ts);
+                InsertTextCommand.InsertText(insertedText, ts);
+                ts.OnTextChanged(ranges[i].Start.iLine, ranges[i].End.iLine);
+            }
+            tb.Selection.EndUpdate();
+            ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1));
+
+            lastSel = new RangeInfo(tb.Selection);
+        }
+
+        public override UndoableCommand Clone()
+        {
+            return new ReplaceTextCommand(ts, new List<Range>(ranges), insertedText);
+        }
+    }
+
+    /// <summary>
+    /// Clear selected text
+    /// </summary>
+    internal class ClearSelectedCommand : UndoableCommand
+    {
+        string deletedText;
+
+        /// <summary>
+        /// Construstor
+        /// </summary>
+        /// <param name="tb">Underlaying textbox</param>
+        public ClearSelectedCommand(TextSource ts) : base(ts)
+        {
+        }
+
+        /// <summary>
+        /// Undo operation
+        /// </summary>
+        public override void Undo()
+        {
+            ts.CurrentTB.Selection.Start = new Place(sel.FromX, Math.Min(sel.Start.iLine, sel.End.iLine));
+            ts.OnTextChanging();
+            InsertTextCommand.InsertText(deletedText, ts);
+            ts.OnTextChanged(sel.Start.iLine, sel.End.iLine);
+            ts.CurrentTB.Selection.Start = sel.Start;
+            ts.CurrentTB.Selection.End = sel.End;
+        }
+
+        /// <summary>
+        /// Execute operation
+        /// </summary>
+        public override void Execute()
+        {
+            var tb = ts.CurrentTB;
+
+            string temp = null;
+            ts.OnTextChanging(ref temp);
+            if (temp == "")
+                throw new ArgumentOutOfRangeException();
+
+            deletedText = tb.Selection.Text;
+            ClearSelected(ts);
+            lastSel = new RangeInfo(tb.Selection);
+            ts.OnTextChanged(lastSel.Start.iLine, lastSel.Start.iLine);
+        }
+
+        internal static void ClearSelected(TextSource ts)
+        {
+            var tb = ts.CurrentTB;
+
+            Place start = tb.Selection.Start;
+            Place end = tb.Selection.End;
+            int fromLine = Math.Min(end.iLine, start.iLine);
+            int toLine = Math.Max(end.iLine, start.iLine);
+            int fromChar = tb.Selection.FromX;
+            int toChar = tb.Selection.ToX;
+            if (fromLine < 0) return;
+            //
+            if (fromLine == toLine)
+                ts[fromLine].RemoveRange(fromChar, toChar - fromChar);
+            else
+            {
+                ts[fromLine].RemoveRange(fromChar, ts[fromLine].Count - fromChar);
+                ts[toLine].RemoveRange(0, toChar);
+                ts.RemoveLine(fromLine + 1, toLine - fromLine - 1);
+                InsertCharCommand.MergeLines(fromLine, ts);
+            }
+            //
+            tb.Selection.Start = new Place(fromChar, fromLine);
+            //
+            ts.NeedRecalc(new TextSource.TextChangedEventArgs(fromLine, toLine));
+        }
+
+        public override UndoableCommand Clone()
+        {
+            return new ClearSelectedCommand(ts);
+        }
+    }
+
+    /// <summary>
+    /// Replaces text
+    /// </summary>
+    internal class ReplaceMultipleTextCommand : UndoableCommand
+    {
+        List<ReplaceRange> ranges;
+        List<string> prevText = new List<string>();
+
+        public class ReplaceRange
+        {
+            public Range ReplacedRange { get; set; }
+            public String ReplaceText { get; set; }
+        }
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="ts">Underlaying textsource</param>
+        /// <param name="ranges">List of ranges for replace</param>
+        public ReplaceMultipleTextCommand(TextSource ts, List<ReplaceRange> ranges)
+            : base(ts)
+        {
+            //sort ranges by place
+            ranges.Sort((r1, r2) =>
+            {
+                if (r1.ReplacedRange.Start.iLine == r2.ReplacedRange.Start.iLine)
+                    return r1.ReplacedRange.Start.iChar.CompareTo(r2.ReplacedRange.Start.iChar);
+                return r1.ReplacedRange.Start.iLine.CompareTo(r2.ReplacedRange.Start.iLine);
+            });
+            //
+            this.ranges = ranges;
+            lastSel = sel = new RangeInfo(ts.CurrentTB.Selection);
+        }
+
+        /// <summary>
+        /// Undo operation
+        /// </summary>
+        public override void Undo()
+        {
+            var tb = ts.CurrentTB;
+
+            ts.OnTextChanging();
+
+            tb.Selection.BeginUpdate();
+            for (int i = 0; i < ranges.Count; i++)
+            {
+                tb.Selection.Start = ranges[i].ReplacedRange.Start;
+                for (int j = 0; j < ranges[i].ReplaceText.Length; j++)
+                    tb.Selection.GoRight(true);
+                ClearSelectedCommand.ClearSelected(ts);
+                var prevTextIndex = ranges.Count - 1 - i;
+                InsertTextCommand.InsertText(prevText[prevTextIndex], ts);
+                ts.OnTextChanged(ranges[i].ReplacedRange.Start.iLine, ranges[i].ReplacedRange.Start.iLine);
+            }
+            tb.Selection.EndUpdate();
+
+            ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1));
+        }
+
+        /// <summary>
+        /// Execute operation
+        /// </summary>
+        public override void Execute()
+        {
+            var tb = ts.CurrentTB;
+            prevText.Clear();
+
+            ts.OnTextChanging();
+
+            tb.Selection.BeginUpdate();
+            for (int i = ranges.Count - 1; i >= 0; i--)
+            {
+                tb.Selection.Start = ranges[i].ReplacedRange.Start;
+                tb.Selection.End = ranges[i].ReplacedRange.End;
+                prevText.Add(tb.Selection.Text);
+                ClearSelectedCommand.ClearSelected(ts);
+                InsertTextCommand.InsertText(ranges[i].ReplaceText, ts);
+                ts.OnTextChanged(ranges[i].ReplacedRange.Start.iLine, ranges[i].ReplacedRange.End.iLine);
+            }
+            tb.Selection.EndUpdate();
+            ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1));
+
+            lastSel = new RangeInfo(tb.Selection);
+        }
+
+        public override UndoableCommand Clone()
+        {
+            return new ReplaceMultipleTextCommand(ts, new List<ReplaceRange>(ranges));
+        }
+    }
+
+    /// <summary>
+    /// Removes lines
+    /// </summary>
+    internal class RemoveLinesCommand : UndoableCommand
+    {
+        List<int> iLines;
+        List<string> prevText = new List<string>();
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="tb">Underlaying textbox</param>
+        /// <param name="ranges">List of ranges for replace</param>
+        /// <param name="insertedText">Text for inserting</param>
+        public RemoveLinesCommand(TextSource ts, List<int> iLines)
+            : base(ts)
+        {
+            //sort iLines
+            iLines.Sort();
+            //
+            this.iLines = iLines;
+            lastSel = sel = new RangeInfo(ts.CurrentTB.Selection);
+        }
+
+        /// <summary>
+        /// Undo operation
+        /// </summary>
+        public override void Undo()
+        {
+            var tb = ts.CurrentTB;
+
+            ts.OnTextChanging();
+
+            tb.Selection.BeginUpdate();
+            //tb.BeginUpdate();
+            for (int i = 0; i < iLines.Count; i++)
+            {
+                var iLine = iLines[i];
+
+                if (iLine < ts.Count)
+                    tb.Selection.Start = new Place(0, iLine);
+                else
+                    tb.Selection.Start = new Place(ts[ts.Count - 1].Count, ts.Count - 1);
+
+                InsertCharCommand.InsertLine(ts);
+                tb.Selection.Start = new Place(0, iLine);
+                var text = prevText[prevText.Count - i - 1];
+                InsertTextCommand.InsertText(text, ts);
+                ts[iLine].IsChanged = true;
+                if (iLine < ts.Count - 1)
+                    ts[iLine + 1].IsChanged = true;
+                else
+                    ts[iLine - 1].IsChanged = true;
+                if (text.Trim() != string.Empty)
+                    ts.OnTextChanged(iLine, iLine);
+            }
+            //tb.EndUpdate();
+            tb.Selection.EndUpdate();
+
+            ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1));
+        }
+
+        /// <summary>
+        /// Execute operation
+        /// </summary>
+        public override void Execute()
+        {
+            var tb = ts.CurrentTB;
+            prevText.Clear();
+
+            ts.OnTextChanging();
+
+            tb.Selection.BeginUpdate();
+            for (int i = iLines.Count - 1; i >= 0; i--)
+            {
+                var iLine = iLines[i];
+
+                prevText.Add(ts[iLine].Text);//backward
+                ts.RemoveLine(iLine);
+                //ts.OnTextChanged(ranges[i].Start.iLine, ranges[i].End.iLine);
+            }
+            tb.Selection.Start = new Place(0, 0);
+            tb.Selection.EndUpdate();
+            ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1));
+
+            lastSel = new RangeInfo(tb.Selection);
+        }
+
+        public override UndoableCommand Clone()
+        {
+            return new RemoveLinesCommand(ts, new List<int>(iLines));
+        }
+    }
+
+    /// <summary>
+    /// Wrapper for multirange commands
+    /// </summary>
+    internal class MultiRangeCommand : UndoableCommand
+    {
+        private UndoableCommand cmd;
+        private Range range;
+        private List<UndoableCommand> commandsByRanges = new List<UndoableCommand>();
+
+        public MultiRangeCommand(UndoableCommand command) : base(command.ts)
+        {
+            this.cmd = command;
+            range = ts.CurrentTB.Selection.Clone();
+        }
+
+        public override void Execute()
+        {
+            commandsByRanges.Clear();
+            var prevSelection = range.Clone();
+            var iChar = -1;
+            var iStartLine = prevSelection.Start.iLine;
+            var iEndLine = prevSelection.End.iLine;
+            ts.CurrentTB.Selection.ColumnSelectionMode = false;
+            ts.CurrentTB.Selection.BeginUpdate();
+            ts.CurrentTB.BeginUpdate();
+            ts.CurrentTB.allowInsertRemoveLines = false;
+            try
+            {
+                if (cmd is InsertTextCommand)
+                    ExecuteInsertTextCommand(ref iChar, (cmd as InsertTextCommand).insertedText);
+                else
+                if (cmd is InsertCharCommand && (cmd as InsertCharCommand).c != '\x0' && (cmd as InsertCharCommand).c != '\b')//if not DEL or BACKSPACE
+                    ExecuteInsertTextCommand(ref iChar, (cmd as InsertCharCommand).c.ToString());
+                else
+                    ExecuteCommand(ref iChar);
+            }
+            catch (ArgumentOutOfRangeException)
+            {
+            }
+            finally
+            {
+                ts.CurrentTB.allowInsertRemoveLines = true;
+                ts.CurrentTB.EndUpdate();
+
+                ts.CurrentTB.Selection = range;
+                if (iChar >= 0)
+                {
+                    ts.CurrentTB.Selection.Start = new Place(iChar, iStartLine);
+                    ts.CurrentTB.Selection.End = new Place(iChar, iEndLine);
+                }
+                ts.CurrentTB.Selection.ColumnSelectionMode = true;
+                ts.CurrentTB.Selection.EndUpdate();
+            }
+        }
+
+        private void ExecuteInsertTextCommand(ref int iChar, string text)
+        {
+            var lines = text.Split('\n');
+            var iLine = 0;
+            foreach (var r in range.GetSubRanges(true))
+            {
+                var line = ts.CurrentTB[r.Start.iLine];
+                var lineIsEmpty = r.End < r.Start && line.StartSpacesCount == line.Count;
+                if (!lineIsEmpty)
+                {
+                    var insertedText = lines[iLine % lines.Length];
+                    if (r.End < r.Start && insertedText != "")
+                    {
+                        //add forwarding spaces
+                        insertedText = new string(' ', r.Start.iChar - r.End.iChar) + insertedText;
+                        r.Start = r.End;
+                    }
+                    ts.CurrentTB.Selection = r;
+                    var c = new InsertTextCommand(ts, insertedText);
+                    c.Execute();
+                    if (ts.CurrentTB.Selection.End.iChar > iChar)
+                        iChar = ts.CurrentTB.Selection.End.iChar;
+                    commandsByRanges.Add(c);
+                }
+                iLine++;
+            }
+        }
+
+        private void ExecuteCommand(ref int iChar)
+        {
+            foreach (var r in range.GetSubRanges(false))
+            {
+                ts.CurrentTB.Selection = r;
+                var c = cmd.Clone();
+                c.Execute();
+                if (ts.CurrentTB.Selection.End.iChar > iChar)
+                    iChar = ts.CurrentTB.Selection.End.iChar;
+                commandsByRanges.Add(c);
+            }
+        }
+
+        public override void Undo()
+        {
+            ts.CurrentTB.BeginUpdate();
+            ts.CurrentTB.Selection.BeginUpdate();
+            try
+            {
+                for (int i = commandsByRanges.Count - 1; i >= 0; i--)
+                    commandsByRanges[i].Undo();
+            }
+            finally
+            {
+                ts.CurrentTB.Selection.EndUpdate();
+                ts.CurrentTB.EndUpdate();
+            }
+            ts.CurrentTB.Selection = range.Clone();
+            ts.CurrentTB.OnTextChanged(range);
+            ts.CurrentTB.OnSelectionChanged();
+            ts.CurrentTB.Selection.ColumnSelectionMode = true;
+        }
+
+        public override UndoableCommand Clone()
+        {
+            throw new NotImplementedException();
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/Export.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Export.cs
new file mode 100644
index 0000000..827c05c
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Export.cs
@@ -0,0 +1,225 @@
+锘縰sing Sunny.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// Exports colored text as HTML
+    /// </summary>
+    /// <remarks>At this time only TextStyle renderer is supported. Other styles is not exported.</remarks>
+    public class ExportToHTML
+    {
+        public string LineNumbersCSS = "<style type=\"text/css\"> .lineNumber{font-family : monospace; font-size : small; font-style : normal; font-weight : normal; color : Teal; background-color : ThreedFace;} </style>";
+
+        /// <summary>
+        /// Use nbsp; instead space
+        /// </summary>
+        public bool UseNbsp { get; set; }
+        /// <summary>
+        /// Use nbsp; instead space in beginning of line
+        /// </summary>
+        public bool UseForwardNbsp { get; set; }
+        /// <summary>
+        /// Use original font
+        /// </summary>
+        public bool UseOriginalFont { get; set; }
+        /// <summary>
+        /// Use style tag instead style attribute
+        /// </summary>
+        public bool UseStyleTag { get; set; }
+        /// <summary>
+        /// Use br tag instead \n
+        /// </summary>
+        public bool UseBr { get; set; }
+        /// <summary>
+        /// Includes line numbers
+        /// </summary>
+        public bool IncludeLineNumbers { get; set; }
+
+        FastColoredTextBox tb;
+
+        public ExportToHTML()
+        {
+            UseNbsp = true;
+            UseOriginalFont = true;
+            UseStyleTag = true;
+            UseBr = true;
+        }
+
+        public string GetHtml(FastColoredTextBox tb)
+        {
+            this.tb = tb;
+            Range sel = new Range(tb);
+            sel.SelectAll();
+            return GetHtml(sel);
+        }
+
+        public string GetHtml(Range r)
+        {
+            this.tb = r.tb;
+            Dictionary<StyleIndex, object> styles = new Dictionary<StyleIndex, object>();
+            StringBuilder sb = new StringBuilder();
+            StringBuilder tempSB = new StringBuilder();
+            StyleIndex currentStyleId = StyleIndex.None;
+            r.Normalize();
+            int currentLine = r.Start.iLine;
+            styles[currentStyleId] = null;
+            //
+            if (UseOriginalFont)
+                sb.AppendFormat("<font style=\"font-family: {0}, monospace; font-size: {1}px; line-height: {2}px;\">",
+                                r.tb.Font.Name, r.tb.CharHeight - r.tb.LineInterval, r.tb.CharHeight);
+            //
+            if (IncludeLineNumbers)
+                tempSB.AppendFormat("<span class=lineNumber>{0}</span>  ", currentLine + 1);
+            //
+            bool hasNonSpace = false;
+            foreach (Place p in r)
+            {
+                Char c = r.tb[p.iLine][p.iChar];
+                if (c.style != currentStyleId)
+                {
+                    Flush(sb, tempSB, currentStyleId);
+                    currentStyleId = c.style;
+                    styles[currentStyleId] = null;
+                }
+
+                if (p.iLine != currentLine)
+                {
+                    for (int i = currentLine; i < p.iLine; i++)
+                    {
+                        tempSB.AppendLine(UseBr ? "<br>" : "");
+                        if (IncludeLineNumbers)
+                            tempSB.AppendFormat("<span class=lineNumber>{0}</span>  ", i + 2);
+                    }
+                    currentLine = p.iLine;
+                    hasNonSpace = false;
+                }
+                switch (c.c)
+                {
+                    case ' ':
+                        if ((hasNonSpace || !UseForwardNbsp) && !UseNbsp)
+                            goto default;
+
+                        tempSB.Append("&nbsp;");
+                        break;
+                    case '<':
+                        tempSB.Append("&lt;");
+                        break;
+                    case '>':
+                        tempSB.Append("&gt;");
+                        break;
+                    case '&':
+                        tempSB.Append("&amp;");
+                        break;
+                    default:
+                        hasNonSpace = true;
+                        tempSB.Append(c.c);
+                        break;
+                }
+            }
+            Flush(sb, tempSB, currentStyleId);
+
+            if (UseOriginalFont)
+                sb.AppendLine("</font>");
+
+            //build styles
+            if (UseStyleTag)
+            {
+                tempSB.Length = 0;
+                tempSB.AppendLine("<style type=\"text/css\">");
+                foreach (var styleId in styles.Keys)
+                    tempSB.AppendFormat(".fctb{0}{{ {1} }}\r\n", GetStyleName(styleId), GetCss(styleId));
+                tempSB.AppendLine("</style>");
+
+                sb.Insert(0, tempSB.ToString());
+            }
+
+            if (IncludeLineNumbers)
+                sb.Insert(0, LineNumbersCSS);
+
+            return sb.ToString();
+        }
+
+        private string GetCss(StyleIndex styleIndex)
+        {
+            List<Style> styles = new List<Style>();
+            //find text renderer
+            TextStyle textStyle = null;
+            int mask = 1;
+            bool hasTextStyle = false;
+            for (int i = 0; i < tb.Styles.Length; i++)
+            {
+                if (tb.Styles[i] != null && ((int)styleIndex & mask) != 0)
+                    if (tb.Styles[i].IsExportable)
+                    {
+                        var style = tb.Styles[i];
+                        styles.Add(style);
+
+                        bool isTextStyle = style is TextStyle;
+                        if (isTextStyle)
+                            if (!hasTextStyle || tb.AllowSeveralTextStyleDrawing)
+                            {
+                                hasTextStyle = true;
+                                textStyle = style as TextStyle;
+                            }
+                    }
+                mask = mask << 1;
+            }
+            //add TextStyle css
+            string result = "";
+
+            if (!hasTextStyle)
+            {
+                //draw by default renderer
+                result = tb.DefaultStyle.GetCSS();
+            }
+            else
+            {
+                result = textStyle.GetCSS();
+            }
+            //add non TextStyle css
+            foreach (var style in styles)
+                if (style != textStyle)
+                    result += style.GetCSS();
+
+            return result;
+        }
+
+        public static string GetColorAsString(Color color)
+        {
+            if (color == Color.Transparent)
+                return "";
+            return string.Format("#{0:x2}{1:x2}{2:x2}", color.R, color.G, color.B);
+        }
+
+        string GetStyleName(StyleIndex styleIndex)
+        {
+            return styleIndex.ToString().Replace(" ", "").Replace(",", "");
+        }
+
+        private void Flush(StringBuilder sb, StringBuilder tempSB, StyleIndex currentStyle)
+        {
+            //find textRenderer
+            //var textStyle = styles.Where(s => s is TextStyle).FirstOrDefault();
+            //
+            if (tempSB.Length == 0)
+                return;
+            if (UseStyleTag)
+                sb.AppendFormat("<font class=fctb{0}>{1}</font>", GetStyleName(currentStyle), tempSB.ToString());
+            else
+            {
+                string css = GetCss(currentStyle);
+                if (css != "")
+                    sb.AppendFormat("<font style=\"{0}\">", css);
+                sb.Append(tempSB.ToString());
+                if (css != "")
+                    sb.Append("</font>");
+            }
+            tempSB.Length = 0;
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.Designer.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.Designer.cs
new file mode 100644
index 0000000..0fc0aed
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.Designer.cs
@@ -0,0 +1,68 @@
+锘縩amespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    partial class FastColoredTextBox
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+            base.Dispose(disposing);
+            if (disposing)
+            {
+                if (SyntaxHighlighter != null)
+                    SyntaxHighlighter.Dispose();
+                timer.Dispose();
+                timer2.Dispose();
+
+                if (findForm != null)
+                    findForm.Dispose();
+
+                if (replaceForm != null)
+                    replaceForm.Dispose();
+
+                if (Font != null)
+                    Font.Dispose();
+
+                if (TextSource != null)
+                    TextSource.Dispose();
+            }
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            SuspendLayout();
+            // 
+            // FastColoredTextBox
+            // 
+            AutoScaleDimensions = new SizeF(10F, 21F);
+            AutoScaleMode = AutoScaleMode.Font;
+            BackColor = Color.FromArgb(32, 41, 50);
+            Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            ForeColor = SystemColors.Control;
+            Margin = new Padding(4, 4, 4, 4);
+            Name = "FastColoredTextBox";
+            Size = new Size(214, 185);
+            ResumeLayout(false);
+        }
+
+        #endregion
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.cs
new file mode 100644
index 0000000..3fe3633
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.cs
@@ -0,0 +1,5473 @@
+锘縰sing Microsoft.Win32;
+using Sunny.UI;
+using System.ComponentModel;
+using System.Drawing.Design;
+using System.Drawing.Drawing2D;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+using System.Windows.Forms.Design;
+using Timer = System.Windows.Forms.Timer;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    public partial class FastColoredTextBox : UserControl
+    {
+
+        #region 鍙橀噺澹版槑
+
+        private const int minLeftIndent = 8;
+        private const int maxBracketSearchIterations = 1000;
+        private const int maxLinesForFolding = 3000;
+        private const int minLinesForAccuracy = 100000;
+        private const int WM_IME_SETCONTEXT = 0x0281;
+        private const int WM_HSCROLL = 0x114;
+        private const int WM_VSCROLL = 0x115;
+        private const int SB_ENDSCROLL = 0x8;
+
+        internal readonly List<LineInfo> lineInfos = new List<LineInfo>();
+        private Range selection;
+        private readonly Timer timer = new Timer();
+        private readonly Timer timer2 = new Timer();
+        private readonly List<VisualMarker> visibleMarkers = new List<VisualMarker>();
+        private Color changedLineColor;
+        private int charHeight;
+        private Color currentLineColor;
+        private bool caretVisible;
+        private Range delayedTextChangedRange;
+        private string descriptionFile;
+        private int endFoldingLine = -1;
+        private Color foldingIndicatorColor;
+        private bool handledChar;
+        private bool highlightFoldingIndicator;
+        private Color indentBackColor;
+        private Color paddingBackColor;
+        private bool isChanged;
+        private Language language;
+        private Keys lastModifiers;
+        private DateTime lastNavigatedDateTime;
+        private Range leftBracketPosition;
+        private Range leftBracketPosition2;
+        private int leftPadding;
+        private int lineInterval;
+        private Color lineNumberColor;
+        private uint lineNumberStartValue;
+        private TextSource lines;
+        private IntPtr m_hImc;
+        private bool mouseIsDrag;
+        private bool isLineSelect;
+        private int lineSelectFrom;
+        private bool multiline;
+        private bool needRecalc;
+        private bool needRiseSelectionChangedDelayed;
+        private bool needRiseTextChangedDelayed;
+        private bool needRiseVisibleRangeChangedDelayed;
+        private int preferredLineWidth;
+        private Range rightBracketPosition;
+        private Range rightBracketPosition2;
+        private bool scrollBars;
+        private Color serviceLinesColor;
+        private bool showLineNumbers;
+        private bool showFoldingLines;
+        private bool needRecalcFoldingLines;
+        private FastColoredTextBox sourceTextBox;
+        private int startFoldingLine = -1;
+        private int updating;
+        private Range updatingRange;
+        private bool wordWrap;
+        private int wordWrapLinesCount;
+        private int maxLineLength = 0;
+        private WordWrapMode wordWrapMode = WordWrapMode.WordWrapControlWidth;
+        private Color selectionColor;
+        private Brush backBrush;
+        internal bool allowInsertRemoveLines = true;
+        bool isReplaceMode = false;
+
+        #endregion
+        public FastColoredTextBox()
+        {
+            InitializeComponent();
+            //type provider
+            TypeDescriptor.AddProvider(new FCTBDescriptionProvider(GetType()), this);
+            //drawing optimization
+            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+            SetStyle(ControlStyles.UserPaint, true);
+            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
+            SetStyle(ControlStyles.ResizeRedraw, true);
+            //append monospace font
+            //Font = new Font("Consolas", 9.75f, FontStyle.Regular, GraphicsUnit.Point);
+            Font = new Font(FontFamily.GenericMonospace, 9.75f);
+            //create one line
+            InitTextSource(CreateTextSource());
+            if (lines.Count == 0)
+                lines.InsertLine(0, lines.CreateLine());
+            selection = new Range(this) { Start = new Place(0, 0) };
+            //default settings
+            Cursor = Cursors.IBeam;
+            BackColor = Color.White;
+            LineNumberColor = Color.Teal;
+            IndentBackColor = Color.White;
+            ServiceLinesColor = Color.Silver;
+            FoldingIndicatorColor = Color.Green;
+            CurrentLineColor = Color.Transparent;
+            ChangedLineColor = Color.Transparent;
+            HighlightFoldingIndicator = true;
+            ShowLineNumbers = true;
+            TabLength = 4;
+            FoldedBlockStyle = new FoldedBlockStyle(Brushes.Gray, null, FontStyle.Regular);
+            SelectionColor = Color.Blue;
+            BracketsStyle = new MarkerStyle(new SolidBrush(Color.FromArgb(80, Color.Lime)));
+            BracketsStyle2 = new MarkerStyle(new SolidBrush(Color.FromArgb(60, Color.Red)));
+            DelayedEventsInterval = 100;
+            DelayedTextChangedInterval = 100;
+            AllowSeveralTextStyleDrawing = false;
+            LeftBracket = '\x0';
+            RightBracket = '\x0';
+            LeftBracket2 = '\x0';
+            RightBracket2 = '\x0';
+            SyntaxHighlighter = new SyntaxHighlighter();
+            language = Language.Custom;
+            PreferredLineWidth = 0;
+            needRecalc = true;
+            lastNavigatedDateTime = DateTime.Now;
+            AutoIndent = true;
+            AutoIndentExistingLines = true;
+            CommentPrefix = "//";
+            lineNumberStartValue = 1;
+            multiline = true;
+            scrollBars = true;
+            AcceptsTab = true;
+            AcceptsReturn = true;
+            caretVisible = true;
+            CaretColor = Color.Black;
+            Paddings = new Padding(0, 0, 0, 0);
+            PaddingBackColor = Color.Transparent;
+            DisabledColor = Color.FromArgb(100, 180, 180, 180);
+            needRecalcFoldingLines = true;
+            AllowDrop = true;
+            FindEndOfFoldingBlockStrategy = FindEndOfFoldingBlockStrategy.Strategy1;
+            VirtualSpace = false;
+            //
+            base.AutoScroll = true;
+            timer.Tick += timer_Tick;
+            timer2.Tick += timer2_Tick;
+        }
+
+        /// <summary>
+        /// Enables virtual spaces
+        /// </summary>
+        [DefaultValue(false)]
+        [Description("Enables virtual spaces.")]
+        public bool VirtualSpace { get; set; }
+
+        /// <summary>
+        /// Strategy of search of end of folding block
+        /// </summary>
+        [DefaultValue(FindEndOfFoldingBlockStrategy.Strategy1)]
+        [Description("Strategy of search of end of folding block.")]
+        public FindEndOfFoldingBlockStrategy FindEndOfFoldingBlockStrategy { get; set; }
+
+        /// <summary>
+        /// Indicates if tab characters are accepted as input
+        /// </summary>
+        [DefaultValue(true)]
+        [Description("Indicates if tab characters are accepted as input.")]
+        public bool AcceptsTab { get; set; }
+
+        /// <summary>
+        /// Indicates if return characters are accepted as input
+        /// </summary>
+        [DefaultValue(true)]
+        [Description("Indicates if return characters are accepted as input.")]
+        public bool AcceptsReturn { get; set; }
+
+        /// <summary>
+        /// Shows or hides the caret
+        /// </summary>
+        [DefaultValue(true)]
+        [Description("Shows or hides the caret")]
+        public bool CaretVisible
+        {
+            get { return caretVisible; }
+            set
+            {
+                caretVisible = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Background color for current line
+        /// </summary>
+        [DefaultValue(typeof(Color), "Transparent")]
+        [Description("Background color for current line. Set to Color.Transparent to hide current line highlighting")]
+        public Color CurrentLineColor
+        {
+            get { return currentLineColor; }
+            set
+            {
+                currentLineColor = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Background color for highlighting of changed lines
+        /// </summary>
+        [DefaultValue(typeof(Color), "Transparent")]
+        [Description(
+            "Background color for highlighting of changed lines. Set to Color.Transparent to hide changed line highlighting"
+            )]
+        public Color ChangedLineColor
+        {
+            get { return changedLineColor; }
+            set
+            {
+                changedLineColor = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Fore color (default style color)
+        /// </summary>
+        public override Color ForeColor
+        {
+            get { return base.ForeColor; }
+            set
+            {
+                base.ForeColor = value;
+                if (lines != null)
+                {
+                    lines.InitDefaultStyle();
+                    Invalidate();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Height of char in pixels
+        /// </summary>
+        [Description("Height of char in pixels")]
+        public int CharHeight
+        {
+            get { return charHeight; }
+            private set
+            {
+                charHeight = value;
+                OnCharSizeChanged();
+            }
+        }
+
+        /// <summary>
+        /// Interval between lines (in pixels)
+        /// </summary>
+        [Description("Interval between lines in pixels")]
+        [DefaultValue(0)]
+        public int LineInterval
+        {
+            get { return lineInterval; }
+            set
+            {
+                lineInterval = value;
+                Font = Font;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Width of char in pixels
+        /// </summary>
+        [Description("Width of char in pixels")]
+        public int CharWidth { get; private set; }
+
+        /// <summary>
+        /// Spaces count for tab
+        /// </summary>
+        [DefaultValue(4)]
+        [Description("Spaces count for tab")]
+        public int TabLength { get; set; }
+
+        /// <summary>
+        /// Text was changed
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public bool IsChanged
+        {
+            get { return isChanged; }
+            set
+            {
+                if (!value)
+                    //clear line's IsChanged property
+                    lines.ClearIsChanged();
+
+                isChanged = value;
+            }
+        }
+
+        /// <summary>
+        /// Text version
+        /// </summary>
+        /// <remarks>This counter is incremented each time changes the text</remarks>
+        [Browsable(false)]
+        public int TextVersion { get; private set; }
+
+        /// <summary>
+        /// Read only
+        /// </summary>
+        [DefaultValue(false)]
+        public bool ReadOnly { get; set; }
+
+        /// <summary>
+        /// Shows line numbers.
+        /// </summary>
+        [DefaultValue(true)]
+        [Description("Shows line numbers.")]
+        public bool ShowLineNumbers
+        {
+            get { return showLineNumbers; }
+            set
+            {
+                showLineNumbers = value;
+                NeedRecalc();
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Shows vertical lines between folding start line and folding end line.
+        /// </summary>
+        [DefaultValue(false)]
+        [Description("Shows vertical lines between folding start line and folding end line.")]
+        public bool ShowFoldingLines
+        {
+            get { return showFoldingLines; }
+            set
+            {
+                showFoldingLines = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Color of line numbers.
+        /// </summary>
+        [DefaultValue(typeof(Color), "Teal")]
+        [Description("Color of line numbers.")]
+        public Color LineNumberColor
+        {
+            get { return lineNumberColor; }
+            set
+            {
+                lineNumberColor = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Start value of first line number.
+        /// </summary>
+        [DefaultValue(typeof(uint), "1")]
+        [Description("Start value of first line number.")]
+        public uint LineNumberStartValue
+        {
+            get { return lineNumberStartValue; }
+            set
+            {
+                lineNumberStartValue = value;
+                needRecalc = true;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Background color of indent area
+        /// </summary>
+        [DefaultValue(typeof(Color), "White")]
+        [Description("Background color of indent area")]
+        public Color IndentBackColor
+        {
+            get { return indentBackColor; }
+            set
+            {
+                indentBackColor = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Background color of padding area
+        /// </summary>
+        [DefaultValue(typeof(Color), "Transparent")]
+        [Description("Background color of padding area")]
+        public Color PaddingBackColor
+        {
+            get { return paddingBackColor; }
+            set
+            {
+                paddingBackColor = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Color of disabled component
+        /// </summary>
+        [DefaultValue(typeof(Color), "100;180;180;180")]
+        [Description("Color of disabled component")]
+        public Color DisabledColor { get; set; }
+
+        /// <summary>
+        /// Color of caret
+        /// </summary>
+        [DefaultValue(typeof(Color), "Black")]
+        [Description("Color of caret.")]
+        public Color CaretColor { get; set; }
+
+        /// <summary>
+        /// Color of service lines (folding lines, borders of blocks etc.)
+        /// </summary>
+        [DefaultValue(typeof(Color), "Silver")]
+        [Description("Color of service lines (folding lines, borders of blocks etc.)")]
+        public Color ServiceLinesColor
+        {
+            get { return serviceLinesColor; }
+            set
+            {
+                serviceLinesColor = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Padings of text area
+        /// </summary>
+        [Browsable(true)]
+        [Description("Paddings of text area.")]
+        public Padding Paddings { get; set; }
+
+        //hide parent padding
+        [Browsable(false)]
+        public new Padding Padding
+        {
+            get { throw new NotImplementedException(); }
+            set { throw new NotImplementedException(); }
+        }
+
+        //hide RTL
+        [Browsable(false)]
+        public new bool RightToLeft
+        {
+            get { throw new NotImplementedException(); }
+            set { throw new NotImplementedException(); }
+        }
+
+        /// <summary>
+        /// Color of folding area indicator
+        /// </summary>
+        [DefaultValue(typeof(Color), "Green")]
+        [Description("Color of folding area indicator.")]
+        public Color FoldingIndicatorColor
+        {
+            get { return foldingIndicatorColor; }
+            set
+            {
+                foldingIndicatorColor = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Enables folding indicator (left vertical line between folding bounds)
+        /// </summary>
+        [DefaultValue(true)]
+        [Description("Enables folding indicator (left vertical line between folding bounds)")]
+        public bool HighlightFoldingIndicator
+        {
+            get { return highlightFoldingIndicator; }
+            set
+            {
+                highlightFoldingIndicator = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Left indent in pixels
+        /// </summary>
+        [Browsable(false)]
+        [Description("Left indent in pixels")]
+        public int LeftIndent { get; private set; }
+
+        /// <summary>
+        /// Left padding in pixels
+        /// </summary>
+        [DefaultValue(0)]
+        [Description("Width of left service area (in pixels)")]
+        public int LeftPadding
+        {
+            get { return leftPadding; }
+            set
+            {
+                leftPadding = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// This property draws vertical line after defined char position.
+        /// Set to 0 for disable drawing of vertical line.
+        /// </summary>
+        [DefaultValue(0)]
+        [Description(
+            "This property draws vertical line after defined char position. Set to 0 for disable drawing of vertical line."
+            )]
+        public int PreferredLineWidth
+        {
+            get { return preferredLineWidth; }
+            set
+            {
+                preferredLineWidth = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Styles
+        /// Maximum style count is 16
+        /// </summary>
+        [Browsable(false)]
+        public Style[] Styles
+        {
+            get { return lines.Styles; }
+        }
+
+        /// <summary>
+        /// Default text style
+        /// This style is using when no one other TextStyle is not defined in Char.style
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public TextStyle DefaultStyle
+        {
+            get { return lines.DefaultStyle; }
+            set { lines.DefaultStyle = value; }
+        }
+
+        /// <summary>
+        /// Style for rendering Selection area
+        /// </summary>
+        [Browsable(false)]
+        public SelectionStyle SelectionStyle { get; set; }
+
+        /// <summary>
+        /// Style for folded block rendering
+        /// </summary>
+        [Browsable(false)]
+        public TextStyle FoldedBlockStyle { get; set; }
+
+        /// <summary>
+        /// Style for brackets highlighting
+        /// </summary>
+        [Browsable(false)]
+        public MarkerStyle BracketsStyle { get; set; }
+
+        /// <summary>
+        /// Style for alternative brackets highlighting
+        /// </summary>
+        [Browsable(false)]
+        public MarkerStyle BracketsStyle2 { get; set; }
+
+        /// <summary>
+        /// Opening bracket for brackets highlighting.
+        /// Set to '\x0' for disable brackets highlighting.
+        /// </summary>
+        [DefaultValue('\x0')]
+        [Description("Opening bracket for brackets highlighting. Set to '\\x0' for disable brackets highlighting.")]
+        public char LeftBracket { get; set; }
+
+        /// <summary>
+        /// Closing bracket for brackets highlighting.
+        /// Set to '\x0' for disable brackets highlighting.
+        /// </summary>
+        [DefaultValue('\x0')]
+        [Description("Closing bracket for brackets highlighting. Set to '\\x0' for disable brackets highlighting.")]
+        public char RightBracket { get; set; }
+
+        /// <summary>
+        /// Alternative opening bracket for brackets highlighting.
+        /// Set to '\x0' for disable brackets highlighting.
+        /// </summary>
+        [DefaultValue('\x0')]
+        [Description(
+            "Alternative opening bracket for brackets highlighting. Set to '\\x0' for disable brackets highlighting.")]
+        public char LeftBracket2 { get; set; }
+
+        /// <summary>
+        /// Alternative closing bracket for brackets highlighting.
+        /// Set to '\x0' for disable brackets highlighting.
+        /// </summary>
+        [DefaultValue('\x0')]
+        [Description(
+            "Alternative closing bracket for brackets highlighting. Set to '\\x0' for disable brackets highlighting.")]
+        public char RightBracket2 { get; set; }
+
+        /// <summary>
+        /// Comment line prefix.
+        /// </summary>
+        [DefaultValue("//")]
+        [Description("Comment line prefix.")]
+        public string CommentPrefix { get; set; }
+
+        /// <summary>
+        /// This property specifies which part of the text will be highlighted as you type (by built-in highlighter).
+        /// </summary>
+        /// <remarks>When a user enters text, a component of rebuilding the highlight (because the text is changed).
+        /// This property specifies exactly which section of the text will be re-highlighted.
+        /// This can be useful to highlight multi-line comments, for example.</remarks>
+        [DefaultValue(typeof(HighlightingRangeType), "ChangedRange")]
+        [Description("This property specifies which part of the text will be highlighted as you type.")]
+        public HighlightingRangeType HighlightingRangeType { get; set; }
+
+        /// <summary>
+        /// Is keyboard in replace mode (wide caret) ?
+        /// </summary>
+        [Browsable(false)]
+        public bool IsReplaceMode
+        {
+            get
+            {
+                return isReplaceMode && Selection.IsEmpty &&
+                       Selection.Start.iChar < lines[Selection.Start.iLine].Count;
+            }
+            set { isReplaceMode = value; }
+        }
+
+        /// <summary>
+        /// Allows text rendering several styles same time.
+        /// </summary>
+        [Browsable(true)]
+        [DefaultValue(false)]
+        [Description("Allows text rendering several styles same time.")]
+        public bool AllowSeveralTextStyleDrawing { get; set; }
+
+        /// <summary>
+        /// Allows AutoIndent. Inserts spaces before new line.
+        /// </summary>
+        [DefaultValue(true)]
+        [Description("Allows auto indent. Inserts spaces before line chars.")]
+        public bool AutoIndent { get; set; }
+
+        /// <summary>
+        /// Does autoindenting in existing lines. It works only if AutoIndent is True.
+        /// </summary>
+        [DefaultValue(true)]
+        [Description("Does autoindenting in existing lines. It works only if AutoIndent is True.")]
+        public bool AutoIndentExistingLines { get; set; }
+
+        /// <summary>
+        /// Minimal delay(ms) for delayed events (except TextChangedDelayed).
+        /// </summary>
+        [Browsable(true)]
+        [DefaultValue(100)]
+        [Description("Minimal delay(ms) for delayed events (except TextChangedDelayed).")]
+        public int DelayedEventsInterval
+        {
+            get { return timer.Interval; }
+            set { timer.Interval = value; }
+        }
+
+        /// <summary>
+        /// Minimal delay(ms) for TextChangedDelayed event.
+        /// </summary>
+        [Browsable(true)]
+        [DefaultValue(100)]
+        [Description("Minimal delay(ms) for TextChangedDelayed event.")]
+        public int DelayedTextChangedInterval
+        {
+            get { return timer2.Interval; }
+            set { timer2.Interval = value; }
+        }
+
+        /// <summary>
+        /// Language for highlighting by built-in highlighter.
+        /// </summary>
+        [Browsable(true)]
+        [DefaultValue(typeof(Language), "Custom")]
+        [Description("Language for highlighting by built-in highlighter.")]
+        public Language Language
+        {
+            get { return language; }
+            set
+            {
+                language = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Syntax Highlighter
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public SyntaxHighlighter SyntaxHighlighter { get; set; }
+
+        /// <summary>
+        /// XML file with description of syntax highlighting.
+        /// This property works only with Language == Language.Custom.
+        /// </summary>
+        [Browsable(true)]
+        [DefaultValue(null)]
+        [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]
+        [Description(
+            "XML file with description of syntax highlighting. This property works only with Language == Language.Custom."
+            )]
+        public string DescriptionFile
+        {
+            get { return descriptionFile; }
+            set
+            {
+                descriptionFile = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Position of left highlighted bracket.
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public Range LeftBracketPosition
+        {
+            get { return leftBracketPosition; }
+        }
+
+        /// <summary>
+        /// Position of right highlighted bracket.
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public Range RightBracketPosition
+        {
+            get { return rightBracketPosition; }
+        }
+
+        /// <summary>
+        /// Position of left highlighted alternative bracket.
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public Range LeftBracketPosition2
+        {
+            get { return leftBracketPosition2; }
+        }
+
+        /// <summary>
+        /// Position of right highlighted alternative bracket.
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public Range RightBracketPosition2
+        {
+            get { return rightBracketPosition2; }
+        }
+
+        /// <summary>
+        /// Start line index of current highlighted folding area. Return -1 if start of area is not found.
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public int StartFoldingLine
+        {
+            get { return startFoldingLine; }
+        }
+
+        /// <summary>
+        /// End line index of current highlighted folding area. Return -1 if end of area is not found.
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public int EndFoldingLine
+        {
+            get { return endFoldingLine; }
+        }
+
+        /// <summary>
+        /// TextSource
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public TextSource TextSource
+        {
+            get { return lines; }
+            set { InitTextSource(value); }
+        }
+
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public bool HasSourceTextBox
+        {
+            get { return SourceTextBox != null; }
+        }
+
+        /// <summary>
+        /// The source of the text.
+        /// Allows to get text from other FastColoredTextBox.
+        /// </summary>
+        [Browsable(true)]
+        [DefaultValue(null)]
+        [Description("Allows to get text from other FastColoredTextBox.")]
+        //[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public FastColoredTextBox SourceTextBox
+        {
+            get { return sourceTextBox; }
+            set
+            {
+                if (value == sourceTextBox)
+                    return;
+
+                sourceTextBox = value;
+
+                if (sourceTextBox == null)
+                {
+                    InitTextSource(CreateTextSource());
+                    lines.InsertLine(0, TextSource.CreateLine());
+                    IsChanged = false;
+                }
+                else
+                {
+                    InitTextSource(SourceTextBox.TextSource);
+                    isChanged = false;
+                }
+                Invalidate();
+            }
+        }
+
+        Range visibleRange = null;
+
+        /// <summary>
+        /// Returns current visible range of text
+        /// </summary>
+        [Browsable(false)]
+        public Range VisibleRange
+        {
+            get
+            {
+                if (visibleRange != null)
+                    return visibleRange;
+                return GetRange(
+                    PointToPlace(new Point(LeftIndent, 0)),
+                    PointToPlace(new Point(ClientSize.Width, ClientSize.Height))
+                    );
+            }
+        }
+
+        /// <summary>
+        /// Current selection range
+        /// </summary>
+        [Browsable(false)]
+        public Range Selection
+        {
+            get { return selection; }
+            set
+            {
+                selection.BeginUpdate();
+                selection.Start = value.Start;
+                selection.End = value.End;
+                selection.EndUpdate();
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Background color.
+        /// It is used if BackBrush is null.
+        /// </summary>
+        [DefaultValue(typeof(Color), "White")]
+        [Description("Background color.")]
+        public override Color BackColor
+        {
+            get { return base.BackColor; }
+            set { base.BackColor = value; }
+        }
+
+        /// <summary>
+        /// Background brush.
+        /// If Null then BackColor is used.
+        /// </summary>
+        [Browsable(false)]
+        public Brush BackBrush
+        {
+            get { return backBrush; }
+            set
+            {
+                backBrush = value;
+                Invalidate();
+            }
+        }
+
+        [Browsable(true)]
+        [DefaultValue(true)]
+        [Description("Scollbars visibility.")]
+        public bool ShowScrollBars
+        {
+            get { return scrollBars; }
+            set
+            {
+                if (value == scrollBars) return;
+                scrollBars = value;
+                needRecalc = true;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Multiline
+        /// </summary>
+        [Browsable(true)]
+        [DefaultValue(true)]
+        [Description("Multiline mode.")]
+        public bool Multiline
+        {
+            get { return multiline; }
+            set
+            {
+                if (multiline == value) return;
+                multiline = value;
+                needRecalc = true;
+                if (multiline)
+                {
+                    base.AutoScroll = true;
+                    ShowScrollBars = true;
+                }
+                else
+                {
+                    base.AutoScroll = false;
+                    ShowScrollBars = false;
+                    if (lines.Count > 1)
+                        lines.RemoveLine(1, lines.Count - 1);
+                    lines.Manager.ClearHistory();
+                }
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// WordWrap.
+        /// </summary>
+        [Browsable(true)]
+        [DefaultValue(false)]
+        [Description("WordWrap.")]
+        public bool WordWrap
+        {
+            get { return wordWrap; }
+            set
+            {
+                if (wordWrap == value) return;
+                wordWrap = value;
+                if (wordWrap)
+                    Selection.ColumnSelectionMode = false;
+                RecalcWordWrap(0, LinesCount - 1);
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// WordWrap mode.
+        /// </summary>
+        [Browsable(true)]
+        [DefaultValue(typeof(WordWrapMode), "WordWrapControlWidth")]
+        [Description("WordWrap mode.")]
+        public WordWrapMode WordWrapMode
+        {
+            get { return wordWrapMode; }
+            set
+            {
+                if (wordWrapMode == value) return;
+                wordWrapMode = value;
+                RecalcWordWrap(0, LinesCount - 1);
+                Invalidate();
+            }
+        }
+
+
+        /// <summary>
+        /// Count of lines with wordwrap effect
+        /// </summary>
+        [Browsable(false)]
+        public int WordWrapLinesCount
+        {
+            get
+            {
+                if (needRecalc)
+                    Recalc();
+                return wordWrapLinesCount;
+            }
+        }
+
+        [Browsable(false)]
+        public FindForm findForm { get; private set; }
+
+        [Browsable(false)]
+        public ReplaceForm replaceForm { get; private set; }
+
+        /// <summary>
+        /// Do not change this property
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public override bool AutoScroll
+        {
+            get { return base.AutoScroll; }
+            set {; }
+        }
+
+        /// <summary>
+        /// Count of lines
+        /// </summary>
+        [Browsable(false)]
+        public int LinesCount
+        {
+            get { return lines.Count; }
+        }
+
+        /// <summary>
+        /// Gets or sets char and styleId for given place
+        /// This property does not fire OnTextChanged event
+        /// </summary>
+        public Char this[Place place]
+        {
+            get { return lines[place.iLine][place.iChar]; }
+            set { lines[place.iLine][place.iChar] = value; }
+        }
+
+        /// <summary>
+        /// Gets Line
+        /// </summary>
+        public Line this[int iLine]
+        {
+            get { return lines[iLine]; }
+        }
+
+        /// <summary>
+        /// Text of control
+        /// </summary>
+        [Browsable(true)]
+        [Localizable(true)]
+        [Editor(
+            "System.ComponentModel.Design.MultilineStringEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
+            , typeof(UITypeEditor))]
+        [SettingsBindable(true)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+        [Description("Text of the control.")]
+        [Bindable(true)]
+        public override string Text
+        {
+            get
+            {
+                var sel = new Range(this);
+                sel.SelectAll();
+                return sel.Text;
+            }
+
+            set
+            {
+                SetAsCurrentTB();
+
+                Selection.ColumnSelectionMode = false;
+
+                Selection.BeginUpdate();
+                try
+                {
+                    Selection.SelectAll();
+                    InsertText(value);
+                    GoHome();
+                }
+                finally
+                {
+                    Selection.EndUpdate();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Text lines
+        /// </summary>
+        [Browsable(false)]
+        public IList<string> Lines
+        {
+            get { return lines.Lines; }
+        }
+
+        /// <summary>
+        /// Gets colored text as HTML
+        /// </summary>
+        /// <remarks>For more flexibility you can use ExportToHTML class also</remarks>
+        [Browsable(false)]
+        public string Html
+        {
+            get
+            {
+                var exporter = new ExportToHTML();
+                exporter.UseNbsp = false;
+                exporter.UseStyleTag = false;
+                exporter.UseBr = false;
+                return "<pre>" + exporter.GetHtml(this) + "</pre>";
+            }
+        }
+
+        /// <summary>
+        /// Text of current selection
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public string SelectedText
+        {
+            get { return Selection.Text; }
+            set { InsertText(value); }
+        }
+
+        /// <summary>
+        /// Start position of selection
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public int SelectionStart
+        {
+            get { return Math.Min(PlaceToPosition(Selection.Start), PlaceToPosition(Selection.End)); }
+            set { Selection.Start = PositionToPlace(value); }
+        }
+
+        /// <summary>
+        /// Length of selected text
+        /// </summary>
+        [Browsable(false)]
+        [DefaultValue(0)]
+        public int SelectionLength
+        {
+            get { return Math.Abs(PlaceToPosition(Selection.Start) - PlaceToPosition(Selection.End)); }
+            set
+            {
+                if (value > 0)
+                    Selection.End = PositionToPlace(SelectionStart + value);
+            }
+        }
+
+        /// <summary>
+        /// Font
+        /// </summary>
+        /// <remarks>Use only monospaced font</remarks>
+        [DefaultValue(typeof(Font), "Courier New, 9.75")]
+        public override Font Font
+        {
+            get { return base.Font; }
+            set
+            {
+                base.Font = value;
+                // 娉ㄩ噴鎺夊己鍒剁瓑瀹藉瓧浣撴鏌�
+                //SizeF sizeM = GetCharSize(base.Font, 'M');
+                //SizeF sizeDot = GetCharSize(base.Font, '.');
+                //if (sizeM != sizeDot)
+                //    base.Font = new Font("Courier New", base.Font.SizeInPoints, FontStyle.Regular, GraphicsUnit.Point);
+
+                // 淇濇寔鍘熸湁鐨勫瓧绗﹀搴﹁绠楋紝浣嗕娇鐢ㄤ紶鍏ョ殑瀛椾綋
+                SizeF size = GetCharSize(base.Font, '.');
+                CharWidth = (int)Math.Round(size.Width * 1f) - 1;
+                CharHeight = lineInterval + (int)Math.Round(size.Height * 1f) - 1;
+                //
+                NeedRecalc();
+                Invalidate();
+            }
+        }
+
+        private new Size AutoScrollMinSize
+        {
+            set
+            {
+                if (scrollBars)
+                {
+                    if (!base.AutoScroll)
+                        base.AutoScroll = true;
+                    Size newSize = value;
+                    if (WordWrap)
+                    {
+                        int maxWidth = GetMaxLineWordWrapedWidth();
+                        newSize = new Size(Math.Min(newSize.Width, maxWidth), newSize.Height);
+                    }
+                    base.AutoScrollMinSize = newSize;
+                }
+                else
+                {
+                    if (base.AutoScroll)
+                        base.AutoScroll = false;
+                    base.AutoScrollMinSize = new Size(0, 0);
+                    VerticalScroll.Visible = false;
+                    HorizontalScroll.Visible = false;
+                    HorizontalScroll.Maximum = value.Width;
+                    VerticalScroll.Maximum = value.Height;
+                }
+            }
+
+            get
+            {
+                if (scrollBars)
+                    return base.AutoScrollMinSize;
+                else
+                    return new Size(HorizontalScroll.Maximum, VerticalScroll.Maximum);
+            }
+        }
+
+        /// <summary>
+        /// Indicates that IME is allowed (for CJK language entering)
+        /// </summary>
+        [Browsable(false)]
+        public bool ImeAllowed
+        {
+            get
+            {
+                return ImeMode != ImeMode.Disable &&
+                       ImeMode != ImeMode.Off &&
+                       ImeMode != ImeMode.NoControl;
+            }
+        }
+
+        /// <summary>
+        /// Is undo enabled?
+        /// </summary>
+        [Browsable(false)]
+        public bool UndoEnabled
+        {
+            get { return lines.Manager.UndoEnabled; }
+        }
+
+        /// <summary>
+        /// Is redo enabled?
+        /// </summary>
+        [Browsable(false)]
+        public bool RedoEnabled
+        {
+            get { return lines.Manager.RedoEnabled; }
+        }
+
+        private int LeftIndentLine
+        {
+            get { return LeftIndent - minLeftIndent / 2 - 3; }
+        }
+
+        /// <summary>
+        /// Range of all text
+        /// </summary>
+        [Browsable(false)]
+        public Range Range
+        {
+            get { return new Range(this, new Place(0, 0), new Place(lines[lines.Count - 1].Count, lines.Count - 1)); }
+        }
+
+        /// <summary>
+        /// Occurs when VisibleRange is changed
+        /// </summary>
+        public virtual void OnVisibleRangeChanged()
+        {
+            needRecalcFoldingLines = true;
+
+            needRiseVisibleRangeChangedDelayed = true;
+            ResetTimer(timer);
+            if (VisibleRangeChanged != null)
+                VisibleRangeChanged(this, new EventArgs());
+        }
+
+        /// <summary>
+        /// Invalidates the entire surface of the control and causes the control to be redrawn.
+        /// This method is thread safe and does not require Invoke.
+        /// </summary>
+        public new void Invalidate()
+        {
+            if (InvokeRequired)
+                BeginInvoke(new MethodInvoker(Invalidate));
+            else
+                base.Invalidate();
+        }
+
+        protected virtual void OnCharSizeChanged()
+        {
+            VerticalScroll.SmallChange = charHeight;
+            VerticalScroll.LargeChange = 10 * charHeight;
+            HorizontalScroll.SmallChange = CharWidth;
+        }
+
+        /// <summary>
+        /// TextChanged event.
+        /// It occurs after insert, delete, clear, undo and redo operations.
+        /// </summary>
+        [Browsable(true)]
+        [Description("It occurs after insert, delete, clear, undo and redo operations.")]
+        public new event EventHandler<TextChangedEventArgs> TextChanged;
+
+        /// <summary>
+        /// Fake event for correct data binding
+        /// </summary>
+        [Browsable(false)]
+        internal new event EventHandler BindingTextChanged;
+
+        /// <summary>
+        /// TextChanging event.
+        /// It occurs before insert, delete, clear, undo and redo operations.
+        /// </summary>
+        [Browsable(true)]
+        [Description("It occurs before insert, delete, clear, undo and redo operations.")]
+        public event EventHandler<TextChangingEventArgs> TextChanging;
+
+        /// <summary>
+        /// SelectionChanged event.
+        /// It occurs after changing of selection.
+        /// </summary>
+        [Browsable(true)]
+        [Description("It occurs after changing of selection.")]
+        public event EventHandler SelectionChanged;
+
+        /// <summary>
+        /// VisibleRangeChanged event.
+        /// It occurs after changing of visible range.
+        /// </summary>
+        [Browsable(true)]
+        [Description("It occurs after changing of visible range.")]
+        public event EventHandler VisibleRangeChanged;
+
+        /// <summary>
+        /// TextChangedDelayed event. 
+        /// It occurs after insert, delete, clear, undo and redo operations. 
+        /// This event occurs with a delay relative to TextChanged, and fires only once.
+        /// </summary>
+        [Browsable(true)]
+        [Description(
+            "It occurs after insert, delete, clear, undo and redo operations. This event occurs with a delay relative to TextChanged, and fires only once."
+            )]
+        public event EventHandler<TextChangedEventArgs> TextChangedDelayed;
+
+        /// <summary>
+        /// SelectionChangedDelayed event.
+        /// It occurs after changing of selection.
+        /// This event occurs with a delay relative to SelectionChanged, and fires only once.
+        /// </summary>
+        [Browsable(true)]
+        [Description(
+            "It occurs after changing of selection. This event occurs with a delay relative to SelectionChanged, and fires only once."
+            )]
+        public event EventHandler SelectionChangedDelayed;
+
+        /// <summary>
+        /// VisibleRangeChangedDelayed event.
+        /// It occurs after changing of visible range.
+        /// This event occurs with a delay relative to VisibleRangeChanged, and fires only once.
+        /// </summary>
+        [Browsable(true)]
+        [Description(
+            "It occurs after changing of visible range. This event occurs with a delay relative to VisibleRangeChanged, and fires only once."
+            )]
+        public event EventHandler VisibleRangeChangedDelayed;
+
+        /// <summary>
+        /// It occurs when user click on VisualMarker.
+        /// </summary>
+        [Browsable(true)]
+        [Description("It occurs when user click on VisualMarker.")]
+        public event EventHandler<VisualMarkerEventArgs> VisualMarkerClick;
+
+        /// <summary>
+        /// It occurs when visible char is enetering (alphabetic, digit, punctuation, DEL, BACKSPACE)
+        /// </summary>
+        /// <remarks>Set Handle to True for cancel key</remarks>
+        [Browsable(true)]
+        [Description("It occurs when visible char is enetering (alphabetic, digit, punctuation, DEL, BACKSPACE).")]
+        public event KeyPressEventHandler KeyPressing;
+
+        /// <summary>
+        /// It occurs when visible char is enetered (alphabetic, digit, punctuation, DEL, BACKSPACE)
+        /// </summary>
+        [Browsable(true)]
+        [Description("It occurs when visible char is enetered (alphabetic, digit, punctuation, DEL, BACKSPACE).")]
+        public event KeyPressEventHandler KeyPressed;
+
+        /// <summary>
+        /// It occurs when calculates AutoIndent for new line
+        /// </summary>
+        [Browsable(true)]
+        [Description("It occurs when calculates AutoIndent for new line.")]
+        public event EventHandler<AutoIndentEventArgs> AutoIndentNeeded;
+
+        /// <summary>
+        /// It occurs when line background is painting
+        /// </summary>
+        [Browsable(true)]
+        [Description("It occurs when line background is painting.")]
+        public event EventHandler<PaintLineEventArgs> PaintLine;
+
+        /// <summary>
+        /// Occurs when line was inserted/added
+        /// </summary>
+        [Browsable(true)]
+        [Description("Occurs when line was inserted/added.")]
+        public event EventHandler<LineInsertedEventArgs> LineInserted;
+
+        /// <summary>
+        /// Occurs when line was removed
+        /// </summary>
+        [Browsable(true)]
+        [Description("Occurs when line was removed.")]
+        public event EventHandler<LineRemovedEventArgs> LineRemoved;
+
+        /// <summary>
+        /// Occurs when current highlighted folding area is changed.
+        /// Current folding area see in StartFoldingLine and EndFoldingLine.
+        /// </summary>
+        /// <remarks></remarks>
+        [Browsable(true)]
+        [Description("Occurs when current highlighted folding area is changed.")]
+        public event EventHandler<EventArgs> FoldingHighlightChanged;
+
+        /// <summary>
+        /// Occurs when undo/redo stack is changed
+        /// </summary>
+        /// <remarks></remarks>
+        [Browsable(true)]
+        [Description("Occurs when undo/redo stack is changed.")]
+        public event EventHandler<EventArgs> UndoRedoStateChanged;
+
+        private TextSource CreateTextSource()
+        {
+            return new TextSource(this);
+        }
+
+        private void SetAsCurrentTB()
+        {
+            TextSource.CurrentTB = this;
+        }
+
+        private void InitTextSource(TextSource ts)
+        {
+            if (lines != null)
+            {
+                ts.LineInserted -= ts_LineInserted;
+                ts.LineRemoved -= ts_LineRemoved;
+                ts.TextChanged -= ts_TextChanged;
+                ts.RecalcNeeded -= ts_RecalcNeeded;
+                ts.TextChanging -= ts_TextChanging;
+
+                lines.Dispose();
+            }
+
+            lineInfos.Clear();
+
+            lines = ts;
+
+            if (ts != null)
+            {
+                ts.LineInserted += ts_LineInserted;
+                ts.LineRemoved += ts_LineRemoved;
+                ts.TextChanged += ts_TextChanged;
+                ts.RecalcNeeded += ts_RecalcNeeded;
+                ts.TextChanging += ts_TextChanging;
+                while (lineInfos.Count < ts.Count)
+                    lineInfos.Add(new LineInfo(-1));
+            }
+
+            isChanged = false;
+            needRecalc = true;
+        }
+
+        private void ts_TextChanging(object sender, TextChangingEventArgs e)
+        {
+            if (TextSource.CurrentTB == this)
+            {
+                string text = e.InsertingText;
+                OnTextChanging(ref text);
+                e.InsertingText = text;
+            }
+        }
+
+        private void ts_RecalcNeeded(object sender, TextSource.TextChangedEventArgs e)
+        {
+            if (e.iFromLine == e.iToLine && !WordWrap && lines.Count > minLinesForAccuracy)
+                RecalcScrollByOneLine(e.iFromLine);
+            else
+                needRecalc = true;
+        }
+
+        /// <summary>
+        /// Call this method if the recalc of the position of lines is needed.
+        /// </summary>
+        public void NeedRecalc()
+        {
+            needRecalc = true;
+        }
+
+        private void ts_TextChanged(object sender, TextSource.TextChangedEventArgs e)
+        {
+            if (e.iFromLine == e.iToLine && !WordWrap)
+                RecalcScrollByOneLine(e.iFromLine);
+            else
+                needRecalc = true;
+
+            Invalidate();
+            if (TextSource.CurrentTB == this)
+                OnTextChanged(e.iFromLine, e.iToLine);
+        }
+
+        private void ts_LineRemoved(object sender, LineRemovedEventArgs e)
+        {
+            lineInfos.RemoveRange(e.Index, e.Count);
+            OnLineRemoved(e.Index, e.Count, e.RemovedLineUniqueIds);
+        }
+
+        private void ts_LineInserted(object sender, LineInsertedEventArgs e)
+        {
+            VisibleState newState = VisibleState.Visible;
+            if (e.Index >= 0 && e.Index < lineInfos.Count && lineInfos[e.Index].VisibleState == VisibleState.Hidden)
+                newState = VisibleState.Hidden;
+
+            var temp = new List<LineInfo>(e.Count);
+            for (int i = 0; i < e.Count; i++)
+                temp.Add(new LineInfo(-1) { VisibleState = newState });
+            lineInfos.InsertRange(e.Index, temp);
+
+            OnLineInserted(e.Index, e.Count);
+        }
+
+        /// <summary>
+        /// Navigates forward (by Line.LastVisit property)
+        /// </summary>
+        public bool NavigateForward()
+        {
+            DateTime min = DateTime.Now;
+            int iLine = -1;
+            for (int i = 0; i < LinesCount; i++)
+                if (lines.IsLineLoaded(i))
+                    if (lines[i].LastVisit > lastNavigatedDateTime && lines[i].LastVisit < min)
+                    {
+                        min = lines[i].LastVisit;
+                        iLine = i;
+                    }
+            if (iLine >= 0)
+            {
+                Navigate(iLine);
+                return true;
+            }
+            else
+                return false;
+        }
+
+        /// <summary>
+        /// Navigates backward (by Line.LastVisit property)
+        /// </summary>
+        public bool NavigateBackward()
+        {
+            var max = new DateTime();
+            int iLine = -1;
+            for (int i = 0; i < LinesCount; i++)
+                if (lines.IsLineLoaded(i))
+                    if (lines[i].LastVisit < lastNavigatedDateTime && lines[i].LastVisit > max)
+                    {
+                        max = lines[i].LastVisit;
+                        iLine = i;
+                    }
+            if (iLine >= 0)
+            {
+                Navigate(iLine);
+                return true;
+            }
+            else
+                return false;
+        }
+
+        /// <summary>
+        /// Navigates to defined line, without Line.LastVisit reseting
+        /// </summary>
+        public void Navigate(int iLine)
+        {
+            if (iLine >= LinesCount) return;
+            lastNavigatedDateTime = lines[iLine].LastVisit;
+            Selection.Start = new Place(0, iLine);
+            DoSelectionVisible();
+        }
+
+        protected override void OnLoad(EventArgs e)
+        {
+            base.OnLoad(e);
+            m_hImc = ImmGetContext(Handle);
+        }
+
+        private void timer2_Tick(object sender, EventArgs e)
+        {
+            timer2.Enabled = false;
+            if (needRiseTextChangedDelayed)
+            {
+                needRiseTextChangedDelayed = false;
+                if (delayedTextChangedRange == null)
+                    return;
+                delayedTextChangedRange = Range.GetIntersectionWith(delayedTextChangedRange);
+                delayedTextChangedRange.Expand();
+                OnTextChangedDelayed(delayedTextChangedRange);
+                delayedTextChangedRange = null;
+            }
+        }
+
+        public void AddVisualMarker(VisualMarker marker)
+        {
+            visibleMarkers.Add(marker);
+        }
+
+        private void timer_Tick(object sender, EventArgs e)
+        {
+            timer.Enabled = false;
+            if (needRiseSelectionChangedDelayed)
+            {
+                needRiseSelectionChangedDelayed = false;
+                OnSelectionChangedDelayed();
+            }
+            if (needRiseVisibleRangeChangedDelayed)
+            {
+                needRiseVisibleRangeChangedDelayed = false;
+                OnVisibleRangeChangedDelayed();
+            }
+        }
+
+        public virtual void OnTextChangedDelayed(Range changedRange)
+        {
+            if (TextChangedDelayed != null)
+                TextChangedDelayed(this, new TextChangedEventArgs(changedRange));
+        }
+
+        public virtual void OnSelectionChangedDelayed()
+        {
+            RecalcScrollByOneLine(Selection.Start.iLine);
+            //highlight brackets
+            ClearBracketsPositions();
+            if (LeftBracket != '\x0' && RightBracket != '\x0')
+                HighlightBrackets(LeftBracket, RightBracket, ref leftBracketPosition, ref rightBracketPosition);
+            if (LeftBracket2 != '\x0' && RightBracket2 != '\x0')
+                HighlightBrackets(LeftBracket2, RightBracket2, ref leftBracketPosition2, ref rightBracketPosition2);
+            //remember last visit time
+            if (Selection.IsEmpty && Selection.Start.iLine < LinesCount)
+            {
+                if (lastNavigatedDateTime != lines[Selection.Start.iLine].LastVisit)
+                {
+                    lines[Selection.Start.iLine].LastVisit = DateTime.Now;
+                    lastNavigatedDateTime = lines[Selection.Start.iLine].LastVisit;
+                }
+            }
+
+            if (SelectionChangedDelayed != null)
+                SelectionChangedDelayed(this, new EventArgs());
+        }
+
+        public virtual void OnVisibleRangeChangedDelayed()
+        {
+            if (VisibleRangeChangedDelayed != null)
+                VisibleRangeChangedDelayed(this, new EventArgs());
+        }
+
+        private void ResetTimer(Timer timer)
+        {
+            timer.Stop();
+            if (IsHandleCreated)
+                timer.Start();
+        }
+
+        /// <summary>
+        /// Adds new style
+        /// </summary>
+        /// <returns>Layer index of this style</returns>
+        public int AddStyle(Style style)
+        {
+            if (style == null) return -1;
+
+            int i = GetStyleIndex(style);
+            if (i >= 0)
+                return i;
+
+            for (i = Styles.Length - 1; i >= 0; i--)
+                if (Styles[i] != null)
+                    break;
+
+            i++;
+            if (i >= Styles.Length)
+                throw new Exception("Maximum count of Styles is exceeded");
+
+            Styles[i] = style;
+            return i;
+        }
+
+        /// <summary>
+        /// Shows find dialog
+        /// </summary>
+        public void ShowFindDialog()
+        {
+            ShowFindDialog(null);
+        }
+
+        /// <summary>
+        /// Shows find dialog
+        /// </summary>
+        public void ShowFindDialog(string findText)
+        {
+            if (findForm == null)
+                findForm = new FindForm(this);
+
+            if (findText != null)
+                findForm.txt_Find.Text = findText;
+            else if (!Selection.IsEmpty && Selection.Start.iLine == Selection.End.iLine)
+                findForm.txt_Find.Text = Selection.Text;
+
+            findForm.txt_Find.Select();
+            findForm.Show();
+        }
+
+        /// <summary>
+        /// Shows replace dialog
+        /// </summary>
+        public void ShowReplaceDialog()
+        {
+            ShowReplaceDialog(null);
+        }
+
+        /// <summary>
+        /// Shows replace dialog
+        /// </summary>
+        public void ShowReplaceDialog(string findText)
+        {
+            if (ReadOnly)
+                return;
+            if (replaceForm == null)
+                replaceForm = new ReplaceForm(this);
+
+            if (findText != null)
+                replaceForm.tbFind.Text = findText;
+            else if (!Selection.IsEmpty && Selection.Start.iLine == Selection.End.iLine)
+                replaceForm.tbFind.Text = Selection.Text;
+
+            replaceForm.tbFind.SelectAll();
+            replaceForm.Show();
+        }
+
+        /// <summary>
+        /// Gets length of given line
+        /// </summary>
+        /// <param name="iLine">Line index</param>
+        /// <returns>Length of line</returns>
+        public int GetLineLength(int iLine)
+        {
+            if (iLine < 0 || iLine >= lines.Count)
+                throw new ArgumentOutOfRangeException("Line index out of range");
+
+            return lines[iLine].Count;
+        }
+
+        /// <summary>
+        /// Get range of line
+        /// </summary>
+        /// <param name="iLine">Line index</param>
+        public Range GetLine(int iLine)
+        {
+            if (iLine < 0 || iLine >= lines.Count)
+                throw new ArgumentOutOfRangeException("Line index out of range");
+
+            var sel = new Range(this);
+            sel.Start = new Place(0, iLine);
+            sel.End = new Place(lines[iLine].Count, iLine);
+            return sel;
+        }
+
+        /// <summary>
+        /// Copy selected text into Clipboard
+        /// </summary>
+        public void Copy()
+        {
+            if (Selection.IsEmpty)
+                Selection.Expand();
+            if (!Selection.IsEmpty)
+            {
+                var exp = new ExportToHTML();
+                exp.UseBr = false;
+                exp.UseNbsp = false;
+                exp.UseStyleTag = true;
+                string html = "<pre>" + exp.GetHtml(Selection.Clone()) + "</pre>";
+                var data = new DataObject();
+                data.SetData(DataFormats.UnicodeText, true, Selection.Text);
+                data.SetData(DataFormats.Html, PrepareHtmlForClipboard(html));
+                //
+                var thread = new Thread(() => Clipboard.SetDataObject(data, true));
+                thread.SetApartmentState(ApartmentState.STA);
+                thread.Start();
+                thread.Join();
+            }
+        }
+
+        public static MemoryStream PrepareHtmlForClipboard(string html)
+        {
+            Encoding enc = Encoding.UTF8;
+
+            string begin = "Version:0.9\r\nStartHTML:{0:000000}\r\nEndHTML:{1:000000}"
+                           + "\r\nStartFragment:{2:000000}\r\nEndFragment:{3:000000}\r\n";
+
+            string html_begin = "<html>\r\n<head>\r\n"
+                                + "<meta http-equiv=\"Content-Type\""
+                                + " content=\"text/html; charset=" + enc.WebName + "\">\r\n"
+                                + "<title>HTML clipboard</title>\r\n</head>\r\n<body>\r\n"
+                                + "<!--StartFragment-->";
+
+            string html_end = "<!--EndFragment-->\r\n</body>\r\n</html>\r\n";
+
+            string begin_sample = String.Format(begin, 0, 0, 0, 0);
+
+            int count_begin = enc.GetByteCount(begin_sample);
+            int count_html_begin = enc.GetByteCount(html_begin);
+            int count_html = enc.GetByteCount(html);
+            int count_html_end = enc.GetByteCount(html_end);
+
+            string html_total = String.Format(
+                begin
+                , count_begin
+                , count_begin + count_html_begin + count_html + count_html_end
+                , count_begin + count_html_begin
+                , count_begin + count_html_begin + count_html
+                                    ) + html_begin + html + html_end;
+
+            return new MemoryStream(enc.GetBytes(html_total));
+        }
+
+
+        /// <summary>
+        /// Cut selected text into Clipboard
+        /// </summary>
+        public void Cut()
+        {
+            if (!Selection.IsEmpty)
+            {
+                Copy();
+                ClearSelected();
+            }
+            else
+            {
+                Copy();
+                //remove current line
+                if (Selection.Start.iLine >= 0 && Selection.Start.iLine < LinesCount)
+                {
+                    var iLine = Selection.Start.iLine;
+                    RemoveLines(new List<int>() { iLine });
+                    Selection.Start = new Place(0, Math.Max(0, Math.Min(iLine, LinesCount - 1)));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Paste text from clipboard into selection position
+        /// </summary>
+        public void Paste()
+        {
+            string text = null;
+            var thread = new Thread(() =>
+            {
+                if (Clipboard.ContainsText())
+                    text = Clipboard.GetText();
+            }
+                );
+            thread.SetApartmentState(ApartmentState.STA);
+            thread.Start();
+            thread.Join();
+
+            if (text != null)
+                InsertText(text.TrimStart());
+        }
+
+        /// <summary>
+        /// Select all chars of text
+        /// </summary>
+        public void SelectAll()
+        {
+            Selection.SelectAll();
+        }
+
+        /// <summary>
+        /// Move caret to end of text
+        /// </summary>
+        public void GoEnd()
+        {
+            if (lines.Count > 0)
+                Selection.Start = new Place(lines[lines.Count - 1].Count, lines.Count - 1);
+            else
+                Selection.Start = new Place(0, 0);
+
+            DoCaretVisible();
+        }
+
+        /// <summary>
+        /// Move caret to first position
+        /// </summary>
+        public void GoHome()
+        {
+            Selection.Start = new Place(0, 0);
+
+            DoCaretVisible();
+            //VerticalScroll.Value = 0;
+            //HorizontalScroll.Value = 0;
+        }
+
+        /// <summary>
+        /// Clear text, styles, history, caches
+        /// </summary>
+        public void Clear()
+        {
+            Selection.BeginUpdate();
+            try
+            {
+                Selection.SelectAll();
+                ClearSelected();
+                lines.Manager.ClearHistory();
+                Invalidate();
+            }
+            finally
+            {
+                Selection.EndUpdate();
+            }
+        }
+
+        /// <summary>
+        /// Clear buffer of styles
+        /// </summary>
+        public void ClearStylesBuffer()
+        {
+            for (int i = 0; i < Styles.Length; i++)
+                Styles[i] = null;
+        }
+
+        /// <summary>
+        /// Clear style of all text
+        /// </summary>
+        public void ClearStyle(StyleIndex styleIndex)
+        {
+            foreach (Line line in lines)
+                line.ClearStyle(styleIndex);
+
+            for (int i = 0; i < lineInfos.Count; i++)
+                SetVisibleState(i, VisibleState.Visible);
+
+            Invalidate();
+        }
+
+
+        /// <summary>
+        /// Clears undo and redo stacks
+        /// </summary>
+        public void ClearUndo()
+        {
+            lines.Manager.ClearHistory();
+        }
+
+        /// <summary>
+        /// Insert text into current selection position
+        /// </summary>
+        /// <param name="text"></param>
+        public void InsertText(string text, bool jumpToCaret = true)
+        {
+            if (text == null)
+                return;
+
+            lines.Manager.BeginAutoUndoCommands();
+            try
+            {
+                if (!Selection.IsEmpty)
+                    lines.Manager.ExecuteCommand(new ClearSelectedCommand(TextSource));
+
+                //insert virtual spaces
+                if (Selection.IsEmpty && Selection.Start.iChar > GetLineLength(Selection.Start.iLine) && VirtualSpace)
+                    InsertVirtualSpaces();
+
+                lines.Manager.ExecuteCommand(new InsertTextCommand(TextSource, text));
+                if (updating <= 0 && jumpToCaret)
+                    DoCaretVisible();
+            }
+            finally
+            {
+                lines.Manager.EndAutoUndoCommands();
+            }
+            //
+            Invalidate();
+        }
+
+        /// <summary>
+        /// Insert text into current selection position (with predefined style)
+        /// </summary>
+        /// <param name="text"></param>
+        public void InsertText(string text, Style style, bool jumpToCaret = true)
+        {
+            if (text == null)
+                return;
+
+            //remember last caret position
+            Place last = Selection.Start;
+            //insert text
+            InsertText(text, jumpToCaret);
+            //get range
+            var range = new Range(this, last, Selection.Start);
+            //set style for range
+            range.SetStyle(style);
+        }
+
+        /// <summary>
+        /// Append string to end of the Text
+        /// </summary>
+        /// <param name="text"></param>
+        public void AppendText(string text)
+        {
+            if (text == null)
+                return;
+
+            Selection.ColumnSelectionMode = false;
+
+            Place oldStart = Selection.Start;
+            Place oldEnd = Selection.End;
+
+            Selection.BeginUpdate();
+            lines.Manager.BeginAutoUndoCommands();
+            try
+            {
+                if (lines.Count > 0)
+                    Selection.Start = new Place(lines[lines.Count - 1].Count, lines.Count - 1);
+                else
+                    Selection.Start = new Place(0, 0);
+
+                lines.Manager.ExecuteCommand(new InsertTextCommand(TextSource, text));
+            }
+            finally
+            {
+                lines.Manager.EndAutoUndoCommands();
+                Selection.Start = oldStart;
+                Selection.End = oldEnd;
+                Selection.EndUpdate();
+            }
+            //
+            Invalidate();
+        }
+
+        /// <summary>
+        /// Returns index of the style in Styles
+        /// -1 otherwise
+        /// </summary>
+        /// <param name="style"></param>
+        /// <returns>Index of the style in Styles</returns>
+        public int GetStyleIndex(Style style)
+        {
+            return Array.IndexOf(Styles, style);
+        }
+
+        /// <summary>
+        /// Returns StyleIndex mask of given styles
+        /// </summary>
+        /// <param name="styles"></param>
+        /// <returns>StyleIndex mask of given styles</returns>
+        public StyleIndex GetStyleIndexMask(Style[] styles)
+        {
+            StyleIndex mask = StyleIndex.None;
+            foreach (Style style in styles)
+            {
+                int i = GetStyleIndex(style);
+                if (i >= 0)
+                    mask |= Range.ToStyleIndex(i);
+            }
+
+            return mask;
+        }
+
+        internal int GetOrSetStyleLayerIndex(Style style)
+        {
+            int i = GetStyleIndex(style);
+            if (i < 0)
+                i = AddStyle(style);
+            return i;
+        }
+
+        public static SizeF GetCharSize(Font font, char c)
+        {
+            Size sz2 = TextRenderer.MeasureText("<" + c.ToString() + ">", font);
+            Size sz3 = TextRenderer.MeasureText("<>", font);
+
+            return new SizeF(sz2.Width - sz3.Width + 1, /*sz2.Height*/font.Height);
+        }
+
+        [DllImport("Imm32.dll")]
+        public static extern IntPtr ImmGetContext(IntPtr hWnd);
+
+        [DllImport("Imm32.dll")]
+        public static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);
+
+        protected override void WndProc(ref Message m)
+        {
+            if (m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL)
+                if (m.WParam.ToInt32() != SB_ENDSCROLL)
+                    Invalidate();
+
+            base.WndProc(ref m);
+
+            if (ImeAllowed)
+                if (m.Msg == WM_IME_SETCONTEXT && m.WParam.ToInt32() == 1)
+                {
+                    ImmAssociateContext(Handle, m_hImc);
+                }
+        }
+
+        protected override void OnScroll(ScrollEventArgs se)
+        {
+            base.OnScroll(se);
+            OnVisibleRangeChanged();
+            //
+            if (se.ScrollOrientation == ScrollOrientation.VerticalScroll)
+                VerticalScroll.Value = se.NewValue;
+            if (se.ScrollOrientation == ScrollOrientation.HorizontalScroll)
+                HorizontalScroll.Value = se.NewValue;
+            UpdateScrollbars();
+            Invalidate();
+        }
+
+        private void InsertChar(char c)
+        {
+            lines.Manager.BeginAutoUndoCommands();
+            try
+            {
+                if (!Selection.IsEmpty)
+                    lines.Manager.ExecuteCommand(new ClearSelectedCommand(TextSource));
+
+                //insert virtual spaces
+                if (Selection.IsEmpty && Selection.Start.iChar > GetLineLength(Selection.Start.iLine) && VirtualSpace)
+                    InsertVirtualSpaces();
+
+                //insert char
+                lines.Manager.ExecuteCommand(new InsertCharCommand(TextSource, c));
+            }
+            finally
+            {
+                lines.Manager.EndAutoUndoCommands();
+            }
+
+            Invalidate();
+        }
+
+        private void InsertVirtualSpaces()
+        {
+            var lineLength = GetLineLength(Selection.Start.iLine);
+            var count = Selection.Start.iChar - lineLength;
+            Selection.BeginUpdate();
+            try
+            {
+                Selection.Start = new Place(lineLength, Selection.Start.iLine);
+                lines.Manager.ExecuteCommand(new InsertTextCommand(TextSource, new string(' ', count)));
+            }
+            finally
+            {
+                Selection.EndUpdate();
+            }
+        }
+
+        /// <summary>
+        /// Deletes selected chars
+        /// </summary>
+        public void ClearSelected()
+        {
+            if (!Selection.IsEmpty)
+            {
+                lines.Manager.ExecuteCommand(new ClearSelectedCommand(TextSource));
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Deletes current line(s)
+        /// </summary>
+        public void ClearCurrentLine()
+        {
+            Selection.Expand();
+            lines.Manager.ExecuteCommand(new ClearSelectedCommand(TextSource));
+            if (Selection.Start.iLine == 0)
+                if (!Selection.GoRightThroughFolded()) return;
+            if (Selection.Start.iLine > 0)
+                lines.Manager.ExecuteCommand(new InsertCharCommand(TextSource, '\b')); //backspace
+            Invalidate();
+        }
+
+        private void Recalc()
+        {
+            if (!needRecalc)
+                return;
+
+#if debug
+            var sw = Stopwatch.StartNew();
+#endif
+
+            needRecalc = false;
+            //calc min left indent
+            LeftIndent = LeftPadding;
+            long maxLineNumber = LinesCount + lineNumberStartValue - 1;
+            int charsForLineNumber = 2 + (maxLineNumber > 0 ? (int)Math.Log10(maxLineNumber) : 0);
+            if (Created)
+            {
+                if (ShowLineNumbers)
+                    LeftIndent += charsForLineNumber * CharWidth + minLeftIndent + 1;
+            }
+            else
+                needRecalc = true;
+            //calc max line length and count of wordWrapLines
+            wordWrapLinesCount = 0;
+
+            maxLineLength = RecalcMaxLineLength();
+
+            //adjust AutoScrollMinSize
+            int minWidth;
+            CalcMinAutosizeWidth(out minWidth, ref maxLineLength);
+
+            AutoScrollMinSize = new Size(minWidth, wordWrapLinesCount * CharHeight + Paddings.Top + Paddings.Bottom);
+
+#if debug
+            sw.Stop();
+            Debug.WriteLine("Recalc: " + sw.ElapsedMilliseconds);
+#endif
+        }
+
+        void CalcMinAutosizeWidth(out int minWidth, ref int maxLineLength)
+        {
+            //adjust AutoScrollMinSize
+            minWidth = LeftIndent + (maxLineLength) * CharWidth + 2 + Paddings.Left + Paddings.Right;
+            if (wordWrap)
+                switch (WordWrapMode)
+                {
+                    case WordWrapMode.WordWrapControlWidth:
+                    case WordWrapMode.CharWrapControlWidth:
+                        maxLineLength = Math.Min(maxLineLength, (ClientSize.Width - LeftIndent - Paddings.Left - Paddings.Right) / CharWidth);
+                        minWidth = 0;
+                        break;
+                    case WordWrapMode.WordWrapPreferredWidth:
+                    case WordWrapMode.CharWrapPreferredWidth:
+                        maxLineLength = Math.Min(maxLineLength, PreferredLineWidth);
+                        minWidth = LeftIndent + PreferredLineWidth * CharWidth + 2 + Paddings.Left + Paddings.Right;
+                        break;
+                }
+        }
+
+        private void RecalcScrollByOneLine(int iLine)
+        {
+            if (iLine >= lines.Count)
+                return;
+
+            int maxLineLength = lines[iLine].Count;
+            if (this.maxLineLength < maxLineLength && !WordWrap)
+                this.maxLineLength = maxLineLength;
+
+            int minWidth;
+            CalcMinAutosizeWidth(out minWidth, ref maxLineLength);
+
+            if (AutoScrollMinSize.Width < minWidth)
+                AutoScrollMinSize = new Size(minWidth, AutoScrollMinSize.Height);
+        }
+
+        private int RecalcMaxLineLength()
+        {
+            int maxLineLength = 0;
+            TextSource lines = this.lines;
+            int count = lines.Count;
+            int charHeight = CharHeight;
+            int topIndent = Paddings.Top;
+
+            for (int i = 0; i < count; i++)
+            {
+                int lineLength = lines.GetLineLength(i);
+                LineInfo lineInfo = lineInfos[i];
+                if (lineLength > maxLineLength && lineInfo.VisibleState == VisibleState.Visible)
+                    maxLineLength = lineLength;
+                lineInfo.startY = wordWrapLinesCount * charHeight + topIndent;
+                wordWrapLinesCount += lineInfo.WordWrapStringsCount;
+                lineInfos[i] = lineInfo;
+            }
+
+            return maxLineLength;
+        }
+
+        private int GetMaxLineWordWrapedWidth()
+        {
+            if (wordWrap)
+                switch (wordWrapMode)
+                {
+                    case WordWrapMode.WordWrapControlWidth:
+                    case WordWrapMode.CharWrapControlWidth:
+                        return ClientSize.Width;
+                    case WordWrapMode.WordWrapPreferredWidth:
+                    case WordWrapMode.CharWrapPreferredWidth:
+                        return LeftIndent + PreferredLineWidth * CharWidth + 2 + Paddings.Left + Paddings.Right;
+                }
+
+            return int.MaxValue;
+        }
+
+        private void RecalcWordWrap(int fromLine, int toLine)
+        {
+            int maxCharsPerLine = 0;
+            bool charWrap = false;
+
+            switch (WordWrapMode)
+            {
+                case WordWrapMode.WordWrapControlWidth:
+                    maxCharsPerLine = (ClientSize.Width - LeftIndent - Paddings.Left - Paddings.Right) / CharWidth;
+                    break;
+                case WordWrapMode.CharWrapControlWidth:
+                    maxCharsPerLine = (ClientSize.Width - LeftIndent - Paddings.Left - Paddings.Right) / CharWidth;
+                    charWrap = true;
+                    break;
+                case WordWrapMode.WordWrapPreferredWidth:
+                    maxCharsPerLine = PreferredLineWidth;
+                    break;
+                case WordWrapMode.CharWrapPreferredWidth:
+                    maxCharsPerLine = PreferredLineWidth;
+                    charWrap = true;
+                    break;
+            }
+
+            for (int iLine = fromLine; iLine <= toLine; iLine++)
+                if (lines.IsLineLoaded(iLine))
+                {
+                    if (!wordWrap)
+                        lineInfos[iLine].CutOffPositions.Clear();
+                    else
+                    {
+                        LineInfo li = lineInfos[iLine];
+                        li.CalcCutOffs(maxCharsPerLine, ImeAllowed, charWrap, lines[iLine]);
+                        lineInfos[iLine] = li;
+                    }
+                }
+            needRecalc = true;
+        }
+
+        protected override void OnClientSizeChanged(EventArgs e)
+        {
+            base.OnClientSizeChanged(e);
+            if (WordWrap)
+            {
+                RecalcWordWrap(0, lines.Count - 1);
+                Invalidate();
+            }
+            OnVisibleRangeChanged();
+        }
+
+        /// <summary>
+        /// Scroll control for display defined rectangle
+        /// </summary>
+        /// <param name="rect"></param>
+        private void DoVisibleRectangle(Rectangle rect)
+        {
+            int oldV = VerticalScroll.Value;
+            int v = VerticalScroll.Value;
+            int h = HorizontalScroll.Value;
+
+            if (rect.Bottom > ClientRectangle.Height)
+                v += rect.Bottom - ClientRectangle.Height;
+            else if (rect.Top < 0)
+                v += rect.Top;
+
+            if (rect.Right > ClientRectangle.Width)
+                h += rect.Right - ClientRectangle.Width;
+            else if (rect.Left < LeftIndent)
+                h += rect.Left - LeftIndent;
+            //
+            if (!Multiline)
+                v = 0;
+            //
+            v = Math.Max(0, v);
+            h = Math.Max(0, h);
+            //
+            try
+            {
+                if (VerticalScroll.Visible || !ShowScrollBars)
+                    VerticalScroll.Value = v;
+                if (HorizontalScroll.Visible || !ShowScrollBars)
+                    HorizontalScroll.Value = h;
+            }
+            catch (ArgumentOutOfRangeException)
+            {
+                ;
+            }
+
+            UpdateScrollbars();
+            //
+            if (oldV != VerticalScroll.Value)
+                OnVisibleRangeChanged();
+        }
+
+
+        /// <summary>
+        /// Updates scrollbar position after Value changed
+        /// </summary>
+        public void UpdateScrollbars()
+        {
+            if (ShowScrollBars)
+            {
+                //some magic for update scrolls
+                base.AutoScrollMinSize -= new Size(1, 0);
+                base.AutoScrollMinSize += new Size(1, 0);
+            }
+        }
+
+        /// <summary>
+        /// Scroll control for display caret
+        /// </summary>
+        public void DoCaretVisible()
+        {
+            Invalidate();
+            Recalc();
+            Point car = PlaceToPoint(Selection.Start);
+            car.Offset(-CharWidth, 0);
+            DoVisibleRectangle(new Rectangle(car, new Size(2 * CharWidth, 2 * CharHeight)));
+        }
+
+        /// <summary>
+        /// Scroll control left
+        /// </summary>
+        public void ScrollLeft()
+        {
+            Invalidate();
+            HorizontalScroll.Value = 0;
+            AutoScrollMinSize -= new Size(1, 0);
+            AutoScrollMinSize += new Size(1, 0);
+        }
+
+        /// <summary>
+        /// Scroll control for display selection area
+        /// </summary>
+        public void DoSelectionVisible()
+        {
+            if (lineInfos[Selection.End.iLine].VisibleState != VisibleState.Visible)
+                ExpandBlock(Selection.End.iLine);
+
+            if (lineInfos[Selection.Start.iLine].VisibleState != VisibleState.Visible)
+                ExpandBlock(Selection.Start.iLine);
+
+            Recalc();
+            DoVisibleRectangle(new Rectangle(PlaceToPoint(new Place(0, Selection.End.iLine)),
+                                             new Size(2 * CharWidth, 2 * CharHeight)));
+
+            Point car = PlaceToPoint(Selection.Start);
+            Point car2 = PlaceToPoint(Selection.End);
+            car.Offset(-CharWidth, -ClientSize.Height / 2);
+            DoVisibleRectangle(new Rectangle(car, new Size(Math.Abs(car2.X - car.X), ClientSize.Height)));//Math.Abs(car2.Y-car.Y) + 2 * CharHeight
+
+            Invalidate();
+        }
+
+        /// <summary>
+        /// Scroll control for display given range
+        /// </summary>
+        public void DoRangeVisible(Range range)
+        {
+            range = range.Clone();
+            range.Normalize();
+            range.End = new Place(range.End.iChar, Math.Min(range.End.iLine, range.Start.iLine + ClientSize.Height / CharHeight));
+
+            if (lineInfos[range.End.iLine].VisibleState != VisibleState.Visible)
+                ExpandBlock(range.End.iLine);
+
+            if (lineInfos[range.Start.iLine].VisibleState != VisibleState.Visible)
+                ExpandBlock(range.Start.iLine);
+
+            Recalc();
+            DoVisibleRectangle(new Rectangle(PlaceToPoint(new Place(0, range.Start.iLine)), new Size(2 * CharWidth, (1 + range.End.iLine - range.Start.iLine) * CharHeight)));
+
+            Invalidate();
+        }
+
+
+        protected override void OnKeyUp(KeyEventArgs e)
+        {
+            base.OnKeyUp(e);
+
+            if (e.KeyCode == Keys.ShiftKey)
+                lastModifiers &= ~Keys.Shift;
+            if (e.KeyCode == Keys.Alt)
+                lastModifiers &= ~Keys.Alt;
+            if (e.KeyCode == Keys.ControlKey)
+                lastModifiers &= ~Keys.Control;
+        }
+
+        private const Keys AltShift = Keys.Alt | Keys.Shift;
+
+        protected override void OnKeyDown(KeyEventArgs e)
+        {
+            base.OnKeyDown(e);
+
+            if (Focused)
+                lastModifiers = e.Modifiers;
+
+            handledChar = false;
+
+            if (e.Handled)
+            {
+                handledChar = true;
+                return;
+            }
+
+            switch (e.KeyCode)
+            {
+                case Keys.G:
+                    if (e.Modifiers == Keys.Control)
+                        ShowGoToDialog();
+                    break;
+                case Keys.F:
+                    if (e.Modifiers == Keys.Control)
+                        ShowFindDialog();
+                    break;
+                case Keys.F3:
+                    if (e.Modifiers == Keys.None)
+                        if (findForm == null || findForm.txt_Find.Text == "")
+                            ShowFindDialog();
+                        else
+                            findForm.FindNext(findForm.txt_Find.Text);
+                    break;
+                case Keys.H:
+                    if (e.Modifiers == Keys.Control)
+                        ShowReplaceDialog();
+                    break;
+                case Keys.C:
+                    if (e.Modifiers == Keys.Control)
+                        Copy();
+                    if (e.Modifiers == (Keys.Control | Keys.Shift))
+                        CommentSelected();
+                    break;
+                case Keys.X:
+                    if (e.Modifiers == Keys.Control && !ReadOnly)
+                        Cut();
+                    break;
+                case Keys.V:
+                    if (e.Modifiers == Keys.Control && !ReadOnly)
+                        Paste();
+                    break;
+                case Keys.A:
+                    if (e.Modifiers == Keys.Control)
+                        Selection.SelectAll();
+                    break;
+                case Keys.Z:
+                    if (e.Modifiers == Keys.Control && !ReadOnly)
+                        Undo();
+                    break;
+                case Keys.R:
+                    if (e.Modifiers == Keys.Control && !ReadOnly)
+                        Redo();
+                    break;
+                case Keys.U:
+                    if (e.Modifiers == (Keys.Control | Keys.Shift))
+                        LowerCase();
+                    if (e.Modifiers == Keys.Control)
+                        UpperCase();
+                    break;
+                case Keys.Tab:
+                    if (e.Modifiers == Keys.Shift && !ReadOnly)
+                        DecreaseIndent();
+                    break;
+                case Keys.OemMinus:
+                    if (e.Modifiers == Keys.Control)
+                        NavigateBackward();
+                    if (e.Modifiers == (Keys.Control | Keys.Shift))
+                        NavigateForward();
+                    break;
+
+                case Keys.Back:
+                    if (ReadOnly) break;
+                    if (e.Modifiers == Keys.Alt)
+                        Undo();
+                    else
+                    if (e.Modifiers == Keys.None || e.Modifiers == Keys.Shift)
+                    {
+                        if (OnKeyPressing('\b')) //KeyPress event processed key
+                            break;
+                        if (!Selection.IsEmpty)
+                            ClearSelected();
+                        else
+                            InsertChar('\b');
+                        OnKeyPressed('\b');
+                    }
+                    else
+                    if (e.Modifiers == Keys.Control)
+                    {
+                        if (OnKeyPressing('\b')) //KeyPress event processed key
+                            break;
+                        if (!Selection.IsEmpty)
+                            ClearSelected();
+                        Selection.GoWordLeft(true);
+                        ClearSelected();
+                        OnKeyPressed('\b');
+                    }
+                    break;
+
+                case Keys.Insert:
+                    if (e.Modifiers == Keys.None)
+                    {
+                        if (!ReadOnly)
+                            isReplaceMode = !isReplaceMode;
+                    }
+                    else
+                    if (e.Modifiers == Keys.Control)
+                    {
+                        Copy();
+                    }
+                    else
+                    if (e.Modifiers == Keys.Shift)
+                    {
+                        if (!ReadOnly)
+                            Paste();
+                    }
+                    break;
+
+                case Keys.Delete:
+                    if (ReadOnly) break;
+                    if (e.Modifiers == Keys.None)
+                    {
+                        if (OnKeyPressing((char)0xff)) //KeyPress event processed key
+                            break;
+                        if (!Selection.IsEmpty)
+                            ClearSelected();
+                        else
+                        {
+                            //if line contains only spaces then delete line
+                            if (this[Selection.Start.iLine].StartSpacesCount == this[Selection.Start.iLine].Count)
+                                RemoveSpacesAfterCaret();
+
+                            if (Selection.GoRightThroughFolded())
+                            {
+                                int iLine = Selection.Start.iLine;
+                                InsertChar('\b');
+
+                                //if removed \n then trim spaces
+                                if (iLine != Selection.Start.iLine && AutoIndent)
+                                    if (Selection.Start.iChar > 0)
+                                        RemoveSpacesAfterCaret();
+                            }
+                        }
+                        OnKeyPressed((char)0xff);
+                    }
+                    else
+                    if (e.Modifiers == Keys.Control)
+                    {
+                        if (OnKeyPressing((char)0xff)) //KeyPress event processed key
+                            break;
+                        if (!Selection.IsEmpty)
+                            ClearSelected();
+                        else
+                        {
+                            Selection.GoWordRight(true);
+                            ClearSelected();
+                        }
+                        OnKeyPressed((char)0xff);
+                    }
+                    else
+                    if (e.Modifiers == Keys.Shift)
+                    {
+                        if (OnKeyPressing((char)0xff)) //KeyPress event processed key
+                            break;
+                        Cut();
+                        OnKeyPressed((char)0xff);
+                    }
+                    break;
+
+                case Keys.Space:
+                    if (ReadOnly) break;
+                    if (e.Modifiers == Keys.None || e.Modifiers == Keys.Shift)
+                    {
+                        if (OnKeyPressing(' ')) //KeyPress event processed key
+                            break;
+                        if (!Selection.IsEmpty)
+                            ClearSelected();
+
+                        //replace mode? select forward char
+                        if (IsReplaceMode)
+                        {
+                            Selection.GoRight(true);
+                            Selection.Inverse();
+                        }
+
+                        InsertChar(' ');
+                        OnKeyPressed(' ');
+                    }
+                    break;
+
+                case Keys.Left:
+                    if (e.Modifiers == Keys.Control || e.Modifiers == (Keys.Control | Keys.Shift))
+                        Selection.GoWordLeft(e.Shift);
+                    if (e.Modifiers == Keys.None || e.Modifiers == Keys.Shift)
+                        Selection.GoLeft(e.Shift);
+                    if (e.Modifiers == AltShift)
+                    {
+                        CheckAndChangeSelectionType();
+                        if (Selection.ColumnSelectionMode)
+                            Selection.GoLeft_ColumnSelectionMode();
+                    }
+                    break;
+                case Keys.Right:
+                    if (e.Modifiers == Keys.Control || e.Modifiers == (Keys.Control | Keys.Shift))
+                        Selection.GoWordRight(e.Shift);
+                    if (e.Modifiers == Keys.None || e.Modifiers == Keys.Shift)
+                        Selection.GoRight(e.Shift);
+                    if (e.Modifiers == AltShift)
+                    {
+                        CheckAndChangeSelectionType();
+                        if (Selection.ColumnSelectionMode)
+                            Selection.GoRight_ColumnSelectionMode();
+                    }
+                    break;
+                case Keys.Up:
+                    if (e.Modifiers == Keys.None || e.Modifiers == Keys.Shift)
+                    {
+                        Selection.GoUp(e.Shift);
+                        ScrollLeft();
+                    }
+                    if (e.Modifiers == AltShift)
+                    {
+                        CheckAndChangeSelectionType();
+                        if (Selection.ColumnSelectionMode)
+                            Selection.GoUp_ColumnSelectionMode();
+                    }
+                    if (e.Modifiers == Keys.Alt)
+                    {
+                        if (!ReadOnly && !Selection.ColumnSelectionMode)
+                            MoveSelectedLinesUp();
+                    }
+                    break;
+                case Keys.Down:
+                    if (e.Modifiers == Keys.None || e.Modifiers == Keys.Shift)
+                    {
+                        Selection.GoDown(e.Shift);
+                        ScrollLeft();
+                    }
+                    else
+                    if (e.Modifiers == AltShift)
+                    {
+                        CheckAndChangeSelectionType();
+                        if (Selection.ColumnSelectionMode)
+                            Selection.GoDown_ColumnSelectionMode();
+                    }
+                    if (e.Modifiers == Keys.Alt)
+                    {
+                        if (!ReadOnly && !Selection.ColumnSelectionMode)
+                            MoveSelectedLinesDown();
+                    }
+                    break;
+                case Keys.PageUp:
+                    if (e.Modifiers == Keys.None || e.Modifiers == Keys.Shift)
+                    {
+                        Selection.GoPageUp(e.Shift);
+                        ScrollLeft();
+                    }
+                    break;
+                case Keys.PageDown:
+                    if (e.Modifiers == Keys.None || e.Modifiers == Keys.Shift)
+                    {
+                        Selection.GoPageDown(e.Shift);
+                        ScrollLeft();
+                    }
+                    break;
+                case Keys.Home:
+                    if (e.Modifiers == Keys.Control || e.Modifiers == (Keys.Control | Keys.Shift))
+                        Selection.GoFirst(e.Shift);
+                    if (e.Modifiers == Keys.None || e.Modifiers == Keys.Shift)
+                    {
+                        GoHome(e.Shift);
+                        ScrollLeft();
+                    }
+                    break;
+                case Keys.End:
+                    if (e.Modifiers == Keys.Control || e.Modifiers == (Keys.Control | Keys.Shift))
+                        Selection.GoLast(e.Shift);
+                    if (e.Modifiers == Keys.None || e.Modifiers == Keys.Shift)
+                        Selection.GoEnd(e.Shift);
+                    break;
+                case Keys.Alt:
+                    return;
+                default:
+                    if ((e.Modifiers & Keys.Control) != 0)
+                        return;
+                    if ((e.Modifiers & Keys.Alt) != 0)
+                    {
+                        if ((Control.MouseButtons & MouseButtons.Left) != 0)
+                            CheckAndChangeSelectionType();
+                        return;
+                    }
+                    if (e.KeyCode == Keys.ShiftKey)
+                        return;
+                    break;
+            }
+
+            e.Handled = true;
+
+            DoCaretVisible();
+            Invalidate();
+        }
+
+        /// <summary>
+        /// Moves selected lines down
+        /// </summary>
+        public virtual void MoveSelectedLinesDown()
+        {
+            var prevSelection = Selection.Clone();
+            Selection.Expand();
+            var iLine = Selection.Start.iLine;
+            if (Selection.End.iLine >= LinesCount - 1)
+            {
+                Selection = prevSelection;
+                return;
+            }
+            var text = SelectedText;
+            var temp = new List<int>();
+            for (int i = Selection.Start.iLine; i <= Selection.End.iLine; i++)
+                temp.Add(i);
+            RemoveLines(temp);
+            Selection.Start = new Place(GetLineLength(iLine), iLine);
+            SelectedText = "\n" + text;
+            Selection.Start = new Place(prevSelection.Start.iChar, prevSelection.Start.iLine + 1);
+            Selection.End = new Place(prevSelection.End.iChar, prevSelection.End.iLine + 1);
+        }
+
+        /// <summary>
+        /// Moves selected lines up
+        /// </summary>
+        public virtual void MoveSelectedLinesUp()
+        {
+            var prevSelection = Selection.Clone();
+            Selection.Expand();
+            var iLine = Selection.Start.iLine;
+            if (iLine == 0)
+            {
+                Selection = prevSelection;
+                return;
+            }
+            var text = SelectedText;
+            var temp = new List<int>();
+            for (int i = Selection.Start.iLine; i <= Selection.End.iLine; i++)
+                temp.Add(i);
+            RemoveLines(temp);
+            Selection.Start = new Place(0, iLine - 1);
+            SelectedText = text + "\n";
+            Selection.Start = new Place(prevSelection.Start.iChar, prevSelection.Start.iLine - 1);
+            Selection.End = new Place(prevSelection.End.iChar, prevSelection.End.iLine - 1);
+        }
+
+        private void GoHome(bool shift)
+        {
+            Selection.BeginUpdate();
+            try
+            {
+                int iLine = Selection.Start.iLine;
+                int spaces = this[iLine].StartSpacesCount;
+                if (Selection.Start.iChar <= spaces)
+                    Selection.GoHome(shift);
+                else
+                {
+                    Selection.GoHome(shift);
+                    for (int i = 0; i < spaces; i++)
+                        Selection.GoRight(shift);
+                }
+            }
+            finally
+            {
+                Selection.EndUpdate();
+            }
+        }
+
+        /// <summary>
+        /// Convert selected text to upper case
+        /// </summary>
+        public void UpperCase()
+        {
+            Range old = Selection.Clone();
+            SelectedText = SelectedText.ToUpper();
+            Selection.Start = old.Start;
+            Selection.End = old.End;
+        }
+
+        /// <summary>
+        /// Convert selected text to lower case
+        /// </summary>
+        public void LowerCase()
+        {
+            Range old = Selection.Clone();
+            SelectedText = SelectedText.ToLower();
+            Selection.Start = old.Start;
+            Selection.End = old.End;
+        }
+
+        /// <summary>
+        /// Insert/remove comment prefix into selected lines
+        /// </summary>
+        public void CommentSelected()
+        {
+            CommentSelected(CommentPrefix);
+        }
+
+        /// <summary>
+        /// Insert/remove comment prefix into selected lines
+        /// </summary>
+        public void CommentSelected(string commentPrefix)
+        {
+            if (string.IsNullOrEmpty(commentPrefix))
+                return;
+            Selection.Normalize();
+            bool isCommented = lines[Selection.Start.iLine].Text.TrimStart().StartsWith(commentPrefix);
+            if (isCommented)
+                RemoveLinePrefix(commentPrefix);
+            else
+                InsertLinePrefix(commentPrefix);
+        }
+
+        /*
+        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+        {
+            if (keyData == Keys.Enter)
+            {
+                bool proc = ProcessKeyPress('\r');
+                if (proc)
+                {
+                    base.OnKeyDown(new KeyEventArgs(Keys.Enter));
+                    return true;
+                }
+            }
+            
+            return base.ProcessCmdKey(ref msg, keyData);
+        }*/
+
+        public void OnKeyPressing(KeyPressEventArgs args)
+        {
+            if (KeyPressing != null)
+                KeyPressing(this, args);
+        }
+
+        private bool OnKeyPressing(char c)
+        {
+            var args = new KeyPressEventArgs(c);
+            OnKeyPressing(args);
+            return args.Handled;
+        }
+
+        public void OnKeyPressed(char c)
+        {
+            var args = new KeyPressEventArgs(c);
+            if (KeyPressed != null)
+                KeyPressed(this, args);
+        }
+
+        /*
+        protected override void OnKeyPress(KeyPressEventArgs e)
+        {
+            base.OnKeyPress(e);
+            ProcessKeyPress(e.KeyChar);
+        }*/
+
+        protected override bool ProcessMnemonic(char charCode)
+        {
+            if (Focused)
+                return ProcessKeyPress(charCode) || base.ProcessMnemonic(charCode);
+            else
+                return false;
+        }
+
+        private bool ProcessKeyPress(char c)
+        {
+            if (handledChar)
+                return true;
+
+            if (c == ' ')
+                return true;
+
+            if (c == '\b' && (lastModifiers & Keys.Alt) != 0)
+                return true;
+
+            if (char.IsControl(c) && c != '\r' && c != '\t')
+                return false;
+
+            if (ReadOnly || !Enabled)
+                return false;
+
+
+            if (lastModifiers != Keys.None &&
+                lastModifiers != Keys.Shift &&
+                lastModifiers != (Keys.Control | Keys.Alt) && //ALT+CTRL is special chars (AltGr)
+                lastModifiers != (Keys.Shift | Keys.Control | Keys.Alt) && //SHIFT + ALT + CTRL is special chars (AltGr)
+                (lastModifiers != (Keys.Alt) || char.IsLetterOrDigit(c)) //may be ALT+LetterOrDigit is mnemonic code
+                )
+                return false; //do not process Ctrl+? and Alt+? keys
+
+            char sourceC = c;
+            if (OnKeyPressing(sourceC)) //KeyPress event processed key
+                return true;
+
+            if (c == '\r' && !AcceptsReturn)
+                return false;
+
+            //tab?
+            if (c == '\t')
+            {
+                if (!AcceptsTab)
+                    return false;
+
+                if (Selection.Start.iLine == Selection.End.iLine)
+                {
+                    ClearSelected();
+                    //insert tab as spaces
+                    int spaces = TabLength - (Selection.Start.iChar % TabLength);
+                    //replace mode? select forward chars
+                    if (IsReplaceMode)
+                    {
+                        for (int i = 0; i < spaces; i++)
+                            Selection.GoRight(true);
+                        Selection.Inverse();
+                    }
+
+                    InsertText(new String(' ', spaces));
+                }
+                else
+                    if ((lastModifiers & Keys.Shift) == 0)
+                    IncreaseIndent();
+            }
+            else
+            {
+                //replace \r on \n
+                if (c == '\r')
+                    c = '\n';
+                //replace mode? select forward char
+                if (IsReplaceMode)
+                {
+                    Selection.GoRight(true);
+                    Selection.Inverse();
+                }
+                //insert char
+                InsertChar(c);
+                //do autoindent
+                if (c == '\n' || AutoIndentExistingLines)
+                    DoAutoIndentIfNeed();
+            }
+
+            DoCaretVisible();
+            Invalidate();
+
+            OnKeyPressed(sourceC);
+
+            return true;
+        }
+
+        private void DoAutoIndentIfNeed()
+        {
+            if (Selection.ColumnSelectionMode)
+                return;
+            if (AutoIndent)
+            {
+                DoCaretVisible();
+                int needSpaces = CalcAutoIndent(Selection.Start.iLine);
+                if (this[Selection.Start.iLine].AutoIndentSpacesNeededCount != needSpaces)
+                {
+                    DoAutoIndent(Selection.Start.iLine);
+                    this[Selection.Start.iLine].AutoIndentSpacesNeededCount = needSpaces;
+                }
+            }
+        }
+
+        private void RemoveSpacesAfterCaret()
+        {
+            if (!Selection.IsEmpty)
+                return;
+            Place end = Selection.Start;
+            while (Selection.CharAfterStart == ' ')
+                Selection.GoRight(true);
+            ClearSelected();
+        }
+
+        /// <summary>
+        /// Inserts autoindent's spaces in the line
+        /// </summary>
+        public virtual void DoAutoIndent(int iLine)
+        {
+            if (Selection.ColumnSelectionMode)
+                return;
+            Place oldStart = Selection.Start;
+            //
+            int needSpaces = CalcAutoIndent(iLine);
+            //
+            int spaces = lines[iLine].StartSpacesCount;
+            int needToInsert = needSpaces - spaces;
+            if (needToInsert < 0)
+                needToInsert = -Math.Min(-needToInsert, spaces);
+            //insert start spaces
+            if (needToInsert == 0)
+                return;
+            Selection.Start = new Place(0, iLine);
+            if (needToInsert > 0)
+                InsertText(new String(' ', needToInsert));
+            else
+            {
+                Selection.Start = new Place(0, iLine);
+                Selection.End = new Place(-needToInsert, iLine);
+                ClearSelected();
+            }
+
+            Selection.Start = new Place(Math.Min(lines[iLine].Count, Math.Max(0, oldStart.iChar + needToInsert)), iLine);
+        }
+
+        /// <summary>
+        /// Returns needed start space count for the line
+        /// </summary>
+        public virtual int CalcAutoIndent(int iLine)
+        {
+            if (iLine < 0 || iLine >= LinesCount) return 0;
+
+
+            EventHandler<AutoIndentEventArgs> calculator = AutoIndentNeeded;
+            if (calculator == null)
+                if (Language != Language.Custom && SyntaxHighlighter != null)
+                    calculator = SyntaxHighlighter.AutoIndentNeeded;
+                else
+                    calculator = CalcAutoIndentShiftByCodeFolding;
+
+            int needSpaces = 0;
+
+            var stack = new Stack<AutoIndentEventArgs>();
+            //calc indent for previous lines, find stable line
+            int i;
+            for (i = iLine - 1; i >= 0; i--)
+            {
+                var args = new AutoIndentEventArgs(i, lines[i].Text, i > 0 ? lines[i - 1].Text : "", TabLength);
+                calculator(this, args);
+                stack.Push(args);
+                if (args.Shift == 0 && args.LineText.Trim() != "")
+                    break;
+            }
+            int indent = lines[i >= 0 ? i : 0].StartSpacesCount;
+            while (stack.Count != 0)
+                indent += stack.Pop().ShiftNextLines;
+            //clalc shift for current line
+            var a = new AutoIndentEventArgs(iLine, lines[iLine].Text, iLine > 0 ? lines[iLine - 1].Text : "", TabLength);
+            calculator(this, a);
+            needSpaces = indent + a.Shift;
+
+            return needSpaces;
+        }
+
+        internal virtual void CalcAutoIndentShiftByCodeFolding(object sender, AutoIndentEventArgs args)
+        {
+            //inset TAB after start folding marker
+            if (string.IsNullOrEmpty(lines[args.iLine].FoldingEndMarker) &&
+                !string.IsNullOrEmpty(lines[args.iLine].FoldingStartMarker))
+            {
+                args.ShiftNextLines = TabLength;
+                return;
+            }
+            //remove TAB before end folding marker
+            if (!string.IsNullOrEmpty(lines[args.iLine].FoldingEndMarker) &&
+                string.IsNullOrEmpty(lines[args.iLine].FoldingStartMarker))
+            {
+                args.Shift = -TabLength;
+                args.ShiftNextLines = -TabLength;
+                return;
+            }
+        }
+
+
+        private int GetMinStartSpacesCount(int fromLine, int toLine)
+        {
+            if (fromLine > toLine)
+                return 0;
+
+            int result = int.MaxValue;
+            for (int i = fromLine; i <= toLine; i++)
+            {
+                int count = lines[i].StartSpacesCount;
+                if (count < result)
+                    result = count;
+            }
+
+            return result;
+        }
+
+        /// <summary>
+        /// Undo last operation
+        /// </summary>
+        public void Undo()
+        {
+            lines.Manager.Undo();
+            DoCaretVisible();
+            Invalidate();
+        }
+
+        /// <summary>
+        /// Redo
+        /// </summary>
+        public void Redo()
+        {
+            lines.Manager.Redo();
+            DoCaretVisible();
+            Invalidate();
+        }
+
+        protected override bool IsInputKey(Keys keyData)
+        {
+            if (keyData == Keys.Tab && !AcceptsTab)
+                return false;
+            if (keyData == Keys.Enter && !AcceptsReturn)
+                return false;
+
+            if ((keyData & Keys.Alt) == Keys.None)
+            {
+                Keys keys = keyData & Keys.KeyCode;
+                if (keys == Keys.Return)
+                    return true;
+            }
+
+            if ((keyData & Keys.Alt) != Keys.Alt)
+            {
+                switch ((keyData & Keys.KeyCode))
+                {
+                    case Keys.Prior:
+                    case Keys.Next:
+                    case Keys.End:
+                    case Keys.Home:
+                    case Keys.Left:
+                    case Keys.Right:
+                    case Keys.Up:
+                    case Keys.Down:
+                        return true;
+
+                    case Keys.Escape:
+                        return false;
+
+                    case Keys.Tab:
+                        return (keyData & Keys.Control) == Keys.None;
+                }
+            }
+
+            return base.IsInputKey(keyData);
+        }
+
+        [DllImport("User32.dll")]
+        private static extern bool CreateCaret(IntPtr hWnd, int hBitmap, int nWidth, int nHeight);
+
+        [DllImport("User32.dll")]
+        private static extern bool SetCaretPos(int x, int y);
+
+        [DllImport("User32.dll")]
+        private static extern bool DestroyCaret();
+
+        [DllImport("User32.dll")]
+        private static extern bool ShowCaret(IntPtr hWnd);
+
+        [DllImport("User32.dll")]
+        private static extern bool HideCaret(IntPtr hWnd);
+
+        protected override void OnPaintBackground(PaintEventArgs e)
+        {
+            if (BackBrush == null)
+                base.OnPaintBackground(e);
+            else
+                e.Graphics.FillRectangle(BackBrush, ClientRectangle);
+        }
+
+        /// <summary>
+        /// Draw control
+        /// </summary>
+        protected override void OnPaint(PaintEventArgs e)
+        {
+            if (needRecalc)
+                Recalc();
+            if (needRecalcFoldingLines)
+                RecalcFoldingLines();
+#if debug
+            var sw = Stopwatch.StartNew();
+#endif
+            visibleMarkers.Clear();
+            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
+            //FCTBRenderingHints.SetGridFitTextHint(e.Graphics);
+            //
+            var servicePen = new Pen(ServiceLinesColor);
+            Brush changedLineBrush = new SolidBrush(ChangedLineColor);
+            Brush indentBrush = new SolidBrush(IndentBackColor);
+            Brush paddingBrush = new SolidBrush(PaddingBackColor);
+            Brush currentLineBrush = new SolidBrush(Color.FromArgb(CurrentLineColor.A == 255 ? 50 : CurrentLineColor.A, CurrentLineColor));
+            //draw padding area
+            //top
+            e.Graphics.FillRectangle(paddingBrush, 0, -VerticalScroll.Value, ClientSize.Width, Math.Max(0, Paddings.Top - 1));
+            //bottom
+            var bottomPaddingStartY = wordWrapLinesCount * charHeight + Paddings.Top;
+            e.Graphics.FillRectangle(paddingBrush, 0, bottomPaddingStartY - VerticalScroll.Value, ClientSize.Width, ClientSize.Height);
+            //right
+            var rightPaddingStartX = LeftIndent + maxLineLength * CharWidth + Paddings.Left + 1;
+            e.Graphics.FillRectangle(paddingBrush, rightPaddingStartX - HorizontalScroll.Value, 0, ClientSize.Width, ClientSize.Height);
+            //left
+            e.Graphics.FillRectangle(paddingBrush, LeftIndentLine, 0, LeftIndent - LeftIndentLine - 1, ClientSize.Height);
+            if (HorizontalScroll.Value <= Paddings.Left)
+                e.Graphics.FillRectangle(paddingBrush, LeftIndent - HorizontalScroll.Value - 2, 0, Math.Max(0, Paddings.Left - 1), ClientSize.Height);
+
+            var leftTextIndent = Math.Max(LeftIndent, LeftIndent + Paddings.Left - HorizontalScroll.Value);
+            var textWidth = rightPaddingStartX - HorizontalScroll.Value - leftTextIndent;
+            //draw indent area
+            e.Graphics.FillRectangle(indentBrush, 0, 0, LeftIndentLine, ClientSize.Height);
+            if (LeftIndent > minLeftIndent)
+                e.Graphics.DrawLine(servicePen, LeftIndentLine, 0, LeftIndentLine, ClientSize.Height);
+            //draw preferred line width
+            if (PreferredLineWidth > 0)
+                e.Graphics.DrawLine(servicePen,
+                                    new Point(LeftIndent + Paddings.Left + PreferredLineWidth * CharWidth - HorizontalScroll.Value + 1, 0),
+                                    new Point(LeftIndent + Paddings.Left + PreferredLineWidth * CharWidth - HorizontalScroll.Value + 1, Height));
+            //
+            int firstChar = (Math.Max(0, HorizontalScroll.Value - Paddings.Left)) / CharWidth;
+            int lastChar = (HorizontalScroll.Value + ClientSize.Width) / CharWidth;
+            //draw chars
+            int startLine = YtoLineIndex(VerticalScroll.Value);
+            int iLine;
+            for (iLine = startLine; iLine < lines.Count; iLine++)
+            {
+                Line line = lines[iLine];
+                LineInfo lineInfo = lineInfos[iLine];
+                //
+                if (lineInfo.startY > VerticalScroll.Value + ClientSize.Height)
+                    break;
+                if (lineInfo.startY + lineInfo.WordWrapStringsCount * CharHeight < VerticalScroll.Value)
+                    continue;
+                if (lineInfo.VisibleState == VisibleState.Hidden)
+                    continue;
+
+                int y = lineInfo.startY - VerticalScroll.Value;
+                //
+                e.Graphics.SmoothingMode = SmoothingMode.None;
+                //draw line background
+                if (lineInfo.VisibleState == VisibleState.Visible)
+                    if (line.BackgroundBrush != null)
+                        e.Graphics.FillRectangle(line.BackgroundBrush,
+                                                 new Rectangle(leftTextIndent, y, textWidth,
+                                                               CharHeight * lineInfo.WordWrapStringsCount));
+                //draw current line background
+                if (CurrentLineColor != Color.Transparent && iLine == Selection.Start.iLine)
+                    if (Selection.IsEmpty)
+                        e.Graphics.FillRectangle(currentLineBrush, new Rectangle(leftTextIndent, y, textWidth, CharHeight));
+                //draw changed line marker
+                if (ChangedLineColor != Color.Transparent && line.IsChanged)
+                    e.Graphics.FillRectangle(changedLineBrush,
+                                             new RectangleF(-10, y, LeftIndent - minLeftIndent - 2 + 10, CharHeight + 1));
+                //
+                e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
+                //OnPaint event
+                if (lineInfo.VisibleState == VisibleState.Visible)
+                    OnPaintLine(new PaintLineEventArgs(iLine,
+                                                       new Rectangle(LeftIndent, y, Width,
+                                                                     CharHeight * lineInfo.WordWrapStringsCount),
+                                                       e.Graphics, e.ClipRectangle));
+                //draw line number
+                if (ShowLineNumbers)
+                    using (var lineNumberBrush = new SolidBrush(LineNumberColor))
+                        e.Graphics.DrawString((iLine + lineNumberStartValue).ToString(), Font, lineNumberBrush,
+                                          new RectangleF(-10, y, LeftIndent - minLeftIndent - 2 + 10, CharHeight),
+                                          new StringFormat(StringFormatFlags.DirectionRightToLeft));
+                //create markers
+                if (lineInfo.VisibleState == VisibleState.StartOfHiddenBlock)
+                    visibleMarkers.Add(new ExpandFoldingMarker(iLine,
+                                                               new Rectangle(LeftIndentLine - 4, y + CharHeight / 2 - 3, 8,
+                                                                             8)));
+                if (!string.IsNullOrEmpty(line.FoldingStartMarker) && lineInfo.VisibleState == VisibleState.Visible &&
+                    string.IsNullOrEmpty(line.FoldingEndMarker))
+                    visibleMarkers.Add(new CollapseFoldingMarker(iLine,
+                                                                 new Rectangle(LeftIndentLine - 4, y + CharHeight / 2 - 3,
+                                                                               8, 8)));
+                if (lineInfo.VisibleState == VisibleState.Visible && !string.IsNullOrEmpty(line.FoldingEndMarker) &&
+                    string.IsNullOrEmpty(line.FoldingStartMarker))
+                    e.Graphics.DrawLine(servicePen, LeftIndentLine, y + CharHeight * lineInfo.WordWrapStringsCount - 1,
+                                        LeftIndentLine + 4, y + CharHeight * lineInfo.WordWrapStringsCount - 1);
+                //draw wordwrap strings of line
+                for (int iWordWrapLine = 0; iWordWrapLine < lineInfo.WordWrapStringsCount; iWordWrapLine++)
+                {
+                    y = lineInfo.startY + iWordWrapLine * CharHeight - VerticalScroll.Value;
+                    //draw chars
+                    DrawLineChars(e, firstChar, lastChar, iLine, iWordWrapLine, LeftIndent + Paddings.Left - HorizontalScroll.Value, y);
+                }
+            }
+
+            var endLine = iLine - 1;
+
+            //draw folding lines
+            if (ShowFoldingLines)
+                DrawFoldingLines(e, startLine, endLine);
+
+            //draw column selection
+            if (Selection.ColumnSelectionMode)
+                if (SelectionStyle.BackgroundBrush is SolidBrush)
+                {
+                    var color = ((SolidBrush)SelectionStyle.BackgroundBrush).Color;
+                    var p1 = PlaceToPoint(Selection.Start);
+                    var p2 = PlaceToPoint(Selection.End);
+                    using (var pen = new Pen(color))
+                        e.Graphics.DrawRectangle(pen, Rectangle.FromLTRB(Math.Min(p1.X, p2.X) - 1, Math.Min(p1.Y, p2.Y), Math.Max(p1.X, p2.X), Math.Max(p1.Y, p2.Y) + CharHeight));
+                }
+            //draw brackets highlighting
+            if (BracketsStyle != null && leftBracketPosition != null && rightBracketPosition != null)
+            {
+                BracketsStyle.Draw(e.Graphics, PlaceToPoint(leftBracketPosition.Start), leftBracketPosition);
+                BracketsStyle.Draw(e.Graphics, PlaceToPoint(rightBracketPosition.Start), rightBracketPosition);
+            }
+            if (BracketsStyle2 != null && leftBracketPosition2 != null && rightBracketPosition2 != null)
+            {
+                BracketsStyle2.Draw(e.Graphics, PlaceToPoint(leftBracketPosition2.Start), leftBracketPosition2);
+                BracketsStyle2.Draw(e.Graphics, PlaceToPoint(rightBracketPosition2.Start), rightBracketPosition2);
+            }
+            //
+            e.Graphics.SmoothingMode = SmoothingMode.None;
+            //draw folding indicator
+            if ((startFoldingLine >= 0 || endFoldingLine >= 0) && Selection.Start == Selection.End)
+                if (endFoldingLine < lineInfos.Count)
+                {
+                    //folding indicator
+                    int startFoldingY = (startFoldingLine >= 0 ? lineInfos[startFoldingLine].startY : 0) -
+                                        VerticalScroll.Value + CharHeight / 2;
+                    int endFoldingY = (endFoldingLine >= 0
+                                           ? lineInfos[endFoldingLine].startY +
+                                             (lineInfos[endFoldingLine].WordWrapStringsCount - 1) * CharHeight
+                                           : (WordWrapLinesCount + 1) * CharHeight) - VerticalScroll.Value + CharHeight;
+
+                    using (var indicatorPen = new Pen(Color.FromArgb(100, FoldingIndicatorColor), 4))
+                        e.Graphics.DrawLine(indicatorPen, LeftIndent - 5, startFoldingY, LeftIndent - 5, endFoldingY);
+                }
+            //draw markers
+            foreach (VisualMarker m in visibleMarkers)
+                m.Draw(e.Graphics, servicePen);
+            //draw caret
+            Point car = PlaceToPoint(Selection.Start);
+
+            if ((Focused || IsDragDrop) && car.X >= LeftIndent && CaretVisible)
+            {
+                int carWidth = IsReplaceMode ? CharWidth : 1;
+                CreateCaret(Handle, 0, carWidth, CharHeight + 1);
+                SetCaretPos(car.X, car.Y);
+                ShowCaret(Handle);
+                //using (Pen pen = new Pen(CaretColor))
+                //    e.Graphics.DrawLine(pen, car.X, car.Y, car.X, car.Y + CharHeight);
+            }
+            else
+                HideCaret(Handle);
+
+            //draw disabled mask
+            if (!Enabled)
+                using (var brush = new SolidBrush(DisabledColor))
+                    e.Graphics.FillRectangle(brush, ClientRectangle);
+
+            //dispose resources
+            servicePen.Dispose();
+            changedLineBrush.Dispose();
+            indentBrush.Dispose();
+            currentLineBrush.Dispose();
+            paddingBrush.Dispose();
+            //
+#if debug
+            Debug.WriteLine("OnPaint: "+ sw.ElapsedMilliseconds);
+#endif
+            //
+            base.OnPaint(e);
+        }
+
+        protected virtual void DrawFoldingLines(PaintEventArgs e, int startLine, int endLine)
+        {
+            e.Graphics.SmoothingMode = SmoothingMode.None;
+            using (var pen = new Pen(Color.FromArgb(200, ServiceLinesColor)) { DashStyle = DashStyle.Dot })
+                foreach (var iLine in foldingPairs)
+                    if (iLine.Key < endLine && iLine.Value > startLine)
+                    {
+                        var line = lines[iLine.Key];
+                        var y = lineInfos[iLine.Key].startY - VerticalScroll.Value + CharHeight;
+                        y += y % 2;
+
+                        int y2;
+
+                        if (iLine.Value >= LinesCount)
+                            y2 = lineInfos[LinesCount - 1].startY + CharHeight - VerticalScroll.Value;
+                        else
+                            if (lineInfos[iLine.Value].VisibleState == VisibleState.Visible)
+                        {
+                            var d = 0;
+                            var spaceCount = line.StartSpacesCount;
+                            if (lines[iLine.Value].Count <= spaceCount || lines[iLine.Value][spaceCount].c == ' ')
+                                d = CharHeight;
+                            y2 = lineInfos[iLine.Value].startY - VerticalScroll.Value + d;
+                        }
+                        else
+                            continue;
+
+                        var x = LeftIndent + Paddings.Left + line.StartSpacesCount * CharWidth - HorizontalScroll.Value;
+                        if (x >= LeftIndent + Paddings.Left)
+                            e.Graphics.DrawLine(pen, x, y >= 0 ? y : 0, x, y2 < ClientSize.Height ? y2 : ClientSize.Height);
+                    }
+        }
+
+        /// <summary>
+        /// Color of selected area
+        /// </summary>
+        [DefaultValue(typeof(Color), "Blue")]
+        [Description("Color of selected area.")]
+        public virtual Color SelectionColor
+        {
+            get
+            {
+                return selectionColor;
+            }
+            set
+            {
+                selectionColor = value;
+                if (selectionColor.A == 255)
+                    selectionColor = Color.FromArgb(50, selectionColor);
+                SelectionStyle = new SelectionStyle(new SolidBrush(selectionColor));
+                Invalidate();
+            }
+        }
+
+        private void DrawLineChars(PaintEventArgs e, int firstChar, int lastChar, int iLine, int iWordWrapLine, int x, int y)
+        {
+            Line line = lines[iLine];
+            LineInfo lineInfo = lineInfos[iLine];
+            int from = lineInfo.GetWordWrapStringStartPosition(iWordWrapLine);
+            int to = lineInfo.GetWordWrapStringFinishPosition(iWordWrapLine, line);
+
+            int startX = x;
+            if (startX < LeftIndent)
+                firstChar++;
+
+            lastChar = Math.Min(to - from, lastChar);
+
+            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
+
+            //folded block ?
+            if (lineInfo.VisibleState == VisibleState.StartOfHiddenBlock)
+            {
+                //rendering by FoldedBlockStyle
+                FoldedBlockStyle.Draw(e.Graphics, new Point(startX + firstChar * CharWidth, y),
+                                      new Range(this, from + firstChar, iLine, from + lastChar + 1, iLine));
+            }
+            else
+            {
+                //render by custom styles
+                StyleIndex currentStyleIndex = StyleIndex.None;
+                int iLastFlushedChar = firstChar - 1;
+
+                for (int iChar = firstChar; iChar <= lastChar; iChar++)
+                {
+                    StyleIndex style = line[from + iChar].style;
+                    if (currentStyleIndex != style)
+                    {
+                        FlushRendering(e.Graphics, currentStyleIndex,
+                                       new Point(startX + (iLastFlushedChar + 1) * CharWidth, y),
+                                       new Range(this, from + iLastFlushedChar + 1, iLine, from + iChar, iLine));
+                        iLastFlushedChar = iChar - 1;
+                        currentStyleIndex = style;
+                    }
+                }
+                FlushRendering(e.Graphics, currentStyleIndex, new Point(startX + (iLastFlushedChar + 1) * CharWidth, y),
+                               new Range(this, from + iLastFlushedChar + 1, iLine, from + lastChar + 1, iLine));
+            }
+
+            //draw selection
+            if (!Selection.IsEmpty && lastChar >= firstChar)
+            {
+                e.Graphics.SmoothingMode = SmoothingMode.None;
+                var textRange = new Range(this, from + firstChar, iLine, from + lastChar + 1, iLine);
+                textRange = Selection.GetIntersectionWith(textRange);
+                if (textRange != null && SelectionStyle != null)
+                {
+                    SelectionStyle.Draw(e.Graphics, new Point(startX + (textRange.Start.iChar - from) * CharWidth, y),
+                                        textRange);
+                }
+            }
+        }
+
+        private void FlushRendering(Graphics gr, StyleIndex styleIndex, Point pos, Range range)
+        {
+            if (range.End > range.Start)
+            {
+                int mask = 1;
+                bool hasTextStyle = false;
+                for (int i = 0; i < Styles.Length; i++)
+                {
+                    if (Styles[i] != null && ((int)styleIndex & mask) != 0)
+                    {
+                        Style style = Styles[i];
+                        bool isTextStyle = style is TextStyle;
+                        if (!hasTextStyle || !isTextStyle || AllowSeveralTextStyleDrawing)
+                            //cancelling secondary rendering by TextStyle
+                            style.Draw(gr, pos, range); //rendering
+                        hasTextStyle |= isTextStyle;
+                    }
+                    mask = mask << 1;
+                }
+                //draw by default renderer
+                if (!hasTextStyle)
+                    DefaultStyle.Draw(gr, pos, range);
+            }
+        }
+
+        protected override void OnEnter(EventArgs e)
+        {
+            base.OnEnter(e);
+            mouseIsDrag = false;
+        }
+
+        protected override void OnMouseUp(MouseEventArgs e)
+        {
+            base.OnMouseUp(e);
+            isLineSelect = false;
+        }
+
+        protected override void OnMouseDown(MouseEventArgs e)
+        {
+            base.OnMouseDown(e);
+
+            if (e.Button == MouseButtons.Left)
+            {
+                VisualMarker marker = FindVisualMarkerForPoint(e.Location);
+                //click on marker
+                if (marker != null)
+                {
+                    mouseIsDrag = false;
+                    OnMarkerClick(e, marker);
+                    return;
+                }
+                mouseIsDrag = true;
+                isLineSelect = e.Location.X < LeftIndentLine;
+                //
+                CheckAndChangeSelectionType();
+                //
+                //click on text
+                Place oldEnd = Selection.End;
+                Selection.BeginUpdate();
+
+                if (isLineSelect)
+                {
+                    //select whole line
+                    var iLine = PointToPlaceSimple(e.Location).iLine;
+                    lineSelectFrom = iLine;
+                    Selection.Start = new Place(0, iLine);
+                    Selection.End = new Place(GetLineLength(iLine), iLine);
+                }
+                else
+                {
+                    if (Selection.ColumnSelectionMode)
+                    {
+                        Selection.Start = PointToPlaceSimple(e.Location);
+                        Selection.ColumnSelectionMode = true;
+                    }
+                    else
+                    {
+                        if (VirtualSpace)
+                            Selection.Start = PointToPlaceSimple(e.Location);
+                        else
+                            Selection.Start = PointToPlace(e.Location);
+                    }
+                    if ((lastModifiers & Keys.Shift) != 0)
+                        Selection.End = oldEnd;
+                }
+                Selection.EndUpdate();
+                Invalidate();
+                return;
+            }
+        }
+
+        private void CheckAndChangeSelectionType()
+        {
+            //change selection type to ColumnSelectionMode
+            if ((Control.ModifierKeys & Keys.Alt) != 0 && !WordWrap)
+            {
+                Selection.ColumnSelectionMode = true;
+            }
+            else
+            //change selection type to Range
+            {
+                Selection.ColumnSelectionMode = false;
+            }
+        }
+
+        protected override void OnMouseWheel(MouseEventArgs e)
+        {
+            Invalidate();
+            base.OnMouseWheel(e);
+            OnVisibleRangeChanged();
+        }
+
+        Cursor defaultCursor;
+
+        public override Cursor Cursor
+        {
+            get
+            {
+                return base.Cursor;
+            }
+            set
+            {
+                defaultCursor = value;
+                base.Cursor = value;
+            }
+        }
+
+        protected override void OnMouseMove(MouseEventArgs e)
+        {
+            base.OnMouseMove(e);
+
+            if (e.Button == MouseButtons.Left && mouseIsDrag)
+            {
+                Place place;
+                if (Selection.ColumnSelectionMode || VirtualSpace)
+                    place = PointToPlaceSimple(e.Location);
+                else
+                    place = PointToPlace(e.Location);
+
+                if (isLineSelect)
+                {
+                    Selection.BeginUpdate();
+
+                    var iLine = place.iLine;
+                    if (iLine < lineSelectFrom)
+                    {
+                        Selection.Start = new Place(0, iLine);
+                        Selection.End = new Place(GetLineLength(lineSelectFrom), lineSelectFrom);
+                    }
+                    else
+                    {
+                        Selection.Start = new Place(GetLineLength(iLine), iLine);
+                        Selection.End = new Place(0, lineSelectFrom);
+                    }
+
+                    Selection.EndUpdate();
+                    DoCaretVisible();
+                    HorizontalScroll.Value = 0;
+                    UpdateScrollbars();
+                    Invalidate();
+                }
+                else
+                if (place != Selection.Start)
+                {
+                    Place oldEnd = Selection.End;
+                    Selection.BeginUpdate();
+                    if (Selection.ColumnSelectionMode)
+                    {
+                        Selection.Start = place;
+                        Selection.ColumnSelectionMode = true;
+                    }
+                    else
+                        Selection.Start = place;
+                    Selection.End = oldEnd;
+                    Selection.EndUpdate();
+                    DoCaretVisible();
+                    Invalidate();
+                    return;
+                }
+            }
+
+            VisualMarker marker = FindVisualMarkerForPoint(e.Location);
+            if (marker != null)
+                base.Cursor = marker.Cursor;
+            else
+            {
+                if (e.Location.X < LeftIndentLine || isLineSelect)
+                    base.Cursor = Cursors.Arrow;
+                else
+                    base.Cursor = defaultCursor;
+            }
+        }
+
+        protected override void OnMouseDoubleClick(MouseEventArgs e)
+        {
+            base.OnMouseDoubleClick(e);
+
+            VisualMarker m = FindVisualMarkerForPoint(e.Location);
+            if (m != null)
+            {
+                OnMarkerDoubleClick(m);
+                return;
+            }
+
+            Place p = PointToPlace(e.Location);
+            int fromX = p.iChar;
+            int toX = p.iChar;
+
+            for (int i = p.iChar; i < lines[p.iLine].Count; i++)
+            {
+                char c = lines[p.iLine][i].c;
+                if (char.IsLetterOrDigit(c) || c == '_')
+                    toX = i + 1;
+                else
+                    break;
+            }
+
+            for (int i = p.iChar - 1; i >= 0; i--)
+            {
+                char c = lines[p.iLine][i].c;
+                if (char.IsLetterOrDigit(c) || c == '_')
+                    fromX = i;
+                else
+                    break;
+            }
+
+            Selection.Start = new Place(toX, p.iLine);
+            Selection.End = new Place(fromX, p.iLine);
+
+            Invalidate();
+        }
+
+        private int YtoLineIndex(int y)
+        {
+            int i = lineInfos.BinarySearch(new LineInfo(-10), new LineYComparer(y));
+            i = i < 0 ? -i - 2 : i;
+            if (i < 0) return 0;
+            if (i > lines.Count - 1) return lines.Count - 1;
+            return i;
+        }
+
+        /// <summary>
+        /// Gets nearest line and char position from coordinates
+        /// </summary>
+        /// <param name="point">Point</param>
+        /// <returns>Line and char position</returns>
+        public Place PointToPlace(Point point)
+        {
+#if debug
+            var sw = Stopwatch.StartNew();
+#endif
+            point.Offset(HorizontalScroll.Value, VerticalScroll.Value);
+            point.Offset(-LeftIndent - Paddings.Left, 0);
+            int iLine = YtoLineIndex(point.Y);
+            int y = 0;
+
+            for (; iLine < lines.Count; iLine++)
+            {
+                y = lineInfos[iLine].startY + lineInfos[iLine].WordWrapStringsCount * CharHeight;
+                if (y > point.Y && lineInfos[iLine].VisibleState == VisibleState.Visible)
+                    break;
+            }
+            if (iLine >= lines.Count)
+                iLine = lines.Count - 1;
+            if (lineInfos[iLine].VisibleState != VisibleState.Visible)
+                iLine = FindPrevVisibleLine(iLine);
+            //
+            int iWordWrapLine = lineInfos[iLine].WordWrapStringsCount;
+            do
+            {
+                iWordWrapLine--;
+                y -= CharHeight;
+            } while (y > point.Y);
+            if (iWordWrapLine < 0) iWordWrapLine = 0;
+            //
+            int start = lineInfos[iLine].GetWordWrapStringStartPosition(iWordWrapLine);
+            int finish = lineInfos[iLine].GetWordWrapStringFinishPosition(iWordWrapLine, lines[iLine]);
+            var x = (int)Math.Round((float)point.X / CharWidth);
+            x = x < 0 ? start : start + x;
+            if (x > finish)
+                x = finish + 1;
+            if (x > lines[iLine].Count)
+                x = lines[iLine].Count;
+
+#if debug
+            Debug.WriteLine("PointToPlace: " + sw.ElapsedMilliseconds);
+#endif
+
+            return new Place(x, iLine);
+        }
+
+        private Place PointToPlaceSimple(Point point)
+        {
+            point.Offset(HorizontalScroll.Value, VerticalScroll.Value);
+            point.Offset(-LeftIndent - Paddings.Left, 0);
+            int iLine = YtoLineIndex(point.Y);
+            var x = (int)Math.Round((float)point.X / CharWidth);
+            if (x < 0) x = 0;
+            return new Place(x, iLine);
+        }
+
+        /// <summary>
+        /// Gets nearest absolute text position for given point
+        /// </summary>
+        /// <param name="point">Point</param>
+        /// <returns>Position</returns>
+        public int PointToPosition(Point point)
+        {
+            return PlaceToPosition(PointToPlace(point));
+        }
+
+        /// <summary>
+        /// Fires TextChanging event
+        /// </summary>
+        public virtual void OnTextChanging(ref string text)
+        {
+            ClearBracketsPositions();
+
+            if (TextChanging != null)
+            {
+                var args = new TextChangingEventArgs { InsertingText = text };
+                TextChanging(this, args);
+                text = args.InsertingText;
+                if (args.Cancel)
+                    text = string.Empty;
+            }
+        }
+
+        public virtual void OnTextChanging()
+        {
+            string temp = null;
+            OnTextChanging(ref temp);
+        }
+
+        /// <summary>
+        /// Fires TextChanged event
+        /// </summary>
+        public virtual void OnTextChanged()
+        {
+            var r = new Range(this);
+            r.SelectAll();
+            OnTextChanged(new TextChangedEventArgs(r));
+        }
+
+        /// <summary>
+        /// Fires TextChanged event
+        /// </summary>
+        public virtual void OnTextChanged(int fromLine, int toLine)
+        {
+            var r = new Range(this);
+            r.Start = new Place(0, Math.Min(fromLine, toLine));
+            r.End = new Place(lines[Math.Max(fromLine, toLine)].Count, Math.Max(fromLine, toLine));
+            OnTextChanged(new TextChangedEventArgs(r));
+        }
+
+        /// <summary>
+        /// Fires TextChanged event
+        /// </summary>
+        public virtual void OnTextChanged(Range r)
+        {
+            OnTextChanged(new TextChangedEventArgs(r));
+        }
+
+        public void BeginUpdate()
+        {
+            if (updating == 0)
+                updatingRange = null;
+            updating++;
+        }
+
+        public void EndUpdate()
+        {
+            updating--;
+
+            if (updating == 0 && updatingRange != null)
+            {
+                updatingRange.Expand();
+                OnTextChanged(updatingRange);
+            }
+        }
+
+
+        /// <summary>
+        /// Fires TextChanged event
+        /// </summary>
+        protected virtual void OnTextChanged(TextChangedEventArgs args)
+        {
+            //
+            args.ChangedRange.Normalize();
+            //
+            if (updating > 0)
+            {
+                if (updatingRange == null)
+                    updatingRange = args.ChangedRange.Clone();
+                else
+                {
+                    if (updatingRange.Start.iLine > args.ChangedRange.Start.iLine)
+                        updatingRange.Start = new Place(0, args.ChangedRange.Start.iLine);
+                    if (updatingRange.End.iLine < args.ChangedRange.End.iLine)
+                        updatingRange.End = new Place(lines[args.ChangedRange.End.iLine].Count,
+                                                      args.ChangedRange.End.iLine);
+                    updatingRange = updatingRange.GetIntersectionWith(Range);
+                }
+                return;
+            }
+            //
+#if debug
+            var sw = Stopwatch.StartNew();
+#endif
+            IsChanged = true;
+            TextVersion++;
+            MarkLinesAsChanged(args.ChangedRange);
+            //
+            if (wordWrap)
+                RecalcWordWrap(args.ChangedRange.Start.iLine, args.ChangedRange.End.iLine);
+            //
+            base.OnTextChanged(args);
+
+            //dalayed event stuffs
+            if (delayedTextChangedRange == null)
+                delayedTextChangedRange = args.ChangedRange.Clone();
+            else
+                delayedTextChangedRange = delayedTextChangedRange.GetUnionWith(args.ChangedRange);
+
+            needRiseTextChangedDelayed = true;
+            ResetTimer(timer2);
+            //
+            OnSyntaxHighlight(args);
+            //
+            if (TextChanged != null)
+                TextChanged(this, args);
+            //
+            if (BindingTextChanged != null)
+                BindingTextChanged(this, EventArgs.Empty);
+            //
+            base.OnTextChanged(EventArgs.Empty);
+            //
+#if debug
+            Debug.WriteLine("OnTextChanged: " + sw.ElapsedMilliseconds);
+#endif
+
+            OnVisibleRangeChanged();
+        }
+
+        private void MarkLinesAsChanged(Range range)
+        {
+            for (int iLine = range.Start.iLine; iLine <= range.End.iLine; iLine++)
+                if (iLine >= 0 && iLine < lines.Count)
+                    lines[iLine].IsChanged = true;
+        }
+
+        /// <summary>
+        /// Fires SelectionCnaged event
+        /// </summary>
+        public virtual void OnSelectionChanged()
+        {
+#if debug
+            var sw = Stopwatch.StartNew();
+#endif
+            //find folding markers for highlighting
+            if (HighlightFoldingIndicator)
+                HighlightFoldings();
+            //
+            needRiseSelectionChangedDelayed = true;
+            ResetTimer(timer);
+
+            if (SelectionChanged != null)
+                SelectionChanged(this, new EventArgs());
+
+#if debug
+            Debug.WriteLine("OnSelectionChanged: "+ sw.ElapsedMilliseconds);
+#endif
+        }
+
+        //find folding markers for highlighting
+        private void HighlightFoldings()
+        {
+            if (LinesCount == 0)
+                return;
+            //
+            int prevStartFoldingLine = startFoldingLine;
+            int prevEndFoldingLine = endFoldingLine;
+            //
+            startFoldingLine = -1;
+            endFoldingLine = -1;
+            //
+            string marker = null;
+            int counter = 0;
+            for (int i = Selection.Start.iLine; i >= Math.Max(Selection.Start.iLine - maxLinesForFolding, 0); i--)
+            {
+                bool hasStartMarker = lines.LineHasFoldingStartMarker(i);
+                bool hasEndMarker = lines.LineHasFoldingEndMarker(i);
+
+                if (hasEndMarker && hasStartMarker)
+                    continue;
+
+                if (hasStartMarker)
+                {
+                    counter--;
+                    if (counter == -1) //found start folding
+                    {
+                        startFoldingLine = i;
+                        marker = lines[i].FoldingStartMarker;
+                        break;
+                    }
+                }
+                if (hasEndMarker && i != Selection.Start.iLine)
+                    counter++;
+            }
+            if (startFoldingLine >= 0)
+            {
+                //find end of block
+                endFoldingLine = FindEndOfFoldingBlock(startFoldingLine, maxLinesForFolding);
+                if (endFoldingLine == startFoldingLine)
+                    endFoldingLine = -1;
+            }
+
+            if (startFoldingLine != prevStartFoldingLine || endFoldingLine != prevEndFoldingLine)
+                OnFoldingHighlightChanged();
+        }
+
+        protected virtual void OnFoldingHighlightChanged()
+        {
+            if (FoldingHighlightChanged != null)
+                FoldingHighlightChanged(this, EventArgs.Empty);
+        }
+
+        protected override void OnGotFocus(EventArgs e)
+        {
+            SetAsCurrentTB();
+            base.OnGotFocus(e);
+            //Invalidate(new Rectangle(PlaceToPoint(Selection.Start), new Size(2, CharHeight+1)));
+            Invalidate();
+        }
+
+        protected override void OnLostFocus(EventArgs e)
+        {
+            base.OnLostFocus(e);
+            //Invalidate(new Rectangle(PlaceToPoint(Selection.Start), new Size(2, CharHeight+1)));
+            Invalidate();
+        }
+
+        /// <summary>
+        /// Gets absolute text position from line and char position
+        /// </summary>
+        /// <param name="point">Line and char position</param>
+        /// <returns>Point of char</returns>
+        public int PlaceToPosition(Place point)
+        {
+            if (point.iLine < 0 || point.iLine >= lines.Count ||
+                point.iChar >= lines[point.iLine].Count + Environment.NewLine.Length)
+                return -1;
+
+            int result = 0;
+            for (int i = 0; i < point.iLine; i++)
+                result += lines[i].Count + Environment.NewLine.Length;
+            result += point.iChar;
+
+            return result;
+        }
+
+        /// <summary>
+        /// Gets line and char position from absolute text position
+        /// </summary>
+        /// <param name="pos"></param>
+        /// <returns></returns>
+        public Place PositionToPlace(int pos)
+        {
+            if (pos < 0)
+                return new Place(0, 0);
+
+            for (int i = 0; i < lines.Count; i++)
+            {
+                int lineLength = lines[i].Count + Environment.NewLine.Length;
+                if (pos < lines[i].Count)
+                    return new Place(pos, i);
+                if (pos < lineLength)
+                    return new Place(lines[i].Count, i);
+
+                pos -= lineLength;
+            }
+
+            if (lines.Count > 0)
+                return new Place(lines[lines.Count - 1].Count, lines.Count - 1);
+            else
+                return new Place(0, 0);
+            //throw new ArgumentOutOfRangeException("Position out of range");
+        }
+
+        /// <summary>
+        /// Gets absolute char position from char position
+        /// </summary>
+        public Point PositionToPoint(int pos)
+        {
+            return PlaceToPoint(PositionToPlace(pos));
+        }
+
+        /// <summary>
+        /// Gets point for given line and char position
+        /// </summary>
+        /// <param name="place">Line and char position</param>
+        /// <returns>Coordiantes</returns>
+        public Point PlaceToPoint(Place place)
+        {
+            if (place.iLine >= lineInfos.Count)
+                return new Point();
+            int y = lineInfos[place.iLine].startY;
+            //
+            int iWordWrapIndex = lineInfos[place.iLine].GetWordWrapStringIndex(place.iChar);
+            y += iWordWrapIndex * CharHeight;
+            int x = (place.iChar - lineInfos[place.iLine].GetWordWrapStringStartPosition(iWordWrapIndex)) * CharWidth;
+            //
+            y = y - VerticalScroll.Value;
+            x = LeftIndent + Paddings.Left + x - HorizontalScroll.Value;
+
+            return new Point(x, y);
+        }
+
+        /// <summary>
+        /// Get range of text
+        /// </summary>
+        /// <param name="fromPos">Absolute start position</param>
+        /// <param name="toPos">Absolute finish position</param>
+        /// <returns>Range</returns>
+        public Range GetRange(int fromPos, int toPos)
+        {
+            var sel = new Range(this);
+            sel.Start = PositionToPlace(fromPos);
+            sel.End = PositionToPlace(toPos);
+            return sel;
+        }
+
+        /// <summary>
+        /// Get range of text
+        /// </summary>
+        /// <param name="fromPlace">Line and char position</param>
+        /// <param name="toPlace">Line and char position</param>
+        /// <returns>Range</returns>
+        public Range GetRange(Place fromPlace, Place toPlace)
+        {
+            return new Range(this, fromPlace, toPlace);
+        }
+
+        /// <summary>
+        /// Finds ranges for given regex pattern
+        /// </summary>
+        /// <param name="regexPattern">Regex pattern</param>
+        /// <returns>Enumeration of ranges</returns>
+        public IEnumerable<Range> GetRanges(string regexPattern)
+        {
+            var range = new Range(this);
+            range.SelectAll();
+            //
+            foreach (Range r in range.GetRanges(regexPattern, RegexOptions.None))
+                yield return r;
+        }
+
+        /// <summary>
+        /// Finds ranges for given regex pattern
+        /// </summary>
+        /// <param name="regexPattern">Regex pattern</param>
+        /// <returns>Enumeration of ranges</returns>
+        public IEnumerable<Range> GetRanges(string regexPattern, RegexOptions options)
+        {
+            var range = new Range(this);
+            range.SelectAll();
+            //
+            foreach (Range r in range.GetRanges(regexPattern, options))
+                yield return r;
+        }
+
+        /// <summary>
+        /// Get text of given line
+        /// </summary>
+        /// <param name="iLine">Line index</param>
+        /// <returns>Text</returns>
+        public string GetLineText(int iLine)
+        {
+            if (iLine < 0 || iLine >= lines.Count)
+                throw new ArgumentOutOfRangeException("Line index out of range");
+            var sb = new StringBuilder(lines[iLine].Count);
+            foreach (Char c in lines[iLine])
+                sb.Append(c.c);
+            return sb.ToString();
+        }
+
+        /// <summary>
+        /// Exapnds folded block
+        /// </summary>
+        /// <param name="iLine">Start line</param>
+        public void ExpandFoldedBlock(int iLine)
+        {
+            if (iLine < 0 || iLine >= lines.Count)
+                throw new ArgumentOutOfRangeException("Line index out of range");
+            //find all hidden lines afetr iLine
+            int end = iLine;
+            for (; end < LinesCount - 1; end++)
+            {
+                if (lineInfos[end + 1].VisibleState != VisibleState.Hidden)
+                    break;
+            }
+
+            ExpandBlock(iLine, end);
+        }
+
+        /// <summary>
+        /// Expand collapsed block
+        /// </summary>
+        public void ExpandBlock(int fromLine, int toLine)
+        {
+            int from = Math.Min(fromLine, toLine);
+            int to = Math.Max(fromLine, toLine);
+            for (int i = from; i <= to; i++)
+                SetVisibleState(i, VisibleState.Visible);
+            needRecalc = true;
+            Invalidate();
+        }
+
+        /// <summary>
+        /// Expand collapsed block
+        /// </summary>
+        /// <param name="iLine">Any line inside collapsed block</param>
+        public void ExpandBlock(int iLine)
+        {
+            if (lineInfos[iLine].VisibleState == VisibleState.Visible)
+                return;
+
+            for (int i = iLine; i < LinesCount; i++)
+                if (lineInfos[i].VisibleState == VisibleState.Visible)
+                    break;
+                else
+                {
+                    SetVisibleState(i, VisibleState.Visible);
+                    needRecalc = true;
+                }
+
+            for (int i = iLine - 1; i >= 0; i--)
+                if (lineInfos[i].VisibleState == VisibleState.Visible)
+                    break;
+                else
+                {
+                    SetVisibleState(i, VisibleState.Visible);
+                    needRecalc = true;
+                }
+
+            Invalidate();
+        }
+
+
+        /// <summary>
+        /// Collapses all folding blocks
+        /// </summary>
+        public void CollapseAllFoldingBlocks()
+        {
+            for (int i = 0; i < LinesCount; i++)
+                if (lines.LineHasFoldingStartMarker(i))
+                {
+                    int iFinish = FindEndOfFoldingBlock(i);
+                    if (iFinish >= 0)
+                    {
+                        CollapseBlock(i, iFinish);
+                        i = iFinish;
+                    }
+                }
+
+            OnVisibleRangeChanged();
+        }
+
+        /// <summary>
+        /// Exapnds all folded blocks
+        /// </summary>
+        /// <param name="iLine"></param>
+        public void ExpandAllFoldingBlocks()
+        {
+            for (int i = 0; i < LinesCount; i++)
+                SetVisibleState(i, VisibleState.Visible);
+
+            OnVisibleRangeChanged();
+            Invalidate();
+        }
+
+        /// <summary>
+        /// Collapses folding block
+        /// </summary>
+        /// <param name="iLine">Start folding line</param>
+        public void CollapseFoldingBlock(int iLine)
+        {
+            if (iLine < 0 || iLine >= lines.Count)
+                throw new ArgumentOutOfRangeException("Line index out of range");
+            if (string.IsNullOrEmpty(lines[iLine].FoldingStartMarker))
+                throw new ArgumentOutOfRangeException("This line is not folding start line");
+            //find end of block
+            int i = FindEndOfFoldingBlock(iLine);
+            //collapse
+            if (i >= 0)
+                CollapseBlock(iLine, i);
+        }
+
+        private int FindEndOfFoldingBlock(int iStartLine)
+        {
+            return FindEndOfFoldingBlock(iStartLine, int.MaxValue);
+        }
+
+        protected virtual int FindEndOfFoldingBlock(int iStartLine, int maxLines)
+        {
+            //find end of block
+            int counter = 0;
+            int i;
+            string marker = lines[iStartLine].FoldingStartMarker;
+            Stack<string> stack = new Stack<string>();
+
+            switch (FindEndOfFoldingBlockStrategy)
+            {
+                case FindEndOfFoldingBlockStrategy.Strategy1:
+                    for (i = iStartLine /*+1*/; i < LinesCount; i++)
+                    {
+                        if (lines.LineHasFoldingStartMarker(i))
+                            stack.Push(lines[i].FoldingStartMarker);
+
+                        if (lines.LineHasFoldingEndMarker(i))
+                        {
+                            var m = lines[i].FoldingEndMarker;
+                            while (stack.Count > 0 && stack.Pop() != m) ;
+                            if (stack.Count == 0)
+                                return i;
+                        }
+
+                        maxLines--;
+                        if (maxLines < 0)
+                            return i;
+                    }
+                    break;
+
+                case FindEndOfFoldingBlockStrategy.Strategy2:
+                    for (i = iStartLine /*+1*/; i < LinesCount; i++)
+                    {
+                        if (lines.LineHasFoldingEndMarker(i))
+                        {
+                            var m = lines[i].FoldingEndMarker;
+                            while (stack.Count > 0 && stack.Pop() != m) ;
+                            if (stack.Count == 0)
+                                return i;
+                        }
+
+                        if (lines.LineHasFoldingStartMarker(i))
+                            stack.Push(lines[i].FoldingStartMarker);
+
+                        maxLines--;
+                        if (maxLines < 0)
+                            return i;
+                    }
+                    break;
+            }
+
+            //return -1;
+            return LinesCount - 1;
+        }
+
+        /// <summary>
+        /// Start foilding marker for the line
+        /// </summary>
+        public string GetLineFoldingStartMarker(int iLine)
+        {
+            if (lines.LineHasFoldingStartMarker(iLine))
+                return lines[iLine].FoldingStartMarker;
+            return null;
+        }
+
+        /// <summary>
+        /// End foilding marker for the line
+        /// </summary>
+        public string GetLineFoldingEndMarker(int iLine)
+        {
+            if (lines.LineHasFoldingEndMarker(iLine))
+                return lines[iLine].FoldingEndMarker;
+            return null;
+        }
+
+        protected Dictionary<int, int> foldingPairs = new Dictionary<int, int>();
+
+        protected virtual void RecalcFoldingLines()
+        {
+            if (!needRecalcFoldingLines)
+                return;
+            needRecalcFoldingLines = false;
+            if (!ShowFoldingLines)
+                return;
+
+            foldingPairs.Clear();
+            //
+            var range = VisibleRange;
+            var startLine = Math.Max(range.Start.iLine - maxLinesForFolding, 0);
+            var endLine = Math.Min(range.End.iLine + maxLinesForFolding, Math.Max(range.End.iLine, LinesCount - 1));
+            var stack = new Stack<int>();
+            for (int i = startLine; i <= endLine; i++)
+            {
+                bool hasStartMarker = lines.LineHasFoldingStartMarker(i);
+                bool hasEndMarker = lines.LineHasFoldingEndMarker(i);
+
+                if (hasEndMarker && hasStartMarker)
+                    continue;
+
+                if (hasStartMarker)
+                {
+                    stack.Push(i);
+                }
+                if (hasEndMarker)
+                {
+                    var m = lines[i].FoldingEndMarker;
+                    while (stack.Count > 0)
+                    {
+                        var iStartLine = stack.Pop();
+                        foldingPairs[iStartLine] = i;
+                        if (m == lines[iStartLine].FoldingStartMarker)
+                            break;
+                    }
+                }
+            }
+
+            while (stack.Count > 0)
+                foldingPairs[stack.Pop()] = endLine + 1;
+        }
+
+        /// <summary>
+        /// Collapse text block
+        /// </summary>
+        public void CollapseBlock(int fromLine, int toLine)
+        {
+            int from = Math.Min(fromLine, toLine);
+            int to = Math.Max(fromLine, toLine);
+            if (from == to)
+                return;
+
+            //find first non empty line
+            for (; from <= to; from++)
+            {
+                if (GetLineText(from).Trim().Length > 0)
+                {
+                    //hide lines
+                    for (int i = from + 1; i <= to; i++)
+                        SetVisibleState(i, VisibleState.Hidden);
+                    SetVisibleState(from, VisibleState.StartOfHiddenBlock);
+                    Invalidate();
+                    break;
+                }
+            }
+            //Move caret outside
+            from = Math.Min(fromLine, toLine);
+            to = Math.Max(fromLine, toLine);
+            int newLine = FindNextVisibleLine(to);
+            if (newLine == to)
+                newLine = FindPrevVisibleLine(from);
+            Selection.Start = new Place(0, newLine);
+            //
+            needRecalc = true;
+            Invalidate();
+        }
+
+
+        internal int FindNextVisibleLine(int iLine)
+        {
+            if (iLine >= lines.Count - 1) return iLine;
+            int old = iLine;
+            do
+                iLine++; while (iLine < lines.Count - 1 && lineInfos[iLine].VisibleState != VisibleState.Visible);
+
+            if (lineInfos[iLine].VisibleState != VisibleState.Visible)
+                return old;
+            else
+                return iLine;
+        }
+
+
+        internal int FindPrevVisibleLine(int iLine)
+        {
+            if (iLine <= 0) return iLine;
+            int old = iLine;
+            do
+                iLine--; while (iLine > 0 && lineInfos[iLine].VisibleState != VisibleState.Visible);
+
+            if (lineInfos[iLine].VisibleState != VisibleState.Visible)
+                return old;
+            else
+                return iLine;
+        }
+
+        private VisualMarker FindVisualMarkerForPoint(Point p)
+        {
+            foreach (VisualMarker m in visibleMarkers)
+                if (m.rectangle.Contains(p))
+                    return m;
+            return null;
+        }
+
+        /// <summary>
+        /// Insert TAB into front of seletcted lines
+        /// </summary>
+        public void IncreaseIndent()
+        {
+            if (Selection.IsEmpty)
+                return;
+            Range old = Selection.Clone();
+            int from = Math.Min(Selection.Start.iLine, Selection.End.iLine);
+            int to = Math.Max(Selection.Start.iLine, Selection.End.iLine);
+            BeginUpdate();
+            Selection.BeginUpdate();
+            lines.Manager.BeginAutoUndoCommands();
+            for (int i = from; i <= to; i++)
+            {
+                if (lines[i].Count == 0) continue;
+                Selection.Start = new Place(0, i);
+                lines.Manager.ExecuteCommand(new InsertTextCommand(TextSource, new String(' ', TabLength)));
+            }
+            lines.Manager.EndAutoUndoCommands();
+            Selection.Start = new Place(0, from);
+            Selection.End = new Place(lines[to].Count, to);
+            needRecalc = true;
+            Selection.EndUpdate();
+            EndUpdate();
+            Invalidate();
+        }
+
+        /// <summary>
+        /// Remove TAB from front of seletcted lines
+        /// </summary>
+        public void DecreaseIndent()
+        {
+            if (Selection.IsEmpty)
+                return;
+            Range old = Selection.Clone();
+            int from = Math.Min(Selection.Start.iLine, Selection.End.iLine);
+            int to = Math.Max(Selection.Start.iLine, Selection.End.iLine);
+            BeginUpdate();
+            Selection.BeginUpdate();
+            lines.Manager.BeginAutoUndoCommands();
+            for (int i = from; i <= to; i++)
+            {
+                Selection.Start = new Place(0, i);
+                Selection.End = new Place(Math.Min(lines[i].Count, TabLength), i);
+                if (Selection.Text.Trim() == "")
+                    ClearSelected();
+            }
+            lines.Manager.EndAutoUndoCommands();
+            Selection.Start = new Place(0, from);
+            Selection.End = new Place(lines[to].Count, to);
+            needRecalc = true;
+            EndUpdate();
+            Selection.EndUpdate();
+        }
+
+        /// <summary>
+        /// Insert autoindents into selected lines
+        /// </summary>
+        public void DoAutoIndent()
+        {
+            if (Selection.ColumnSelectionMode)
+                return;
+            Range r = Selection.Clone();
+            r.Normalize();
+            //
+            BeginUpdate();
+            Selection.BeginUpdate();
+            lines.Manager.BeginAutoUndoCommands();
+            //
+            for (int i = r.Start.iLine; i <= r.End.iLine; i++)
+                DoAutoIndent(i);
+            //
+            lines.Manager.EndAutoUndoCommands();
+            Selection.Start = r.Start;
+            Selection.End = r.End;
+            Selection.Expand();
+            //
+            Selection.EndUpdate();
+            EndUpdate();
+        }
+
+        /// <summary>
+        /// Insert prefix into front of seletcted lines
+        /// </summary>
+        public void InsertLinePrefix(string prefix)
+        {
+            Range old = Selection.Clone();
+            int from = Math.Min(Selection.Start.iLine, Selection.End.iLine);
+            int to = Math.Max(Selection.Start.iLine, Selection.End.iLine);
+            BeginUpdate();
+            Selection.BeginUpdate();
+            lines.Manager.BeginAutoUndoCommands();
+            int spaces = GetMinStartSpacesCount(from, to);
+            for (int i = from; i <= to; i++)
+            {
+                Selection.Start = new Place(spaces, i);
+                lines.Manager.ExecuteCommand(new InsertTextCommand(TextSource, prefix));
+            }
+            Selection.Start = new Place(0, from);
+            Selection.End = new Place(lines[to].Count, to);
+            needRecalc = true;
+            lines.Manager.EndAutoUndoCommands();
+            Selection.EndUpdate();
+            EndUpdate();
+            Invalidate();
+        }
+
+        /// <summary>
+        /// Remove prefix from front of seletcted lines
+        /// </summary>
+        public void RemoveLinePrefix(string prefix)
+        {
+            Range old = Selection.Clone();
+            int from = Math.Min(Selection.Start.iLine, Selection.End.iLine);
+            int to = Math.Max(Selection.Start.iLine, Selection.End.iLine);
+            BeginUpdate();
+            Selection.BeginUpdate();
+            lines.Manager.BeginAutoUndoCommands();
+            for (int i = from; i <= to; i++)
+            {
+                string text = lines[i].Text;
+                string trimmedText = text.TrimStart();
+                if (trimmedText.StartsWith(prefix))
+                {
+                    int spaces = text.Length - trimmedText.Length;
+                    Selection.Start = new Place(spaces, i);
+                    Selection.End = new Place(spaces + prefix.Length, i);
+                    ClearSelected();
+                }
+            }
+            Selection.Start = new Place(0, from);
+            Selection.End = new Place(lines[to].Count, to);
+            needRecalc = true;
+            lines.Manager.EndAutoUndoCommands();
+            Selection.EndUpdate();
+            EndUpdate();
+        }
+
+        /// <summary>
+        /// Begins AutoUndo block.
+        /// All changes of text between BeginAutoUndo() and EndAutoUndo() will be canceled in one operation Undo.
+        /// </summary>
+        public void BeginAutoUndo()
+        {
+            lines.Manager.BeginAutoUndoCommands();
+        }
+
+        /// <summary>
+        /// Ends AutoUndo block.
+        /// All changes of text between BeginAutoUndo() and EndAutoUndo() will be canceled in one operation Undo.
+        /// </summary>
+        public void EndAutoUndo()
+        {
+            lines.Manager.EndAutoUndoCommands();
+        }
+
+        public virtual void OnVisualMarkerClick(MouseEventArgs args, StyleVisualMarker marker)
+        {
+            if (VisualMarkerClick != null)
+                VisualMarkerClick(this, new VisualMarkerEventArgs(marker.Style, marker, args));
+        }
+
+        protected virtual void OnMarkerClick(MouseEventArgs args, VisualMarker marker)
+        {
+            if (marker is StyleVisualMarker)
+            {
+                OnVisualMarkerClick(args, marker as StyleVisualMarker);
+                return;
+            }
+            if (marker is CollapseFoldingMarker)
+            {
+                CollapseFoldingBlock((marker as CollapseFoldingMarker).iLine);
+                OnVisibleRangeChanged();
+                Invalidate();
+                return;
+            }
+
+            if (marker is ExpandFoldingMarker)
+            {
+                ExpandFoldedBlock((marker as ExpandFoldingMarker).iLine);
+                OnVisibleRangeChanged();
+                Invalidate();
+                return;
+            }
+
+            if (marker is FoldedAreaMarker)
+            {
+                //select folded block
+                int iStart = (marker as FoldedAreaMarker).iLine;
+                int iEnd = FindEndOfFoldingBlock(iStart);
+                if (iEnd < 0)
+                    return;
+                Selection.BeginUpdate();
+                Selection.Start = new Place(0, iStart);
+                Selection.End = new Place(lines[iEnd].Count, iEnd);
+                Selection.EndUpdate();
+                Invalidate();
+                return;
+            }
+        }
+
+        protected virtual void OnMarkerDoubleClick(VisualMarker marker)
+        {
+            if (marker is FoldedAreaMarker)
+            {
+                ExpandFoldedBlock((marker as FoldedAreaMarker).iLine);
+                Invalidate();
+                return;
+            }
+        }
+
+        private void ClearBracketsPositions()
+        {
+            leftBracketPosition = null;
+            rightBracketPosition = null;
+            leftBracketPosition2 = null;
+            rightBracketPosition2 = null;
+        }
+
+        private void HighlightBrackets(char LeftBracket, char RightBracket, ref Range leftBracketPosition,
+                                       ref Range rightBracketPosition)
+        {
+            if (!Selection.IsEmpty)
+                return;
+            if (LinesCount == 0)
+                return;
+            //
+            Range oldLeftBracketPosition = leftBracketPosition;
+            Range oldRightBracketPosition = rightBracketPosition;
+            Range range = Selection.Clone(); //need clone because we will move caret
+            int counter = 0;
+            int maxIterations = maxBracketSearchIterations;
+            while (range.GoLeftThroughFolded()) //move caret left
+            {
+                if (range.CharAfterStart == LeftBracket) counter++;
+                if (range.CharAfterStart == RightBracket) counter--;
+                if (counter == 1)
+                {
+                    //highlighting
+                    range.End = new Place(range.Start.iChar + 1, range.Start.iLine);
+                    leftBracketPosition = range;
+                    break;
+                }
+                //
+                maxIterations--;
+                if (maxIterations <= 0) break;
+            }
+            //
+            range = Selection.Clone(); //need clone because we will move caret
+            counter = 0;
+            maxIterations = maxBracketSearchIterations;
+            do
+            {
+                if (range.CharAfterStart == LeftBracket) counter++;
+                if (range.CharAfterStart == RightBracket) counter--;
+                if (counter == -1)
+                {
+                    //highlighting
+                    range.End = new Place(range.Start.iChar + 1, range.Start.iLine);
+                    rightBracketPosition = range;
+                    break;
+                }
+                //
+                maxIterations--;
+                if (maxIterations <= 0) break;
+            } while (range.GoRightThroughFolded()); //move caret right
+
+            if (oldLeftBracketPosition != leftBracketPosition ||
+                oldRightBracketPosition != rightBracketPosition)
+                Invalidate();
+        }
+
+        public virtual void OnSyntaxHighlight(TextChangedEventArgs args)
+        {
+#if debug
+            Stopwatch sw = Stopwatch.StartNew();
+#endif
+
+            Range range;
+
+            switch (HighlightingRangeType)
+            {
+                case HighlightingRangeType.VisibleRange:
+                    range = VisibleRange.GetUnionWith(args.ChangedRange);
+                    break;
+                case HighlightingRangeType.AllTextRange:
+                    range = Range;
+                    break;
+                default:
+                    range = args.ChangedRange;
+                    break;
+            }
+
+            if (SyntaxHighlighter != null)
+            {
+                if (Language == Language.Custom && !string.IsNullOrEmpty(DescriptionFile))
+                    SyntaxHighlighter.HighlightSyntax(DescriptionFile, range);
+                else
+                    SyntaxHighlighter.HighlightSyntax(Language, range);
+            }
+
+#if debug
+            Debug.WriteLine("OnSyntaxHighlight: "+ sw.ElapsedMilliseconds);
+#endif
+        }
+
+        /// <summary>
+        /// Prints range of text
+        /// </summary>
+        public virtual void Print(Range range, PrintDialogSettings settings)
+        {
+            //prepare export with wordwrapping
+            var exporter = new ExportToHTML();
+            exporter.UseBr = true;
+            exporter.UseForwardNbsp = true;
+            exporter.UseNbsp = true;
+            exporter.UseStyleTag = false;
+            exporter.IncludeLineNumbers = settings.IncludeLineNumbers;
+
+            if (range == null)
+                range = this.Range;
+
+            if (range.Text == string.Empty)
+                return;
+
+            //change visible range
+            visibleRange = range;
+            try
+            {
+                //call handlers for VisibleRange
+                if (VisibleRangeChanged != null)
+                    VisibleRangeChanged(this, new EventArgs());
+                if (VisibleRangeChangedDelayed != null)
+                    VisibleRangeChangedDelayed(this, new EventArgs());
+            }
+            finally
+            {
+                //restore visible range
+                visibleRange = null;
+            }
+
+            //generate HTML
+            var HTML = exporter.GetHtml(range);
+            HTML = "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\"><head><title>" + PrepareHtmlText(settings.Title) + "</title></head>" + HTML + SelectHTMLRangeScript();
+            var tempFile = Path.GetTempPath() + "fctb.html";
+            File.WriteAllText(tempFile, HTML);
+
+            //clear wb page setup settings
+            SetPageSetupSettings(settings);
+
+            //create wb
+            var wb = new WebBrowser();
+            wb.Tag = settings;
+            wb.Visible = false;
+            wb.Location = new Point(-1000, -1000);
+            wb.Parent = this;
+            wb.StatusTextChanged += new EventHandler(wb_StatusTextChanged);
+            wb.Navigate(tempFile);
+        }
+
+        protected virtual string PrepareHtmlText(string s)
+        {
+            return s.Replace("<", "&lt;").Replace(">", "&gt;").Replace("&", "&amp;");
+        }
+
+        void wb_StatusTextChanged(object sender, EventArgs e)
+        {
+            var wb = sender as WebBrowser;
+            if (wb.StatusText.Contains("#print"))
+            {
+                var settings = wb.Tag as PrintDialogSettings;
+                try
+                {
+                    //show print dialog
+                    if (settings.ShowPrintPreviewDialog)
+                        wb.ShowPrintPreviewDialog();
+                    else
+                    {
+                        if (settings.ShowPageSetupDialog)
+                            wb.ShowPageSetupDialog();
+
+                        if (settings.ShowPrintDialog)
+                            wb.ShowPrintDialog();
+                        else
+                            wb.Print();
+                    }
+                }
+                finally
+                {
+                    //destroy webbrowser
+                    wb.Parent = null;
+                    wb.Dispose();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Prints all text
+        /// </summary>
+        public void Print(PrintDialogSettings settings)
+        {
+            Print(Range, settings);
+        }
+
+        /// <summary>
+        /// Prints all text, without any dialog windows
+        /// </summary>
+        public void Print()
+        {
+            Print(Range,
+                  new PrintDialogSettings
+                  { ShowPageSetupDialog = false, ShowPrintDialog = false, ShowPrintPreviewDialog = false });
+        }
+
+        private string SelectHTMLRangeScript()
+        {
+            var sel = Selection.Clone();
+            sel.Normalize();
+            var start = PlaceToPosition(sel.Start) - sel.Start.iLine;
+            var len = sel.Text.Length - (sel.End.iLine - sel.Start.iLine);
+            return string.Format(
+@"<script type=""text/javascript"">
+try{{
+    var sel = document.selection;
+    var rng = sel.createRange();
+    rng.moveStart(""character"", {0});
+    rng.moveEnd(""character"", {1});
+    rng.select();
+}}catch(ex){{}}
+window.status = ""#print"";
+</script>", start, len);
+        }
+
+        private static void SetPageSetupSettings(PrintDialogSettings settings)
+        {
+            var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Internet Explorer\PageSetup", true);
+            if (key != null)
+            {
+                key.SetValue("footer", settings.Footer);
+                key.SetValue("header", settings.Header);
+            }
+        }
+
+        //protected override void Dispose(bool disposing)
+        //{
+        //    base.Dispose(disposing);
+        //    if (disposing)
+        //    {
+        //        if (SyntaxHighlighter != null)
+        //            SyntaxHighlighter.Dispose();
+        //        timer.Dispose();
+        //        timer2.Dispose();
+
+        //        if (findForm != null)
+        //            findForm.Dispose();
+
+        //        if (replaceForm != null)
+        //            replaceForm.Dispose();
+
+        //        if (Font != null)
+        //            Font.Dispose();
+
+        //        if (TextSource != null)
+        //            TextSource.Dispose();
+        //    }
+        //}
+
+        protected virtual void OnPaintLine(PaintLineEventArgs e)
+        {
+            if (PaintLine != null)
+                PaintLine(this, e);
+        }
+
+        internal void OnLineInserted(int index)
+        {
+            OnLineInserted(index, 1);
+        }
+
+        internal void OnLineInserted(int index, int count)
+        {
+            if (LineInserted != null)
+                LineInserted(this, new LineInsertedEventArgs(index, count));
+        }
+
+        internal void OnLineRemoved(int index, int count, List<int> removedLineIds)
+        {
+            if (count > 0)
+                if (LineRemoved != null)
+                    LineRemoved(this, new LineRemovedEventArgs(index, count, removedLineIds));
+        }
+
+        /// <summary>
+        /// Open file binding mode
+        /// </summary>
+        /// <param name="fileName"></param>
+        /// <param name="enc"></param>
+        public void OpenBindingFile(string fileName, Encoding enc)
+        {
+            try
+            {
+                var fts = new FileTextSource(this);
+                InitTextSource(fts);
+                fts.OpenFile(fileName, enc);
+                IsChanged = false;
+                OnVisibleRangeChanged();
+            }
+            catch
+            {
+                InitTextSource(CreateTextSource());
+                lines.InsertLine(0, TextSource.CreateLine());
+                IsChanged = false;
+                throw;
+            }
+        }
+
+        /// <summary>
+        /// Close file binding mode
+        /// </summary>
+        public void CloseBindingFile()
+        {
+            if (lines is FileTextSource)
+            {
+                var fts = lines as FileTextSource;
+                fts.CloseFile();
+
+                InitTextSource(CreateTextSource());
+                lines.InsertLine(0, TextSource.CreateLine());
+                IsChanged = false;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Save text to the file
+        /// </summary>
+        /// <param name="fileName"></param>
+        /// <param name="enc"></param>
+        public void SaveToFile(string fileName, Encoding enc)
+        {
+            lines.SaveToFile(fileName, enc);
+            IsChanged = false;
+            OnVisibleRangeChanged();
+        }
+
+        /// <summary>
+        /// Set VisibleState of line
+        /// </summary>
+        public void SetVisibleState(int iLine, VisibleState state)
+        {
+            LineInfo li = lineInfos[iLine];
+            li.VisibleState = state;
+            lineInfos[iLine] = li;
+            needRecalc = true;
+        }
+
+        /// <summary>
+        /// Returns VisibleState of the line
+        /// </summary>
+        public VisibleState GetVisibleState(int iLine)
+        {
+            return lineInfos[iLine].VisibleState;
+        }
+
+        /// <summary>
+        /// Shows Goto dialog form
+        /// </summary>
+        public void ShowGoToDialog()
+        {
+            var form = new GoToForm();
+            form.TotalLineCount = LinesCount;
+            form.SelectedLineNumber = Selection.Start.iLine + 1;
+
+            if (form.ShowDialog() == DialogResult.OK)
+            {
+                int line = Math.Min(LinesCount - 1, Math.Max(0, form.SelectedLineNumber - 1));
+                Selection = new Range(this, 0, line, 0, line);
+                DoSelectionVisible();
+            }
+        }
+
+        /// <summary>
+        /// Occurs when undo/redo stack is changed
+        /// </summary>
+        public void OnUndoRedoStateChanged()
+        {
+            if (UndoRedoStateChanged != null)
+                UndoRedoStateChanged(this, EventArgs.Empty);
+        }
+
+        /// <summary>
+        /// Search lines by regex pattern
+        /// </summary>
+        public List<int> FindLines(string searchPattern, RegexOptions options)
+        {
+            List<int> iLines = new List<int>();
+            foreach (var r in Range.GetRangesByLines(searchPattern, options))
+                iLines.Add(r.Start.iLine);
+
+            return iLines;
+        }
+
+        /// <summary>
+        /// Removes given lines
+        /// </summary>
+        public void RemoveLines(List<int> iLines)
+        {
+            TextSource.Manager.ExecuteCommand(new RemoveLinesCommand(TextSource, iLines));
+            if (iLines.Count > 0)
+                IsChanged = true;
+            if (LinesCount == 0)
+                Text = "";
+            NeedRecalc();
+            Invalidate();
+        }
+
+        #region Drag and drop
+
+        private bool IsDragDrop { get; set; }
+
+        protected override void OnDragEnter(DragEventArgs e)
+        {
+            if (e.Data.GetDataPresent(DataFormats.Text))
+            {
+                e.Effect = DragDropEffects.Copy;
+                IsDragDrop = true;
+            }
+            base.OnDragEnter(e);
+        }
+
+        protected override void OnDragDrop(DragEventArgs e)
+        {
+            if (e.Data.GetDataPresent(DataFormats.Text))
+            {
+                if (ParentForm != null)
+                    ParentForm.Activate();
+                Focus();
+                var p = PointToClient(new Point(e.X, e.Y));
+                Selection.Start = PointToPlace(p);
+                InsertText(e.Data.GetData(DataFormats.Text).ToString());
+                IsDragDrop = false;
+            }
+            base.OnDragDrop(e);
+        }
+
+        protected override void OnDragOver(DragEventArgs e)
+        {
+            if (e.Data.GetDataPresent(DataFormats.Text))
+            {
+                var p = PointToClient(new Point(e.X, e.Y));
+                Selection.Start = PointToPlace(p);
+                Invalidate();
+            }
+            base.OnDragOver(e);
+        }
+
+        protected override void OnDragLeave(EventArgs e)
+        {
+            IsDragDrop = false;
+            base.OnDragLeave(e);
+        }
+
+        #endregion
+
+        #region Nested type: LineYComparer
+
+        private class LineYComparer : IComparer<LineInfo>
+        {
+            private readonly int Y;
+
+            public LineYComparer(int Y)
+            {
+                this.Y = Y;
+            }
+
+            #region IComparer<LineInfo> Members
+
+            public int Compare(LineInfo x, LineInfo y)
+            {
+                if (x.startY == -10)
+                    return -y.startY.CompareTo(Y);
+                else
+                    return x.startY.CompareTo(Y);
+            }
+
+            #endregion
+        }
+
+        #endregion
+
+
+    }
+
+
+    public class PaintLineEventArgs : PaintEventArgs
+    {
+        public PaintLineEventArgs(int iLine, Rectangle rect, Graphics gr, Rectangle clipRect) : base(gr, clipRect)
+        {
+            LineIndex = iLine;
+            LineRect = rect;
+        }
+
+        public int LineIndex { get; private set; }
+        public Rectangle LineRect { get; private set; }
+    }
+
+    public class LineInsertedEventArgs : EventArgs
+    {
+        public LineInsertedEventArgs(int index, int count)
+        {
+            Index = index;
+            Count = count;
+        }
+
+        /// <summary>
+        /// Inserted line index
+        /// </summary>
+        public int Index { get; private set; }
+
+        /// <summary>
+        /// Count of inserted lines
+        /// </summary>
+        public int Count { get; private set; }
+    }
+
+    public class LineRemovedEventArgs : EventArgs
+    {
+        public LineRemovedEventArgs(int index, int count, List<int> removedLineIds)
+        {
+            Index = index;
+            Count = count;
+            RemovedLineUniqueIds = removedLineIds;
+        }
+
+        /// <summary>
+        /// Removed line index
+        /// </summary>
+        public int Index { get; private set; }
+
+        /// <summary>
+        /// Count of removed lines
+        /// </summary>
+        public int Count { get; private set; }
+
+        /// <summary>
+        /// UniqueIds of removed lines
+        /// </summary>
+        public List<int> RemovedLineUniqueIds { get; private set; }
+    }
+
+    /// <summary>
+    /// TextChanged event argument
+    /// </summary>
+    public class TextChangedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        public TextChangedEventArgs(Range changedRange)
+        {
+            ChangedRange = changedRange;
+        }
+
+        /// <summary>
+        /// This range contains changed area of text
+        /// </summary>
+        public Range ChangedRange { get; set; }
+    }
+
+    public class TextChangingEventArgs : EventArgs
+    {
+        public string InsertingText { get; set; }
+        /// <summary>
+        /// Set to true if you want to cancel text inserting
+        /// </summary>
+        public bool Cancel { get; set; }
+    }
+
+    public enum WordWrapMode
+    {
+        /// <summary>
+        /// Word wrapping by control width
+        /// </summary>
+        WordWrapControlWidth,
+
+        /// <summary>
+        /// Word wrapping by preferred line width (PreferredLineWidth)
+        /// </summary>
+        WordWrapPreferredWidth,
+
+        /// <summary>
+        /// Char wrapping by control width
+        /// </summary>
+        CharWrapControlWidth,
+
+        /// <summary>
+        /// Char wrapping by preferred line width (PreferredLineWidth)
+        /// </summary>
+        CharWrapPreferredWidth
+    }
+
+    public class PrintDialogSettings
+    {
+        public bool ShowPageSetupDialog { get; set; }
+        public bool ShowPrintDialog { get; set; }
+        public bool ShowPrintPreviewDialog { get; set; }
+        /// <summary>
+        /// Title of page. If you want to print Title on the page, insert code &amp;w in Footer or Header.
+        /// </summary>
+        public string Title { get; set; }
+        /// <summary>
+        /// Footer of page.
+        /// Here you can use special codes: &amp;w (Window title), &amp;D, &amp;d (Date), &amp;t(), &amp;4 (Time), &amp;p (Current page number), &amp;P (Total number of pages),  &amp;&amp; (A single ampersand), &amp;b (Right justify text, Center text. If &amp;b occurs once, then anything after the &amp;b is right justified. If &amp;b occurs twice, then anything between the two &amp;b is centered, and anything after the second &amp;b is right justified).
+        /// More detailed see <see cref="http://msdn.microsoft.com/en-us/library/aa969429(v=vs.85).aspx">here</see>
+        /// </summary>
+        public string Footer { get; set; }
+        /// <summary>
+        /// Header of page
+        /// Here you can use special codes: &amp;w (Window title), &amp;D, &amp;d (Date), &amp;t(), &amp;4 (Time), &amp;p (Current page number), &amp;P (Total number of pages),  &amp;&amp; (A single ampersand), &amp;b (Right justify text, Center text. If &amp;b occurs once, then anything after the &amp;b is right justified. If &amp;b occurs twice, then anything between the two &amp;b is centered, and anything after the second &amp;b is right justified).
+        /// More detailed see <see cref="http://msdn.microsoft.com/en-us/library/aa969429(v=vs.85).aspx">here</see>
+        /// </summary>
+        public string Header { get; set; }
+
+        /// <summary>
+        /// Prints line numbers
+        /// </summary>
+        public bool IncludeLineNumbers { get; set; }
+
+        public PrintDialogSettings()
+        {
+            ShowPrintPreviewDialog = true;
+            Title = "";
+            Footer = "";
+            Header = "";
+            Footer = "";
+            Header = "";
+        }
+    }
+
+    public class AutoIndentEventArgs : EventArgs
+    {
+        public AutoIndentEventArgs(int iLine, string lineText, string prevLineText, int tabLength)
+        {
+            this.iLine = iLine;
+            LineText = lineText;
+            PrevLineText = prevLineText;
+            TabLength = tabLength;
+        }
+
+        public int iLine { get; internal set; }
+        public int TabLength { get; internal set; }
+        public string LineText { get; internal set; }
+        public string PrevLineText { get; internal set; }
+
+        /// <summary>
+        /// Additional spaces count for this line, relative to previous line
+        /// </summary>
+        public int Shift { get; set; }
+
+        /// <summary>
+        /// Additional spaces count for next line, relative to previous line
+        /// </summary>
+        public int ShiftNextLines { get; set; }
+    }
+
+    /// <summary>
+    /// Type of highlighting
+    /// </summary>
+    public enum HighlightingRangeType
+    {
+        /// <summary>
+        /// Highlight only changed range of text. Highest performance.
+        /// </summary>
+        ChangedRange,
+
+        /// <summary>
+        /// Highlight visible range of text. Middle performance.
+        /// </summary>
+        VisibleRange,
+
+        /// <summary>
+        /// Highlight all (visible and invisible) text. Lowest performance.
+        /// </summary>
+        AllTextRange
+    }
+
+    /// <summary>
+    /// Strategy of search of end of folding block
+    /// </summary>
+    public enum FindEndOfFoldingBlockStrategy
+    {
+        Strategy1,
+        Strategy2
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.resx b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FastColoredTextBox.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/LB_VisionControl/ScriptEditControl/FastColorTextBox/FileTextSource.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FileTextSource.cs
new file mode 100644
index 0000000..5e86327
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FileTextSource.cs
@@ -0,0 +1,411 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// This class contains the source text (chars and styles).
+    /// It stores a text lines, the manager of commands, undo/redo stack, styles.
+    /// </summary>
+    public class FileTextSource : TextSource, IDisposable
+    {
+        List<int> sourceFileLinePositions = new List<int>();
+        FileStream fs;
+        Encoding fileEncoding;
+        System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
+
+        /// <summary>
+        /// Occurs when need to display line in the textbox
+        /// </summary>
+        public event EventHandler<LineNeededEventArgs> LineNeeded;
+
+        /// <summary>
+        /// Occurs when need to save line in the file
+        /// </summary>
+        public event EventHandler<LinePushedEventArgs> LinePushed;
+
+        public FileTextSource(FastColoredTextBox currentTB)
+            : base(currentTB)
+        {
+            timer.Interval = 10000;
+            timer.Tick += new EventHandler(timer_Tick);
+            timer.Enabled = true;
+        }
+
+        void timer_Tick(object sender, EventArgs e)
+        {
+            timer.Enabled = false;
+            try
+            {
+                UnloadUnusedLines();
+            }
+            finally
+            {
+                timer.Enabled = true;
+            }
+        }
+
+        private void UnloadUnusedLines()
+        {
+            const int margin = 2000;
+            var iStartVisibleLine = CurrentTB.VisibleRange.Start.iLine;
+            var iFinishVisibleLine = CurrentTB.VisibleRange.End.iLine;
+
+            int count = 0;
+            for (int i = 0; i < Count; i++)
+                if (base.lines[i] != null && !base.lines[i].IsChanged && Math.Abs(i - iFinishVisibleLine) > margin)
+                {
+                    base.lines[i] = null;
+                    count++;
+                }
+#if debug
+            Debug.WriteLine("UnloadUnusedLines: " + count);
+#endif
+        }
+
+        public void OpenFile(string fileName, Encoding enc)
+        {
+            Clear();
+
+            if (fs != null)
+                fs.Dispose();
+
+            //read lines of file
+            fs = new FileStream(fileName, FileMode.Open);
+            var length = fs.Length;
+            //read signature
+            enc = DefineEncoding(enc, fs);
+            int shift = DefineShift(enc);
+            //first line
+            sourceFileLinePositions.Add((int)fs.Position);
+            base.lines.Add(null);
+            //other lines
+            while (fs.Position < length)
+            {
+                var b = fs.ReadByte();
+                if (b == 10)// char \n
+                {
+                    sourceFileLinePositions.Add((int)(fs.Position) + shift);
+                    base.lines.Add(null);
+                }
+            }
+
+            Line[] temp = new Line[100];
+            var c = base.lines.Count;
+            base.lines.AddRange(temp);
+            base.lines.TrimExcess();
+            base.lines.RemoveRange(c, temp.Length);
+
+
+            int[] temp2 = new int[100];
+            c = base.lines.Count;
+            sourceFileLinePositions.AddRange(temp2);
+            sourceFileLinePositions.TrimExcess();
+            sourceFileLinePositions.RemoveRange(c, temp.Length);
+
+
+            fileEncoding = enc;
+
+            OnLineInserted(0, Count);
+            //load first lines for calc width of the text
+            var linesCount = Math.Min(lines.Count, CurrentTB.Height / CurrentTB.CharHeight);
+            for (int i = 0; i < linesCount; i++)
+                LoadLineFromSourceFile(i);
+            //
+            NeedRecalc(new TextChangedEventArgs(0, 1));
+        }
+
+        private int DefineShift(Encoding enc)
+        {
+            if (enc.IsSingleByte)
+                return 0;
+
+            if (enc.HeaderName == "unicodeFFFE")
+                return 0;//UTF16 BE
+
+            if (enc.HeaderName == "utf-16")
+                return 1;//UTF16 LE
+
+            if (enc.HeaderName == "utf-32BE")
+                return 0;//UTF32 BE
+
+            if (enc.HeaderName == "utf-32")
+                return 3;//UTF32 LE
+
+            return 0;
+        }
+
+        private static Encoding DefineEncoding(Encoding enc, FileStream fs)
+        {
+            int bytesPerSignature = 0;
+            byte[] signature = new byte[4];
+            int c = fs.Read(signature, 0, 4);
+            if (signature[0] == 0xFF && signature[1] == 0xFE && signature[2] == 0x00 && signature[3] == 0x00 && c >= 4)
+            {
+                enc = Encoding.UTF32;//UTF32 LE
+                bytesPerSignature = 4;
+            }
+            else
+            if (signature[0] == 0x00 && signature[1] == 0x00 && signature[2] == 0xFE && signature[3] == 0xFF)
+            {
+                enc = new UTF32Encoding(true, true);//UTF32 BE
+                bytesPerSignature = 4;
+            }
+            else
+            if (signature[0] == 0xEF && signature[1] == 0xBB && signature[2] == 0xBF)
+            {
+                enc = Encoding.UTF8;//UTF8
+                bytesPerSignature = 3;
+            }
+            else
+            if (signature[0] == 0xFE && signature[1] == 0xFF)
+            {
+                enc = Encoding.BigEndianUnicode;//UTF16 BE
+                bytesPerSignature = 2;
+            }
+            else
+            if (signature[0] == 0xFF && signature[1] == 0xFE)
+            {
+                enc = Encoding.Unicode;//UTF16 LE
+                bytesPerSignature = 2;
+            }
+
+            fs.Seek(bytesPerSignature, SeekOrigin.Begin);
+
+            return enc;
+        }
+
+        public void CloseFile()
+        {
+            if (fs != null)
+                fs.Dispose();
+            fs = null;
+        }
+
+        public override void SaveToFile(string fileName, Encoding enc)
+        {
+            //
+            var newLinePos = new List<int>(Count);
+            //create temp file
+            var dir = Path.GetDirectoryName(fileName);
+            var tempFileName = Path.Combine(dir, Path.GetFileNameWithoutExtension(fileName) + ".tmp");
+
+            StreamReader sr = new StreamReader(fs, fileEncoding);
+            using (FileStream tempFs = new FileStream(tempFileName, FileMode.Create))
+            using (StreamWriter sw = new StreamWriter(tempFs, enc))
+            {
+                sw.Flush();
+
+                for (int i = 0; i < Count; i++)
+                {
+                    newLinePos.Add((int)tempFs.Length);
+
+                    var sourceLine = ReadLine(sr, i);//read line from source file
+                    string line;
+
+                    bool lineIsChanged = lines[i] != null && lines[i].IsChanged;
+
+                    if (lineIsChanged)
+                        line = lines[i].Text;
+                    else
+                        line = sourceLine;
+
+                    //call event handler
+                    if (LinePushed != null)
+                    {
+                        var args = new LinePushedEventArgs(sourceLine, i, lineIsChanged ? line : null);
+                        LinePushed(this, args);
+
+                        if (args.SavedText != null)
+                            line = args.SavedText;
+                    }
+
+                    //save line to file
+                    if (i == Count - 1)
+                        sw.Write(line);
+                    else
+                        sw.WriteLine(line);
+
+                    sw.Flush();
+                }
+            }
+
+            //clear lines buffer
+            for (int i = 0; i < Count; i++)
+                lines[i] = null;
+            //deattach from source file
+            sr.Dispose();
+            fs.Dispose();
+            //delete target file
+            if (File.Exists(fileName))
+                File.Delete(fileName);
+            //rename temp file
+            File.Move(tempFileName, fileName);
+
+            //binding to new file
+            sourceFileLinePositions = newLinePos;
+            fs = new FileStream(fileName, FileMode.Open);
+            this.fileEncoding = enc;
+        }
+
+        private string ReadLine(StreamReader sr, int i)
+        {
+            string line;
+            var filePos = sourceFileLinePositions[i];
+            if (filePos < 0)
+                return "";
+            fs.Seek(filePos, SeekOrigin.Begin);
+            sr.DiscardBufferedData();
+            line = sr.ReadLine();
+            return line;
+        }
+
+        public override void ClearIsChanged()
+        {
+            foreach (var line in lines)
+                if (line != null)
+                    line.IsChanged = false;
+        }
+
+        public override Line this[int i]
+        {
+            get
+            {
+                if (base.lines[i] != null)
+                    return lines[i];
+                else
+                    LoadLineFromSourceFile(i);
+
+                return lines[i];
+            }
+            set
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        private void LoadLineFromSourceFile(int i)
+        {
+            var line = CreateLine();
+            fs.Seek(sourceFileLinePositions[i], SeekOrigin.Begin);
+            StreamReader sr = new StreamReader(fs, fileEncoding);
+
+            var s = sr.ReadLine();
+            if (s == null)
+                s = "";
+
+            //call event handler
+            if (LineNeeded != null)
+            {
+                var args = new LineNeededEventArgs(s, i);
+                LineNeeded(this, args);
+                s = args.DisplayedLineText;
+                if (s == null)
+                    return;
+            }
+
+            foreach (var c in s)
+                line.Add(new Char(c));
+            base.lines[i] = line;
+        }
+
+        public override void InsertLine(int index, Line line)
+        {
+            sourceFileLinePositions.Insert(index, -1);
+            base.InsertLine(index, line);
+        }
+
+        public override void RemoveLine(int index, int count)
+        {
+            sourceFileLinePositions.RemoveRange(index, count);
+            base.RemoveLine(index, count);
+        }
+
+        public override void Clear()
+        {
+            base.Clear();
+        }
+
+        public override int GetLineLength(int i)
+        {
+            if (base.lines[i] == null)
+                return 0;
+            else
+                return base.lines[i].Count;
+        }
+
+        public override bool LineHasFoldingStartMarker(int iLine)
+        {
+            if (lines[iLine] == null)
+                return false;
+            else
+                return !string.IsNullOrEmpty(lines[iLine].FoldingStartMarker);
+        }
+
+        public override bool LineHasFoldingEndMarker(int iLine)
+        {
+            if (lines[iLine] == null)
+                return false;
+            else
+                return !string.IsNullOrEmpty(lines[iLine].FoldingEndMarker);
+        }
+
+        public void Dispose()
+        {
+            if (fs != null)
+                fs.Dispose();
+
+            timer.Dispose();
+        }
+
+        internal void UnloadLine(int iLine)
+        {
+            if (lines[iLine] != null && !lines[iLine].IsChanged)
+                lines[iLine] = null;
+        }
+    }
+
+    public class LineNeededEventArgs : EventArgs
+    {
+        public string SourceLineText { get; private set; }
+        public int DisplayedLineIndex { get; private set; }
+        /// <summary>
+        /// This text will be displayed in textbox
+        /// </summary>
+        public string DisplayedLineText { get; set; }
+
+        public LineNeededEventArgs(string sourceLineText, int displayedLineIndex)
+        {
+            this.SourceLineText = sourceLineText;
+            this.DisplayedLineIndex = displayedLineIndex;
+            this.DisplayedLineText = sourceLineText;
+        }
+    }
+
+    public class LinePushedEventArgs : EventArgs
+    {
+        public string SourceLineText { get; private set; }
+        public int DisplayedLineIndex { get; private set; }
+        /// <summary>
+        /// This property contains only changed text.
+        /// If text of line is not changed, this property contains null.
+        /// </summary>
+        public string DisplayedLineText { get; private set; }
+        /// <summary>
+        /// This text will be saved in the file
+        /// </summary>
+        public string SavedText { get; set; }
+
+        public LinePushedEventArgs(string sourceLineText, int displayedLineIndex, string displayedLineText)
+        {
+            this.SourceLineText = sourceLineText;
+            this.DisplayedLineIndex = displayedLineIndex;
+            this.DisplayedLineText = displayedLineText;
+            this.SavedText = displayedLineText;
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.Designer.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.Designer.cs
new file mode 100644
index 0000000..4b833d7
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.Designer.cs
@@ -0,0 +1,215 @@
+锘縩amespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    partial class FindForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FindForm));
+            theme_FindForm = new ReaLTaiizor.Forms.ThemeForm();
+            btn_Close = new ReaLTaiizor.Controls.Button();
+            btn_FindNext = new ReaLTaiizor.Controls.Button();
+            cbRegex = new ReaLTaiizor.Controls.CheckBox();
+            cbWholeWord = new ReaLTaiizor.Controls.CheckBox();
+            cbMatchCase = new ReaLTaiizor.Controls.CheckBox();
+            txt_Find = new ReaLTaiizor.Controls.AloneTextBox();
+            lb_Find = new ReaLTaiizor.Controls.BigLabel();
+            theme_FindForm.SuspendLayout();
+            SuspendLayout();
+            // 
+            // theme_FindForm
+            // 
+            theme_FindForm.BackColor = Color.FromArgb(32, 41, 50);
+            theme_FindForm.Controls.Add(btn_Close);
+            theme_FindForm.Controls.Add(btn_FindNext);
+            theme_FindForm.Controls.Add(cbRegex);
+            theme_FindForm.Controls.Add(cbWholeWord);
+            theme_FindForm.Controls.Add(cbMatchCase);
+            theme_FindForm.Controls.Add(txt_Find);
+            theme_FindForm.Controls.Add(lb_Find);
+            theme_FindForm.Dock = DockStyle.Fill;
+            theme_FindForm.Font = new Font("Microsoft Sans Serif", 9F);
+            theme_FindForm.Image = (Image)resources.GetObject("theme_FindForm.Image");
+            theme_FindForm.Location = new Point(0, 0);
+            theme_FindForm.Name = "theme_FindForm";
+            theme_FindForm.Padding = new Padding(10, 70, 10, 9);
+            theme_FindForm.RoundCorners = true;
+            theme_FindForm.Sizable = true;
+            theme_FindForm.Size = new Size(436, 227);
+            theme_FindForm.SmartBounds = true;
+            theme_FindForm.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            theme_FindForm.TabIndex = 0;
+            theme_FindForm.Text = "鏌ユ壘";
+            // 
+            // btn_Close
+            // 
+            btn_Close.BackColor = Color.Transparent;
+            btn_Close.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_Close.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Close.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_Close.Font = new Font("Microsoft Sans Serif", 12F);
+            btn_Close.Image = null;
+            btn_Close.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_Close.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_Close.Location = new Point(304, 175);
+            btn_Close.Name = "btn_Close";
+            btn_Close.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Close.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_Close.Size = new Size(120, 40);
+            btn_Close.TabIndex = 4;
+            btn_Close.Text = "鍏抽棴";
+            btn_Close.TextAlignment = StringAlignment.Center;
+            btn_Close.Click += btn_Close_Click;
+            // 
+            // btn_FindNext
+            // 
+            btn_FindNext.BackColor = Color.Transparent;
+            btn_FindNext.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_FindNext.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_FindNext.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_FindNext.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            btn_FindNext.Image = null;
+            btn_FindNext.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_FindNext.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_FindNext.Location = new Point(156, 175);
+            btn_FindNext.Name = "btn_FindNext";
+            btn_FindNext.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_FindNext.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_FindNext.Size = new Size(120, 40);
+            btn_FindNext.TabIndex = 4;
+            btn_FindNext.Text = "鏌ユ壘涓嬩竴涓�";
+            btn_FindNext.TextAlignment = StringAlignment.Center;
+            btn_FindNext.Click += btn_FindNext_Click;
+            // 
+            // cbRegex
+            // 
+            cbRegex.Checked = false;
+            cbRegex.CheckedBackColor = Color.FromArgb(66, 76, 85);
+            cbRegex.CheckedBorderColor = Color.FromArgb(66, 76, 85);
+            cbRegex.CheckedDisabledColor = Color.Gray;
+            cbRegex.CheckedEnabledColor = Color.FromArgb(32, 34, 37);
+            cbRegex.Enable = true;
+            cbRegex.Font = new Font("Microsoft YaHei UI", 9F);
+            cbRegex.ForeColor = SystemColors.Control;
+            cbRegex.Location = new Point(276, 121);
+            cbRegex.Name = "cbRegex";
+            cbRegex.Size = new Size(85, 16);
+            cbRegex.TabIndex = 3;
+            cbRegex.Text = "姝e垯鍖归厤";
+            cbRegex.CheckedChanged += cbRegex_CheckedChanged;
+            // 
+            // cbWholeWord
+            // 
+            cbWholeWord.Checked = false;
+            cbWholeWord.CheckedBackColor = Color.FromArgb(66, 76, 85);
+            cbWholeWord.CheckedBorderColor = Color.FromArgb(66, 76, 85);
+            cbWholeWord.CheckedDisabledColor = Color.Gray;
+            cbWholeWord.CheckedEnabledColor = Color.FromArgb(32, 34, 37);
+            cbWholeWord.Enable = true;
+            cbWholeWord.Font = new Font("Microsoft YaHei UI", 9F);
+            cbWholeWord.ForeColor = SystemColors.Control;
+            cbWholeWord.Location = new Point(174, 121);
+            cbWholeWord.Name = "cbWholeWord";
+            cbWholeWord.Size = new Size(85, 16);
+            cbWholeWord.TabIndex = 3;
+            cbWholeWord.Text = "鍏ㄦ枃鍖归厤";
+            cbWholeWord.CheckedChanged += cbWholeWord_CheckedChanged;
+            // 
+            // cbMatchCase
+            // 
+            cbMatchCase.Checked = false;
+            cbMatchCase.CheckedBackColor = Color.FromArgb(66, 76, 85);
+            cbMatchCase.CheckedBorderColor = Color.FromArgb(66, 76, 85);
+            cbMatchCase.CheckedDisabledColor = Color.Gray;
+            cbMatchCase.CheckedEnabledColor = Color.FromArgb(32, 34, 37);
+            cbMatchCase.Enable = true;
+            cbMatchCase.Font = new Font("Microsoft YaHei UI", 9F);
+            cbMatchCase.ForeColor = SystemColors.Control;
+            cbMatchCase.Location = new Point(72, 121);
+            cbMatchCase.Name = "cbMatchCase";
+            cbMatchCase.Size = new Size(85, 16);
+            cbMatchCase.TabIndex = 3;
+            cbMatchCase.Text = "閮ㄥ垎鍖归厤";
+            cbMatchCase.CheckedChanged += cbMatchCase_CheckedChanged;
+            // 
+            // txt_Find
+            // 
+            txt_Find.BackColor = Color.Transparent;
+            txt_Find.EnabledCalc = true;
+            txt_Find.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            txt_Find.ForeColor = Color.FromArgb(124, 133, 142);
+            txt_Find.Location = new Point(67, 73);
+            txt_Find.MaxLength = 32767;
+            txt_Find.MultiLine = false;
+            txt_Find.Name = "txt_Find";
+            txt_Find.ReadOnly = false;
+            txt_Find.Size = new Size(356, 29);
+            txt_Find.TabIndex = 2;
+            txt_Find.TextAlign = HorizontalAlignment.Left;
+            txt_Find.UseSystemPasswordChar = false;
+            txt_Find.KeyPress += txt_Find_KeyPress;
+            // 
+            // lb_Find
+            // 
+            lb_Find.AutoSize = true;
+            lb_Find.BackColor = Color.Transparent;
+            lb_Find.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            lb_Find.ForeColor = Color.White;
+            lb_Find.Location = new Point(13, 81);
+            lb_Find.Name = "lb_Find";
+            lb_Find.Size = new Size(58, 21);
+            lb_Find.TabIndex = 1;
+            lb_Find.Text = "鏌ユ壘锛�";
+            // 
+            // FindForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(436, 227);
+            Controls.Add(theme_FindForm);
+            FormBorderStyle = FormBorderStyle.None;
+            MinimumSize = new Size(261, 61);
+            Name = "FindForm";
+            Text = "鏌ユ壘";
+            TransparencyKey = Color.Fuchsia;
+            FormClosing += FindForm_FormClosing;
+            theme_FindForm.ResumeLayout(false);
+            theme_FindForm.PerformLayout();
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ReaLTaiizor.Forms.ThemeForm theme_FindForm;
+        public ReaLTaiizor.Controls.AloneTextBox txt_Find;
+        private ReaLTaiizor.Controls.BigLabel lb_Find;
+        private ReaLTaiizor.Controls.CheckBox cbRegex;
+        private ReaLTaiizor.Controls.CheckBox cbWholeWord;
+        private ReaLTaiizor.Controls.CheckBox cbMatchCase;
+        private ReaLTaiizor.Controls.Button btn_Close;
+        private ReaLTaiizor.Controls.Button btn_FindNext;
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.cs
new file mode 100644
index 0000000..42859c6
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.cs
@@ -0,0 +1,135 @@
+锘縰sing Sunny.UI;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    public partial class FindForm : Form
+    {
+        bool firstSearch = true;
+        Place startPlace;
+        FastColoredTextBox tb;
+
+        public FindForm(FastColoredTextBox tb)
+        {
+            InitializeComponent();
+            this.tb = tb;
+        }
+        private void btn_Close_Click(object sender, EventArgs e)
+        {
+            Close();
+        }
+
+        public void FindNext(string pattern)
+        {
+            try
+            {
+                RegexOptions opt = cbMatchCase.Checked ? RegexOptions.None : RegexOptions.IgnoreCase;
+                if (!cbRegex.Checked)
+                    pattern = Regex.Escape(pattern);
+                if (cbWholeWord.Checked)
+                    pattern = "\\b" + pattern + "\\b";
+                //
+                Range range = tb.Selection.Clone();
+                range.Normalize();
+                //
+                if (firstSearch)
+                {
+                    startPlace = range.Start;
+                    firstSearch = false;
+                }
+                //
+                range.Start = range.End;
+                if (range.Start >= startPlace)
+                    range.End = new Place(tb.GetLineLength(tb.LinesCount - 1), tb.LinesCount - 1);
+                else
+                    range.End = startPlace;
+                //
+                foreach (var r in range.GetRangesByLines(pattern, opt))
+                {
+                    tb.Selection = r;
+                    tb.DoSelectionVisible();
+                    tb.Invalidate();
+                    return;
+                }
+                //
+                if (range.Start >= startPlace && startPlace > Place.Empty)
+                {
+                    tb.Selection.Start = new Place(0, 0);
+                    FindNext(pattern);
+                    return;
+                }
+            }
+            catch { }
+        }
+
+        private void txt_Find_KeyPress(object sender, KeyPressEventArgs e)
+        {
+            if (e.KeyChar == '\r')
+            {
+                btn_FindNext_Click(null, null);
+                e.Handled = true;
+                return;
+            }
+            if (e.KeyChar == '\x1b')
+            {
+                Hide();
+                e.Handled = true;
+                return;
+            }
+        }
+
+        private void FindForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            if (e.CloseReason == CloseReason.UserClosing)
+            {
+                e.Cancel = true;
+                Hide();
+            }
+        }
+
+        protected override void OnActivated(EventArgs e)
+        {
+            txt_Find.Focus();
+            ResetSerach();
+        }
+
+        void ResetSerach()
+        {
+            firstSearch = true;
+        }
+
+        private void cbMatchCase_CheckedChanged(object sender, EventArgs e)
+        {
+            ResetSerach();
+        }
+
+        private void cbRegex_CheckedChanged(object sender)
+        {
+            ResetSerach();
+        }
+
+        private void cbWholeWord_CheckedChanged(object sender)
+        {
+            ResetSerach();
+        }
+
+        private void cbMatchCase_CheckedChanged(object sender)
+        {
+            ResetSerach();
+        }
+
+        private void btn_FindNext_Click(object sender, EventArgs e)
+        {
+            FindNext(txt_Find.Text);
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.resx b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.resx
new file mode 100644
index 0000000..aaff337
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/FindForm.resx
@@ -0,0 +1,144 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="theme_FindForm.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        vAAADrwBlbxySQAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
+        BkVBUPCBCEG8BXNQ48GLeImCehIJxMsqhsSZruod46K4HtSIGjU+4iOr0c1I9fSsM3/PLNtCPO0H36m/
+        evz/X11VnreKVRTAHPOZumkY6lFwqURws3BwZ8ywTQnuiCP/+iTCzY1qaUPzdm/Atf3PaHre6XPsjyQM
+        2xLGV4XwIyX4QRj+UMK/lPFvJTyhBMeV8IgQvmRJuH4Ko+l5p9UjGBbCJ5RxTgj+VMZmXxKcSAjekHE/
+        NNs5DgaTKLinEQYVO4Trf1mkV81wixLUslPmA3bzF2XcKeP+hWY/u3n0fCXcrQwLyjAvjNsb1dI6N05P
+        mFAIHlHG73sEypPgGwnhfpn0zzH7jzddcK4Q7kqfKNMI4a9K+MwBDgbdeF04MBWsFYYdQvhbLlBvfhKT
+        f+vMtLfG7C0JJXxKGY67WnvCmPAFGRs7z42boul5AzHBfdK6TjdQtzPGk8oos5F/5Y7sfVvPhg+lp+1h
+        0yIsxARPmtaN78WEl8eEX+SNclxUhne0glUrNrN9zfMGlPAuZTzaQ99FYfwuDv3ruoLvq5bWaQSvZCfL
+        GXUYLwrj240Qxtu2lkSN4FpdWfKZH9jb9RQ1Cq62f9sVOlxUxn3KQXnJ0PO8QxU/jBm1h74v7ZniEG9K
+        Hdg/quzvXO709k0Y3u08ucGqWgheX862H4XgxbR47SqU8D1X0EXC2VmGizqDz0xPr0kYH9eO360gNe0b
+        jWppozB+1kOQEb5MCLa0C64NoeGrhOGrvH6lhK81GiIvnggmrDLzgvTkvwvDA+5wsU4nhG/m9AUoBD/F
+        HFzWN4H0XQn2vF8eXN8Z3FAPYasl59oUYjuB+sTImDB+nhfgYQ39STf4fmu1DHtz+oIUgiM1KkWtwcFw
+        sOujVT3hrnaL7UQc+hcL5W+sKIXhw0OVjaW0iwnBc47gqIQ45QY32PKRzv8eTguRYM9SS5YouEEZjv37
+        EffbzbjBDdZyxZYQ12EB2qS0bWrJqRVazPDWkojwZbuZrsgZtDJ0iY1g12khEtTicMTvclwn2CKE32YJ
+        7G5PORfZ1HtMCH7MOV4BrQ3XCe92+4onk5Nn2PolDAvWXnuOzAwzo6Nnx4Q3SrojwqfKeMxWMpsXWVs+
+        2WrfKRdbW1W6Hf0shM/33Y7my4PrleFZIfhAaWjU/e5ivlw+y3S2FySMtynjvcrwsFiLJv/RhPBB2ws1
+        hK2WcBLBFf1qawlplwvxaQlxe786OOU4PBWsjSO85mBlQ8n99r/BisSdAas4FfgHpdEUZpwUX7sAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.Designer.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.Designer.cs
new file mode 100644
index 0000000..cc56de4
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.Designer.cs
@@ -0,0 +1,151 @@
+锘縩amespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    partial class GoToForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(GoToForm));
+            themeForm1 = new ReaLTaiizor.Forms.ThemeForm();
+            btn_Cancel = new ReaLTaiizor.Controls.Button();
+            btn_OK = new ReaLTaiizor.Controls.Button();
+            txt_LineInput = new ReaLTaiizor.Controls.AloneTextBox();
+            lb_LineInput = new ReaLTaiizor.Controls.BigLabel();
+            themeForm1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // themeForm1
+            // 
+            themeForm1.BackColor = Color.FromArgb(32, 41, 50);
+            themeForm1.Controls.Add(btn_Cancel);
+            themeForm1.Controls.Add(btn_OK);
+            themeForm1.Controls.Add(txt_LineInput);
+            themeForm1.Controls.Add(lb_LineInput);
+            themeForm1.Dock = DockStyle.Fill;
+            themeForm1.Font = new Font("Microsoft YaHei UI", 12F);
+            themeForm1.Image = (Image)resources.GetObject("themeForm1.Image");
+            themeForm1.Location = new Point(0, 0);
+            themeForm1.Name = "themeForm1";
+            themeForm1.Padding = new Padding(10, 70, 10, 9);
+            themeForm1.RoundCorners = true;
+            themeForm1.Sizable = true;
+            themeForm1.Size = new Size(400, 210);
+            themeForm1.SmartBounds = true;
+            themeForm1.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            themeForm1.TabIndex = 0;
+            themeForm1.Text = "琛�";
+            // 
+            // btn_Cancel
+            // 
+            btn_Cancel.BackColor = Color.Transparent;
+            btn_Cancel.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_Cancel.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Cancel.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_Cancel.Font = new Font("Microsoft YaHei UI", 12F);
+            btn_Cancel.Image = null;
+            btn_Cancel.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_Cancel.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_Cancel.Location = new Point(271, 162);
+            btn_Cancel.Name = "btn_Cancel";
+            btn_Cancel.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Cancel.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_Cancel.Size = new Size(120, 40);
+            btn_Cancel.TabIndex = 3;
+            btn_Cancel.Text = "鍙栨秷";
+            btn_Cancel.TextAlignment = StringAlignment.Center;
+            // 
+            // btn_OK
+            // 
+            btn_OK.BackColor = Color.Transparent;
+            btn_OK.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_OK.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_OK.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_OK.Font = new Font("Microsoft YaHei UI", 12F);
+            btn_OK.Image = null;
+            btn_OK.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_OK.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_OK.Location = new Point(138, 162);
+            btn_OK.Name = "btn_OK";
+            btn_OK.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_OK.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_OK.Size = new Size(120, 40);
+            btn_OK.TabIndex = 2;
+            btn_OK.Text = "纭畾";
+            btn_OK.TextAlignment = StringAlignment.Center;
+            // 
+            // txt_LineInput
+            // 
+            txt_LineInput.BackColor = Color.Transparent;
+            txt_LineInput.EnabledCalc = true;
+            txt_LineInput.Font = new Font("Microsoft YaHei UI", 12F);
+            txt_LineInput.ForeColor = Color.FromArgb(124, 133, 142);
+            txt_LineInput.Location = new Point(8, 110);
+            txt_LineInput.MaxLength = 32767;
+            txt_LineInput.MultiLine = false;
+            txt_LineInput.Name = "txt_LineInput";
+            txt_LineInput.ReadOnly = false;
+            txt_LineInput.Size = new Size(380, 46);
+            txt_LineInput.TabIndex = 1;
+            txt_LineInput.TextAlign = HorizontalAlignment.Left;
+            txt_LineInput.UseSystemPasswordChar = false;
+            // 
+            // lb_LineInput
+            // 
+            lb_LineInput.AutoSize = true;
+            lb_LineInput.BackColor = Color.Transparent;
+            lb_LineInput.Font = new Font("Microsoft YaHei UI", 12F);
+            lb_LineInput.ForeColor = Color.White;
+            lb_LineInput.Location = new Point(8, 73);
+            lb_LineInput.Name = "lb_LineInput";
+            lb_LineInput.Size = new Size(86, 21);
+            lb_LineInput.TabIndex = 0;
+            lb_LineInput.Text = "琛屽彿 (1/1):";
+            // 
+            // GoToForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(400, 210);
+            Controls.Add(themeForm1);
+            FormBorderStyle = FormBorderStyle.None;
+            MinimumSize = new Size(261, 61);
+            Name = "GoToForm";
+            Text = "琛�";
+            TransparencyKey = Color.Fuchsia;
+            themeForm1.ResumeLayout(false);
+            themeForm1.PerformLayout();
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ReaLTaiizor.Forms.ThemeForm themeForm1;
+        private ReaLTaiizor.Controls.Button btn_Cancel;
+        private ReaLTaiizor.Controls.Button btn_OK;
+        private ReaLTaiizor.Controls.AloneTextBox txt_LineInput;
+        private ReaLTaiizor.Controls.BigLabel lb_LineInput;
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.cs
new file mode 100644
index 0000000..66673dc
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.cs
@@ -0,0 +1,29 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    public partial class GoToForm : Form
+    {
+        public int SelectedLineNumber { get; set; }
+        public int TotalLineCount { get; set; }
+
+        public GoToForm()
+        {
+            InitializeComponent();
+        }
+        protected override void OnLoad(EventArgs e)
+        {
+            base.OnLoad(e);
+            this.lb_LineInput.Text = String.Format("Line number (1 - {0}):", this.TotalLineCount);
+            this.txt_LineInput.DataBindings.Add("Text", this, "SelectedLineNumber", true, DataSourceUpdateMode.OnPropertyChanged);
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.resx b/LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.resx
new file mode 100644
index 0000000..9ca1331
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/GoToForm.resx
@@ -0,0 +1,144 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="themeForm1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        wgAADsIBFShKgAAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
+        BkVBUPCBCEG8BXNQ48GLeImCehIJxMsqhsSZruod46K4HtSIGjU+4iOr0c1I9fSsM3/PLNtCPO0H36m/
+        evz/X11VnreKVRTAHPOZumkY6lFwqURws3BwZ8ywTQnuiCP/+iTCzY1qaUPzdm/Atf3PaHre6XPsjyQM
+        2xLGV4XwIyX4QRj+UMK/lPFvJTyhBMeV8IgQvmRJuH4Ko+l5p9UjGBbCJ5RxTgj+VMZmXxKcSAjekHE/
+        NNs5DgaTKLinEQYVO4Trf1mkV81wixLUslPmA3bzF2XcKeP+hWY/u3n0fCXcrQwLyjAvjNsb1dI6N05P
+        mFAIHlHG73sEypPgGwnhfpn0zzH7jzddcK4Q7kqfKNMI4a9K+MwBDgbdeF04MBWsFYYdQvhbLlBvfhKT
+        f+vMtLfG7C0JJXxKGY67WnvCmPAFGRs7z42boul5AzHBfdK6TjdQtzPGk8oos5F/5Y7sfVvPhg+lp+1h
+        0yIsxARPmtaN78WEl8eEX+SNclxUhne0glUrNrN9zfMGlPAuZTzaQ99FYfwuDv3ruoLvq5bWaQSvZCfL
+        GXUYLwrj240Qxtu2lkSN4FpdWfKZH9jb9RQ1Cq62f9sVOlxUxn3KQXnJ0PO8QxU/jBm1h74v7ZniEG9K
+        Hdg/quzvXO709k0Y3u08ucGqWgheX862H4XgxbR47SqU8D1X0EXC2VmGizqDz0xPr0kYH9eO360gNe0b
+        jWppozB+1kOQEb5MCLa0C64NoeGrhOGrvH6lhK81GiIvnggmrDLzgvTkvwvDA+5wsU4nhG/m9AUoBD/F
+        HFzWN4H0XQn2vF8eXN8Z3FAPYasl59oUYjuB+sTImDB+nhfgYQ39STf4fmu1DHtz+oIUgiM1KkWtwcFw
+        sOujVT3hrnaL7UQc+hcL5W+sKIXhw0OVjaW0iwnBc47gqIQ45QY32PKRzv8eTguRYM9SS5YouEEZjv37
+        EffbzbjBDdZyxZYQ12EB2qS0bWrJqRVazPDWkojwZbuZrsgZtDJ0iY1g12khEtTicMTvclwn2CKE32YJ
+        7G5PORfZ1HtMCH7MOV4BrQ3XCe92+4onk5Nn2PolDAvWXnuOzAwzo6Nnx4Q3SrojwqfKeMxWMpsXWVs+
+        2WrfKRdbW1W6Hf0shM/33Y7my4PrleFZIfhAaWjU/e5ivlw+y3S2FySMtynjvcrwsFiLJv/RhPBB2ws1
+        hK2WcBLBFf1qawlplwvxaQlxe786OOU4PBWsjSO85mBlQ8n99r/BisSdAas4FfgHpdEUZpwUX7sAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/LimitedStack.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/LimitedStack.cs
new file mode 100644
index 0000000..99e74d2
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/LimitedStack.cs
@@ -0,0 +1,109 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// Limited stack
+    /// </summary>
+    public class LimitedStack<T>
+    {
+        T[] items;
+        int count;
+        int start;
+
+        /// <summary>
+        /// Max stack length
+        /// </summary>
+        public int MaxItemCount
+        {
+            get { return items.Length; }
+        }
+
+        /// <summary>
+        /// Current length of stack
+        /// </summary>
+        public int Count
+        {
+            get { return count; }
+        }
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="maxItemCount">Maximum length of stack</param>
+        public LimitedStack(int maxItemCount)
+        {
+            items = new T[maxItemCount];
+            count = 0;
+            start = 0;
+        }
+
+        /// <summary>
+        /// Pop item
+        /// </summary>
+        public T Pop()
+        {
+            if (count == 0)
+                throw new Exception("Stack is empty");
+
+            int i = LastIndex;
+            T item = items[i];
+            items[i] = default(T);
+
+            count--;
+
+            return item;
+        }
+
+        int LastIndex
+        {
+            get { return (start + count - 1) % items.Length; }
+        }
+
+        /// <summary>
+        /// Peek item
+        /// </summary>
+        public T Peek()
+        {
+            if (count == 0)
+                return default(T);
+
+            return items[LastIndex];
+        }
+
+        /// <summary>
+        /// Push item
+        /// </summary>
+        public void Push(T item)
+        {
+            if (count == items.Length)
+                start = (start + 1) % items.Length;
+            else
+                count++;
+
+            items[LastIndex] = item;
+        }
+
+        /// <summary>
+        /// Clear stack
+        /// </summary>
+        public void Clear()
+        {
+            items = new T[items.Length];
+            count = 0;
+            start = 0;
+        }
+
+        public T[] ToArray()
+        {
+            T[] result = new T[count];
+            for (int i = 0; i < count; i++)
+                result[i] = items[(start + i) % items.Length];
+            return result;
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/Line.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Line.cs
new file mode 100644
index 0000000..81bb7e2
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Line.cs
@@ -0,0 +1,356 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// Line of text
+    /// </summary>
+    public class Line : IList<Char>
+    {
+        protected List<Char> chars;
+
+        public string FoldingStartMarker { get; set; }
+        public string FoldingEndMarker { get; set; }
+        /// <summary>
+        /// Text of line was changed
+        /// </summary>
+        public bool IsChanged { get; set; }
+        /// <summary>
+        /// Time of last visit of caret in this line
+        /// </summary>
+        /// <remarks>This property can be used for forward/backward navigating</remarks>
+        public DateTime LastVisit { get; set; }
+        /// <summary>
+        /// Background brush.
+        /// </summary>
+        public Brush BackgroundBrush { get; set; }
+        /// <summary>
+        /// Unique ID
+        /// </summary>
+        public int UniqueId { get; private set; }
+        /// <summary>
+        /// Count of needed start spaces for AutoIndent
+        /// </summary>
+        public int AutoIndentSpacesNeededCount
+        {
+            get;
+            internal set;
+        }
+
+        internal Line(int uid)
+        {
+            this.UniqueId = uid;
+            chars = new List<Char>();
+        }
+
+
+        /// <summary>
+        /// Clears style of chars, delete folding markers
+        /// </summary>
+        public void ClearStyle(StyleIndex styleIndex)
+        {
+            FoldingStartMarker = null;
+            FoldingEndMarker = null;
+            for (int i = 0; i < Count; i++)
+            {
+                Char c = this[i];
+                c.style &= ~styleIndex;
+                this[i] = c;
+            }
+        }
+
+        /// <summary>
+        /// Text of the line
+        /// </summary>
+        public virtual string Text
+        {
+            get
+            {
+                StringBuilder sb = new StringBuilder(Count);
+                foreach (Char c in this)
+                    sb.Append(c.c);
+                return sb.ToString();
+            }
+        }
+
+        /// <summary>
+        /// Clears folding markers
+        /// </summary>
+        public void ClearFoldingMarkers()
+        {
+            FoldingStartMarker = null;
+            FoldingEndMarker = null;
+        }
+
+        /// <summary>
+        /// Count of start spaces
+        /// </summary>
+        public int StartSpacesCount
+        {
+            get
+            {
+                int spacesCount = 0;
+                for (int i = 0; i < Count; i++)
+                    if (this[i].c == ' ')
+                        spacesCount++;
+                    else
+                        break;
+                return spacesCount;
+            }
+        }
+
+        public int IndexOf(Char item)
+        {
+            return chars.IndexOf(item);
+        }
+
+        public void Insert(int index, Char item)
+        {
+            chars.Insert(index, item);
+        }
+
+        public void RemoveAt(int index)
+        {
+            chars.RemoveAt(index);
+        }
+
+        public Char this[int index]
+        {
+            get
+            {
+                return chars[index];
+            }
+            set
+            {
+                chars[index] = value;
+            }
+        }
+
+        public void Add(Char item)
+        {
+            chars.Add(item);
+        }
+
+        public void Clear()
+        {
+            chars.Clear();
+        }
+
+        public bool Contains(Char item)
+        {
+            return chars.Contains(item);
+        }
+
+        public void CopyTo(Char[] array, int arrayIndex)
+        {
+            chars.CopyTo(array, arrayIndex);
+        }
+
+        /// <summary>
+        /// Chars count
+        /// </summary>
+        public int Count
+        {
+            get { return chars.Count; }
+        }
+
+        public bool IsReadOnly
+        {
+            get { return false; }
+        }
+
+        public bool Remove(Char item)
+        {
+            return chars.Remove(item);
+        }
+
+        public IEnumerator<Char> GetEnumerator()
+        {
+            return chars.GetEnumerator();
+        }
+
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+        {
+            return chars.GetEnumerator() as System.Collections.IEnumerator;
+        }
+
+        public virtual void RemoveRange(int index, int count)
+        {
+            if (index >= Count)
+                return;
+            chars.RemoveRange(index, Math.Min(Count - index, count));
+        }
+
+        public virtual void TrimExcess()
+        {
+            chars.TrimExcess();
+        }
+
+        public virtual void AddRange(IEnumerable<Char> collection)
+        {
+            chars.AddRange(collection);
+        }
+    }
+
+    public struct LineInfo
+    {
+        List<int> cutOffPositions;
+        //Y coordinate of line on screen
+        internal int startY;// = -1;
+        /// <summary>
+        /// Visible state
+        /// </summary>
+        public VisibleState VisibleState;
+
+        public LineInfo(int startY)
+        {
+            cutOffPositions = null;
+            VisibleState = VisibleState.Visible;
+            this.startY = startY;
+        }
+        /// <summary>
+        /// Positions for wordwrap cutoffs
+        /// </summary>
+        public List<int> CutOffPositions
+        {
+            get
+            {
+                if (cutOffPositions == null)
+                    cutOffPositions = new List<int>();
+                return cutOffPositions;
+            }
+        }
+
+        /// <summary>
+        /// Count of wordwrap string count for this line
+        /// </summary>
+        public int WordWrapStringsCount
+        {
+            get
+            {
+                switch (VisibleState)
+                {
+                    case VisibleState.Visible:
+                        if (cutOffPositions == null)
+                            return 1;
+                        else
+                            return cutOffPositions.Count + 1;
+                    case VisibleState.Hidden: return 0;
+                    case VisibleState.StartOfHiddenBlock: return 1;
+                }
+
+                return 0;
+            }
+        }
+
+        internal int GetWordWrapStringStartPosition(int iWordWrapLine)
+        {
+            return iWordWrapLine == 0 ? 0 : CutOffPositions[iWordWrapLine - 1];
+        }
+
+        internal int GetWordWrapStringFinishPosition(int iWordWrapLine, Line line)
+        {
+            if (WordWrapStringsCount <= 0)
+                return 0;
+            return iWordWrapLine == WordWrapStringsCount - 1 ? line.Count - 1 : CutOffPositions[iWordWrapLine] - 1;
+        }
+
+        /// <summary>
+        /// Gets index of wordwrap string for given char position
+        /// </summary>
+        public int GetWordWrapStringIndex(int iChar)
+        {
+            if (cutOffPositions == null || cutOffPositions.Count == 0) return 0;
+            for (int i = 0; i < cutOffPositions.Count; i++)
+                if (cutOffPositions[i] >/*>=*/ iChar)
+                    return i;
+            return cutOffPositions.Count;
+        }
+
+        /// <summary>
+        /// Calculates wordwrap cutoffs
+        /// </summary>
+        internal void CalcCutOffs(int maxCharsPerLine, bool allowIME, bool charWrap, Line line)
+        {
+            int segmentLength = 0;
+            int cutOff = 0;
+            CutOffPositions.Clear();
+
+            for (int i = 0; i < line.Count; i++)
+            {
+                char c = line[i].c;
+                if (charWrap)
+                {
+                    //char wrapping
+                    cutOff = Math.Min(i + 1, line.Count - 1);
+                }
+                else
+                {
+                    //word wrapping
+                    if (allowIME && isCJKLetter(c))//in CJK languages cutoff can be in any letter
+                    {
+                        cutOff = i;
+                    }
+                    else
+                        if (!char.IsLetterOrDigit(c) && c != '_')
+                        cutOff = Math.Min(i + 1, line.Count - 1);
+                }
+
+                segmentLength++;
+
+                if (segmentLength == maxCharsPerLine)
+                {
+                    if (cutOff == 0 || (cutOffPositions.Count > 0 && cutOff == cutOffPositions[cutOffPositions.Count - 1]))
+                        cutOff = i + 1;
+                    CutOffPositions.Add(cutOff);
+                    segmentLength = 1 + i - cutOff;
+                }
+            }
+        }
+
+        private bool isCJKLetter(char c)
+        {
+            int code = Convert.ToInt32(c);
+            return
+            (code >= 0x3300 && code <= 0x33FF) ||
+            (code >= 0xFE30 && code <= 0xFE4F) ||
+            (code >= 0xF900 && code <= 0xFAFF) ||
+            (code >= 0x2E80 && code <= 0x2EFF) ||
+            (code >= 0x31C0 && code <= 0x31EF) ||
+            (code >= 0x4E00 && code <= 0x9FFF) ||
+            (code >= 0x3400 && code <= 0x4DBF) ||
+            (code >= 0x3200 && code <= 0x32FF) ||
+            (code >= 0x2460 && code <= 0x24FF) ||
+            (code >= 0x3040 && code <= 0x309F) ||
+            (code >= 0x2F00 && code <= 0x2FDF) ||
+            (code >= 0x31A0 && code <= 0x31BF) ||
+            (code >= 0x4DC0 && code <= 0x4DFF) ||
+            (code >= 0x3100 && code <= 0x312F) ||
+            (code >= 0x30A0 && code <= 0x30FF) ||
+            (code >= 0x31F0 && code <= 0x31FF) ||
+            (code >= 0x2FF0 && code <= 0x2FFF) ||
+            (code >= 0x1100 && code <= 0x11FF) ||
+            (code >= 0xA960 && code <= 0xA97F) ||
+            (code >= 0xD7B0 && code <= 0xD7FF) ||
+            (code >= 0x3130 && code <= 0x318F) ||
+            (code >= 0xAC00 && code <= 0xD7AF);
+
+        }
+    }
+
+    public enum VisibleState : byte
+    {
+        Visible, StartOfHiddenBlock, Hidden
+    }
+
+    public enum IndentMarker
+    {
+        None,
+        Increased,
+        Decreased
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/LinesAccessor.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/LinesAccessor.cs
new file mode 100644
index 0000000..add4e61
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/LinesAccessor.cs
@@ -0,0 +1,100 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    class LinesAccessor : IList<string>
+    {
+        IList<Line> ts;
+
+        public LinesAccessor(IList<Line> ts)
+        {
+            this.ts = ts;
+        }
+
+        public int IndexOf(string item)
+        {
+            for (int i = 0; i < ts.Count; i++)
+                if (ts[i].Text == item)
+                    return i;
+
+            return -1;
+        }
+
+        public void Insert(int index, string item)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void RemoveAt(int index)
+        {
+            throw new NotImplementedException();
+        }
+
+        public string this[int index]
+        {
+            get
+            {
+                return ts[index].Text;
+            }
+            set
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        public void Add(string item)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void Clear()
+        {
+            throw new NotImplementedException();
+        }
+
+        public bool Contains(string item)
+        {
+            for (int i = 0; i < ts.Count; i++)
+                if (ts[i].Text == item)
+                    return true;
+
+            return false;
+        }
+
+        public void CopyTo(string[] array, int arrayIndex)
+        {
+            for (int i = 0; i < ts.Count; i++)
+                array[i + arrayIndex] = ts[i].Text;
+        }
+
+        public int Count
+        {
+            get { return ts.Count; }
+        }
+
+        public bool IsReadOnly
+        {
+            get { return true; }
+        }
+
+        public bool Remove(string item)
+        {
+            throw new NotImplementedException();
+        }
+
+        public IEnumerator<string> GetEnumerator()
+        {
+            for (int i = 0; i < ts.Count; i++)
+                yield return ts[i].Text;
+        }
+
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/Place.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Place.cs
new file mode 100644
index 0000000..fd61ec4
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Place.cs
@@ -0,0 +1,83 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// Line index and char index
+    /// </summary>
+    public struct Place
+    {
+        public int iChar;
+        public int iLine;
+
+        public Place(int iChar, int iLine)
+        {
+            this.iChar = iChar;
+            this.iLine = iLine;
+        }
+
+        public void Offset(int dx, int dy)
+        {
+            iChar += dx;
+            iLine += dy;
+        }
+
+        public static bool operator !=(Place p1, Place p2)
+        {
+            return !p1.Equals(p2);
+        }
+
+        public static bool operator ==(Place p1, Place p2)
+        {
+            return p1.Equals(p2);
+        }
+
+        public static bool operator <(Place p1, Place p2)
+        {
+            if (p1.iLine < p2.iLine) return true;
+            if (p1.iLine > p2.iLine) return false;
+            if (p1.iChar < p2.iChar) return true;
+            return false;
+        }
+
+        public static bool operator <=(Place p1, Place p2)
+        {
+            if (p1.Equals(p2)) return true;
+            if (p1.iLine < p2.iLine) return true;
+            if (p1.iLine > p2.iLine) return false;
+            if (p1.iChar < p2.iChar) return true;
+            return false;
+        }
+
+        public static bool operator >(Place p1, Place p2)
+        {
+            if (p1.iLine > p2.iLine) return true;
+            if (p1.iLine < p2.iLine) return false;
+            if (p1.iChar > p2.iChar) return true;
+            return false;
+        }
+
+        public static bool operator >=(Place p1, Place p2)
+        {
+            if (p1.Equals(p2)) return true;
+            if (p1.iLine > p2.iLine) return true;
+            if (p1.iLine < p2.iLine) return false;
+            if (p1.iChar > p2.iChar) return true;
+            return false;
+        }
+
+        public static Place Empty
+        {
+            get { return new Place(); }
+        }
+
+        public override string ToString()
+        {
+            return "(" + iChar + "," + iLine + ")";
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/PlatformType.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/PlatformType.cs
new file mode 100644
index 0000000..699c4be
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/PlatformType.cs
@@ -0,0 +1,76 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    public static class PlatformType
+    {
+        const ushort PROCESSOR_ARCHITECTURE_INTEL = 0;
+        const ushort PROCESSOR_ARCHITECTURE_IA64 = 6;
+        const ushort PROCESSOR_ARCHITECTURE_AMD64 = 9;
+        const ushort PROCESSOR_ARCHITECTURE_UNKNOWN = 0xFFFF;
+
+        [StructLayout(LayoutKind.Sequential)]
+        struct SYSTEM_INFO
+        {
+            public ushort wProcessorArchitecture;
+            public ushort wReserved;
+            public uint dwPageSize;
+            public IntPtr lpMinimumApplicationAddress;
+            public IntPtr lpMaximumApplicationAddress;
+            public UIntPtr dwActiveProcessorMask;
+            public uint dwNumberOfProcessors;
+            public uint dwProcessorType;
+            public uint dwAllocationGranularity;
+            public ushort wProcessorLevel;
+            public ushort wProcessorRevision;
+        };
+
+        [DllImport("kernel32.dll")]
+        static extern void GetNativeSystemInfo(ref SYSTEM_INFO lpSystemInfo);
+
+        [DllImport("kernel32.dll")]
+        static extern void GetSystemInfo(ref SYSTEM_INFO lpSystemInfo);
+
+        public static Platform GetOperationSystemPlatform()
+        {
+            var sysInfo = new SYSTEM_INFO();
+
+            // WinXP and older - use GetNativeSystemInfo
+            if (Environment.OSVersion.Version.Major > 5 ||
+                (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1))
+            {
+                GetNativeSystemInfo(ref sysInfo);
+            }
+            // else use GetSystemInfo
+            else
+            {
+                GetSystemInfo(ref sysInfo);
+            }
+
+            switch (sysInfo.wProcessorArchitecture)
+            {
+                case PROCESSOR_ARCHITECTURE_IA64:
+                case PROCESSOR_ARCHITECTURE_AMD64:
+                    return Platform.X64;
+
+                case PROCESSOR_ARCHITECTURE_INTEL:
+                    return Platform.X86;
+
+                default:
+                    return Platform.Unknown;
+            }
+        }
+    }
+
+    public enum Platform
+    {
+        X86,
+        X64,
+        Unknown
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/Range.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Range.cs
new file mode 100644
index 0000000..1b22ba4
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Range.cs
@@ -0,0 +1,1330 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// Diapason of text chars
+    /// </summary>
+    public class Range : IEnumerable<Place>
+    {
+        Place start;
+        Place end;
+        public readonly FastColoredTextBox tb;
+        int preferedPos = -1;
+        int updating = 0;
+
+        string cachedText;
+        List<Place> cachedCharIndexToPlace;
+        int cachedTextVersion = -1;
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        public Range(FastColoredTextBox tb)
+        {
+            this.tb = tb;
+        }
+
+        /// <summary>
+        /// Return true if no selected text
+        /// </summary>
+        public virtual bool IsEmpty
+        {
+            get
+            {
+                if (ColumnSelectionMode)
+                    return Start.iChar == End.iChar;
+                else
+                    return Start == End;
+            }
+        }
+
+        private bool columnSelectionMode;
+
+        /// <summary>
+        /// Column selection mode
+        /// </summary>
+        public bool ColumnSelectionMode
+        {
+            get { return columnSelectionMode; }
+            set { columnSelectionMode = value; }
+        }
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        public Range(FastColoredTextBox tb, int iStartChar, int iStartLine, int iEndChar, int iEndLine)
+            : this(tb)
+        {
+            start = new Place(iStartChar, iStartLine);
+            end = new Place(iEndChar, iEndLine);
+        }
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        public Range(FastColoredTextBox tb, Place start, Place end)
+            : this(tb)
+        {
+            this.start = start;
+            this.end = end;
+        }
+
+        public bool Contains(Place place)
+        {
+            if (place.iLine < Math.Min(start.iLine, end.iLine)) return false;
+            if (place.iLine > Math.Max(start.iLine, end.iLine)) return false;
+
+            Place s = start;
+            Place e = end;
+
+            if (s.iLine > e.iLine || (s.iLine == e.iLine && s.iChar > e.iChar))
+            {
+                var temp = s;
+                s = e;
+                e = temp;
+            }
+
+            if (place.iLine == s.iLine && place.iChar < s.iChar) return false;
+            if (place.iLine == e.iLine && place.iChar > e.iChar) return false;
+
+            return true;
+        }
+
+        /// <summary>
+        /// Returns intersection with other range,
+        /// empty range returned otherwise
+        /// </summary>
+        /// <param name="range"></param>
+        /// <returns></returns>
+        public virtual Range GetIntersectionWith(Range range)
+        {
+            if (ColumnSelectionMode)
+                return GetIntersectionWith_ColumnSelectionMode(range);
+
+            Range r1 = this.Clone();
+            Range r2 = range.Clone();
+            r1.Normalize();
+            r2.Normalize();
+            Place newStart = r1.Start > r2.Start ? r1.Start : r2.Start;
+            Place newEnd = r1.End < r2.End ? r1.End : r2.End;
+            if (newEnd < newStart)
+                return new Range(tb, start, start);
+            return tb.GetRange(newStart, newEnd);
+        }
+
+        /// <summary>
+        /// Returns union with other range.
+        /// </summary>
+        /// <param name="range"></param>
+        /// <returns></returns>
+        public Range GetUnionWith(Range range)
+        {
+            Range r1 = this.Clone();
+            Range r2 = range.Clone();
+            r1.Normalize();
+            r2.Normalize();
+            Place newStart = r1.Start < r2.Start ? r1.Start : r2.Start;
+            Place newEnd = r1.End > r2.End ? r1.End : r2.End;
+
+            return tb.GetRange(newStart, newEnd);
+        }
+
+        /// <summary>
+        /// Select all chars of control
+        /// </summary>
+        public void SelectAll()
+        {
+            ColumnSelectionMode = false;
+
+            Start = new Place(0, 0);
+            if (tb.LinesCount == 0)
+                Start = new Place(0, 0);
+            else
+            {
+                end = new Place(0, 0);
+                start = new Place(tb[tb.LinesCount - 1].Count, tb.LinesCount - 1);
+            }
+            if (this == tb.Selection)
+                tb.Invalidate();
+        }
+
+        /// <summary>
+        /// Start line and char position
+        /// </summary>
+        public Place Start
+        {
+            get { return start; }
+            set
+            {
+                end = start = value;
+                preferedPos = -1;
+                OnSelectionChanged();
+            }
+        }
+
+        /// <summary>
+        /// Finish line and char position
+        /// </summary>
+        public Place End
+        {
+            get
+            {
+                return end;
+            }
+            set
+            {
+                end = value;
+                OnSelectionChanged();
+            }
+        }
+
+        /// <summary>
+        /// Text of range
+        /// </summary>
+        /// <remarks>This property has not 'set' accessor because undo/redo stack works only with 
+        /// FastColoredTextBox.Selection range. So, if you want to set text, you need to use FastColoredTextBox.Selection
+        /// and FastColoredTextBox.InsertText() mehtod.
+        /// </remarks>
+        public virtual string Text
+        {
+            get
+            {
+                if (ColumnSelectionMode)
+                    return Text_ColumnSelectionMode;
+
+                int fromLine = Math.Min(end.iLine, start.iLine);
+                int toLine = Math.Max(end.iLine, start.iLine);
+                int fromChar = FromX;
+                int toChar = ToX;
+                if (fromLine < 0) return null;
+                //
+                StringBuilder sb = new StringBuilder();
+                for (int y = fromLine; y <= toLine; y++)
+                {
+                    int fromX = y == fromLine ? fromChar : 0;
+                    int toX = y == toLine ? Math.Min(tb[y].Count - 1, toChar - 1) : tb[y].Count - 1;
+                    for (int x = fromX; x <= toX; x++)
+                        sb.Append(tb[y][x].c);
+                    if (y != toLine && fromLine != toLine)
+                        sb.AppendLine();
+                }
+                return sb.ToString();
+            }
+        }
+
+        internal void GetText(out string text, out List<Place> charIndexToPlace)
+        {
+            //try get cached text
+            if (tb.TextVersion == cachedTextVersion)
+            {
+                text = cachedText;
+                charIndexToPlace = cachedCharIndexToPlace;
+                return;
+            }
+            //
+            int fromLine = Math.Min(end.iLine, start.iLine);
+            int toLine = Math.Max(end.iLine, start.iLine);
+            int fromChar = FromX;
+            int toChar = ToX;
+
+            StringBuilder sb = new StringBuilder((toLine - fromLine) * 50);
+            charIndexToPlace = new List<Place>(sb.Capacity);
+            if (fromLine >= 0)
+            {
+                for (int y = fromLine; y <= toLine; y++)
+                {
+                    int fromX = y == fromLine ? fromChar : 0;
+                    int toX = y == toLine ? Math.Min(toChar - 1, tb[y].Count - 1) : tb[y].Count - 1;
+                    for (int x = fromX; x <= toX; x++)
+                    {
+                        sb.Append(tb[y][x].c);
+                        charIndexToPlace.Add(new Place(x, y));
+                    }
+                    if (y != toLine && fromLine != toLine)
+                        foreach (char c in Environment.NewLine)
+                        {
+                            sb.Append(c);
+                            charIndexToPlace.Add(new Place(tb[y].Count/*???*/, y));
+                        }
+                }
+            }
+            text = sb.ToString();
+            charIndexToPlace.Add(End > Start ? End : Start);
+            //caching
+            cachedText = text;
+            cachedCharIndexToPlace = charIndexToPlace;
+            cachedTextVersion = tb.TextVersion;
+        }
+
+        /// <summary>
+        /// Returns first char after Start place
+        /// </summary>
+        public char CharAfterStart
+        {
+            get
+            {
+                if (Start.iChar >= tb[Start.iLine].Count)
+                    return '\n';
+                else
+                    return tb[Start.iLine][Start.iChar].c;
+            }
+        }
+
+        /// <summary>
+        /// Returns first char before Start place
+        /// </summary>
+        public char CharBeforeStart
+        {
+            get
+            {
+                if (Start.iChar > tb[Start.iLine].Count)
+                    return '\n';
+
+                if (Start.iChar <= 0)
+                    return '\n';
+                else
+                    return tb[Start.iLine][Start.iChar - 1].c;
+            }
+        }
+
+        /// <summary>
+        /// Clone range
+        /// </summary>
+        /// <returns></returns>
+        public Range Clone()
+        {
+            return (Range)MemberwiseClone();
+        }
+
+        /// <summary>
+        /// Return minimum of end.X and start.X
+        /// </summary>
+        internal int FromX
+        {
+            get
+            {
+                if (end.iLine < start.iLine) return end.iChar;
+                if (end.iLine > start.iLine) return start.iChar;
+                return Math.Min(end.iChar, start.iChar);
+            }
+        }
+
+        /// <summary>
+        /// Return maximum of end.X and start.X
+        /// </summary>
+        internal int ToX
+        {
+            get
+            {
+                if (end.iLine < start.iLine) return start.iChar;
+                if (end.iLine > start.iLine) return end.iChar;
+                return Math.Max(end.iChar, start.iChar);
+            }
+        }
+
+        /// <summary>
+        /// Move range right
+        /// </summary>
+        /// <remarks>This method jump over folded blocks</remarks>
+        public bool GoRight()
+        {
+            Place prevStart = start;
+            GoRight(false);
+            return prevStart != start;
+        }
+
+        /// <summary>
+        /// Move range left
+        /// </summary>
+        /// <remarks>This method can to go inside folded blocks</remarks>
+        public virtual bool GoRightThroughFolded()
+        {
+            if (ColumnSelectionMode)
+                return GoRightThroughFolded_ColumnSelectionMode();
+
+            if (start.iLine >= tb.LinesCount - 1 && start.iChar >= tb[tb.LinesCount - 1].Count)
+                return false;
+
+            if (start.iChar < tb[start.iLine].Count)
+                start.Offset(1, 0);
+            else
+                start = new Place(0, start.iLine + 1);
+
+            preferedPos = -1;
+            end = start;
+            OnSelectionChanged();
+            return true;
+        }
+
+        /// <summary>
+        /// Move range left
+        /// </summary>
+        /// <remarks>This method jump over folded blocks</remarks>
+        public bool GoLeft()
+        {
+            ColumnSelectionMode = false;
+
+            Place prevStart = start;
+            GoLeft(false);
+            return prevStart != start;
+        }
+
+        /// <summary>
+        /// Move range left
+        /// </summary>
+        /// <remarks>This method can to go inside folded blocks</remarks>
+        public bool GoLeftThroughFolded()
+        {
+            ColumnSelectionMode = false;
+
+            if (start.iChar == 0 && start.iLine == 0)
+                return false;
+
+            if (start.iChar > 0)
+                start.Offset(-1, 0);
+            else
+                start = new Place(tb[start.iLine - 1].Count, start.iLine - 1);
+
+            preferedPos = -1;
+            end = start;
+            OnSelectionChanged();
+            return true;
+        }
+
+        public void GoLeft(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            if (!shift)
+                if (start > end)
+                {
+                    Start = End;
+                    return;
+                }
+
+            if (start.iChar != 0 || start.iLine != 0)
+            {
+                if (start.iChar > 0 && tb.lineInfos[start.iLine].VisibleState == VisibleState.Visible)
+                    start.Offset(-1, 0);
+                else
+                {
+                    int i = tb.FindPrevVisibleLine(start.iLine);
+                    if (i == start.iLine) return;
+                    start = new Place(tb[i].Count, i);
+                }
+            }
+
+            if (!shift)
+                end = start;
+
+            OnSelectionChanged();
+
+            preferedPos = -1;
+        }
+
+        public void GoRight(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            if (!shift)
+                if (start < end)
+                {
+                    Start = End;
+                    return;
+                }
+
+            if (start.iLine < tb.LinesCount - 1 || start.iChar < tb[tb.LinesCount - 1].Count)
+            {
+                if (start.iChar < tb[start.iLine].Count && tb.lineInfos[start.iLine].VisibleState == VisibleState.Visible)
+                    start.Offset(1, 0);
+                else
+                {
+                    int i = tb.FindNextVisibleLine(start.iLine);
+                    if (i == start.iLine) return;
+                    start = new Place(0, i);
+                }
+            }
+
+            if (!shift)
+                end = start;
+
+            OnSelectionChanged();
+
+            preferedPos = -1;
+        }
+
+        internal void GoUp(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            if (!shift)
+                if (start.iLine > end.iLine)
+                {
+                    Start = End;
+                    return;
+                }
+
+            if (preferedPos < 0)
+                preferedPos = start.iChar - tb.lineInfos[start.iLine].GetWordWrapStringStartPosition(tb.lineInfos[start.iLine].GetWordWrapStringIndex(start.iChar));
+
+            int iWW = tb.lineInfos[start.iLine].GetWordWrapStringIndex(start.iChar);
+            if (iWW == 0)
+            {
+                if (start.iLine <= 0) return;
+                int i = tb.FindPrevVisibleLine(start.iLine);
+                if (i == start.iLine) return;
+                start.iLine = i;
+                iWW = tb.lineInfos[start.iLine].WordWrapStringsCount;
+            }
+
+            if (iWW > 0)
+            {
+                int finish = tb.lineInfos[start.iLine].GetWordWrapStringFinishPosition(iWW - 1, tb[start.iLine]);
+                start.iChar = tb.lineInfos[start.iLine].GetWordWrapStringStartPosition(iWW - 1) + preferedPos;
+                if (start.iChar > finish + 1)
+                    start.iChar = finish + 1;
+            }
+
+            if (!shift)
+                end = start;
+
+            OnSelectionChanged();
+        }
+
+        internal void GoPageUp(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            if (preferedPos < 0)
+                preferedPos = start.iChar - tb.lineInfos[start.iLine].GetWordWrapStringStartPosition(tb.lineInfos[start.iLine].GetWordWrapStringIndex(start.iChar));
+
+            int pageHeight = tb.ClientRectangle.Height / tb.CharHeight - 1;
+
+            for (int i = 0; i < pageHeight; i++)
+            {
+                int iWW = tb.lineInfos[start.iLine].GetWordWrapStringIndex(start.iChar);
+                if (iWW == 0)
+                {
+                    if (start.iLine <= 0) break;
+                    //pass hidden
+                    int newLine = tb.FindPrevVisibleLine(start.iLine);
+                    if (newLine == start.iLine) break;
+                    start.iLine = newLine;
+                    iWW = tb.lineInfos[start.iLine].WordWrapStringsCount;
+                }
+
+                if (iWW > 0)
+                {
+                    int finish = tb.lineInfos[start.iLine].GetWordWrapStringFinishPosition(iWW - 1, tb[start.iLine]);
+                    start.iChar = tb.lineInfos[start.iLine].GetWordWrapStringStartPosition(iWW - 1) + preferedPos;
+                    if (start.iChar > finish + 1)
+                        start.iChar = finish + 1;
+                }
+            }
+
+            if (!shift)
+                end = start;
+
+            OnSelectionChanged();
+        }
+
+        internal void GoDown(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            if (!shift)
+                if (start.iLine < end.iLine)
+                {
+                    Start = End;
+                    return;
+                }
+
+            if (preferedPos < 0)
+                preferedPos = start.iChar - tb.lineInfos[start.iLine].GetWordWrapStringStartPosition(tb.lineInfos[start.iLine].GetWordWrapStringIndex(start.iChar));
+
+            int iWW = tb.lineInfos[start.iLine].GetWordWrapStringIndex(start.iChar);
+            if (iWW >= tb.lineInfos[start.iLine].WordWrapStringsCount - 1)
+            {
+                if (start.iLine >= tb.LinesCount - 1) return;
+                //pass hidden
+                int i = tb.FindNextVisibleLine(start.iLine);
+                if (i == start.iLine) return;
+                start.iLine = i;
+                iWW = -1;
+            }
+
+            if (iWW < tb.lineInfos[start.iLine].WordWrapStringsCount - 1)
+            {
+                int finish = tb.lineInfos[start.iLine].GetWordWrapStringFinishPosition(iWW + 1, tb[start.iLine]);
+                start.iChar = tb.lineInfos[start.iLine].GetWordWrapStringStartPosition(iWW + 1) + preferedPos;
+                if (start.iChar > finish + 1)
+                    start.iChar = finish + 1;
+            }
+
+            if (!shift)
+                end = start;
+
+            OnSelectionChanged();
+        }
+
+        internal void GoPageDown(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            if (preferedPos < 0)
+                preferedPos = start.iChar - tb.lineInfos[start.iLine].GetWordWrapStringStartPosition(tb.lineInfos[start.iLine].GetWordWrapStringIndex(start.iChar));
+
+            int pageHeight = tb.ClientRectangle.Height / tb.CharHeight - 1;
+
+            for (int i = 0; i < pageHeight; i++)
+            {
+                int iWW = tb.lineInfos[start.iLine].GetWordWrapStringIndex(start.iChar);
+                if (iWW >= tb.lineInfos[start.iLine].WordWrapStringsCount - 1)
+                {
+                    if (start.iLine >= tb.LinesCount - 1) break;
+                    //pass hidden
+                    int newLine = tb.FindNextVisibleLine(start.iLine);
+                    if (newLine == start.iLine) break;
+                    start.iLine = newLine;
+                    iWW = -1;
+                }
+
+                if (iWW < tb.lineInfos[start.iLine].WordWrapStringsCount - 1)
+                {
+                    int finish = tb.lineInfos[start.iLine].GetWordWrapStringFinishPosition(iWW + 1, tb[start.iLine]);
+                    start.iChar = tb.lineInfos[start.iLine].GetWordWrapStringStartPosition(iWW + 1) + preferedPos;
+                    if (start.iChar > finish + 1)
+                        start.iChar = finish + 1;
+                }
+            }
+
+            if (!shift)
+                end = start;
+
+            OnSelectionChanged();
+        }
+
+        internal void GoHome(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            if (start.iLine < 0)
+                return;
+
+            if (tb.lineInfos[start.iLine].VisibleState != VisibleState.Visible)
+                return;
+
+            start = new Place(0, start.iLine);
+
+            if (!shift)
+                end = start;
+
+            OnSelectionChanged();
+
+            preferedPos = -1;
+        }
+
+        internal void GoEnd(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            if (start.iLine < 0)
+                return;
+            if (tb.lineInfos[start.iLine].VisibleState != VisibleState.Visible)
+                return;
+
+            start = new Place(tb[start.iLine].Count, start.iLine);
+
+            if (!shift)
+                end = start;
+
+            OnSelectionChanged();
+
+            preferedPos = -1;
+        }
+
+        /// <summary>
+        /// Set style for range
+        /// </summary>
+        public void SetStyle(Style style)
+        {
+            //search code for style
+            int code = tb.GetOrSetStyleLayerIndex(style);
+            //set code to chars
+            SetStyle(ToStyleIndex(code));
+            //
+            tb.Invalidate();
+        }
+
+        /// <summary>
+        /// Set style for given regex pattern
+        /// </summary>
+        public void SetStyle(Style style, string regexPattern)
+        {
+            //search code for style
+            StyleIndex layer = ToStyleIndex(tb.GetOrSetStyleLayerIndex(style));
+            SetStyle(layer, regexPattern, RegexOptions.None);
+        }
+
+        /// <summary>
+        /// Set style for given regex
+        /// </summary>
+        public void SetStyle(Style style, Regex regex)
+        {
+            //search code for style
+            StyleIndex layer = ToStyleIndex(tb.GetOrSetStyleLayerIndex(style));
+            SetStyle(layer, regex);
+        }
+
+
+        /// <summary>
+        /// Set style for given regex pattern
+        /// </summary>
+        public void SetStyle(Style style, string regexPattern, RegexOptions options)
+        {
+            //search code for style
+            StyleIndex layer = ToStyleIndex(tb.GetOrSetStyleLayerIndex(style));
+            SetStyle(layer, regexPattern, options);
+        }
+
+        /// <summary>
+        /// Set style for given regex pattern
+        /// </summary>
+        public void SetStyle(StyleIndex styleLayer, string regexPattern, RegexOptions options)
+        {
+            if (Math.Abs(Start.iLine - End.iLine) > 1000)
+                options |= SyntaxHighlighter.RegexCompiledOption;
+            //
+            foreach (var range in GetRanges(regexPattern, options))
+                range.SetStyle(styleLayer);
+            //
+            tb.Invalidate();
+        }
+
+        /// <summary>
+        /// Set style for given regex pattern
+        /// </summary>
+        public void SetStyle(StyleIndex styleLayer, Regex regex)
+        {
+            foreach (var range in GetRanges(regex))
+                range.SetStyle(styleLayer);
+            //
+            tb.Invalidate();
+        }
+
+        /// <summary>
+        /// Appends style to chars of range
+        /// </summary>
+        public void SetStyle(StyleIndex styleIndex)
+        {
+            //set code to chars
+            int fromLine = Math.Min(End.iLine, Start.iLine);
+            int toLine = Math.Max(End.iLine, Start.iLine);
+            int fromChar = FromX;
+            int toChar = ToX;
+            if (fromLine < 0) return;
+            //
+            for (int y = fromLine; y <= toLine; y++)
+            {
+                int fromX = y == fromLine ? fromChar : 0;
+                int toX = y == toLine ? Math.Min(toChar - 1, tb[y].Count - 1) : tb[y].Count - 1;
+                for (int x = fromX; x <= toX; x++)
+                {
+                    Char c = tb[y][x];
+                    c.style |= styleIndex;
+                    tb[y][x] = c;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Sets folding markers
+        /// </summary>
+        /// <param name="startFoldingPattern">Pattern for start folding line</param>
+        /// <param name="finishFoldingPattern">Pattern for finish folding line</param>
+        public void SetFoldingMarkers(string startFoldingPattern, string finishFoldingPattern)
+        {
+            SetFoldingMarkers(startFoldingPattern, finishFoldingPattern, SyntaxHighlighter.RegexCompiledOption);
+        }
+
+        /// <summary>
+        /// Sets folding markers
+        /// </summary>
+        /// <param name="startFoldingPattern">Pattern for start folding line</param>
+        /// <param name="finishFoldingPattern">Pattern for finish folding line</param>
+        public void SetFoldingMarkers(string startFoldingPattern, string finishFoldingPattern, RegexOptions options)
+        {
+            if (startFoldingPattern == finishFoldingPattern)
+            {
+                SetFoldingMarkers(startFoldingPattern, options);
+                return;
+            }
+
+            foreach (var range in GetRanges(startFoldingPattern, options))
+                tb[range.Start.iLine].FoldingStartMarker = startFoldingPattern;
+
+            foreach (var range in GetRanges(finishFoldingPattern, options))
+                tb[range.Start.iLine].FoldingEndMarker = startFoldingPattern;
+            //
+            tb.Invalidate();
+        }
+
+        /// <summary>
+        /// Sets folding markers
+        /// </summary>
+        /// <param name="startEndFoldingPattern">Pattern for start and end folding line</param>
+        public void SetFoldingMarkers(string foldingPattern, RegexOptions options)
+        {
+            foreach (var range in GetRanges(foldingPattern, options))
+            {
+                if (range.Start.iLine > 0)
+                    tb[range.Start.iLine - 1].FoldingEndMarker = foldingPattern;
+                tb[range.Start.iLine].FoldingStartMarker = foldingPattern;
+            }
+
+            tb.Invalidate();
+        }
+        /// <summary>
+        /// Finds ranges for given regex pattern
+        /// </summary>
+        /// <param name="regexPattern">Regex pattern</param>
+        /// <returns>Enumeration of ranges</returns>
+        public IEnumerable<Range> GetRanges(string regexPattern)
+        {
+            return GetRanges(regexPattern, RegexOptions.None);
+        }
+
+        /// <summary>
+        /// Finds ranges for given regex pattern
+        /// </summary>
+        /// <param name="regexPattern">Regex pattern</param>
+        /// <returns>Enumeration of ranges</returns>
+        public IEnumerable<Range> GetRanges(string regexPattern, RegexOptions options)
+        {
+            //get text
+            string text;
+            List<Place> charIndexToPlace;
+            GetText(out text, out charIndexToPlace);
+            //create regex
+            Regex regex = new Regex(regexPattern, options);
+            //
+            foreach (Match m in regex.Matches(text))
+            {
+                Range r = new Range(this.tb);
+                //try get 'range' group, otherwise use group 0
+                Group group = m.Groups["range"];
+                if (!group.Success)
+                    group = m.Groups[0];
+                //
+                r.Start = charIndexToPlace[group.Index];
+                r.End = charIndexToPlace[group.Index + group.Length];
+                yield return r;
+            }
+        }
+
+        /// <summary>
+        /// Finds ranges for given regex pattern.
+        /// Search is separately in each line.
+        /// This method requires less memory than GetRanges().
+        /// </summary>
+        /// <param name="regexPattern">Regex pattern</param>
+        /// <returns>Enumeration of ranges</returns>
+        public IEnumerable<Range> GetRangesByLines(string regexPattern, RegexOptions options)
+        {
+            Normalize();
+            //create regex
+            Regex regex = new Regex(regexPattern, options);
+            //
+            var fts = tb.TextSource as FileTextSource;//<----!!!! ugly
+            //enumaerate lines
+            for (int iLine = Start.iLine; iLine <= End.iLine; iLine++)
+            {
+                //
+                bool isLineLoaded = fts != null ? fts.IsLineLoaded(iLine) : true;
+                //
+                var r = new Range(tb, new Place(0, iLine), new Place(tb[iLine].Count, iLine));
+                if (iLine == Start.iLine || iLine == End.iLine)
+                    r = r.GetIntersectionWith(this);
+
+                foreach (var foundRange in r.GetRanges(regex))
+                    yield return foundRange;
+
+                if (!isLineLoaded)
+                    fts.UnloadLine(iLine);
+            }
+        }
+
+        /// <summary>
+        /// Finds ranges for given regex
+        /// </summary>
+        /// <returns>Enumeration of ranges</returns>
+        public IEnumerable<Range> GetRanges(Regex regex)
+        {
+            //get text
+            string text;
+            List<Place> charIndexToPlace;
+            GetText(out text, out charIndexToPlace);
+            //
+            foreach (Match m in regex.Matches(text))
+            {
+                Range r = new Range(this.tb);
+                //try get 'range' group, otherwise use group 0
+                Group group = m.Groups["range"];
+                if (!group.Success)
+                    group = m.Groups[0];
+                //
+                r.Start = charIndexToPlace[group.Index];
+                r.End = charIndexToPlace[group.Index + group.Length];
+                yield return r;
+            }
+        }
+
+        /// <summary>
+        /// Clear styles of range
+        /// </summary>
+        public void ClearStyle(params Style[] styles)
+        {
+            try
+            {
+                ClearStyle(tb.GetStyleIndexMask(styles));
+            }
+            catch {; }
+        }
+
+        /// <summary>
+        /// Clear styles of range
+        /// </summary>
+        public void ClearStyle(StyleIndex styleIndex)
+        {
+            //set code to chars
+            int fromLine = Math.Min(End.iLine, Start.iLine);
+            int toLine = Math.Max(End.iLine, Start.iLine);
+            int fromChar = FromX;
+            int toChar = ToX;
+            if (fromLine < 0) return;
+            //
+            for (int y = fromLine; y <= toLine; y++)
+            {
+                int fromX = y == fromLine ? fromChar : 0;
+                int toX = y == toLine ? Math.Min(toChar - 1, tb[y].Count - 1) : tb[y].Count - 1;
+                for (int x = fromX; x <= toX; x++)
+                {
+                    Char c = tb[y][x];
+                    c.style &= ~styleIndex;
+                    tb[y][x] = c;
+                }
+            }
+            //
+            tb.Invalidate();
+        }
+
+        /// <summary>
+        /// Clear folding markers of all lines of range
+        /// </summary>
+        public void ClearFoldingMarkers()
+        {
+            //set code to chars
+            int fromLine = Math.Min(End.iLine, Start.iLine);
+            int toLine = Math.Max(End.iLine, Start.iLine);
+            if (fromLine < 0) return;
+            //
+            for (int y = fromLine; y <= toLine; y++)
+                tb[y].ClearFoldingMarkers();
+            //
+            tb.Invalidate();
+        }
+
+        void OnSelectionChanged()
+        {
+            //clear cache
+            cachedTextVersion = -1;
+            cachedText = null;
+            cachedCharIndexToPlace = null;
+            //
+            if (tb.Selection == this)
+                if (updating == 0)
+                    tb.OnSelectionChanged();
+        }
+
+        /// <summary>
+        /// Starts selection position updating
+        /// </summary>
+        public void BeginUpdate()
+        {
+            updating++;
+        }
+
+        /// <summary>
+        /// Ends selection position updating
+        /// </summary>
+        public void EndUpdate()
+        {
+            updating--;
+            if (updating == 0)
+                OnSelectionChanged();
+        }
+
+        public override string ToString()
+        {
+            return "Start: " + Start + " End: " + End;
+        }
+
+        /// <summary>
+        /// Exchanges Start and End if End appears before Start
+        /// </summary>
+        public void Normalize()
+        {
+            if (Start > End)
+                Inverse();
+        }
+
+        /// <summary>
+        /// Exchanges Start and End
+        /// </summary>
+        public void Inverse()
+        {
+            var temp = start;
+            start = end;
+            end = temp;
+        }
+
+        /// <summary>
+        /// Expands range from first char of Start line to last char of End line
+        /// </summary>
+        public void Expand()
+        {
+            Normalize();
+            start = new Place(0, start.iLine);
+            end = new Place(tb.GetLineLength(end.iLine), end.iLine);
+        }
+
+        IEnumerator<Place> IEnumerable<Place>.GetEnumerator()
+        {
+            if (ColumnSelectionMode)
+            {
+                foreach (var p in GetEnumerator_ColumnSelectionMode())
+                    yield return p;
+                yield break;
+            }
+
+            int fromLine = Math.Min(end.iLine, start.iLine);
+            int toLine = Math.Max(end.iLine, start.iLine);
+            int fromChar = FromX;
+            int toChar = ToX;
+            if (fromLine < 0) yield break;
+            //
+            for (int y = fromLine; y <= toLine; y++)
+            {
+                int fromX = y == fromLine ? fromChar : 0;
+                int toX = y == toLine ? Math.Min(toChar - 1, tb[y].Count - 1) : tb[y].Count - 1;
+                for (int x = fromX; x <= toX; x++)
+                    yield return new Place(x, y);
+            }
+        }
+
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+        {
+            return (this as IEnumerable<Place>).GetEnumerator();
+        }
+
+        /// <summary>
+        /// Get fragment of text around Start place. Returns maximal mathed to pattern fragment.
+        /// </summary>
+        /// <param name="allowedSymbolsPattern">Allowed chars pattern for fragment</param>
+        /// <returns>Range of found fragment</returns>
+        public Range GetFragment(string allowedSymbolsPattern)
+        {
+            return GetFragment(allowedSymbolsPattern, RegexOptions.None);
+        }
+
+        /// <summary>
+        /// Get fragment of text around Start place. Returns maximal mathed to pattern fragment.
+        /// </summary>
+        /// <param name="allowedSymbolsPattern">Allowed chars pattern for fragment</param>
+        /// <returns>Range of found fragment</returns>
+        public Range GetFragment(string allowedSymbolsPattern, RegexOptions options)
+        {
+            Range r = new Range(tb);
+            r.Start = Start;
+            Regex regex = new Regex(allowedSymbolsPattern, options);
+            //go left, check symbols
+            while (r.GoLeftThroughFolded())
+            {
+                if (!regex.IsMatch(r.CharAfterStart.ToString()))
+                {
+                    r.GoRightThroughFolded();
+                    break;
+                }
+            }
+            Place startFragment = r.Start;
+
+            r.Start = Start;
+            //go right, check symbols
+            do
+            {
+                if (!regex.IsMatch(r.CharAfterStart.ToString()))
+                    break;
+            } while (r.GoRightThroughFolded());
+            Place endFragment = r.Start;
+
+            return new Range(tb, startFragment, endFragment);
+        }
+
+        bool IsIdentifierChar(char c)
+        {
+            return char.IsLetterOrDigit(c) || c == '_';
+        }
+
+        public void GoWordLeft(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            if (!shift)
+                if (start > end)
+                {
+                    Start = End;
+                    return;
+                }
+
+            Range range = this.Clone();//for OnSelectionChanged disable
+
+            Place prev;
+            bool findIdentifier = IsIdentifierChar(range.CharBeforeStart);
+
+            do
+            {
+                prev = range.Start;
+                if (IsIdentifierChar(range.CharBeforeStart) ^ findIdentifier)
+                    break;
+
+                //move left
+                range.GoLeft(shift);
+            } while (prev != range.Start);
+
+            this.Start = range.Start;
+            this.End = range.End;
+
+            if (tb.lineInfos[Start.iLine].VisibleState != VisibleState.Visible)
+                GoRight(shift);
+        }
+
+        public void GoWordRight(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            if (!shift)
+                if (start < end)
+                {
+                    Start = End;
+                    return;
+                }
+
+            Range range = this.Clone();//for OnSelectionChanged disable
+
+            Place prev;
+            bool findIdentifier = IsIdentifierChar(range.CharAfterStart);
+
+            do
+            {
+                prev = range.Start;
+                if (IsIdentifierChar(range.CharAfterStart) ^ findIdentifier)
+                    break;
+
+                //move right
+                range.GoRight(shift);
+            } while (prev != range.Start);
+
+            this.Start = range.Start;
+            this.End = range.End;
+
+            if (tb.lineInfos[Start.iLine].VisibleState != VisibleState.Visible)
+                GoLeft(shift);
+        }
+
+        internal void GoFirst(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            start = new Place(0, 0);
+            if (tb.lineInfos[Start.iLine].VisibleState != VisibleState.Visible)
+                GoRight(shift);
+            if (!shift)
+                end = start;
+
+            OnSelectionChanged();
+        }
+
+        internal void GoLast(bool shift)
+        {
+            ColumnSelectionMode = false;
+
+            start = new Place(tb[tb.LinesCount - 1].Count, tb.LinesCount - 1);
+            if (tb.lineInfos[Start.iLine].VisibleState != VisibleState.Visible)
+                GoLeft(shift);
+            if (!shift)
+                end = start;
+
+            OnSelectionChanged();
+        }
+
+        public static StyleIndex ToStyleIndex(int i)
+        {
+            return (StyleIndex)(1 << i);
+        }
+
+        public RangeRect Bounds
+        {
+            get
+            {
+                int minX = Math.Min(Start.iChar, End.iChar);
+                int minY = Math.Min(Start.iLine, End.iLine);
+                int maxX = Math.Max(Start.iChar, End.iChar);
+                int maxY = Math.Max(Start.iLine, End.iLine);
+                return new RangeRect(minY, minX, maxY, maxX);
+            }
+        }
+
+        public IEnumerable<Range> GetSubRanges(bool includeEmpty)
+        {
+            if (!ColumnSelectionMode)
+            {
+                yield return this;
+                yield break;
+            }
+
+            var rect = Bounds;
+            for (int y = rect.iStartLine; y <= rect.iEndLine; y++)
+            {
+                if (rect.iStartChar > tb[y].Count && !includeEmpty)
+                    continue;
+
+                var r = new Range(tb, rect.iStartChar, y, Math.Min(rect.iEndChar, tb[y].Count), y);
+                yield return r;
+            }
+        }
+
+        #region ColumnSelectionMode
+
+        private Range GetIntersectionWith_ColumnSelectionMode(Range range)
+        {
+            if (range.Start.iLine != range.End.iLine)
+                return new Range(tb, Start, Start);
+            var rect = Bounds;
+            if (range.Start.iLine < rect.iStartLine || range.Start.iLine > rect.iEndLine)
+                return new Range(tb, Start, Start);
+
+            return new Range(tb, rect.iStartChar, range.Start.iLine, rect.iEndChar, range.Start.iLine).GetIntersectionWith(range);
+        }
+
+        private bool GoRightThroughFolded_ColumnSelectionMode()
+        {
+            var boundes = Bounds;
+            var endOfLines = true;
+            for (int iLine = boundes.iStartLine; iLine <= boundes.iEndLine; iLine++)
+                if (boundes.iEndChar < tb[iLine].Count)
+                {
+                    endOfLines = false;
+                    break;
+                }
+
+            if (endOfLines)
+                return false;
+
+            var start = Start;
+            var end = End;
+            start.Offset(1, 0);
+            end.Offset(1, 0);
+            BeginUpdate();
+            Start = start;
+            End = end;
+            EndUpdate();
+
+            return true;
+        }
+
+        private IEnumerable<Place> GetEnumerator_ColumnSelectionMode()
+        {
+            var bounds = Bounds;
+            if (bounds.iStartLine < 0) yield break;
+            //
+            for (int y = bounds.iStartLine; y <= bounds.iEndLine; y++)
+            {
+                for (int x = bounds.iStartChar; x < bounds.iEndChar; x++)
+                {
+                    if (x < tb[y].Count)
+                        yield return new Place(x, y);
+                }
+            }
+        }
+
+        private string Text_ColumnSelectionMode
+        {
+            get
+            {
+                StringBuilder sb = new StringBuilder();
+                var bounds = Bounds;
+                if (bounds.iStartLine < 0) return "";
+                //
+                for (int y = bounds.iStartLine; y <= bounds.iEndLine; y++)
+                {
+                    for (int x = bounds.iStartChar; x < bounds.iEndChar; x++)
+                    {
+                        if (x < tb[y].Count)
+                            sb.Append(tb[y][x].c);
+                    }
+                    if (bounds.iEndLine != bounds.iStartLine && y != bounds.iEndLine)
+                        sb.AppendLine();
+                }
+
+                return sb.ToString();
+            }
+        }
+
+        internal void GoDown_ColumnSelectionMode()
+        {
+            var iLine = tb.FindNextVisibleLine(End.iLine);
+            End = new Place(End.iChar, iLine);
+        }
+
+        internal void GoUp_ColumnSelectionMode()
+        {
+            var iLine = tb.FindPrevVisibleLine(End.iLine);
+            End = new Place(End.iChar, iLine);
+        }
+
+        internal void GoRight_ColumnSelectionMode()
+        {
+            End = new Place(End.iChar + 1, End.iLine);
+        }
+
+        internal void GoLeft_ColumnSelectionMode()
+        {
+            if (End.iChar > 0)
+                End = new Place(End.iChar - 1, End.iLine);
+        }
+
+        #endregion
+    }
+
+    public struct RangeRect
+    {
+        public RangeRect(int iStartLine, int iStartChar, int iEndLine, int iEndChar)
+        {
+            this.iStartLine = iStartLine;
+            this.iStartChar = iStartChar;
+            this.iEndLine = iEndLine;
+            this.iEndChar = iEndChar;
+        }
+
+        public int iStartLine;
+        public int iStartChar;
+        public int iEndLine;
+        public int iEndChar;
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.Designer.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.Designer.cs
new file mode 100644
index 0000000..785ca2b
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.Designer.cs
@@ -0,0 +1,245 @@
+锘縩amespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    partial class ReplaceForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ReplaceForm));
+            btClose = new Button();
+            btFindNext = new Button();
+            tbFind = new TextBox();
+            cbRegex = new CheckBox();
+            cbMatchCase = new CheckBox();
+            label1 = new Label();
+            cbWholeWord = new CheckBox();
+            btReplace = new Button();
+            btReplaceAll = new Button();
+            label2 = new Label();
+            tbReplace = new TextBox();
+            theme_ReplaceForm = new ReaLTaiizor.Forms.ThemeForm();
+            SuspendLayout();
+            // 
+            // btClose
+            // 
+            btClose.ForeColor = SystemColors.ControlText;
+            btClose.Location = new Point(318, 238);
+            btClose.Margin = new Padding(4, 4, 4, 4);
+            btClose.Name = "btClose";
+            btClose.Size = new Size(88, 30);
+            btClose.TabIndex = 7;
+            btClose.Text = "Close";
+            btClose.UseVisualStyleBackColor = true;
+            btClose.Click += btClose_Click;
+            // 
+            // btFindNext
+            // 
+            btFindNext.ForeColor = SystemColors.ControlText;
+            btFindNext.Location = new Point(130, 201);
+            btFindNext.Margin = new Padding(4, 4, 4, 4);
+            btFindNext.Name = "btFindNext";
+            btFindNext.Size = new Size(88, 30);
+            btFindNext.TabIndex = 4;
+            btFindNext.Text = "Find next";
+            btFindNext.UseVisualStyleBackColor = true;
+            btFindNext.Click += btFindNext_Click;
+            // 
+            // tbFind
+            // 
+            tbFind.Font = new Font("Consolas", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 204);
+            tbFind.ForeColor = SystemColors.ControlText;
+            tbFind.Location = new Point(72, 74);
+            tbFind.Margin = new Padding(4, 4, 4, 4);
+            tbFind.Name = "tbFind";
+            tbFind.Size = new Size(333, 20);
+            tbFind.TabIndex = 0;
+            tbFind.TextChanged += cbMatchCase_CheckedChanged;
+            tbFind.KeyPress += tbFind_KeyPress;
+            // 
+            // cbRegex
+            // 
+            cbRegex.AutoSize = true;
+            cbRegex.ForeColor = SystemColors.Control;
+            cbRegex.Location = new Point(318, 108);
+            cbRegex.Margin = new Padding(4, 4, 4, 4);
+            cbRegex.Name = "cbRegex";
+            cbRegex.Size = new Size(63, 21);
+            cbRegex.TabIndex = 3;
+            cbRegex.Text = "Regex";
+            cbRegex.UseVisualStyleBackColor = true;
+            cbRegex.CheckedChanged += cbMatchCase_CheckedChanged;
+            // 
+            // cbMatchCase
+            // 
+            cbMatchCase.AutoSize = true;
+            cbMatchCase.ForeColor = SystemColors.Control;
+            cbMatchCase.Location = new Point(77, 108);
+            cbMatchCase.Margin = new Padding(4, 4, 4, 4);
+            cbMatchCase.Name = "cbMatchCase";
+            cbMatchCase.Size = new Size(93, 21);
+            cbMatchCase.TabIndex = 1;
+            cbMatchCase.Text = "Match case";
+            cbMatchCase.UseVisualStyleBackColor = true;
+            cbMatchCase.CheckedChanged += cbMatchCase_CheckedChanged;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.ForeColor = SystemColors.Control;
+            label1.Location = new Point(27, 76);
+            label1.Margin = new Padding(4, 0, 4, 0);
+            label1.Name = "label1";
+            label1.Size = new Size(39, 17);
+            label1.TabIndex = 5;
+            label1.Text = "Find: ";
+            // 
+            // cbWholeWord
+            // 
+            cbWholeWord.AutoSize = true;
+            cbWholeWord.ForeColor = SystemColors.Control;
+            cbWholeWord.Location = new Point(180, 108);
+            cbWholeWord.Margin = new Padding(4, 4, 4, 4);
+            cbWholeWord.Name = "cbWholeWord";
+            cbWholeWord.Size = new Size(135, 21);
+            cbWholeWord.TabIndex = 2;
+            cbWholeWord.Text = "Match whole word";
+            cbWholeWord.UseVisualStyleBackColor = true;
+            cbWholeWord.CheckedChanged += cbMatchCase_CheckedChanged;
+            // 
+            // btReplace
+            // 
+            btReplace.ForeColor = SystemColors.ControlText;
+            btReplace.Location = new Point(224, 201);
+            btReplace.Margin = new Padding(4, 4, 4, 4);
+            btReplace.Name = "btReplace";
+            btReplace.Size = new Size(88, 30);
+            btReplace.TabIndex = 5;
+            btReplace.Text = "Replace";
+            btReplace.UseVisualStyleBackColor = true;
+            btReplace.Click += btReplace_Click;
+            // 
+            // btReplaceAll
+            // 
+            btReplaceAll.ForeColor = SystemColors.ControlText;
+            btReplaceAll.Location = new Point(318, 201);
+            btReplaceAll.Margin = new Padding(4, 4, 4, 4);
+            btReplaceAll.Name = "btReplaceAll";
+            btReplaceAll.Size = new Size(88, 30);
+            btReplaceAll.TabIndex = 6;
+            btReplaceAll.Text = "Replace all";
+            btReplaceAll.UseVisualStyleBackColor = true;
+            btReplaceAll.Click += btReplaceAll_Click;
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.ForeColor = SystemColors.Control;
+            label2.Location = new Point(7, 155);
+            label2.Margin = new Padding(4, 0, 4, 0);
+            label2.Name = "label2";
+            label2.Size = new Size(57, 17);
+            label2.TabIndex = 9;
+            label2.Text = "Replace:";
+            // 
+            // tbReplace
+            // 
+            tbReplace.Font = new Font("Consolas", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 204);
+            tbReplace.ForeColor = SystemColors.ControlText;
+            tbReplace.Location = new Point(72, 151);
+            tbReplace.Margin = new Padding(4, 4, 4, 4);
+            tbReplace.Name = "tbReplace";
+            tbReplace.Size = new Size(333, 20);
+            tbReplace.TabIndex = 0;
+            tbReplace.TextChanged += cbMatchCase_CheckedChanged;
+            tbReplace.KeyPress += tbFind_KeyPress;
+            // 
+            // theme_ReplaceForm
+            // 
+            theme_ReplaceForm.BackColor = Color.FromArgb(32, 41, 50);
+            theme_ReplaceForm.Dock = DockStyle.Fill;
+            theme_ReplaceForm.Font = new Font("Microsoft Sans Serif", 9F);
+            theme_ReplaceForm.ForeColor = SystemColors.Control;
+            theme_ReplaceForm.Image = (Image)resources.GetObject("theme_ReplaceForm.Image");
+            theme_ReplaceForm.Location = new Point(0, 0);
+            theme_ReplaceForm.Name = "theme_ReplaceForm";
+            theme_ReplaceForm.Padding = new Padding(10, 70, 10, 9);
+            theme_ReplaceForm.RoundCorners = true;
+            theme_ReplaceForm.Sizable = true;
+            theme_ReplaceForm.Size = new Size(420, 281);
+            theme_ReplaceForm.SmartBounds = true;
+            theme_ReplaceForm.StartPosition = FormStartPosition.CenterScreen;
+            theme_ReplaceForm.TabIndex = 10;
+            theme_ReplaceForm.Text = "ReplaceForm";
+            // 
+            // ReplaceForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(420, 281);
+            Controls.Add(tbFind);
+            Controls.Add(label2);
+            Controls.Add(tbReplace);
+            Controls.Add(btReplaceAll);
+            Controls.Add(btReplace);
+            Controls.Add(cbWholeWord);
+            Controls.Add(label1);
+            Controls.Add(cbMatchCase);
+            Controls.Add(cbRegex);
+            Controls.Add(btFindNext);
+            Controls.Add(btClose);
+            Controls.Add(theme_ReplaceForm);
+            FormBorderStyle = FormBorderStyle.None;
+            Margin = new Padding(4, 4, 4, 4);
+            MinimumSize = new Size(261, 61);
+            Name = "ReplaceForm";
+            ShowIcon = false;
+            ShowInTaskbar = false;
+            StartPosition = FormStartPosition.CenterScreen;
+            Text = "ReplaceForm";
+            TopMost = true;
+            TransparencyKey = Color.Fuchsia;
+            FormClosing += FindForm_FormClosing;
+            ResumeLayout(false);
+            PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Button btClose;
+        private System.Windows.Forms.Button btFindNext;
+        private System.Windows.Forms.CheckBox cbRegex;
+        private System.Windows.Forms.CheckBox cbMatchCase;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.CheckBox cbWholeWord;
+        private System.Windows.Forms.Button btReplace;
+        private System.Windows.Forms.Button btReplaceAll;
+        private System.Windows.Forms.Label label2;
+        public System.Windows.Forms.TextBox tbFind;
+        public System.Windows.Forms.TextBox tbReplace;
+        private ReaLTaiizor.Forms.ThemeForm theme_ReplaceForm;
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.cs
new file mode 100644
index 0000000..038f80f
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.cs
@@ -0,0 +1,169 @@
+锘縰sing System;
+using System.Windows.Forms;
+using System.Text.RegularExpressions;
+using System.Collections.Generic;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    public partial class ReplaceForm : Form
+    {
+        FastColoredTextBox tb;
+        bool firstSearch = true;
+        Place startPlace;
+
+        public ReplaceForm(FastColoredTextBox tb)
+        {
+            InitializeComponent();
+            this.tb = tb;
+        }
+
+        private void btClose_Click(object sender, EventArgs e)
+        {
+            Close();
+        }
+
+        private void btFindNext_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                if (!Find(tbFind.Text))
+                    MessageBox.Show("Not found");
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.Message);
+            }
+        }
+
+        public List<Range> FindAll(string pattern)
+        {
+            RegexOptions opt = cbMatchCase.Checked ? RegexOptions.None : RegexOptions.IgnoreCase;
+            if (!cbRegex.Checked)
+                pattern = Regex.Escape(pattern);
+            if (cbWholeWord.Checked)
+                pattern = "\\b" + pattern + "\\b";
+            //
+            Range range = tb.Selection.Clone();
+            range.Normalize();
+            range.Start = range.End;
+            range.End = new Place(tb.GetLineLength(tb.LinesCount - 1), tb.LinesCount - 1);
+            //
+            List<Range> list = new List<Range>();
+            foreach (var r in range.GetRangesByLines(pattern, opt))
+                list.Add(r);
+
+            return list;
+        }
+
+        public bool Find(string pattern)
+        {
+            RegexOptions opt = cbMatchCase.Checked ? RegexOptions.None : RegexOptions.IgnoreCase;
+            if (!cbRegex.Checked)
+                pattern = Regex.Escape(pattern);
+            if (cbWholeWord.Checked)
+                pattern = "\\b" + pattern + "\\b";
+            //
+            Range range = tb.Selection.Clone();
+            range.Normalize();
+            //
+            if (firstSearch)
+            {
+                startPlace = range.Start;
+                firstSearch = false;
+            }
+            //
+            range.Start = range.End;
+            if (range.Start >= startPlace)
+                range.End = new Place(tb.GetLineLength(tb.LinesCount - 1), tb.LinesCount - 1);
+            else
+                range.End = startPlace;
+            //
+            foreach (var r in range.GetRangesByLines(pattern, opt))
+            {
+                tb.Selection.Start = r.Start;
+                tb.Selection.End = r.End;
+                tb.DoSelectionVisible();
+                tb.Invalidate();
+                return true;
+            }
+            if (range.Start >= startPlace && startPlace > Place.Empty)
+            {
+                tb.Selection.Start = new Place(0, 0);
+                return Find(pattern);
+            }
+            return false;
+        }
+
+        private void tbFind_KeyPress(object sender, KeyPressEventArgs e)
+        {
+            if (e.KeyChar == '\r')
+                btFindNext_Click(sender, null);
+            if (e.KeyChar == '\x1b')
+                Hide();
+        }
+
+        private void FindForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            if (e.CloseReason == CloseReason.UserClosing)
+            {
+                e.Cancel = true;
+                Hide();
+            }
+        }
+
+        private void btReplace_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                if (tb.SelectionLength != 0)
+                    tb.InsertText(tbReplace.Text);
+                btFindNext_Click(sender, null);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.Message);
+            }
+        }
+
+        private void btReplaceAll_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                tb.Selection.BeginUpdate();
+                tb.Selection.Start = new Place(0, 0);
+                //search
+                var ranges = FindAll(tbFind.Text);
+                //replace
+                if (ranges.Count > 0)
+                {
+                    tb.TextSource.Manager.ExecuteCommand(new ReplaceTextCommand(tb.TextSource, ranges, tbReplace.Text));
+                    tb.Selection.Start = new Place(0, 0);
+                }
+                //
+                tb.Invalidate();
+                MessageBox.Show(ranges.Count + " occurrence(s) replaced");
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.Message);
+            }
+            tb.Selection.EndUpdate();
+        }
+
+        protected override void OnActivated(EventArgs e)
+        {
+            tbFind.Focus();
+            ResetSerach();
+        }
+
+        void ResetSerach()
+        {
+            firstSearch = true;
+        }
+
+        private void cbMatchCase_CheckedChanged(object sender, EventArgs e)
+        {
+            ResetSerach();
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.resx b/LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.resx
new file mode 100644
index 0000000..9171b5c
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/ReplaceForm.resx
@@ -0,0 +1,144 @@
+锘�<?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=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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="theme_ReplaceForm.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAPiSURBVFhH7VZLiBxlEG7d+IjBKKtktqt6d8kybLqqZyfi
+        +lgUXcGooKIXxYBKLgZFQVDwgQhBvAVzUOPBi3iJgnoSCcTLKobEma7qHeOiuB7UiBo1PuIjq9HNSPX0
+        rDN/zyzbQjztB9+pv3r8/19dVZ63ilUUwBzzmbppGOpRcKlEcLNwcGfMsE0J7ogj//okws2NamlD83Zv
+        wLX9z2h63ulz7I8kDNsSxleF8CMl+EEY/lDCv5TxbyU8oQTHlfCIEL5kSbh+CqPpeafVIxgWwieUcU4I
+        /lTGZl8SnEgI3pBxPzTbOQ4Gkyi4pxEGFTuE639ZpFfNcIsS1LJT5gN28xdl3Cnj/oVmP7t59Hwl3K0M
+        C8owL4zbG9XSOjdOT5hQCB5Rxu97BMqT4BsJ4X6Z9M8x+483XXCuEO5KnyjTCOGvSvjMAQ4G3XhdODAV
+        rBWGHUL4Wy5Qb34Sk3/rzLS3xuwtCSV8ShmOu1p7wpjwBRkbO8+Nm6LpeQMxwX3Suk43ULczxpPKKLOR
+        f+WO7H1bz4YPpaftYdMiLMQET5rWje/FhJfHhF/kjXJcVIZ3tIJVKzazfc3zBpTwLmU82kPfRWH8Lg79
+        67qC76uW1mkEr2Qnyxl1GC8K49uNEMbbtpZEjeBaXVnymR/Y2/UUNQqutn/bFTpcVMZ9ykF5ydDzvEMV
+        P4wZtYe+L+2Z4hBvSh3YP6rs71zu9PZNGN7tPLnBqloIXl/Oth+F4MW0eO0qlPA9V9BFwtlZhos6g89M
+        T69JGB/Xjt+tIDXtG41qaaMwftZDkBG+TAi2tAuuDaHhq4Thq7x+pYSvNRoiL54IJqwy84L05L8LwwPu
+        cLFOJ4Rv5vQFKAQ/xRxc1jeB9F0J9rxfHlzfGdxQD2GrJefaFGI7gfrEyJgwfp4X4GEN/Uk3+H5rtQx7
+        c/qCFIIjNSpFrcHBcLDro1U94a52i+1EHPoXC+VvrCiF4cNDlY2ltIsJwXOO4KiEOOUGN9jykc7/Hk4L
+        kWDPUkuWKLhBGY79+xH32824wQ3WcsWWENdhAdqktG1qyakVWszw1pKI8GW7ma7IGbQydImNYNdpIRLU
+        4nDE73JcJ9gihN9mCexuTzkX2dR7TAh+zDleAa0N1wnvdvuKJ5OTZ9j6JQwL1l57jswMM6OjZ8eEN0q6
+        I8KnynjMVjKbF1lbPtlq3ykXW1tVuh39LITP992O5suD65XhWSH4QGlo1P3uYr5cPst0thckjLcp473K
+        8LBYiyb/0YTwQdsLNYStlnASwRX9amsJaZcL8WkJcXu/OjjlODwVrI0jvOZgZUPJ/fa/wYrEnQGrOBX4
+        B6XRFGacFF+7AAAAAElFTkSuQmCC
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/Style.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Style.cs
new file mode 100644
index 0000000..2c1129d
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/Style.cs
@@ -0,0 +1,410 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Drawing.Drawing2D;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// Style of chars
+    /// </summary>
+    /// <remarks>This is base class for all text and design renderers</remarks>
+    public abstract class Style : IDisposable
+    {
+        /// <summary>
+        /// This style is exported to outer formats (HTML for example)
+        /// </summary>
+        public virtual bool IsExportable { get; set; }
+        /// <summary>
+        /// Occurs when user click on StyleVisualMarker joined to this style 
+        /// </summary>
+        public event EventHandler<VisualMarkerEventArgs> VisualMarkerClick;
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        public Style()
+        {
+            IsExportable = true;
+        }
+
+        /// <summary>
+        /// Renders given range of text
+        /// </summary>
+        /// <param name="gr">Graphics object</param>
+        /// <param name="position">Position of the range in absolute control coordinates</param>
+        /// <param name="range">Rendering range of text</param>
+        public abstract void Draw(Graphics gr, Point position, Range range);
+
+        /// <summary>
+        /// Occurs when user click on StyleVisualMarker joined to this style 
+        /// </summary>
+        public virtual void OnVisualMarkerClick(FastColoredTextBox tb, VisualMarkerEventArgs args)
+        {
+            if (VisualMarkerClick != null)
+                VisualMarkerClick(tb, args);
+        }
+
+        /// <summary>
+        /// Shows VisualMarker
+        /// Call this method in Draw method, when you need to show VisualMarker for your style
+        /// </summary>
+        protected virtual void AddVisualMarker(FastColoredTextBox tb, StyleVisualMarker marker)
+        {
+            tb.AddVisualMarker(marker);
+        }
+
+        public static Size GetSizeOfRange(Range range)
+        {
+            return new Size((range.End.iChar - range.Start.iChar) * range.tb.CharWidth, range.tb.CharHeight);
+        }
+
+        public static GraphicsPath GetRoundedRectangle(Rectangle rect, int d)
+        {
+            GraphicsPath gp = new GraphicsPath();
+
+            gp.AddArc(rect.X, rect.Y, d, d, 180, 90);
+            gp.AddArc(rect.X + rect.Width - d, rect.Y, d, d, 270, 90);
+            gp.AddArc(rect.X + rect.Width - d, rect.Y + rect.Height - d, d, d, 0, 90);
+            gp.AddArc(rect.X, rect.Y + rect.Height - d, d, d, 90, 90);
+            gp.AddLine(rect.X, rect.Y + rect.Height - d, rect.X, rect.Y + d / 2);
+
+            return gp;
+        }
+
+        public virtual void Dispose()
+        {
+            ;
+        }
+
+        /// <summary>
+        /// Returns CSS for export to HTML
+        /// </summary>
+        /// <returns></returns>
+        public virtual string GetCSS()
+        {
+            return "";
+        }
+    }
+
+    /// <summary>
+    /// Style for chars rendering
+    /// This renderer can draws chars, with defined fore and back colors
+    /// </summary>
+    public class TextStyle : Style
+    {
+        public Brush ForeBrush { get; set; }
+        public Brush BackgroundBrush { get; set; }
+        public FontStyle FontStyle { get; set; }
+        //public readonly Font Font;
+        public StringFormat stringFormat;
+
+        public TextStyle(Brush foreBrush, Brush backgroundBrush, FontStyle fontStyle)
+        {
+            this.ForeBrush = foreBrush;
+            this.BackgroundBrush = backgroundBrush;
+            this.FontStyle = fontStyle;
+            stringFormat = new StringFormat(StringFormatFlags.MeasureTrailingSpaces);
+        }
+
+        public override void Draw(Graphics gr, Point position, Range range)
+        {
+            //draw background
+            if (BackgroundBrush != null)
+                gr.FillRectangle(BackgroundBrush, position.X, position.Y, (range.End.iChar - range.Start.iChar) * range.tb.CharWidth, range.tb.CharHeight);
+            //draw chars
+            Font f = new Font(range.tb.Font, FontStyle);
+            //Font fHalfSize = new Font(range.tb.Font.FontFamily, f.SizeInPoints/2, FontStyle);
+            Line line = range.tb[range.Start.iLine];
+            float dx = range.tb.CharWidth;
+            float y = position.Y + range.tb.LineInterval / 2;
+            float x = position.X - range.tb.CharWidth / 3;
+
+            if (ForeBrush == null)
+                ForeBrush = new SolidBrush(range.tb.ForeColor);
+
+            //IME mode
+            if (range.tb.ImeAllowed)
+                for (int i = range.Start.iChar; i < range.End.iChar; i++)
+                {
+                    SizeF size = FastColoredTextBox.GetCharSize(f, line[i].c);
+
+                    var gs = gr.Save();
+                    float k = size.Width > range.tb.CharWidth + 1 ? range.tb.CharWidth / size.Width : 1;
+                    gr.TranslateTransform(x, y + (1 - k) * range.tb.CharHeight / 2);
+                    gr.ScaleTransform(k, (float)Math.Sqrt(k));
+                    gr.DrawString(line[i].c.ToString(), f, ForeBrush, 0, 0, stringFormat);
+                    gr.Restore(gs);
+                    /*
+                    if(size.Width>range.tb.CharWidth*1.5f)
+                        gr.DrawString(line[i].c.ToString(), fHalfSize, foreBrush, x, y+range.tb.CharHeight/4, stringFormat);
+                    else
+                        gr.DrawString(line[i].c.ToString(), f, foreBrush, x, y, stringFormat);
+                     * */
+                    x += dx;
+                }
+            else
+                //classic mode 
+                for (int i = range.Start.iChar; i < range.End.iChar; i++)
+                {
+                    //draw char
+                    gr.DrawString(line[i].c.ToString(), f, ForeBrush, x, y, stringFormat);
+                    x += dx;
+                }
+            //
+            f.Dispose();
+        }
+
+        public override void Dispose()
+        {
+            base.Dispose();
+
+            if (ForeBrush != null)
+                ForeBrush.Dispose();
+            if (BackgroundBrush != null)
+                BackgroundBrush.Dispose();
+        }
+
+        public override string GetCSS()
+        {
+            string result = "";
+
+            if (BackgroundBrush is SolidBrush)
+            {
+                var s = ExportToHTML.GetColorAsString((BackgroundBrush as SolidBrush).Color);
+                if (s != "")
+                    result += "background-color:" + s + ";";
+            }
+            if (ForeBrush is SolidBrush)
+            {
+                var s = ExportToHTML.GetColorAsString((ForeBrush as SolidBrush).Color);
+                if (s != "")
+                    result += "color:" + s + ";";
+            }
+            if ((FontStyle & FontStyle.Bold) != 0)
+                result += "font-weight:bold;";
+            if ((FontStyle & FontStyle.Italic) != 0)
+                result += "font-style:oblique;";
+            if ((FontStyle & FontStyle.Strikeout) != 0)
+                result += "text-decoration:line-through;";
+            if ((FontStyle & FontStyle.Underline) != 0)
+                result += "text-decoration:underline;";
+
+            return result;
+        }
+    }
+
+    /// <summary>
+    /// Renderer for folded block
+    /// </summary>
+    public class FoldedBlockStyle : TextStyle
+    {
+        public FoldedBlockStyle(Brush foreBrush, Brush backgroundBrush, FontStyle fontStyle) :
+            base(foreBrush, backgroundBrush, fontStyle)
+        {
+        }
+
+        public override void Draw(Graphics gr, Point position, Range range)
+        {
+            if (range.End.iChar > range.Start.iChar)
+            {
+                base.Draw(gr, position, range);
+
+                int firstNonSpaceSymbolX = position.X;
+
+                //find first non space symbol
+                for (int i = range.Start.iChar; i < range.End.iChar; i++)
+                    if (range.tb[range.Start.iLine][i].c != ' ')
+                        break;
+                    else
+                        firstNonSpaceSymbolX += range.tb.CharWidth;
+
+                //create marker
+                range.tb.AddVisualMarker(new FoldedAreaMarker(range.Start.iLine, new Rectangle(firstNonSpaceSymbolX, position.Y, position.X + (range.End.iChar - range.Start.iChar) * range.tb.CharWidth - firstNonSpaceSymbolX, range.tb.CharHeight)));
+            }
+            else
+            {
+                //draw '...'
+                using (Font f = new Font(range.tb.Font, FontStyle))
+                    gr.DrawString("...", f, ForeBrush, range.tb.LeftIndent, position.Y - 2);
+                //create marker
+                range.tb.AddVisualMarker(new FoldedAreaMarker(range.Start.iLine, new Rectangle(range.tb.LeftIndent + 2, position.Y, 2 * range.tb.CharHeight, range.tb.CharHeight)));
+            }
+        }
+    }
+
+    /// <summary>
+    /// Renderer for selection area
+    /// </summary>
+    public class SelectionStyle : Style
+    {
+        public Brush BackgroundBrush { get; set; }
+
+        public override bool IsExportable
+        {
+            get { return false; }
+            set { }
+        }
+
+        public SelectionStyle(Brush backgroundBrush)
+        {
+            this.BackgroundBrush = backgroundBrush;
+        }
+
+        public override void Draw(Graphics gr, Point position, Range range)
+        {
+            //draw background
+            if (BackgroundBrush != null)
+            {
+                Rectangle rect = new Rectangle(position.X, position.Y, (range.End.iChar - range.Start.iChar) * range.tb.CharWidth, range.tb.CharHeight);
+                if (rect.Width == 0)
+                    return;
+                gr.FillRectangle(BackgroundBrush, rect);
+            }
+        }
+
+        public override void Dispose()
+        {
+            base.Dispose();
+
+            if (BackgroundBrush != null)
+                BackgroundBrush.Dispose();
+        }
+    }
+
+    /// <summary>
+    /// Marker style
+    /// Draws background color for text
+    /// </summary>
+    public class MarkerStyle : Style
+    {
+        public Brush BackgroundBrush { get; set; }
+
+        public MarkerStyle(Brush backgroundBrush)
+        {
+            this.BackgroundBrush = backgroundBrush;
+            IsExportable = true;
+        }
+
+        public override void Draw(Graphics gr, Point position, Range range)
+        {
+            //draw background
+            if (BackgroundBrush != null)
+            {
+                Rectangle rect = new Rectangle(position.X, position.Y, (range.End.iChar - range.Start.iChar) * range.tb.CharWidth, range.tb.CharHeight);
+                if (rect.Width == 0)
+                    return;
+                //var path = GetRoundedRectangle(rect, 5);
+                //gr.FillPath(BackgroundBrush, path);
+                gr.FillRectangle(BackgroundBrush, rect);
+            }
+        }
+
+        public override void Dispose()
+        {
+            base.Dispose();
+
+            if (BackgroundBrush != null)
+                BackgroundBrush.Dispose();
+        }
+
+        public override string GetCSS()
+        {
+            string result = "";
+
+            if (BackgroundBrush is SolidBrush)
+            {
+                var s = ExportToHTML.GetColorAsString((BackgroundBrush as SolidBrush).Color);
+                if (s != "")
+                    result += "background-color:" + s + ";";
+            }
+
+            return result;
+        }
+    }
+
+    /// <summary>
+    /// Draws small rectangle for popup menu
+    /// </summary>
+    public class ShortcutStyle : Style
+    {
+        public Pen borderPen;
+
+        public ShortcutStyle(Pen borderPen)
+        {
+            this.borderPen = borderPen;
+        }
+
+        public override void Draw(Graphics gr, Point position, Range range)
+        {
+            //get last char coordinates
+            Point p = range.tb.PlaceToPoint(range.End);
+            //draw small square under char
+            Rectangle rect = new Rectangle(p.X - 5, p.Y + range.tb.CharHeight - 2, 4, 3);
+            gr.FillPath(Brushes.White, GetRoundedRectangle(rect, 1));
+            gr.DrawPath(borderPen, GetRoundedRectangle(rect, 1));
+            //add visual marker for handle mouse events
+            AddVisualMarker(range.tb, new StyleVisualMarker(new Rectangle(p.X - range.tb.CharWidth, p.Y, range.tb.CharWidth, range.tb.CharHeight), this));
+        }
+
+        public override void Dispose()
+        {
+            base.Dispose();
+
+            if (borderPen != null)
+                borderPen.Dispose();
+        }
+    }
+
+    /// <summary>
+    /// This style draws a wavy line below a given text range.
+    /// </summary>
+    /// <remarks>Thanks for Yallie</remarks>
+    public class WavyLineStyle : Style
+    {
+        private Pen Pen { get; set; }
+
+        public WavyLineStyle(int alpha, Color color)
+        {
+            Pen = new Pen(Color.FromArgb(alpha, color));
+        }
+
+        public override void Draw(Graphics gr, Point pos, Range range)
+        {
+            var size = GetSizeOfRange(range);
+            var start = new Point(pos.X, pos.Y + size.Height - 1);
+            var end = new Point(pos.X + size.Width, pos.Y + size.Height - 1);
+            DrawWavyLine(gr, start, end);
+        }
+
+        private void DrawWavyLine(Graphics graphics, Point start, Point end)
+        {
+            if (end.X - start.X < 2)
+            {
+                graphics.DrawLine(Pen, start, end);
+                return;
+            }
+
+            var offset = -1;
+            var points = new List<Point>();
+
+            for (int i = start.X; i <= end.X; i += 2)
+            {
+                points.Add(new Point(i, start.Y + offset));
+                offset = -offset;
+            }
+
+            graphics.DrawLines(Pen, points.ToArray());
+        }
+
+        public override void Dispose()
+        {
+            base.Dispose();
+            if (Pen != null)
+                Pen.Dispose();
+        }
+    }
+
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/SyntaxDescriptor.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/SyntaxDescriptor.cs
new file mode 100644
index 0000000..b122293
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/SyntaxDescriptor.cs
@@ -0,0 +1,53 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    public class SyntaxDescriptor : IDisposable
+    {
+        public char leftBracket = '(';
+        public char rightBracket = ')';
+        public char leftBracket2 = '\x0';
+        public char rightBracket2 = '\x0';
+        public readonly List<Style> styles = new List<Style>();
+        public readonly List<RuleDesc> rules = new List<RuleDesc>();
+        public readonly List<FoldingDesc> foldings = new List<FoldingDesc>();
+
+        public void Dispose()
+        {
+            foreach (var style in styles)
+                style.Dispose();
+        }
+    }
+
+    public class RuleDesc
+    {
+        Regex regex;
+        public string pattern;
+        public RegexOptions options = RegexOptions.None;
+        public Style style;
+
+        public Regex Regex
+        {
+            get
+            {
+                if (regex == null)
+                {
+                    regex = new Regex(pattern, RegexOptions.Compiled | options);
+                }
+                return regex;
+            }
+        }
+    }
+
+    public class FoldingDesc
+    {
+        public string startMarkerRegex;
+        public string finishMarkerRegex;
+        public RegexOptions options = RegexOptions.None;
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/SyntaxHighlighter.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/SyntaxHighlighter.cs
new file mode 100644
index 0000000..d9254b8
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/SyntaxHighlighter.cs
@@ -0,0 +1,710 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    public class SyntaxHighlighter : IDisposable
+    {
+
+        //styles for twzy
+        public readonly Style BlueStyle = new TextStyle(Brushes.RoyalBlue, null, FontStyle.Regular);
+        public readonly Style BlueBoldStyle = new TextStyle(Brushes.Blue, null, FontStyle.Bold);
+        public readonly Style BoldStyle = new TextStyle(Brushes.Orange, null, FontStyle.Bold);
+        public readonly Style GrayStyle = new TextStyle(Brushes.Gray, null, FontStyle.Regular);
+        public readonly Style MagentaStyle = new TextStyle(Brushes.Magenta, null, FontStyle.Regular);
+        public readonly Style GreenStyle = new TextStyle(Brushes.Green, null, FontStyle.Regular);
+        public readonly Style BrownStyle = new TextStyle(Brushes.Lime, null, FontStyle.Regular);
+        public readonly Style RedStyle = new TextStyle(Brushes.Red, null, FontStyle.Regular);
+        public readonly Style MaroonStyle = new TextStyle(Brushes.Maroon, null, FontStyle.Regular);
+
+        //
+        Dictionary<string, SyntaxDescriptor> descByXMLfileNames = new Dictionary<string, SyntaxDescriptor>();
+        static readonly Platform platformType = PlatformType.GetOperationSystemPlatform();
+
+        public static RegexOptions RegexCompiledOption
+        {
+            get
+            {
+                if (platformType == Platform.X86)
+                    return RegexOptions.Compiled;
+                else
+                    return RegexOptions.None;
+            }
+        }
+
+        /// <summary>
+        /// Highlights syntax for given language
+        /// </summary>
+        public virtual void HighlightSyntax(Language language, Range range)
+        {
+            switch (language)
+            {
+                case Language.CSharp: CSharpSyntaxHighlight(range); break;
+                case Language.VB: VBSyntaxHighlight(range); break;
+                case Language.HTML: HTMLSyntaxHighlight(range); break;
+                case Language.SQL: SQLSyntaxHighlight(range); break;
+                case Language.PHP: PHPSyntaxHighlight(range); break;
+                case Language.JS: JScriptSyntaxHighlight(range); break;
+                default:
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// Highlights syntax for given XML description file
+        /// </summary>
+        public virtual void HighlightSyntax(string XMLdescriptionFile, Range range)
+        {
+            SyntaxDescriptor desc = null;
+            if (!descByXMLfileNames.TryGetValue(XMLdescriptionFile, out desc))
+            {
+                var doc = new XmlDocument();
+                string file = XMLdescriptionFile;
+                if (!File.Exists(file))
+                    file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(file));
+
+                doc.LoadXml(File.ReadAllText(file));
+                desc = ParseXmlDescription(doc);
+                descByXMLfileNames[XMLdescriptionFile] = desc;
+            }
+            HighlightSyntax(desc, range);
+        }
+
+        public virtual void AutoIndentNeeded(object sender, AutoIndentEventArgs args)
+        {
+            FastColoredTextBox tb = (sender as FastColoredTextBox);
+            Language language = tb.Language;
+            switch (language)
+            {
+                case Language.CSharp: CSharpAutoIndentNeeded(sender, args); break;
+                case Language.VB: VBAutoIndentNeeded(sender, args); break;
+                case Language.HTML: HTMLAutoIndentNeeded(sender, args); break;
+                case Language.SQL: SQLAutoIndentNeeded(sender, args); break;
+                case Language.PHP: PHPAutoIndentNeeded(sender, args); break;
+                case Language.JS: CSharpAutoIndentNeeded(sender, args); break;//JS like C#
+                default:
+                    break;
+            }
+        }
+
+        private void PHPAutoIndentNeeded(object sender, AutoIndentEventArgs args)
+        {
+            /*
+            FastColoredTextBox tb = sender as FastColoredTextBox;
+            tb.CalcAutoIndentShiftByCodeFolding(sender, args);*/
+            //block {}
+            if (Regex.IsMatch(args.LineText, @"^[^""']*\{.*\}[^""']*$"))
+                return;
+            //start of block {}
+            if (Regex.IsMatch(args.LineText, @"^[^""']*\{"))
+            {
+                args.ShiftNextLines = args.TabLength;
+                return;
+            }
+            //end of block {}
+            if (Regex.IsMatch(args.LineText, @"}[^""']*$"))
+            {
+                args.Shift = -args.TabLength;
+                args.ShiftNextLines = -args.TabLength;
+                return;
+            }
+            //is unclosed operator in previous line ?
+            if (Regex.IsMatch(args.PrevLineText, @"^\s*(if|for|foreach|while|[\}\s]*else)\b[^{]*$"))
+                if (!Regex.IsMatch(args.PrevLineText, @"(;\s*$)|(;\s*//)"))//operator is unclosed
+                {
+                    args.Shift = args.TabLength;
+                    return;
+                }
+        }
+
+        private void SQLAutoIndentNeeded(object sender, AutoIndentEventArgs args)
+        {
+            FastColoredTextBox tb = sender as FastColoredTextBox;
+            tb.CalcAutoIndentShiftByCodeFolding(sender, args);
+        }
+
+        private void HTMLAutoIndentNeeded(object sender, AutoIndentEventArgs args)
+        {
+            FastColoredTextBox tb = sender as FastColoredTextBox;
+            tb.CalcAutoIndentShiftByCodeFolding(sender, args);
+        }
+
+        private void VBAutoIndentNeeded(object sender, AutoIndentEventArgs args)
+        {
+            //end of block
+            if (Regex.IsMatch(args.LineText, @"^\s*(End|EndIf|Next|Loop)\b", RegexOptions.IgnoreCase))
+            {
+                args.Shift = -args.TabLength;
+                args.ShiftNextLines = -args.TabLength;
+                return;
+            }
+            //start of declaration
+            if (Regex.IsMatch(args.LineText, @"\b(Class|Property|Enum|Structure|Sub|Function|Namespace|Interface|Get|Set)\b", RegexOptions.IgnoreCase))
+            {
+                args.ShiftNextLines = args.TabLength;
+                return;
+            }
+            // then ...
+            if (Regex.IsMatch(args.LineText, @"\b(Then)\s*\S+", RegexOptions.IgnoreCase))
+                return;
+            //start of operator block
+            if (Regex.IsMatch(args.LineText, @"^\s*(If|While|For|Do|Try|With|Using|Select)\b", RegexOptions.IgnoreCase))
+            {
+                args.ShiftNextLines = args.TabLength;
+                return;
+            }
+
+            //Statements else, elseif, case etc
+            if (Regex.IsMatch(args.LineText, @"^\s*(Else|ElseIf|Case|Catch|Finally)\b", RegexOptions.IgnoreCase))
+            {
+                args.Shift = -args.TabLength;
+                return;
+            }
+
+            //Char _
+            if (args.PrevLineText.TrimEnd().EndsWith("_"))
+            {
+                args.Shift = args.TabLength;
+                return;
+            }
+        }
+
+        private void CSharpAutoIndentNeeded(object sender, AutoIndentEventArgs args)
+        {
+            //block {}
+            if (Regex.IsMatch(args.LineText, @"^[^""']*\{.*\}[^""']*$"))
+                return;
+            //start of block {}
+            if (Regex.IsMatch(args.LineText, @"^[^""']*\{"))
+            {
+                args.ShiftNextLines = args.TabLength;
+                return;
+            }
+            //end of block {}
+            if (Regex.IsMatch(args.LineText, @"}[^""']*$"))
+            {
+                args.Shift = -args.TabLength;
+                args.ShiftNextLines = -args.TabLength;
+                return;
+            }
+            //label
+            if (Regex.IsMatch(args.LineText, @"^\s*\w+\s*:\s*($|//)") &&
+                !Regex.IsMatch(args.LineText, @"^\s*default\s*:"))
+            {
+                args.Shift = -args.TabLength;
+                return;
+            }
+            //some statements: case, default
+            if (Regex.IsMatch(args.LineText, @"^\s*(case|default)\b.*:\s*($|//)"))
+            {
+                args.Shift = -args.TabLength / 2;
+                return;
+            }
+            //is unclosed operator in previous line ?
+            if (Regex.IsMatch(args.PrevLineText, @"^\s*(if|for|foreach|while|[\}\s]*else)\b[^{]*$"))
+                if (!Regex.IsMatch(args.PrevLineText, @"(;\s*$)|(;\s*//)"))//operator is unclosed
+                {
+                    args.Shift = args.TabLength;
+                    return;
+                }
+        }
+
+        public static SyntaxDescriptor ParseXmlDescription(XmlDocument doc)
+        {
+            SyntaxDescriptor desc = new SyntaxDescriptor();
+            XmlNode brackets = doc.SelectSingleNode("doc/brackets");
+            if (brackets != null)
+            {
+                if (brackets.Attributes["left"] == null || brackets.Attributes["right"] == null ||
+                    brackets.Attributes["left"].Value == "" || brackets.Attributes["right"].Value == "")
+                {
+                    desc.leftBracket = '\x0';
+                    desc.rightBracket = '\x0';
+                }
+                else
+                {
+                    desc.leftBracket = brackets.Attributes["left"].Value[0];
+                    desc.rightBracket = brackets.Attributes["right"].Value[0];
+                }
+
+                if (brackets.Attributes["left2"] == null || brackets.Attributes["right2"] == null ||
+    brackets.Attributes["left2"].Value == "" || brackets.Attributes["right2"].Value == "")
+                {
+                    desc.leftBracket2 = '\x0';
+                    desc.rightBracket2 = '\x0';
+                }
+                else
+                {
+                    desc.leftBracket2 = brackets.Attributes["left2"].Value[0];
+                    desc.rightBracket2 = brackets.Attributes["right2"].Value[0];
+                }
+            }
+
+            Dictionary<string, Style> styleByName = new Dictionary<string, Style>();
+
+            foreach (XmlNode style in doc.SelectNodes("doc/style"))
+            {
+                var s = ParseStyle(style);
+                styleByName[style.Attributes["name"].Value] = s;
+                desc.styles.Add(s);
+            }
+            foreach (XmlNode rule in doc.SelectNodes("doc/rule"))
+                desc.rules.Add(ParseRule(rule, styleByName));
+            foreach (XmlNode folding in doc.SelectNodes("doc/folding"))
+                desc.foldings.Add(ParseFolding(folding));
+
+            return desc;
+        }
+
+        private static FoldingDesc ParseFolding(XmlNode foldingNode)
+        {
+            FoldingDesc folding = new FoldingDesc();
+            //regex
+            folding.startMarkerRegex = foldingNode.Attributes["start"].Value;
+            folding.finishMarkerRegex = foldingNode.Attributes["finish"].Value;
+            //options
+            var optionsA = foldingNode.Attributes["options"];
+            if (optionsA != null)
+                folding.options = (RegexOptions)Enum.Parse(typeof(RegexOptions), optionsA.Value);
+
+            return folding;
+        }
+
+        private static RuleDesc ParseRule(XmlNode ruleNode, Dictionary<string, Style> styles)
+        {
+            RuleDesc rule = new RuleDesc();
+            rule.pattern = ruleNode.InnerText;
+            //
+            var styleA = ruleNode.Attributes["style"];
+            var optionsA = ruleNode.Attributes["options"];
+            //Style
+            if (styleA == null)
+                throw new Exception("Rule must contain style name.");
+            if (!styles.ContainsKey(styleA.Value))
+                throw new Exception("Style '" + styleA.Value + "' is not found.");
+            rule.style = styles[styleA.Value];
+            //options
+            if (optionsA != null)
+                rule.options = (RegexOptions)Enum.Parse(typeof(RegexOptions), optionsA.Value);
+
+            return rule;
+        }
+
+        private static Style ParseStyle(XmlNode styleNode)
+        {
+            var typeA = styleNode.Attributes["type"];
+            var colorA = styleNode.Attributes["color"];
+            var backColorA = styleNode.Attributes["backColor"];
+            var fontStyleA = styleNode.Attributes["fontStyle"];
+            var nameA = styleNode.Attributes["name"];
+            //colors
+            SolidBrush foreBrush = null;
+            if (colorA != null)
+                foreBrush = new SolidBrush(ParseColor(colorA.Value));
+            SolidBrush backBrush = null;
+            if (backColorA != null)
+                backBrush = new SolidBrush(ParseColor(backColorA.Value));
+            //fontStyle
+            FontStyle fontStyle = FontStyle.Regular;
+            if (fontStyleA != null)
+                fontStyle = (FontStyle)Enum.Parse(typeof(FontStyle), fontStyleA.Value);
+
+            return new TextStyle(foreBrush, backBrush, fontStyle);
+        }
+
+        private static Color ParseColor(string s)
+        {
+            if (s.StartsWith("#"))
+            {
+                if (s.Length <= 7)
+                    return Color.FromArgb(255, Color.FromArgb(Int32.Parse(s.Substring(1), System.Globalization.NumberStyles.AllowHexSpecifier)));
+                else
+                    return Color.FromArgb(Int32.Parse(s.Substring(1), System.Globalization.NumberStyles.AllowHexSpecifier));
+            }
+            else
+                return Color.FromName(s);
+        }
+
+        public void HighlightSyntax(SyntaxDescriptor desc, Range range)
+        {
+            //set style order
+            range.tb.ClearStylesBuffer();
+            for (int i = 0; i < desc.styles.Count; i++)
+                range.tb.Styles[i] = desc.styles[i];
+            //brackets
+            range.tb.LeftBracket = desc.leftBracket;
+            range.tb.RightBracket = desc.rightBracket;
+            range.tb.LeftBracket2 = desc.leftBracket2;
+            range.tb.RightBracket2 = desc.rightBracket2;
+            //clear styles of range
+            range.ClearStyle(desc.styles.ToArray());
+            //highlight syntax
+            foreach (var rule in desc.rules)
+                range.SetStyle(rule.style, rule.Regex);
+            //clear folding
+            range.ClearFoldingMarkers();
+            //folding markers
+            foreach (var folding in desc.foldings)
+                range.SetFoldingMarkers(folding.startMarkerRegex, folding.finishMarkerRegex, folding.options);
+        }
+
+        Regex CSharpStringRegex, CSharpCommentRegex1, CSharpCommentRegex2, CSharpCommentRegex3, CSharpNumberRegex, CSharpAttributeRegex, CSharpClassNameRegex, CSharpKeywordRegex;
+
+        void InitCShaprRegex()
+        {
+            CSharpStringRegex = new Regex(@"""""|@""""|''|@"".*?""|(?<!@)(?<range>"".*?[^\\]"")|'.*?[^\\]'", RegexCompiledOption);
+            CSharpCommentRegex1 = new Regex(@"//.*$", RegexOptions.Multiline | RegexCompiledOption);
+            CSharpCommentRegex2 = new Regex(@"(/\*.*?\*/)|(/\*.*)", RegexOptions.Singleline | RegexCompiledOption);
+            CSharpCommentRegex3 = new Regex(@"(/\*.*?\*/)|(.*\*/)", RegexOptions.Singleline | RegexOptions.RightToLeft | RegexCompiledOption);
+            CSharpNumberRegex = new Regex(@"\b\d+[\.]?\d*([eE]\-?\d+)?[lLdDfF]?\b|\b0x[a-fA-F\d]+\b", RegexCompiledOption);
+            CSharpAttributeRegex = new Regex(@"^\s*(?<range>\[.+?\])\s*$", RegexOptions.Multiline | RegexCompiledOption);
+            CSharpClassNameRegex = new Regex(@"\b(class|struct|enum|interface)\s+(?<range>\w+?)\b", RegexCompiledOption);
+            CSharpKeywordRegex = new Regex(@"\b(abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while|add|alias|ascending|descending|dynamic|from|get|global|group|into|join|let|orderby|partial|remove|select|set|value|var|where|yield)\b|#region\b|#endregion\b", RegexCompiledOption);
+        }
+        /// <summary>
+        /// Highlights C# code
+        /// </summary>
+        /// <param name="range"></param>
+        public virtual void CSharpSyntaxHighlight(Range range)
+        {
+            range.tb.CommentPrefix = "//";
+            range.tb.LeftBracket = '(';
+            range.tb.RightBracket = ')';
+            range.tb.LeftBracket2 = '\x0';
+            range.tb.RightBracket2 = '\x0';
+            //clear style of changed range
+            range.ClearStyle(BlueStyle, BoldStyle, GrayStyle, MagentaStyle, GreenStyle, BrownStyle);
+            //
+            if (CSharpStringRegex == null)
+                InitCShaprRegex();
+            //string highlighting
+            range.SetStyle(BrownStyle, CSharpStringRegex);
+            //comment highlighting
+            range.SetStyle(GreenStyle, CSharpCommentRegex1);
+            range.SetStyle(GreenStyle, CSharpCommentRegex2);
+            range.SetStyle(GreenStyle, CSharpCommentRegex3);
+            //number highlighting
+            range.SetStyle(MagentaStyle, CSharpNumberRegex);
+            //attribute highlighting
+            range.SetStyle(GreenStyle, CSharpAttributeRegex);
+            //class name highlighting
+            range.SetStyle(BoldStyle, CSharpClassNameRegex);
+            //keyword highlighting
+            range.SetStyle(BlueStyle, CSharpKeywordRegex);
+
+
+            //find document comments
+            foreach (var r in range.GetRanges(@"^\s*///.*$", RegexOptions.Multiline))
+            {
+                //remove C# highlighting from this fragment
+                r.ClearStyle(StyleIndex.All);
+                //do XML highlighting
+                if (HTMLTagRegex == null)
+                    InitHTMLRegex();
+                //
+                r.SetStyle(GreenStyle);
+                //tags
+                foreach (var rr in r.GetRanges(HTMLTagContentRegex))
+                {
+                    rr.ClearStyle(StyleIndex.All);
+                    rr.SetStyle(GrayStyle);
+                }
+                //prefix '///'
+                foreach (var rr in r.GetRanges(@"^\s*///", RegexOptions.Multiline))
+                {
+                    rr.ClearStyle(StyleIndex.All);
+                    rr.SetStyle(GrayStyle);
+                }
+            }
+
+            //clear folding markers
+            range.ClearFoldingMarkers();
+            //set folding markers
+            range.SetFoldingMarkers("{", "}");//allow to collapse brackets block
+            range.SetFoldingMarkers(@"#region\b", @"#endregion\b");//allow to collapse #region blocks
+            range.SetFoldingMarkers(@"/\*", @"\*/");//allow to collapse comment block
+        }
+
+        Regex VBStringRegex, VBCommentRegex, VBNumberRegex, VBClassNameRegex, VBKeywordRegex;
+
+        void InitVBRegex()
+        {
+            VBStringRegex = new Regex(@"""""|"".*?[^\\]""", RegexCompiledOption);
+            VBCommentRegex = new Regex(@"'.*$", RegexOptions.Multiline | RegexCompiledOption);
+            VBNumberRegex = new Regex(@"\b\d+[\.]?\d*([eE]\-?\d+)?\b", RegexCompiledOption);
+            VBClassNameRegex = new Regex(@"\b(Class|Structure|Enum|Interface)[ ]+(?<range>\w+?)\b", RegexOptions.IgnoreCase | RegexCompiledOption);
+            VBKeywordRegex = new Regex(@"\b(AddHandler|AddressOf|Alias|And|AndAlso|As|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|CBool|CByte|CChar|CDate|CDbl|CDec|Char|CInt|Class|CLng|CObj|Const|Continue|CSByte|CShort|CSng|CStr|CType|CUInt|CULng|CUShort|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else|ElseIf|End|EndIf|Enum|Erase|Error|Event|Exit|False|Finally|For|Friend|Function|Get|GetType|GetXMLNamespace|Global|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|IsNot|Let|Lib|Like|Long|Loop|Me|Mod|Module|MustInherit|MustOverride|MyBase|MyClass|Namespace|Narrowing|New|Next|Not|Nothing|NotInheritable|NotOverridable|Object|Of|On|Operator|Option|Optional|Or|OrElse|Overloads|Overridable|Overrides|ParamArray|Partial|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|REM|RemoveHandler|Resume|Return|SByte|Select|Set|Shadows|Shared|Short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|True|Try|TryCast|TypeOf|UInteger|ULong|UShort|Using|Variant|Wend|When|While|Widening|With|WithEvents|WriteOnly|Xor|Region)\b|(#Const|#Else|#ElseIf|#End|#If|#Region)\b", RegexOptions.IgnoreCase | RegexCompiledOption);
+        }
+
+        /// <summary>
+        /// Highlights VB code
+        /// </summary>
+        /// <param name="range"></param>
+        public virtual void VBSyntaxHighlight(Range range)
+        {
+            range.tb.CommentPrefix = "'";
+            range.tb.LeftBracket = '(';
+            range.tb.RightBracket = ')';
+            range.tb.LeftBracket2 = '\x0';
+            range.tb.RightBracket2 = '\x0';
+            //clear style of changed range
+            range.ClearStyle(BrownStyle, GreenStyle, MagentaStyle, BoldStyle, BlueStyle);
+            //
+            if (VBStringRegex == null)
+                InitVBRegex();
+            //string highlighting
+            range.SetStyle(BrownStyle, VBStringRegex);
+            //comment highlighting
+            range.SetStyle(GreenStyle, VBCommentRegex);
+            //number highlighting
+            range.SetStyle(MagentaStyle, VBNumberRegex);
+            //class name highlighting
+            range.SetStyle(BoldStyle, VBClassNameRegex);
+            //keyword highlighting
+            range.SetStyle(BlueStyle, VBKeywordRegex);
+
+            //clear folding markers
+            range.ClearFoldingMarkers();
+            //set folding markers
+            range.SetFoldingMarkers(@"#Region\b", @"#End\s+Region\b", RegexOptions.IgnoreCase);
+            range.SetFoldingMarkers(@"\b(Class|Property|Enum|Structure|Interface)[ \t]+\S+", @"\bEnd (Class|Property|Enum|Structure|Interface)\b", RegexOptions.IgnoreCase);
+            range.SetFoldingMarkers(@"^\s*(?<range>While)[ \t]+\S+", @"^\s*(?<range>End While)\b", RegexOptions.Multiline | RegexOptions.IgnoreCase);
+            range.SetFoldingMarkers(@"\b(Sub|Function)[ \t]+[^\s']+", @"\bEnd (Sub|Function)\b", RegexOptions.IgnoreCase);//this declared separately because Sub and Function can be unclosed
+            range.SetFoldingMarkers(@"(\r|\n|^)[ \t]*(?<range>Get|Set)[ \t]*(\r|\n|$)", @"\bEnd (Get|Set)\b", RegexOptions.IgnoreCase);
+            range.SetFoldingMarkers(@"^\s*(?<range>For|For\s+Each)\b", @"^\s*(?<range>Next)\b", RegexOptions.Multiline | RegexOptions.IgnoreCase);
+            range.SetFoldingMarkers(@"^\s*(?<range>Do)\b", @"^\s*(?<range>Loop)\b", RegexOptions.Multiline | RegexOptions.IgnoreCase);
+        }
+
+        Regex HTMLTagRegex, HTMLTagNameRegex, HTMLEndTagRegex, HTMLAttrRegex, HTMLAttrValRegex, HTMLCommentRegex1, HTMLCommentRegex2, HTMLEntityRegex, HTMLTagContentRegex;
+
+        void InitHTMLRegex()
+        {
+            HTMLCommentRegex1 = new Regex(@"(<!--.*?-->)|(<!--.*)", RegexOptions.Singleline | RegexCompiledOption);
+            HTMLCommentRegex2 = new Regex(@"(<!--.*?-->)|(.*-->)", RegexOptions.Singleline | RegexOptions.RightToLeft | RegexCompiledOption);
+            HTMLTagRegex = new Regex(@"<|/>|</|>", RegexCompiledOption);
+            HTMLTagNameRegex = new Regex(@"<(?<range>[!\w:]+)", RegexCompiledOption);
+            HTMLEndTagRegex = new Regex(@"</(?<range>[\w:]+)>", RegexCompiledOption);
+            HTMLTagContentRegex = new Regex(@"<[^>]+>", RegexCompiledOption);
+            HTMLAttrRegex = new Regex(@"(?<range>[\w\d\-]{1,20}?)='[^']*'|(?<range>[\w\d\-]{1,20})=""[^""]*""|(?<range>[\w\d\-]{1,20})=[\w\d\-]{1,20}", RegexCompiledOption);
+            HTMLAttrValRegex = new Regex(@"[\w\d\-]{1,20}?=(?<range>'[^']*')|[\w\d\-]{1,20}=(?<range>""[^""]*"")|[\w\d\-]{1,20}=(?<range>[\w\d\-]{1,20})", RegexCompiledOption);
+            HTMLEntityRegex = new Regex(@"\&(amp|gt|lt|nbsp|quot|apos|copy|reg|#[0-9]{1,8}|#x[0-9a-f]{1,8});", RegexCompiledOption | RegexOptions.IgnoreCase);
+        }
+
+        /// <summary>
+        /// Highlights HTML code
+        /// </summary>
+        /// <param name="range"></param>
+        public virtual void HTMLSyntaxHighlight(Range range)
+        {
+            range.tb.CommentPrefix = null;
+            range.tb.LeftBracket = '<';
+            range.tb.RightBracket = '>';
+            range.tb.LeftBracket2 = '(';
+            range.tb.RightBracket2 = ')';
+            //clear style of changed range
+            range.ClearStyle(BlueStyle, MaroonStyle, RedStyle);
+            //
+            if (HTMLTagRegex == null)
+                InitHTMLRegex();
+            //comment highlighting
+            range.SetStyle(GreenStyle, HTMLCommentRegex1);
+            range.SetStyle(GreenStyle, HTMLCommentRegex2);
+            //tag brackets highlighting
+            range.SetStyle(BlueStyle, HTMLTagRegex);
+            //tag name
+            range.SetStyle(MaroonStyle, HTMLTagNameRegex);
+            //end of tag
+            range.SetStyle(MaroonStyle, HTMLEndTagRegex);
+            //attributes
+            range.SetStyle(RedStyle, HTMLAttrRegex);
+            //attribute values
+            range.SetStyle(BlueStyle, HTMLAttrValRegex);
+            //html entity
+            range.SetStyle(RedStyle, HTMLEntityRegex);
+
+            //clear folding markers
+            range.ClearFoldingMarkers();
+            //set folding markers
+            range.SetFoldingMarkers("<head", "</head>", RegexOptions.IgnoreCase);
+            range.SetFoldingMarkers("<body", "</body>", RegexOptions.IgnoreCase);
+            range.SetFoldingMarkers("<table", "</table>", RegexOptions.IgnoreCase);
+            range.SetFoldingMarkers("<form", "</form>", RegexOptions.IgnoreCase);
+            range.SetFoldingMarkers("<div", "</div>", RegexOptions.IgnoreCase);
+            range.SetFoldingMarkers("<script", "</script>", RegexOptions.IgnoreCase);
+            range.SetFoldingMarkers("<tr", "</tr>", RegexOptions.IgnoreCase);
+        }
+
+        Regex SQLStringRegex, SQLNumberRegex, SQLCommentRegex1, SQLCommentRegex2, SQLCommentRegex3, SQLVarRegex, SQLStatementsRegex, SQLKeywordsRegex, SQLFunctionsRegex;
+
+        void InitSQLRegex()
+        {
+            SQLStringRegex = new Regex(@"""""|''|"".*?[^\\]""|'.*?[^\\]'", RegexCompiledOption);
+            SQLNumberRegex = new Regex(@"\b\d+[\.]?\d*([eE]\-?\d+)?\b", RegexCompiledOption);
+            SQLCommentRegex1 = new Regex(@"--.*$", RegexOptions.Multiline | RegexCompiledOption);
+            SQLCommentRegex2 = new Regex(@"(/\*.*?\*/)|(/\*.*)", RegexOptions.Singleline | RegexCompiledOption);
+            SQLCommentRegex3 = new Regex(@"(/\*.*?\*/)|(.*\*/)", RegexOptions.Singleline | RegexOptions.RightToLeft | RegexCompiledOption);
+            SQLVarRegex = new Regex(@"@[a-zA-Z_\d]*\b", RegexCompiledOption);
+            SQLStatementsRegex = new Regex(@"\b(ALTER APPLICATION ROLE|ALTER ASSEMBLY|ALTER ASYMMETRIC KEY|ALTER AUTHORIZATION|ALTER BROKER PRIORITY|ALTER CERTIFICATE|ALTER CREDENTIAL|ALTER CRYPTOGRAPHIC PROVIDER|ALTER DATABASE|ALTER DATABASE AUDIT SPECIFICATION|ALTER DATABASE ENCRYPTION KEY|ALTER ENDPOINT|ALTER EVENT SESSION|ALTER FULLTEXT CATALOG|ALTER FULLTEXT INDEX|ALTER FULLTEXT STOPLIST|ALTER FUNCTION|ALTER INDEX|ALTER LOGIN|ALTER MASTER KEY|ALTER MESSAGE TYPE|ALTER PARTITION FUNCTION|ALTER PARTITION SCHEME|ALTER PROCEDURE|ALTER QUEUE|ALTER REMOTE SERVICE BINDING|ALTER RESOURCE GOVERNOR|ALTER RESOURCE POOL|ALTER ROLE|ALTER ROUTE|ALTER SCHEMA|ALTER SERVER AUDIT|ALTER SERVER AUDIT SPECIFICATION|ALTER SERVICE|ALTER SERVICE MASTER KEY|ALTER SYMMETRIC KEY|ALTER TABLE|ALTER TRIGGER|ALTER USER|ALTER VIEW|ALTER WORKLOAD GROUP|ALTER XML SCHEMA COLLECTION|BULK INSERT|CREATE AGGREGATE|CREATE APPLICATION ROLE|CREATE ASSEMBLY|CREATE ASYMMETRIC KEY|CREATE BROKER PRIORITY|CREATE CERTIFICATE|CREATE CONTRACT|CREATE CREDENTIAL|CREATE CRYPTOGRAPHIC PROVIDER|CREATE DATABASE|CREATE DATABASE AUDIT SPECIFICATION|CREATE DATABASE ENCRYPTION KEY|CREATE DEFAULT|CREATE ENDPOINT|CREATE EVENT NOTIFICATION|CREATE EVENT SESSION|CREATE FULLTEXT CATALOG|CREATE FULLTEXT INDEX|CREATE FULLTEXT STOPLIST|CREATE FUNCTION|CREATE INDEX|CREATE LOGIN|CREATE MASTER KEY|CREATE MESSAGE TYPE|CREATE PARTITION FUNCTION|CREATE PARTITION SCHEME|CREATE PROCEDURE|CREATE QUEUE|CREATE REMOTE SERVICE BINDING|CREATE RESOURCE POOL|CREATE ROLE|CREATE ROUTE|CREATE RULE|CREATE SCHEMA|CREATE SERVER AUDIT|CREATE SERVER AUDIT SPECIFICATION|CREATE SERVICE|CREATE SPATIAL INDEX|CREATE STATISTICS|CREATE SYMMETRIC KEY|CREATE SYNONYM|CREATE TABLE|CREATE TRIGGER|CREATE TYPE|CREATE USER|CREATE VIEW|CREATE WORKLOAD GROUP|CREATE XML INDEX|CREATE XML SCHEMA COLLECTION|DELETE|DISABLE TRIGGER|DROP AGGREGATE|DROP APPLICATION ROLE|DROP ASSEMBLY|DROP ASYMMETRIC KEY|DROP BROKER PRIORITY|DROP CERTIFICATE|DROP CONTRACT|DROP CREDENTIAL|DROP CRYPTOGRAPHIC PROVIDER|DROP DATABASE|DROP DATABASE AUDIT SPECIFICATION|DROP DATABASE ENCRYPTION KEY|DROP DEFAULT|DROP ENDPOINT|DROP EVENT NOTIFICATION|DROP EVENT SESSION|DROP FULLTEXT CATALOG|DROP FULLTEXT INDEX|DROP FULLTEXT STOPLIST|DROP FUNCTION|DROP INDEX|DROP LOGIN|DROP MASTER KEY|DROP MESSAGE TYPE|DROP PARTITION FUNCTION|DROP PARTITION SCHEME|DROP PROCEDURE|DROP QUEUE|DROP REMOTE SERVICE BINDING|DROP RESOURCE POOL|DROP ROLE|DROP ROUTE|DROP RULE|DROP SCHEMA|DROP SERVER AUDIT|DROP SERVER AUDIT SPECIFICATION|DROP SERVICE|DROP SIGNATURE|DROP STATISTICS|DROP SYMMETRIC KEY|DROP SYNONYM|DROP TABLE|DROP TRIGGER|DROP TYPE|DROP USER|DROP VIEW|DROP WORKLOAD GROUP|DROP XML SCHEMA COLLECTION|ENABLE TRIGGER|EXEC|EXECUTE|FROM|INSERT|MERGE|OPTION|OUTPUT|SELECT|TOP|TRUNCATE TABLE|UPDATE|UPDATE STATISTICS|WHERE|WITH)\b", RegexOptions.IgnoreCase | RegexCompiledOption);
+            SQLKeywordsRegex = new Regex(@"\b(ADD|ALL|AND|ANY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BY|CASCADE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COLLATE|COLUMN|COMMIT|COMPUTE|CONSTRAINT|CONTAINS|CONTINUE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DOUBLE|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXISTS|EXIT|EXTERNAL|FETCH|FILE|FILLFACTOR|FOR|FOREIGN|FREETEXT|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITY_INSERT|IDENTITYCOL|IF|IN|INDEX|INNER|INTERSECT|INTO|IS|JOIN|KEY|KILL|LIKE|LINENO|LOAD|NATIONAL|NOCHECK|NONCLUSTERED|NOT|NULL|OF|OFF|OFFSETS|ON|OPEN|OR|ORDER|OUTER|OVER|PERCENT|PIVOT|PLAN|PRECISION|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVERT|REVOKE|ROLLBACK|ROWCOUNT|ROWGUIDCOL|RULE|SAVE|SCHEMA|SECURITYAUDIT|SET|SHUTDOWN|SOME|STATISTICS|TABLE|TABLESAMPLE|TEXTSIZE|THEN|TO|TRAN|TRANSACTION|TRIGGER|TSEQUAL|UNION|UNIQUE|UNPIVOT|UPDATETEXT|USE|USER|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHILE|WRITETEXT)\b", RegexOptions.IgnoreCase | RegexCompiledOption);
+            SQLFunctionsRegex = new Regex(@"(@@CONNECTIONS|@@CPU_BUSY|@@CURSOR_ROWS|@@DATEFIRST|@@DATEFIRST|@@DBTS|@@ERROR|@@FETCH_STATUS|@@IDENTITY|@@IDLE|@@IO_BUSY|@@LANGID|@@LANGUAGE|@@LOCK_TIMEOUT|@@MAX_CONNECTIONS|@@MAX_PRECISION|@@NESTLEVEL|@@OPTIONS|@@PACKET_ERRORS|@@PROCID|@@REMSERVER|@@ROWCOUNT|@@SERVERNAME|@@SERVICENAME|@@SPID|@@TEXTSIZE|@@TRANCOUNT|@@VERSION)\b|\b(ABS|ACOS|APP_NAME|ASCII|ASIN|ASSEMBLYPROPERTY|AsymKey_ID|ASYMKEY_ID|asymkeyproperty|ASYMKEYPROPERTY|ATAN|ATN2|AVG|CASE|CAST|CEILING|Cert_ID|Cert_ID|CertProperty|CHAR|CHARINDEX|CHECKSUM_AGG|COALESCE|COL_LENGTH|COL_NAME|COLLATIONPROPERTY|COLLATIONPROPERTY|COLUMNPROPERTY|COLUMNS_UPDATED|COLUMNS_UPDATED|CONTAINSTABLE|CONVERT|COS|COT|COUNT|COUNT_BIG|CRYPT_GEN_RANDOM|CURRENT_TIMESTAMP|CURRENT_TIMESTAMP|CURRENT_USER|CURRENT_USER|CURSOR_STATUS|DATABASE_PRINCIPAL_ID|DATABASE_PRINCIPAL_ID|DATABASEPROPERTY|DATABASEPROPERTYEX|DATALENGTH|DATALENGTH|DATEADD|DATEDIFF|DATENAME|DATEPART|DAY|DB_ID|DB_NAME|DECRYPTBYASYMKEY|DECRYPTBYCERT|DECRYPTBYKEY|DECRYPTBYKEYAUTOASYMKEY|DECRYPTBYKEYAUTOCERT|DECRYPTBYPASSPHRASE|DEGREES|DENSE_RANK|DIFFERENCE|ENCRYPTBYASYMKEY|ENCRYPTBYCERT|ENCRYPTBYKEY|ENCRYPTBYPASSPHRASE|ERROR_LINE|ERROR_MESSAGE|ERROR_NUMBER|ERROR_PROCEDURE|ERROR_SEVERITY|ERROR_STATE|EVENTDATA|EXP|FILE_ID|FILE_IDEX|FILE_NAME|FILEGROUP_ID|FILEGROUP_NAME|FILEGROUPPROPERTY|FILEPROPERTY|FLOOR|fn_helpcollations|fn_listextendedproperty|fn_servershareddrives|fn_virtualfilestats|fn_virtualfilestats|FORMATMESSAGE|FREETEXTTABLE|FULLTEXTCATALOGPROPERTY|FULLTEXTSERVICEPROPERTY|GETANSINULL|GETDATE|GETUTCDATE|GROUPING|HAS_PERMS_BY_NAME|HOST_ID|HOST_NAME|IDENT_CURRENT|IDENT_CURRENT|IDENT_INCR|IDENT_INCR|IDENT_SEED|IDENTITY\(|INDEX_COL|INDEXKEY_PROPERTY|INDEXPROPERTY|IS_MEMBER|IS_OBJECTSIGNED|IS_SRVROLEMEMBER|ISDATE|ISDATE|ISNULL|ISNUMERIC|Key_GUID|Key_GUID|Key_ID|Key_ID|KEY_NAME|KEY_NAME|LEFT|LEN|LOG|LOG10|LOWER|LTRIM|MAX|MIN|MONTH|NCHAR|NEWID|NTILE|NULLIF|OBJECT_DEFINITION|OBJECT_ID|OBJECT_NAME|OBJECT_SCHEMA_NAME|OBJECTPROPERTY|OBJECTPROPERTYEX|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|ORIGINAL_LOGIN|ORIGINAL_LOGIN|PARSENAME|PATINDEX|PATINDEX|PERMISSIONS|PI|POWER|PUBLISHINGSERVERNAME|PWDCOMPARE|PWDENCRYPT|QUOTENAME|RADIANS|RAND|RANK|REPLACE|REPLICATE|REVERSE|RIGHT|ROUND|ROW_NUMBER|ROWCOUNT_BIG|RTRIM|SCHEMA_ID|SCHEMA_ID|SCHEMA_NAME|SCHEMA_NAME|SCOPE_IDENTITY|SERVERPROPERTY|SESSION_USER|SESSION_USER|SESSIONPROPERTY|SETUSER|SIGN|SignByAsymKey|SignByCert|SIN|SOUNDEX|SPACE|SQL_VARIANT_PROPERTY|SQRT|SQUARE|STATS_DATE|STDEV|STDEVP|STR|STUFF|SUBSTRING|SUM|SUSER_ID|SUSER_NAME|SUSER_SID|SUSER_SNAME|SWITCHOFFSET|SYMKEYPROPERTY|symkeyproperty|sys\.dm_db_index_physical_stats|sys\.fn_builtin_permissions|sys\.fn_my_permissions|SYSDATETIME|SYSDATETIMEOFFSET|SYSTEM_USER|SYSTEM_USER|SYSUTCDATETIME|TAN|TERTIARY_WEIGHTS|TEXTPTR|TODATETIMEOFFSET|TRIGGER_NESTLEVEL|TYPE_ID|TYPE_NAME|TYPEPROPERTY|UNICODE|UPDATE\(|UPPER|USER_ID|USER_NAME|USER_NAME|VAR|VARP|VerifySignedByAsymKey|VerifySignedByCert|XACT_STATE|YEAR)\b", RegexOptions.IgnoreCase | RegexCompiledOption);
+        }
+
+        /// <summary>
+        /// Highlights SQL code
+        /// </summary>
+        /// <param name="range"></param>
+        public virtual void SQLSyntaxHighlight(Range range)
+        {
+            range.tb.CommentPrefix = "--";
+            range.tb.LeftBracket = '(';
+            range.tb.RightBracket = ')';
+            range.tb.LeftBracket2 = '\x0';
+            range.tb.RightBracket2 = '\x0';
+            //clear style of changed range
+            range.ClearStyle(RedStyle, MagentaStyle, GreenStyle, BlueBoldStyle, BlueStyle, MaroonStyle);
+            //
+            if (SQLStringRegex == null)
+                InitSQLRegex();
+            //comment highlighting
+            range.SetStyle(GreenStyle, SQLCommentRegex1);
+            range.SetStyle(GreenStyle, SQLCommentRegex2);
+            range.SetStyle(GreenStyle, SQLCommentRegex3);
+            //string highlighting
+            range.SetStyle(RedStyle, SQLStringRegex);
+            //number highlighting
+            range.SetStyle(MagentaStyle, SQLNumberRegex);
+            //var highlighting
+            range.SetStyle(MaroonStyle, SQLVarRegex);
+            //statements
+            range.SetStyle(BlueBoldStyle, SQLStatementsRegex);
+            //keywords
+            range.SetStyle(BlueStyle, SQLKeywordsRegex);
+            //functions
+            range.SetStyle(MaroonStyle, SQLFunctionsRegex);
+
+            //clear folding markers
+            range.ClearFoldingMarkers();
+            //set folding markers
+            range.SetFoldingMarkers(@"\bBEGIN\b", @"\bEND\b", RegexOptions.IgnoreCase);//allow to collapse BEGIN..END blocks
+            range.SetFoldingMarkers(@"/\*", @"\*/");//allow to collapse comment block
+        }
+
+        Regex PHPStringRegex, PHPNumberRegex, PHPCommentRegex1, PHPCommentRegex2, PHPCommentRegex3, PHPVarRegex, PHPKeywordRegex1, PHPKeywordRegex2, PHPKeywordRegex3;
+
+        void InitPHPRegex()
+        {
+            PHPStringRegex = new Regex(@"""""|''|"".*?[^\\]""|'.*?[^\\]'", RegexCompiledOption);
+            PHPNumberRegex = new Regex(@"\b\d+[\.]?\d*\b", RegexCompiledOption);
+            PHPCommentRegex1 = new Regex(@"(//|#).*$", RegexOptions.Multiline | RegexCompiledOption);
+            PHPCommentRegex2 = new Regex(@"(/\*.*?\*/)|(/\*.*)", RegexOptions.Singleline | RegexCompiledOption);
+            PHPCommentRegex3 = new Regex(@"(/\*.*?\*/)|(.*\*/)", RegexOptions.Singleline | RegexOptions.RightToLeft | RegexCompiledOption);
+            PHPVarRegex = new Regex(@"\$[a-zA-Z_\d]*\b", RegexCompiledOption);
+            PHPKeywordRegex1 = new Regex(@"\b(die|echo|empty|exit|eval|include|include_once|isset|list|require|require_once|return|print|unset)\b", RegexCompiledOption);
+            PHPKeywordRegex2 = new Regex(@"\b(abstract|and|array|as|break|case|catch|cfunction|class|clone|const|continue|declare|default|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|final|for|foreach|function|global|goto|if|implements|instanceof|interface|namespace|new|or|private|protected|public|static|switch|throw|try|use|var|while|xor)\b", RegexCompiledOption);
+            PHPKeywordRegex3 = new Regex(@"__CLASS__|__DIR__|__FILE__|__LINE__|__FUNCTION__|__METHOD__|__NAMESPACE__", RegexCompiledOption);
+        }
+
+        /// <summary>
+        /// Highlights PHP code
+        /// </summary>
+        /// <param name="range"></param>
+        public virtual void PHPSyntaxHighlight(Range range)
+        {
+            range.tb.CommentPrefix = "#";
+            range.tb.LeftBracket = '(';
+            range.tb.RightBracket = ')';
+            range.tb.LeftBracket2 = '\x0';
+            range.tb.RightBracket2 = '\x0';
+            //clear style of changed range
+            range.ClearStyle(BlueStyle, GrayStyle, MagentaStyle, GreenStyle, RedStyle, MaroonStyle);
+            //
+            if (PHPStringRegex == null)
+                InitPHPRegex();
+            //string highlighting
+            range.SetStyle(RedStyle, PHPStringRegex);
+            //comment highlighting
+            range.SetStyle(GreenStyle, PHPCommentRegex1);
+            range.SetStyle(GreenStyle, PHPCommentRegex2);
+            range.SetStyle(GreenStyle, PHPCommentRegex3);
+            //number highlighting
+            range.SetStyle(RedStyle, PHPNumberRegex);
+            //var highlighting
+            range.SetStyle(MaroonStyle, PHPVarRegex);
+            //keyword highlighting
+            range.SetStyle(MagentaStyle, PHPKeywordRegex1);
+            range.SetStyle(BlueStyle, PHPKeywordRegex2);
+            range.SetStyle(GrayStyle, PHPKeywordRegex3);
+
+            //clear folding markers
+            range.ClearFoldingMarkers();
+            //set folding markers
+            range.SetFoldingMarkers("{", "}");//allow to collapse brackets block
+            range.SetFoldingMarkers(@"/\*", @"\*/");//allow to collapse comment block
+        }
+
+        Regex JScriptStringRegex, JScriptCommentRegex1, JScriptCommentRegex2, JScriptCommentRegex3, JScriptNumberRegex, JScriptKeywordRegex;
+
+        void InitJScriptRegex()
+        {
+            JScriptStringRegex = new Regex(@"""""|''|"".*?[^\\]""|'.*?[^\\]'", RegexCompiledOption);
+            JScriptCommentRegex1 = new Regex(@"//.*$", RegexOptions.Multiline | RegexCompiledOption);
+            JScriptCommentRegex2 = new Regex(@"(/\*.*?\*/)|(/\*.*)", RegexOptions.Singleline | RegexCompiledOption);
+            JScriptCommentRegex3 = new Regex(@"(/\*.*?\*/)|(.*\*/)", RegexOptions.Singleline | RegexOptions.RightToLeft | RegexCompiledOption);
+            JScriptNumberRegex = new Regex(@"\b\d+[\.]?\d*([eE]\-?\d+)?[lLdDfF]?\b|\b0x[a-fA-F\d]+\b", RegexCompiledOption);
+            JScriptKeywordRegex = new Regex(@"\b(true|false|break|case|catch|const|continue|default|delete|do|else|export|for|function|if|in|instanceof|new|null|return|switch|this|throw|try|var|void|while|with|typeof)\b", RegexCompiledOption);
+        }
+
+        /// <summary>
+        /// Highlights JavaScript code
+        /// </summary>
+        /// <param name="range"></param>
+        public virtual void JScriptSyntaxHighlight(Range range)
+        {
+            range.tb.CommentPrefix = "//";
+            range.tb.LeftBracket = '(';
+            range.tb.RightBracket = ')';
+            range.tb.LeftBracket2 = '\x0';
+            range.tb.RightBracket2 = '\x0';
+            //clear style of changed range
+            range.ClearStyle(BlueStyle, BoldStyle, GrayStyle, MagentaStyle, GreenStyle, BrownStyle);
+            //
+            if (JScriptStringRegex == null)
+                InitJScriptRegex();
+            //string highlighting
+            range.SetStyle(BrownStyle, JScriptStringRegex);
+            //comment highlighting
+            range.SetStyle(GreenStyle, JScriptCommentRegex1);
+            range.SetStyle(GreenStyle, JScriptCommentRegex2);
+            range.SetStyle(GreenStyle, JScriptCommentRegex3);
+            //number highlighting
+            range.SetStyle(MagentaStyle, JScriptNumberRegex);
+            //keyword highlighting
+            range.SetStyle(BlueStyle, JScriptKeywordRegex);
+            //clear folding markers
+            range.ClearFoldingMarkers();
+            //set folding markers
+            range.SetFoldingMarkers("{", "}");//allow to collapse brackets block
+            range.SetFoldingMarkers(@"/\*", @"\*/");//allow to collapse comment block
+        }
+
+
+        public void Dispose()
+        {
+            foreach (var desc in descByXMLfileNames.Values)
+                desc.Dispose();
+        }
+    }
+
+    /// <summary>
+    /// Language
+    /// </summary>
+    public enum Language
+    {
+        Custom, CSharp, VB, HTML, SQL, PHP, JS
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/TextSource.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/TextSource.cs
new file mode 100644
index 0000000..f1c028d
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/TextSource.cs
@@ -0,0 +1,329 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    /// <summary>
+    /// This class contains the source text (chars and styles).
+    /// It stores a text lines, the manager of commands, undo/redo stack, styles.
+    /// </summary>
+    public class TextSource : IList<Line>, IDisposable
+    {
+        readonly protected List<Line> lines = new List<Line>();
+        LinesAccessor linesAccessor;
+        int lastLineUniqueId;
+        internal CommandManager Manager { get; private set; }
+        FastColoredTextBox currentTB;
+        /// <summary>
+        /// Styles
+        /// Maximum style count is 16
+        /// </summary>
+        public readonly Style[] Styles = new Style[sizeof(ushort) * 8];
+        /// <summary>
+        /// Occurs when line was inserted/added
+        /// </summary>
+        public event EventHandler<LineInsertedEventArgs> LineInserted;
+        /// <summary>
+        /// Occurs when line was removed
+        /// </summary>
+        public event EventHandler<LineRemovedEventArgs> LineRemoved;
+        /// <summary>
+        /// Occurs when text was changed
+        /// </summary>
+        public event EventHandler<TextChangedEventArgs> TextChanged;
+        /// <summary>
+        /// Occurs when recalc is needed
+        /// </summary>
+        public event EventHandler<TextChangedEventArgs> RecalcNeeded;
+        /// <summary>
+        /// Occurs before text changing
+        /// </summary>
+        public event EventHandler<TextChangingEventArgs> TextChanging;
+        /// <summary>
+        /// Occurs after CurrentTB was changed
+        /// </summary>
+        public event EventHandler CurrentTBChanged;
+        /// <summary>
+        /// Current focused FastColoredTextBox
+        /// </summary>
+        public FastColoredTextBox CurrentTB
+        {
+            get { return currentTB; }
+            set
+            {
+                currentTB = value;
+                OnCurrentTBChanged();
+            }
+        }
+
+        public virtual void ClearIsChanged()
+        {
+            foreach (var line in lines)
+                line.IsChanged = false;
+        }
+
+        public virtual Line CreateLine()
+        {
+            return new Line(GenerateUniqueLineId());
+        }
+
+        private void OnCurrentTBChanged()
+        {
+            if (CurrentTBChanged != null)
+                CurrentTBChanged(this, EventArgs.Empty);
+        }
+
+        /// <summary>
+        /// Default text style
+        /// This style is using when no one other TextStyle is not defined in Char.style
+        /// </summary>
+        public TextStyle DefaultStyle { get; set; }
+
+        public TextSource(FastColoredTextBox currentTB)
+        {
+            this.CurrentTB = currentTB;
+            linesAccessor = new LinesAccessor(this);
+            Manager = new CommandManager(this);
+            InitDefaultStyle();
+        }
+
+        public void InitDefaultStyle()
+        {
+            DefaultStyle = new TextStyle(null, null, FontStyle.Regular);
+        }
+
+        public virtual Line this[int i]
+        {
+            get
+            {
+                return lines[i];
+            }
+            set
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        public virtual bool IsLineLoaded(int iLine)
+        {
+            return lines[iLine] != null;
+        }
+
+        /// <summary>
+        /// Text lines
+        /// </summary>
+        public IList<string> Lines
+        {
+            get
+            {
+                return linesAccessor;
+            }
+        }
+
+        public IEnumerator<Line> GetEnumerator()
+        {
+            return lines.GetEnumerator();
+        }
+
+        IEnumerator System.Collections.IEnumerable.GetEnumerator()
+        {
+            return (lines as IEnumerator);
+        }
+
+        public int BinarySearch(Line item, IComparer<Line> comparer)
+        {
+            return lines.BinarySearch(item, comparer);
+        }
+
+        public int GenerateUniqueLineId()
+        {
+            return lastLineUniqueId++;
+        }
+
+        public virtual void InsertLine(int index, Line line)
+        {
+            lines.Insert(index, line);
+            OnLineInserted(index);
+        }
+
+        public void OnLineInserted(int index)
+        {
+            OnLineInserted(index, 1);
+        }
+
+        public void OnLineInserted(int index, int count)
+        {
+            if (LineInserted != null)
+                LineInserted(this, new LineInsertedEventArgs(index, count));
+        }
+
+        public virtual void RemoveLine(int index)
+        {
+            RemoveLine(index, 1);
+        }
+
+        public bool IsNeedBuildRemovedLineIds
+        {
+            get { return LineRemoved != null; }
+        }
+
+        public virtual void RemoveLine(int index, int count)
+        {
+            List<int> removedLineIds = new List<int>();
+            //
+            if (count > 0)
+                if (IsNeedBuildRemovedLineIds)
+                    for (int i = 0; i < count; i++)
+                        removedLineIds.Add(this[index + i].UniqueId);
+            //
+            lines.RemoveRange(index, count);
+
+            OnLineRemoved(index, count, removedLineIds);
+        }
+
+        public void OnLineRemoved(int index, int count, List<int> removedLineIds)
+        {
+            if (count > 0)
+                if (LineRemoved != null)
+                    LineRemoved(this, new LineRemovedEventArgs(index, count, removedLineIds));
+        }
+
+        public void OnTextChanged(int fromLine, int toLine)
+        {
+            if (TextChanged != null)
+                TextChanged(this, new TextChangedEventArgs(Math.Min(fromLine, toLine), Math.Max(fromLine, toLine)));
+        }
+
+        public class TextChangedEventArgs : EventArgs
+        {
+            public int iFromLine;
+            public int iToLine;
+
+            public TextChangedEventArgs(int iFromLine, int iToLine)
+            {
+                this.iFromLine = iFromLine;
+                this.iToLine = iToLine;
+            }
+        }
+
+        public virtual int IndexOf(Line item)
+        {
+            return lines.IndexOf(item);
+        }
+
+        public virtual void Insert(int index, Line item)
+        {
+            InsertLine(index, item);
+        }
+
+        public virtual void RemoveAt(int index)
+        {
+            RemoveLine(index);
+        }
+
+        public virtual void Add(Line item)
+        {
+            InsertLine(Count, item);
+        }
+
+        public virtual void Clear()
+        {
+            RemoveLine(0, Count);
+        }
+
+        public virtual bool Contains(Line item)
+        {
+            return lines.Contains(item);
+        }
+
+        public virtual void CopyTo(Line[] array, int arrayIndex)
+        {
+            lines.CopyTo(array, arrayIndex);
+        }
+
+        /// <summary>
+        /// Lines count
+        /// </summary>
+        public virtual int Count
+        {
+            get { return lines.Count; }
+        }
+
+        public virtual bool IsReadOnly
+        {
+            get { return false; }
+        }
+
+        public virtual bool Remove(Line item)
+        {
+            int i = IndexOf(item);
+            if (i >= 0)
+            {
+                RemoveLine(i);
+                return true;
+            }
+            else
+                return false;
+        }
+
+        internal void NeedRecalc(TextChangedEventArgs args)
+        {
+            if (RecalcNeeded != null)
+                RecalcNeeded(this, args);
+        }
+
+        internal void OnTextChanging()
+        {
+            string temp = null;
+            OnTextChanging(ref temp);
+        }
+
+        internal void OnTextChanging(ref string text)
+        {
+            if (TextChanging != null)
+            {
+                var args = new TextChangingEventArgs() { InsertingText = text };
+                TextChanging(this, args);
+                text = args.InsertingText;
+                if (args.Cancel)
+                    text = string.Empty;
+            }
+            ;
+        }
+
+        public virtual int GetLineLength(int i)
+        {
+            return lines[i].Count;
+        }
+
+        public virtual bool LineHasFoldingStartMarker(int iLine)
+        {
+            return !string.IsNullOrEmpty(lines[iLine].FoldingStartMarker);
+        }
+
+        public virtual bool LineHasFoldingEndMarker(int iLine)
+        {
+            return !string.IsNullOrEmpty(lines[iLine].FoldingEndMarker);
+        }
+
+        public virtual void Dispose()
+        {
+            ;
+        }
+
+        public virtual void SaveToFile(string fileName, Encoding enc)
+        {
+            using (StreamWriter sw = new StreamWriter(fileName, false, enc))
+            {
+                for (int i = 0; i < Count - 1; i++)
+                    sw.WriteLine(lines[i].Text);
+
+                sw.Write(lines[Count - 1].Text);
+            }
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/TypeDescriptor.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/TypeDescriptor.cs
new file mode 100644
index 0000000..454acdb
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/TypeDescriptor.cs
@@ -0,0 +1,99 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    ///
+    /// This classes is required for correct data binding to Text property of FastColoredTextbox
+    /// 
+    class FCTBDescriptionProvider : TypeDescriptionProvider
+    {
+        public FCTBDescriptionProvider(Type type)
+            : base(GetDefaultTypeProvider(type))
+        {
+        }
+
+        private static TypeDescriptionProvider GetDefaultTypeProvider(Type type)
+        {
+            return TypeDescriptor.GetProvider(type);
+        }
+
+
+
+        public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
+        {
+            ICustomTypeDescriptor defaultDescriptor = base.GetTypeDescriptor(objectType, instance);
+            return new FCTBTypeDescriptor(defaultDescriptor, instance);
+        }
+    }
+
+    class FCTBTypeDescriptor : CustomTypeDescriptor
+    {
+        ICustomTypeDescriptor parent;
+        object instance;
+
+        public FCTBTypeDescriptor(ICustomTypeDescriptor parent, object instance)
+            : base(parent)
+        {
+            this.parent = parent;
+            this.instance = instance;
+        }
+
+        public override string GetComponentName()
+        {
+            var ctrl = (instance as Control);
+            return ctrl == null ? null : ctrl.Name;
+        }
+
+        public override EventDescriptorCollection GetEvents()
+        {
+            var coll = base.GetEvents();
+            var list = new EventDescriptor[coll.Count];
+
+            for (int i = 0; i < coll.Count; i++)
+                if (coll[i].Name == "TextChanged")//instead of TextChanged slip BindingTextChanged for binding
+                    list[i] = new FooTextChangedDescriptor(coll[i]);
+                else
+                    list[i] = coll[i];
+
+            return new EventDescriptorCollection(list);
+        }
+    }
+
+    class FooTextChangedDescriptor : EventDescriptor
+    {
+        public FooTextChangedDescriptor(MemberDescriptor desc)
+            : base(desc)
+        {
+        }
+
+        public override void AddEventHandler(object component, Delegate value)
+        {
+            (component as FastColoredTextBox).BindingTextChanged += value as EventHandler;
+        }
+
+        public override Type ComponentType
+        {
+            get { return typeof(FastColoredTextBox); }
+        }
+
+        public override Type EventType
+        {
+            get { return typeof(EventHandler); }
+        }
+
+        public override bool IsMulticast
+        {
+            get { return true; }
+        }
+
+        public override void RemoveEventHandler(object component, Delegate value)
+        {
+            (component as FastColoredTextBox).BindingTextChanged -= value as EventHandler;
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/FastColorTextBox/VisualMarker.cs.cs b/LB_VisionControl/ScriptEditControl/FastColorTextBox/VisualMarker.cs.cs
new file mode 100644
index 0000000..b8113af
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/FastColorTextBox/VisualMarker.cs.cs
@@ -0,0 +1,107 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionControl.ScriptEditControl.FastColorTextBox
+{
+    public class VisualMarker
+    {
+        public readonly Rectangle rectangle;
+
+        public VisualMarker(Rectangle rectangle)
+        {
+            this.rectangle = rectangle;
+        }
+
+        public virtual void Draw(Graphics gr, Pen pen)
+        {
+        }
+
+        public virtual Cursor Cursor
+        {
+            get { return Cursors.Hand; }
+        }
+    }
+
+    class CollapseFoldingMarker : VisualMarker
+    {
+        public readonly int iLine;
+
+        public CollapseFoldingMarker(int iLine, Rectangle rectangle)
+            : base(rectangle)
+        {
+            this.iLine = iLine;
+        }
+
+        public override void Draw(Graphics gr, Pen pen)
+        {
+            //draw minus
+            gr.FillRectangle(Brushes.White, rectangle);
+            gr.DrawRectangle(pen, rectangle);
+            gr.DrawLine(pen, rectangle.Left + 2, rectangle.Top + rectangle.Height / 2, rectangle.Right - 2, rectangle.Top + rectangle.Height / 2);
+        }
+    }
+
+    class ExpandFoldingMarker : VisualMarker
+    {
+        public readonly int iLine;
+
+        public ExpandFoldingMarker(int iLine, Rectangle rectangle)
+            : base(rectangle)
+        {
+            this.iLine = iLine;
+        }
+
+        public override void Draw(Graphics gr, Pen pen)
+        {
+            //draw plus
+            gr.FillRectangle(Brushes.White, rectangle);
+            gr.DrawRectangle(pen, rectangle);
+            gr.DrawLine(Pens.Red, rectangle.Left + 2, rectangle.Top + rectangle.Height / 2, rectangle.Right - 2, rectangle.Top + rectangle.Height / 2);
+            gr.DrawLine(Pens.Red, rectangle.Left + rectangle.Width / 2, rectangle.Top + 2, rectangle.Left + rectangle.Width / 2, rectangle.Bottom - 2);
+        }
+    }
+
+    public class FoldedAreaMarker : VisualMarker
+    {
+        public readonly int iLine;
+
+        public FoldedAreaMarker(int iLine, Rectangle rectangle)
+            : base(rectangle)
+        {
+            this.iLine = iLine;
+        }
+
+        public override void Draw(Graphics gr, Pen pen)
+        {
+            gr.DrawRectangle(pen, rectangle);
+        }
+    }
+
+    public class StyleVisualMarker : VisualMarker
+    {
+        public Style Style { get; private set; }
+
+        public StyleVisualMarker(Rectangle rectangle, Style style)
+            : base(rectangle)
+        {
+            this.Style = style;
+        }
+    }
+
+    public class VisualMarkerEventArgs : MouseEventArgs
+    {
+        public Style Style { get; private set; }
+        public StyleVisualMarker Marker { get; private set; }
+
+        public VisualMarkerEventArgs(Style style, StyleVisualMarker marker, MouseEventArgs args)
+            : base(args.Button, args.Clicks, args.X, args.Y, args.Delta)
+        {
+            this.Style = style;
+            this.Marker = marker;
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/KeyWordsAuto.cs b/LB_VisionControl/ScriptEditControl/KeyWordsAuto.cs
new file mode 100644
index 0000000..6205516
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/KeyWordsAuto.cs
@@ -0,0 +1,229 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+using System.Drawing;
+using LB_VisionControl.ScriptEditControl.FastColorTextBox;
+using Range = LB_VisionControl.ScriptEditControl.FastColorTextBox.Range;
+//_5_1_a_s_p_x
+namespace LB_VisionControl.ScriptEditControl
+{
+    class KeyWordsAuto
+    {
+
+        static string[] keywords = { "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char",
+                                      "checked", "class", "const", "continue", "decimal", "default", "delegate",
+                                      "do", "double", "else", "enum", "event", "explicit", "extern", "false",
+                                      "finally", "fixed", "float", "for", "foreach", "goto",
+                                      "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long",
+                                      "namespace", "new", "null", "object", "operator", "out", "override", "params",
+                                      "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed",
+                                      "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this",
+                                      "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort",
+                                      "using", "virtual", "void", "volatile", "while", "add", "alias", "ascending",
+                                      "descending", "dynamic", "from", "get", "global", "group", "into", "join", "let",
+                                      "orderby", "partial", "remove", "select", "set", "value", "var", "where", "yield" };
+
+        static string[] methods = { "Equals()", "GetHashCode()", "GetType()", "ToString()", "Length", "Count" };
+
+        static string[] snippets = { "if(^)\n{\n;\n}", "if(^)\n{\n;\n}\nelse\n{\n;\n}", "for(^;;)\n{\n;\n}",
+                                      "for(int i=0;i<^;i++)\n{\n;\n}","foreach(var i in ^)\n{\n;\n}" ,"while(^)\n{\n;\n}",
+                                      "do${\n^;\n}while();", "switch(^)\n{\ncase : break;\n}",
+                                  };
+        static string[] declarationSnippets = {
+               "public class ^\n{\n}", "private class ^\n{\n}", "internal class ^\n{\n}",
+               "public struct ^\n{\n;\n}", "private struct ^\n{\n;\n}", "internal struct ^\n{\n;\n}",
+               "public void ^()\n{\n;\n}", "private void ^()\n{\n;\n}", "internal void ^()\n{\n;\n}", "protected void ^()\n{\n;\n}",
+               "public ^{ get; set; }", "private ^{ get; set; }", "internal ^{ get; set; }", "protected ^{ get; set; }",
+               "Debug.WriteLine(^)", "Debug.Write(^)", "Debug.ReadLine()^", "Debug.Read()^", "Debug.ReadKey()^",
+               "System;^", "System.Text;^", "System.Linq;^", "System.Collections.Generic;^", "System.Text.RegularExpressions;^", "System.Windows.Forms;^",
+               "Application.Run(new Form())^","Application.Run(^)","Convert^","Convert.ToString(^)","Convert.ToString(^,2)"
+               };
+        static AutocompleteMenu popupMenu;
+        static FastColoredTextBox CurrentTB;
+        public static void CreatMenu(FastColoredTextBox fctb, ImageList imgList)
+        {
+            //create autocomplete popup menu
+            popupMenu = new AutocompleteMenu(fctb);
+            CurrentTB = fctb;
+            popupMenu.Items.ImageList = imgList;
+            popupMenu.Opening += new EventHandler<System.ComponentModel.CancelEventArgs>(popupMenu_Opening);
+            BuildAutocompleteMenu();
+        }
+
+        static void popupMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
+        {
+            //---block autocomplete menu for comments
+            //get index of green style (used for comments)
+            var iGreenStyle = CurrentTB.GetStyleIndex(CurrentTB.SyntaxHighlighter.GreenStyle);
+            if (iGreenStyle >= 0)
+                if (CurrentTB.Selection.Start.iChar > 0)
+                {
+                    //current char (before caret)
+                    var c = CurrentTB[CurrentTB.Selection.Start.iLine][CurrentTB.Selection.Start.iChar - 1];
+                    //green Style
+                    var greenStyleIndex = Range.ToStyleIndex(iGreenStyle);
+                    //if char contains green style then block popup menu
+                    if ((c.style & greenStyleIndex) != 0)
+                        e.Cancel = true;
+                }
+        }
+        private static void BuildAutocompleteMenu()
+        {
+            List<AutocompleteItem> items = new List<AutocompleteItem>();
+            foreach (var item in snippets)
+                items.Add(new SnippetAutocompleteItem(item) { ImageIndex = 0 });
+            foreach (var item in declarationSnippets)
+                items.Add(new DeclarationSnippet(item) { ImageIndex = 1 });
+            foreach (var item in methods)
+                items.Add(new MethodAutocompleteItem(item) { ImageIndex = 2 });
+            foreach (var item in keywords)
+                items.Add(new AutocompleteItem(item) { ImageIndex = 3 });
+
+
+            items.Add(new InsertSpaceSnippet());
+            items.Add(new InsertSpaceSnippet(@"^(\w+)([=<>!:]+)(\w+)$"));
+            items.Add(new InsertEnterSnippet());
+
+            //set as autocomplete source
+            popupMenu.Items.SetAutocompleteItems(items);
+            popupMenu.SearchPattern = @"[\w\.:=!<>]";
+        }
+        /// <summary>
+        /// This item appears when any part of snippet text is typed
+        /// </summary>
+        class DeclarationSnippet : SnippetAutocompleteItem
+        {
+            public DeclarationSnippet(string snippet)
+                : base(snippet)
+            {
+            }
+
+            public override CompareResult Compare(string fragmentText)
+            {
+                var pattern = Regex.Escape(fragmentText);
+                if (Regex.IsMatch(Text, "\\b" + pattern, RegexOptions.IgnoreCase))
+                    return CompareResult.Visible;
+                return CompareResult.Hidden;
+            }
+        }
+
+        /// <summary>
+        /// Divides numbers and words: "123AND456" -> "123 AND 456"
+        /// Or "i=2" -> "i = 2"
+        /// </summary>
+        class InsertSpaceSnippet : AutocompleteItem
+        {
+            string pattern;
+
+            public InsertSpaceSnippet(string pattern)
+                : base("")
+            {
+                this.pattern = pattern;
+            }
+
+            public InsertSpaceSnippet()
+                : this(@"^(\d+)([a-zA-Z_]+)(\d*)$")
+            {
+            }
+
+            public override CompareResult Compare(string fragmentText)
+            {
+                if (Regex.IsMatch(fragmentText, pattern))
+                {
+                    Text = InsertSpaces(fragmentText);
+                    if (Text != fragmentText)
+                        return CompareResult.Visible;
+                }
+                return CompareResult.Hidden;
+            }
+
+            public string InsertSpaces(string fragment)
+            {
+                var m = Regex.Match(fragment, pattern);
+                if (m == null)
+                    return fragment;
+                if (m.Groups[1].Value == "" && m.Groups[3].Value == "")
+                    return fragment;
+                return (m.Groups[1].Value + " " + m.Groups[2].Value + " " + m.Groups[3].Value).Trim();
+            }
+
+            public override string ToolTipTitle
+            {
+                get
+                {
+                    return Text;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Inerts line break after '}'
+        /// </summary>
+        class InsertEnterSnippet : AutocompleteItem
+        {
+            Place enterPlace = Place.Empty;
+
+            public InsertEnterSnippet()
+                : base("[Line break]")
+            {
+            }
+
+            public override CompareResult Compare(string fragmentText)
+            {
+                var r = Parent.Fragment.Clone();
+                while (r.Start.iChar > 0)
+                {
+                    if (r.CharBeforeStart == '}')
+                    {
+                        enterPlace = r.Start;
+                        return CompareResult.Visible;
+                    }
+
+                    r.GoLeftThroughFolded();
+                }
+
+                return CompareResult.Hidden;
+            }
+
+            public override string GetTextForReplace()
+            {
+                //extend range
+                Range r = Parent.Fragment;
+                Place end = r.End;
+                r.Start = enterPlace;
+                r.End = r.End;
+                //insert line break
+                return Environment.NewLine + r.Text;
+            }
+
+            public override void OnSelected(AutocompleteMenu popupMenu, SelectedEventArgs e)
+            {
+                base.OnSelected(popupMenu, e);
+                if (Parent.Fragment.tb.AutoIndent)
+                    Parent.Fragment.tb.DoAutoIndent();
+            }
+
+            public override string ToolTipTitle
+            {
+                get
+                {
+                    return "Insert line break after '}'";
+                }
+            }
+        }
+        static readonly Platform platformType = PlatformType.GetOperationSystemPlatform();
+        public static RegexOptions RegexCompiledOption
+        {
+            get
+            {
+                if (platformType == Platform.X86)
+                    return RegexOptions.Compiled;
+                else
+                    return RegexOptions.None;
+            }
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/KeysWordCMDAuto.cs b/LB_VisionControl/ScriptEditControl/KeysWordCMDAuto.cs
new file mode 100644
index 0000000..fa3c2c4
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/KeysWordCMDAuto.cs
@@ -0,0 +1,32 @@
+锘縰sing LB_VisionControl.ScriptEditControl.FastColorTextBox;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    class KeysWordCMDAuto
+    {
+        static string[] CommandArrys = { "help","?","csc","clear","min","max","nor","exit","save","code","hide","new","exe",
+                                       "winexe","dll","arg:","wd","show"};
+        static AutocompleteMenu popupMenu;
+        public static void CreatMenu(FastColoredTextBox fctb, ImageList imgList)
+        {
+            //create autocomplete popup menu
+            popupMenu = new AutocompleteMenu(fctb);
+
+            popupMenu.Items.ImageList = imgList;
+            BuildAutocompleteMenu();
+        }
+
+        private static void BuildAutocompleteMenu()
+        {
+            List<AutocompleteItem> items = new List<AutocompleteItem>();
+            foreach (var item in CommandArrys)
+                items.Add(new AutocompleteItem(item) { ImageIndex = 4 });
+            popupMenu.Items.SetAutocompleteItems(items);
+        }
+    }
+}
diff --git a/LB_VisionControl/ScriptEditControl/ScriptEditControl.Designer.cs b/LB_VisionControl/ScriptEditControl/ScriptEditControl.Designer.cs
new file mode 100644
index 0000000..4098727
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ScriptEditControl.Designer.cs
@@ -0,0 +1,234 @@
+锘縰sing LB_VisionControl.ScriptEditControl.FastColorTextBox;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    partial class ScriptEditControl
+    {
+        /// <summary>
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows 绐椾綋璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary>
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            components = new System.ComponentModel.Container();
+            fctb_ScriptEditControl = new FastColoredTextBox();
+            contextMenuStripEx1 = new ContextMenuStripEx();
+            澶嶅埗ToolStripMenuItem1 = new ToolStripMenuItem();
+            鍓垏ToolStripMenuItem1 = new ToolStripMenuItem();
+            toolStripMenuItem4 = new ToolStripSeparator();
+            绮樿创ToolStripMenuItem1 = new ToolStripMenuItem();
+            toolStripMenuItem5 = new ToolStripSeparator();
+            鍏ㄩ�塗oolStripMenuItem1 = new ToolStripMenuItem();
+            toolStripMenuItem6 = new ToolStripSeparator();
+            娓呴櫎ToolStripMenuItem1 = new ToolStripMenuItem();
+            鏂板缓ToolStripMenuItem = new ToolStripMenuItem();
+            imageList1 = new ImageList(components);
+            timerCell = new System.Windows.Forms.Timer(components);
+            timerBack = new System.Windows.Forms.Timer(components);
+            pnl_ScriptEditControl = new Panel();
+            pnl_ControlView = new Panel();
+            contextMenuStripEx1.SuspendLayout();
+            pnl_ScriptEditControl.SuspendLayout();
+            SuspendLayout();
+            // 
+            // fctb_ScriptEditControl
+            // 
+            fctb_ScriptEditControl.AllowDrop = true;
+            fctb_ScriptEditControl.AutoScrollMinSize = new Size(31, 18);
+            fctb_ScriptEditControl.BackBrush = null;
+            fctb_ScriptEditControl.BackColor = SystemColors.Control;
+            fctb_ScriptEditControl.CaretColor = Color.White;
+            fctb_ScriptEditControl.ContextMenuStrip = contextMenuStripEx1;
+            fctb_ScriptEditControl.Cursor = Cursors.IBeam;
+            fctb_ScriptEditControl.DelayedEventsInterval = 1000;
+            fctb_ScriptEditControl.DelayedTextChangedInterval = 1000;
+            fctb_ScriptEditControl.DisabledColor = Color.FromArgb(30, 17, 18);
+            fctb_ScriptEditControl.Dock = DockStyle.Fill;
+            fctb_ScriptEditControl.FoldingIndicatorColor = Color.Chartreuse;
+            fctb_ScriptEditControl.Font = new Font("Courier New", 12F);
+            fctb_ScriptEditControl.ForeColor = Color.Black;
+            fctb_ScriptEditControl.HighlightingRangeType = HighlightingRangeType.VisibleRange;
+            fctb_ScriptEditControl.ImeMode = ImeMode.On;
+            fctb_ScriptEditControl.IndentBackColor = SystemColors.Control;
+            fctb_ScriptEditControl.IsReplaceMode = false;
+            fctb_ScriptEditControl.Language = Language.CSharp;
+            fctb_ScriptEditControl.LineNumberColor = Color.Black;
+            fctb_ScriptEditControl.Location = new Point(0, 0);
+            fctb_ScriptEditControl.Margin = new Padding(4, 4, 4, 4);
+            fctb_ScriptEditControl.Name = "fctb_ScriptEditControl";
+            fctb_ScriptEditControl.Paddings = new Padding(0);
+            fctb_ScriptEditControl.SelectionColor = Color.FromArgb(100, 255, 255, 128);
+            fctb_ScriptEditControl.ServiceLinesColor = Color.DarkGoldenrod;
+            fctb_ScriptEditControl.Size = new Size(568, 298);
+            fctb_ScriptEditControl.TabIndex = 0;
+            fctb_ScriptEditControl.KeyDown += fctb_KeyDown;
+            // 
+            // contextMenuStripEx1
+            // 
+            contextMenuStripEx1.Items.AddRange(new ToolStripItem[] { 澶嶅埗ToolStripMenuItem1, 鍓垏ToolStripMenuItem1, toolStripMenuItem4, 绮樿创ToolStripMenuItem1, toolStripMenuItem5, 鍏ㄩ�塗oolStripMenuItem1, toolStripMenuItem6, 娓呴櫎ToolStripMenuItem1, 鏂板缓ToolStripMenuItem });
+            contextMenuStripEx1.Name = "contextMenuStripEx1";
+            contextMenuStripEx1.RenderMode = ToolStripRenderMode.System;
+            contextMenuStripEx1.Size = new Size(101, 154);
+            // 
+            // 澶嶅埗ToolStripMenuItem1
+            // 
+            澶嶅埗ToolStripMenuItem1.ForeColor = Color.FromArgb(255, 255, 128);
+            澶嶅埗ToolStripMenuItem1.Name = "澶嶅埗ToolStripMenuItem1";
+            澶嶅埗ToolStripMenuItem1.Size = new Size(100, 22);
+            澶嶅埗ToolStripMenuItem1.Text = "澶嶅埗";
+            澶嶅埗ToolStripMenuItem1.Click += 澶嶅埗ToolStripMenuItem_Click;
+            // 
+            // 鍓垏ToolStripMenuItem1
+            // 
+            鍓垏ToolStripMenuItem1.ForeColor = Color.FromArgb(255, 255, 128);
+            鍓垏ToolStripMenuItem1.Name = "鍓垏ToolStripMenuItem1";
+            鍓垏ToolStripMenuItem1.Size = new Size(100, 22);
+            鍓垏ToolStripMenuItem1.Text = "鍓垏";
+            鍓垏ToolStripMenuItem1.Click += 鍓垏ToolStripMenuItem_Click;
+            // 
+            // toolStripMenuItem4
+            // 
+            toolStripMenuItem4.ForeColor = SystemColors.ControlDarkDark;
+            toolStripMenuItem4.Name = "toolStripMenuItem4";
+            toolStripMenuItem4.Size = new Size(97, 6);
+            // 
+            // 绮樿创ToolStripMenuItem1
+            // 
+            绮樿创ToolStripMenuItem1.ForeColor = Color.FromArgb(255, 255, 128);
+            绮樿创ToolStripMenuItem1.Name = "绮樿创ToolStripMenuItem1";
+            绮樿创ToolStripMenuItem1.Size = new Size(100, 22);
+            绮樿创ToolStripMenuItem1.Text = "绮樿创";
+            绮樿创ToolStripMenuItem1.Click += 绮樿创ToolStripMenuItem_Click;
+            // 
+            // toolStripMenuItem5
+            // 
+            toolStripMenuItem5.ForeColor = SystemColors.ControlDarkDark;
+            toolStripMenuItem5.Name = "toolStripMenuItem5";
+            toolStripMenuItem5.Size = new Size(97, 6);
+            // 
+            // 鍏ㄩ�塗oolStripMenuItem1
+            // 
+            鍏ㄩ�塗oolStripMenuItem1.ForeColor = Color.FromArgb(255, 255, 128);
+            鍏ㄩ�塗oolStripMenuItem1.Name = "鍏ㄩ�塗oolStripMenuItem1";
+            鍏ㄩ�塗oolStripMenuItem1.Size = new Size(100, 22);
+            鍏ㄩ�塗oolStripMenuItem1.Text = "鍏ㄩ��";
+            鍏ㄩ�塗oolStripMenuItem1.Click += 鍏ㄩ�塗oolStripMenuItem_Click;
+            // 
+            // toolStripMenuItem6
+            // 
+            toolStripMenuItem6.ForeColor = SystemColors.ControlDarkDark;
+            toolStripMenuItem6.Name = "toolStripMenuItem6";
+            toolStripMenuItem6.Size = new Size(97, 6);
+            // 
+            // 娓呴櫎ToolStripMenuItem1
+            // 
+            娓呴櫎ToolStripMenuItem1.ForeColor = Color.FromArgb(255, 255, 128);
+            娓呴櫎ToolStripMenuItem1.Name = "娓呴櫎ToolStripMenuItem1";
+            娓呴櫎ToolStripMenuItem1.Size = new Size(100, 22);
+            娓呴櫎ToolStripMenuItem1.Text = "娓呴櫎";
+            娓呴櫎ToolStripMenuItem1.Click += 娓呴櫎ToolStripMenuItem_Click;
+            // 
+            // 鏂板缓ToolStripMenuItem
+            // 
+            鏂板缓ToolStripMenuItem.ForeColor = Color.FromArgb(255, 255, 128);
+            鏂板缓ToolStripMenuItem.Name = "鏂板缓ToolStripMenuItem";
+            鏂板缓ToolStripMenuItem.Size = new Size(100, 22);
+            鏂板缓ToolStripMenuItem.Text = "鏂板缓";
+            鏂板缓ToolStripMenuItem.Click += 鏂板缓ToolStripMenuItem_Click;
+            // 
+            // imageList1
+            // 
+            imageList1.ColorDepth = ColorDepth.Depth32Bit;
+            imageList1.ImageSize = new Size(16, 16);
+            imageList1.TransparentColor = Color.Black;
+            // 
+            // timerCell
+            // 
+            timerCell.Interval = 10;
+            timerCell.Tick += timerCell_Tick;
+            // 
+            // timerBack
+            // 
+            timerBack.Interval = 10;
+            timerBack.Tick += timerBack_Tick;
+            // 
+            // pnl_ScriptEditControl
+            // 
+            pnl_ScriptEditControl.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            pnl_ScriptEditControl.BackColor = Color.DarkSlateGray;
+            pnl_ScriptEditControl.Controls.Add(pnl_ControlView);
+            pnl_ScriptEditControl.Location = new Point(-75, 128);
+            pnl_ScriptEditControl.Margin = new Padding(4, 4, 4, 4);
+            pnl_ScriptEditControl.Name = "pnl_ScriptEditControl";
+            pnl_ScriptEditControl.Size = new Size(719, 42);
+            pnl_ScriptEditControl.TabIndex = 2;
+            pnl_ScriptEditControl.Visible = false;
+            // 
+            // panControlView
+            // 
+            pnl_ControlView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
+            pnl_ControlView.Location = new Point(2, 3);
+            pnl_ControlView.Margin = new Padding(4, 4, 4, 4);
+            pnl_ControlView.Name = "panControlView";
+            pnl_ControlView.Size = new Size(1292, 0);
+            pnl_ControlView.TabIndex = 8;
+            // 
+            // ScriptEditControl
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            BackColor = Color.DimGray;
+            Controls.Add(pnl_ScriptEditControl);
+            Controls.Add(fctb_ScriptEditControl);
+            DoubleBuffered = true;
+            Margin = new Padding(4, 4, 4, 4);
+            Name = "ScriptEditControl";
+            Size = new Size(568, 298);
+            KeyDown += Form1_KeyDown;
+            contextMenuStripEx1.ResumeLayout(false);
+            pnl_ScriptEditControl.ResumeLayout(false);
+            ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.ImageList imageList1;
+        private System.Windows.Forms.Timer timerCell;
+        private System.Windows.Forms.Timer timerBack;
+        public FastColoredTextBox fctb_ScriptEditControl;
+        private ContextMenuStripEx contextMenuStripEx1;
+        private System.Windows.Forms.ToolStripMenuItem 澶嶅埗ToolStripMenuItem1;
+        private System.Windows.Forms.ToolStripMenuItem 鍓垏ToolStripMenuItem1;
+        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4;
+        private System.Windows.Forms.ToolStripMenuItem 绮樿创ToolStripMenuItem1;
+        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5;
+        private System.Windows.Forms.ToolStripMenuItem 鍏ㄩ�塗oolStripMenuItem1;
+        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem6;
+        private System.Windows.Forms.ToolStripMenuItem 娓呴櫎ToolStripMenuItem1;
+        private System.Windows.Forms.ToolStripMenuItem 鏂板缓ToolStripMenuItem;
+        private Panel pnl_ScriptEditControl;
+        private Panel pnl_ControlView;
+    }
+}
+
diff --git a/LB_VisionControl/ScriptEditControl/ScriptEditControl.cs b/LB_VisionControl/ScriptEditControl/ScriptEditControl.cs
new file mode 100644
index 0000000..a10a035
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ScriptEditControl.cs
@@ -0,0 +1,366 @@
+锘縰sing System.Runtime.InteropServices;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    public partial class ScriptEditControl : UserControl
+    {
+        public string ScriptText
+        {
+            get { return fctb_ScriptEditControl.Text; }
+            set { fctb_ScriptEditControl.Text = value; }
+        }
+
+        public ScriptEditControl()
+        {
+            InitializeComponent();
+            CommConfig.AppLocationPath = Application.StartupPath;
+            UpStyle();
+
+            InitStylesPriority();
+
+            #region 鏂板鑷畾涔夎彍鍗�
+            // 
+            // toolStripMenuItem1
+            // 
+            toolStripMenuItem1.ForeColor = SystemColors.ControlDarkDark;
+            toolStripMenuItem1.Name = "toolStripMenuItem1";
+            toolStripMenuItem1.Size = new Size(109, 6);
+
+            鑾峰彇杈撳叆鍙橀噺StripMenuItem.ForeColor = Color.FromArgb(255, 255, 128);
+            鑾峰彇鍏ㄥ眬鍙橀噺StripMenuItem.ForeColor = Color.FromArgb(255, 255, 128);
+            璁剧疆杈撳嚭鍙橀噺StripMenuItem.ForeColor = Color.FromArgb(255, 255, 128);
+            璁剧疆鍏ㄥ眬鍙橀噺StripMenuItem.ForeColor = Color.FromArgb(255, 255, 128);
+
+            鑾峰彇杈撳叆鍙橀噺StripMenuItem.Size = new Size(112, 26);
+            鑾峰彇鍏ㄥ眬鍙橀噺StripMenuItem.Size = new Size(112, 26);
+            璁剧疆杈撳嚭鍙橀噺StripMenuItem.Size = new Size(112, 26);
+            璁剧疆鍏ㄥ眬鍙橀噺StripMenuItem.Size = new Size(112, 26);
+
+            鑾峰彇杈撳叆鍙橀噺StripMenuItem.Text = "鑾峰彇杈撳叆鍙橀噺";
+            鑾峰彇鍏ㄥ眬鍙橀噺StripMenuItem.Text = "鑾峰彇鍏ㄥ眬鍙橀噺";
+            璁剧疆杈撳嚭鍙橀噺StripMenuItem.Text = "璁剧疆杈撳嚭鍙橀噺";
+            璁剧疆鍏ㄥ眬鍙橀噺StripMenuItem.Text = "璁剧疆鍏ㄥ眬鍙橀噺";
+
+            // 鎻掑叆鍥哄畾鐨勬枃鏈�
+            鑾峰彇杈撳叆鍙橀噺StripMenuItem.Click += (sender, e) => fctb_ScriptEditControl.InsertText("object temp = GetInputs(\"key\");\n");
+            鑾峰彇鍏ㄥ眬鍙橀噺StripMenuItem.Click += (sender, e) => fctb_ScriptEditControl.InsertText("object temp = GetGlobalVars(\"key\");\n");
+            璁剧疆杈撳嚭鍙橀噺StripMenuItem.Click += (sender, e) => fctb_ScriptEditControl.InsertText("AddOutputs(\"key\", \"value\")\n;");
+            璁剧疆鍏ㄥ眬鍙橀噺StripMenuItem.Click += (sender, e) => fctb_ScriptEditControl.InsertText("AddGlobalVars(\"key\", \"value\")\n;");
+
+            contextMenuStripEx1.Items.Clear();
+            contextMenuStripEx1.Items.AddRange(new ToolStripItem[]
+{
+                澶嶅埗ToolStripMenuItem1,
+                鍓垏ToolStripMenuItem1,
+                toolStripMenuItem4,
+                绮樿创ToolStripMenuItem1,
+                toolStripMenuItem5,
+                鍏ㄩ�塗oolStripMenuItem1,
+                toolStripMenuItem6,
+                娓呴櫎ToolStripMenuItem1,
+                鏂板缓ToolStripMenuItem,
+                toolStripMenuItem1,
+                鑾峰彇杈撳叆鍙橀噺StripMenuItem,
+                鑾峰彇鍏ㄥ眬鍙橀噺StripMenuItem,
+                璁剧疆杈撳嚭鍙橀噺StripMenuItem,
+                璁剧疆鍏ㄥ眬鍙橀噺StripMenuItem
+            });
+            #endregion
+        }
+
+        #region 鑷畾涔夎彍鍗�
+        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1 = new ToolStripSeparator();
+        private System.Windows.Forms.ToolStripMenuItem 鑾峰彇杈撳叆鍙橀噺StripMenuItem = new ToolStripMenuItem();
+        private System.Windows.Forms.ToolStripMenuItem 鑾峰彇鍏ㄥ眬鍙橀噺StripMenuItem = new ToolStripMenuItem();
+        private System.Windows.Forms.ToolStripMenuItem 璁剧疆杈撳嚭鍙橀噺StripMenuItem = new ToolStripMenuItem();
+        private System.Windows.Forms.ToolStripMenuItem 璁剧疆鍏ㄥ眬鍙橀噺StripMenuItem = new ToolStripMenuItem();
+        #endregion
+
+        private void UpStyle()
+        {
+            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);
+            UpdateStyles();
+        }
+        private void CreatNew()
+        {
+            #region 鍒濆鍖栨暟鎹�
+            fctb_ScriptEditControl.Text = @"/*
+鏃ュ織璁板綍
+鏃堕棿锛�" + DateTime.Now.ToLocalTime() + @"
+鐢ㄦ埛锛�" + Environment.UserName + @"
+璁板綍锛�
+*/
+using System;
+using System.Text;
+class Program
+{
+    static void Main()
+    {
+       //浠g爜
+       
+    }
+}";
+
+            #endregion
+        }
+        private void InitStylesPriority()
+        {
+
+            fctb_ScriptEditControl.ClearUndo();
+            fctb_ScriptEditControl.IsChanged = false;
+
+            CreatNew();
+
+            KeyWordsAuto.CreatMenu(fctb_ScriptEditControl, imageList1);
+            //KeysWordCMDAuto.CreatMenu(DebugTextBox1, imageList1);
+        }
+        #region 绯荤粺UI
+        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            try
+            {
+                if (Directory.Exists(CommConfig.BinPath))
+                    Directory.Delete(CommConfig.BinPath, true);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.Message);
+            }
+        }
+        private void Form1_KeyDown(object sender, KeyEventArgs e)
+        {
+            if ((Control.ModifierKeys & Keys.Control) != 0 && e.KeyCode == Keys.Up)
+            { fctb_ScriptEditControl.Focus(); }
+            //else if ((Control.ModifierKeys & Keys.Control) != 0 && e.KeyCode == Keys.Down)
+            //{ DebugTextBox1.Focus(); }
+        }
+        private void fctb_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (CompliReslut.RowErrorNumber != -1)
+            {
+                fctb_ScriptEditControl[CompliReslut.RowErrorNumber - 1].BackgroundBrush = null;
+                fctb_ScriptEditControl.Invalidate();
+                CompliReslut.RowErrorNumber = -1;
+            }
+        }
+        #endregion
+
+        #region 鍙冲嚮鑿滃崟
+        private void 绮樿创ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            fctb_ScriptEditControl.Paste();
+        }
+
+        private void 澶嶅埗ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            fctb_ScriptEditControl.Copy();
+        }
+
+        private void 鍓垏ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            fctb_ScriptEditControl.Cut();
+
+        }
+
+        private void 鍏ㄩ�塗oolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            fctb_ScriptEditControl.SelectAll();
+        }
+
+        private void 娓呴櫎ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            fctb_ScriptEditControl.Clear();
+        }
+        #endregion
+
+        #region 绉诲姩
+        public const int WM_NCLBUTTONDOWN = 0xA1;
+        public const int HT_CAPTION = 0x2;
+        [DllImportAttribute("user32.dll")]
+        public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+        [DllImportAttribute("user32.dll")]
+        public static extern bool ReleaseCapture();
+
+        private void splitContainer1_Panel1_MouseMove(object sender, MouseEventArgs e)
+        {
+            //绉诲姩
+            if (e.Button == MouseButtons.Left)
+            {
+                if (e.X < this.Width)
+                {
+                    ReleaseCapture();
+                    SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
+                }
+            }
+        }
+        private void label1_MouseMove(object sender, MouseEventArgs e)
+        {
+            //绉诲姩
+            if (e.Button == MouseButtons.Left)
+            {
+                if (e.X < this.Width)
+                {
+                    ReleaseCapture();
+                    SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
+                }
+            }
+        }
+        #endregion
+
+        #region 鍔ㄧ敾
+        public bool isShow = true;
+        int loadSpeed = 10;
+        public void StartMeun()
+        {
+            if (isShow)
+            {
+                timerBack.Enabled = true;
+            }
+            else
+            {
+                timerCell.Enabled = true;
+            }
+        }
+        private void CellOutputHide()
+        {
+            pnl_ScriptEditControl.Height -= loadSpeed;
+            loadSpeed += loadSpeed;
+            if (pnl_ScriptEditControl.Height <= 30)
+            {
+                timerCell.Enabled = false;
+                pnl_ScriptEditControl.Height = 30;
+                loadSpeed = 10;
+
+                //back
+                timerBack.Enabled = true;
+            }
+        }
+        private void CellOutputShow()
+        {
+            pnl_ScriptEditControl.Height += loadSpeed;
+            loadSpeed += loadSpeed;
+            if (pnl_ScriptEditControl.Height >= 310)
+            {
+                timerCell.Enabled = false;
+                pnl_ScriptEditControl.Height = 310;
+                loadSpeed = 10;
+
+                //OK
+                // picDic.Image = Properties.Resources.rdir1;
+                isShow = false;//鏄剧ず杩囩▼瀹屾垚
+            }
+        }
+
+        private void backOutputHide()
+        {
+            pnl_ScriptEditControl.Left += loadSpeed;
+            loadSpeed += loadSpeed;
+            if (pnl_ScriptEditControl.Left >= this.Width)
+            {
+                timerBack.Enabled = false;
+                pnl_ScriptEditControl.Left = this.Width;
+                loadSpeed = 10;
+
+                //OK
+                //picDic.Image = Properties.Resources.dir1;
+                isShow = true;//鏄剧ず杩囩▼缁撴潫
+            }
+        }
+        private void backOutputShow()
+        {
+            pnl_ScriptEditControl.Left -= loadSpeed;
+            loadSpeed += loadSpeed;
+            if (pnl_ScriptEditControl.Left <= this.Width - pnl_ScriptEditControl.Width - 18)
+            {
+                timerBack.Enabled = false;
+                pnl_ScriptEditControl.Left = this.Width - pnl_ScriptEditControl.Width - 18;
+                loadSpeed = 10;
+
+                //celll
+                timerCell.Enabled = true;
+            }
+        }
+        private void timerCell_Tick(object sender, EventArgs e)
+        {
+            if (isShow)
+            {
+                CellOutputShow();
+            }
+            else
+            {
+                CellOutputHide();
+            }
+        }
+
+        private void timerBack_Tick(object sender, EventArgs e)
+        {
+            if (isShow)
+            {
+                backOutputShow();
+            }
+            else
+            {
+                backOutputHide();
+            }
+        }
+
+        #endregion
+
+
+        public void FileSave()
+        {
+            if (!Directory.Exists(CommConfig.ClassLibPath))
+            {
+                Directory.CreateDirectory(CommConfig.ClassLibPath);
+            }
+            File.WriteAllText(CommConfig.fileName, fctb_ScriptEditControl.Text);
+        }
+
+        #region 娣诲姞UI
+        public void AddCsc()
+        {
+            pnl_ControlView.Controls.Clear();
+            ComplieUI cp = new ComplieUI();
+            cp.BackColor = Color.Transparent;
+            cp.fctb = this.fctb_ScriptEditControl;
+            cp.Dock = DockStyle.Fill;
+            pnl_ControlView.Controls.Add(cp);
+        }
+        public void AddClassFileList()
+        {
+            pnl_ControlView.Controls.Clear();
+            ClassFileList cp = new ClassFileList();
+            cp.BackColor = Color.Transparent;
+            cp.fctb = this.fctb_ScriptEditControl;
+            cp.Dock = DockStyle.Fill;
+            pnl_ControlView.Controls.Add(cp);
+        }
+        public void AddText(string txt)
+        {
+            pnl_ControlView.Controls.Clear();
+            TextBox tx = new TextBox();
+            tx.Text = txt;
+            tx.Dock = DockStyle.Fill;
+            tx.BorderStyle = BorderStyle.None;
+            tx.BackColor = Color.FromArgb(30, 17, 18);
+            tx.ForeColor = Color.Green;
+            tx.Multiline = true;
+            tx.ScrollBars = ScrollBars.Both;
+            tx.Font = new System.Drawing.Font("寰蒋闆呴粦", 9);
+            pnl_ControlView.Controls.Add(tx);
+        }
+        #endregion
+
+        private void DebugTextBox1_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyCode == Keys.Up)
+                e.Handled = true;
+        }
+
+        private void 鏂板缓ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            InitStylesPriority();
+        }
+    }
+
+}
diff --git a/LB_VisionControl/ScriptEditControl/ScriptEditControl.resx b/LB_VisionControl/ScriptEditControl/ScriptEditControl.resx
new file mode 100644
index 0000000..86b5a5e
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ScriptEditControl.resx
@@ -0,0 +1,135 @@
+锘�<?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=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>
+  <metadata name="contextMenuStripEx1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>130, 22</value>
+  </metadata>
+  <metadata name="imageList1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 22</value>
+  </metadata>
+  <metadata name="timerCell.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>298, 23</value>
+  </metadata>
+  <metadata name="timerBack.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>415, 23</value>
+  </metadata>
+  <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>62</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionControl/ScriptEditControl/ScriptEditForm.Designer.cs b/LB_VisionControl/ScriptEditControl/ScriptEditForm.Designer.cs
new file mode 100644
index 0000000..0765b90
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ScriptEditForm.Designer.cs
@@ -0,0 +1,463 @@
+锘縰sing LB_VisionControl.ScriptEditControl.FastColorTextBox;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    partial class ScriptEditForm
+    {
+        /// <summary>
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows 绐椾綋璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary>
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            components = new System.ComponentModel.Container();
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ScriptEditForm));
+            splitContainer1 = new SplitContainer();
+            label1 = new Label();
+            picMin = new PictureBox();
+            picMax = new PictureBox();
+            picClose = new PictureBox();
+            pictureBox1 = new PictureBox();
+            panel1 = new Panel();
+            panControlView = new Panel();
+            splitContainer2 = new SplitContainer();
+            fctb = new FastColoredTextBox();
+            contextMenuStripEx1 = new ContextMenuStripEx();
+            澶嶅埗ToolStripMenuItem1 = new ToolStripMenuItem();
+            鍓垏ToolStripMenuItem1 = new ToolStripMenuItem();
+            toolStripMenuItem4 = new ToolStripSeparator();
+            绮樿创ToolStripMenuItem1 = new ToolStripMenuItem();
+            toolStripMenuItem5 = new ToolStripSeparator();
+            鍏ㄩ�塗oolStripMenuItem1 = new ToolStripMenuItem();
+            toolStripMenuItem6 = new ToolStripSeparator();
+            娓呴櫎ToolStripMenuItem1 = new ToolStripMenuItem();
+            鏂板缓ToolStripMenuItem = new ToolStripMenuItem();
+            splitContainer3 = new SplitContainer();
+            DebugTextBox1 = new DebugTextBox();
+            imageList1 = new ImageList(components);
+            timerCell = new System.Windows.Forms.Timer(components);
+            timerBack = new System.Windows.Forms.Timer(components);
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
+            splitContainer1.Panel1.SuspendLayout();
+            splitContainer1.Panel2.SuspendLayout();
+            splitContainer1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)picMin).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)picMax).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)picClose).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
+            panel1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)splitContainer2).BeginInit();
+            splitContainer2.Panel1.SuspendLayout();
+            splitContainer2.Panel2.SuspendLayout();
+            splitContainer2.SuspendLayout();
+            contextMenuStripEx1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)splitContainer3).BeginInit();
+            splitContainer3.Panel1.SuspendLayout();
+            splitContainer3.SuspendLayout();
+            SuspendLayout();
+            // 
+            // splitContainer1
+            // 
+            splitContainer1.Dock = DockStyle.Fill;
+            splitContainer1.FixedPanel = FixedPanel.Panel1;
+            splitContainer1.IsSplitterFixed = true;
+            splitContainer1.Location = new Point(0, 0);
+            splitContainer1.Margin = new Padding(4);
+            splitContainer1.Name = "splitContainer1";
+            splitContainer1.Orientation = Orientation.Horizontal;
+            // 
+            // splitContainer1.Panel1
+            // 
+            splitContainer1.Panel1.BackColor = Color.FromArgb(30, 17, 18);
+            splitContainer1.Panel1.Controls.Add(label1);
+            splitContainer1.Panel1.Controls.Add(picMin);
+            splitContainer1.Panel1.Controls.Add(picMax);
+            splitContainer1.Panel1.Controls.Add(picClose);
+            splitContainer1.Panel1.Controls.Add(pictureBox1);
+            splitContainer1.Panel1.MouseMove += splitContainer1_Panel1_MouseMove;
+            // 
+            // splitContainer1.Panel2
+            // 
+            splitContainer1.Panel2.Controls.Add(panel1);
+            splitContainer1.Panel2.Controls.Add(splitContainer2);
+            splitContainer1.Size = new Size(1050, 865);
+            splitContainer1.SplitterDistance = 44;
+            splitContainer1.SplitterWidth = 2;
+            splitContainer1.TabIndex = 1;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Font = new Font("寰蒋闆呴粦", 10.5F, FontStyle.Bold, GraphicsUnit.Point, 134);
+            label1.ForeColor = Color.White;
+            label1.Location = new Point(35, 6);
+            label1.Margin = new Padding(4, 0, 4, 0);
+            label1.Name = "label1";
+            label1.Size = new Size(65, 19);
+            label1.TabIndex = 3;
+            label1.Text = "缂栬緫宸ュ叿";
+            label1.MouseMove += label1_MouseMove;
+            // 
+            // picMin
+            // 
+            picMin.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            picMin.BackColor = Color.Gray;
+            picMin.Location = new Point(954, 0);
+            picMin.Margin = new Padding(4);
+            picMin.Name = "picMin";
+            picMin.Size = new Size(27, 32);
+            picMin.SizeMode = PictureBoxSizeMode.StretchImage;
+            picMin.TabIndex = 2;
+            picMin.TabStop = false;
+            picMin.MouseDown += picMin_MouseDown;
+            picMin.MouseEnter += picMin_MouseEnter;
+            picMin.MouseLeave += picMin_MouseLeave;
+            picMin.MouseUp += picMin_MouseUp;
+            // 
+            // picMax
+            // 
+            picMax.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            picMax.BackColor = Color.FromArgb(0, 128, 18);
+            picMax.Location = new Point(984, 0);
+            picMax.Margin = new Padding(4);
+            picMax.Name = "picMax";
+            picMax.Size = new Size(30, 32);
+            picMax.SizeMode = PictureBoxSizeMode.StretchImage;
+            picMax.TabIndex = 2;
+            picMax.TabStop = false;
+            picMax.MouseDown += picMax_MouseDown;
+            picMax.MouseEnter += picMax_MouseEnter;
+            picMax.MouseLeave += picMax_MouseLeave;
+            picMax.MouseUp += picMax_MouseUp;
+            // 
+            // picClose
+            // 
+            picClose.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            picClose.BackColor = Color.FromArgb(0, 0, 180);
+            picClose.Location = new Point(1016, 0);
+            picClose.Margin = new Padding(4);
+            picClose.Name = "picClose";
+            picClose.Size = new Size(27, 32);
+            picClose.SizeMode = PictureBoxSizeMode.StretchImage;
+            picClose.TabIndex = 2;
+            picClose.TabStop = false;
+            picClose.MouseDown += picClose_MouseDown;
+            picClose.MouseEnter += picClose_MouseEnter;
+            picClose.MouseLeave += picClose_MouseLeave;
+            picClose.MouseUp += picClose_MouseUp;
+            // 
+            // pictureBox1
+            // 
+            pictureBox1.Image = (Image)resources.GetObject("pictureBox1.Image");
+            pictureBox1.Location = new Point(-1, -2);
+            pictureBox1.Margin = new Padding(4);
+            pictureBox1.Name = "pictureBox1";
+            pictureBox1.Size = new Size(34, 40);
+            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
+            pictureBox1.TabIndex = 1;
+            pictureBox1.TabStop = false;
+            // 
+            // panel1
+            // 
+            panel1.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            panel1.BackColor = Color.DarkSlateGray;
+            panel1.Controls.Add(panControlView);
+            panel1.Location = new Point(1059, 3);
+            panel1.Margin = new Padding(4);
+            panel1.Name = "panel1";
+            panel1.Size = new Size(719, 42);
+            panel1.TabIndex = 1;
+            // 
+            // panControlView
+            // 
+            panControlView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
+            panControlView.Location = new Point(2, 3);
+            panControlView.Margin = new Padding(4);
+            panControlView.Name = "panControlView";
+            panControlView.Size = new Size(713, 37);
+            panControlView.TabIndex = 8;
+            // 
+            // splitContainer2
+            // 
+            splitContainer2.Dock = DockStyle.Fill;
+            splitContainer2.FixedPanel = FixedPanel.Panel2;
+            splitContainer2.Location = new Point(0, 0);
+            splitContainer2.Margin = new Padding(4);
+            splitContainer2.Name = "splitContainer2";
+            splitContainer2.Orientation = Orientation.Horizontal;
+            // 
+            // splitContainer2.Panel1
+            // 
+            splitContainer2.Panel1.Controls.Add(fctb);
+            // 
+            // splitContainer2.Panel2
+            // 
+            splitContainer2.Panel2.BackColor = Color.DimGray;
+            splitContainer2.Panel2.Controls.Add(splitContainer3);
+            splitContainer2.Size = new Size(1050, 819);
+            splitContainer2.SplitterDistance = 636;
+            splitContainer2.SplitterWidth = 3;
+            splitContainer2.TabIndex = 2;
+            // 
+            // fctb
+            // 
+            fctb.AllowDrop = true;
+            fctb.AutoScrollMinSize = new Size(29, 16);
+            fctb.BackBrush = null;
+            fctb.BackColor = Color.FromArgb(30, 17, 18);
+            fctb.CaretColor = Color.White;
+            fctb.ContextMenuStrip = contextMenuStripEx1;
+            fctb.Cursor = Cursors.IBeam;
+            fctb.DelayedEventsInterval = 1000;
+            fctb.DelayedTextChangedInterval = 1000;
+            fctb.DisabledColor = Color.FromArgb(30, 17, 18);
+            fctb.Dock = DockStyle.Fill;
+            fctb.FoldingIndicatorColor = Color.Chartreuse;
+            fctb.Font = new Font("Courier New", 11.25F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            fctb.ForeColor = Color.White;
+            fctb.HighlightingRangeType = HighlightingRangeType.VisibleRange;
+            fctb.ImeMode = ImeMode.On;
+            fctb.IndentBackColor = Color.FromArgb(30, 17, 18);
+            fctb.IsReplaceMode = false;
+            fctb.Language = Language.CSharp;
+            fctb.LineNumberColor = Color.MintCream;
+            fctb.Location = new Point(0, 0);
+            fctb.Margin = new Padding(4);
+            fctb.Name = "fctb";
+            fctb.Paddings = new Padding(0);
+            fctb.SelectionColor = Color.FromArgb(100, 255, 255, 128);
+            fctb.ServiceLinesColor = Color.DarkGoldenrod;
+            fctb.Size = new Size(1050, 636);
+            fctb.TabIndex = 0;
+            fctb.TextChanged += fctb_TextChanged;
+            fctb.KeyDown += fctb_KeyDown;
+            // 
+            // contextMenuStripEx1
+            // 
+            contextMenuStripEx1.Items.AddRange(new ToolStripItem[] { 澶嶅埗ToolStripMenuItem1, 鍓垏ToolStripMenuItem1, toolStripMenuItem4, 绮樿创ToolStripMenuItem1, toolStripMenuItem5, 鍏ㄩ�塗oolStripMenuItem1, toolStripMenuItem6, 娓呴櫎ToolStripMenuItem1, 鏂板缓ToolStripMenuItem });
+            contextMenuStripEx1.Name = "contextMenuStripEx1";
+            contextMenuStripEx1.RenderMode = ToolStripRenderMode.System;
+            contextMenuStripEx1.Size = new Size(101, 154);
+            // 
+            // 澶嶅埗ToolStripMenuItem1
+            // 
+            澶嶅埗ToolStripMenuItem1.ForeColor = Color.FromArgb(255, 255, 128);
+            澶嶅埗ToolStripMenuItem1.Name = "澶嶅埗ToolStripMenuItem1";
+            澶嶅埗ToolStripMenuItem1.Size = new Size(100, 22);
+            澶嶅埗ToolStripMenuItem1.Text = "澶嶅埗";
+            澶嶅埗ToolStripMenuItem1.Click += 澶嶅埗ToolStripMenuItem_Click;
+            // 
+            // 鍓垏ToolStripMenuItem1
+            // 
+            鍓垏ToolStripMenuItem1.ForeColor = Color.FromArgb(255, 255, 128);
+            鍓垏ToolStripMenuItem1.Name = "鍓垏ToolStripMenuItem1";
+            鍓垏ToolStripMenuItem1.Size = new Size(100, 22);
+            鍓垏ToolStripMenuItem1.Text = "鍓垏";
+            鍓垏ToolStripMenuItem1.Click += 鍓垏ToolStripMenuItem_Click;
+            // 
+            // toolStripMenuItem4
+            // 
+            toolStripMenuItem4.ForeColor = SystemColors.ControlDarkDark;
+            toolStripMenuItem4.Name = "toolStripMenuItem4";
+            toolStripMenuItem4.Size = new Size(97, 6);
+            // 
+            // 绮樿创ToolStripMenuItem1
+            // 
+            绮樿创ToolStripMenuItem1.ForeColor = Color.FromArgb(255, 255, 128);
+            绮樿创ToolStripMenuItem1.Name = "绮樿创ToolStripMenuItem1";
+            绮樿创ToolStripMenuItem1.Size = new Size(100, 22);
+            绮樿创ToolStripMenuItem1.Text = "绮樿创";
+            绮樿创ToolStripMenuItem1.Click += 绮樿创ToolStripMenuItem_Click;
+            // 
+            // toolStripMenuItem5
+            // 
+            toolStripMenuItem5.ForeColor = SystemColors.ControlDarkDark;
+            toolStripMenuItem5.Name = "toolStripMenuItem5";
+            toolStripMenuItem5.Size = new Size(97, 6);
+            // 
+            // 鍏ㄩ�塗oolStripMenuItem1
+            // 
+            鍏ㄩ�塗oolStripMenuItem1.ForeColor = Color.FromArgb(255, 255, 128);
+            鍏ㄩ�塗oolStripMenuItem1.Name = "鍏ㄩ�塗oolStripMenuItem1";
+            鍏ㄩ�塗oolStripMenuItem1.Size = new Size(100, 22);
+            鍏ㄩ�塗oolStripMenuItem1.Text = "鍏ㄩ��";
+            鍏ㄩ�塗oolStripMenuItem1.Click += 鍏ㄩ�塗oolStripMenuItem_Click;
+            // 
+            // toolStripMenuItem6
+            // 
+            toolStripMenuItem6.ForeColor = SystemColors.ControlDarkDark;
+            toolStripMenuItem6.Name = "toolStripMenuItem6";
+            toolStripMenuItem6.Size = new Size(97, 6);
+            // 
+            // 娓呴櫎ToolStripMenuItem1
+            // 
+            娓呴櫎ToolStripMenuItem1.ForeColor = Color.FromArgb(255, 255, 128);
+            娓呴櫎ToolStripMenuItem1.Name = "娓呴櫎ToolStripMenuItem1";
+            娓呴櫎ToolStripMenuItem1.Size = new Size(100, 22);
+            娓呴櫎ToolStripMenuItem1.Text = "娓呴櫎";
+            娓呴櫎ToolStripMenuItem1.Click += 娓呴櫎ToolStripMenuItem_Click;
+            // 
+            // 鏂板缓ToolStripMenuItem
+            // 
+            鏂板缓ToolStripMenuItem.ForeColor = Color.FromArgb(255, 255, 128);
+            鏂板缓ToolStripMenuItem.Name = "鏂板缓ToolStripMenuItem";
+            鏂板缓ToolStripMenuItem.Size = new Size(100, 22);
+            鏂板缓ToolStripMenuItem.Text = "鏂板缓";
+            鏂板缓ToolStripMenuItem.Click += 鏂板缓ToolStripMenuItem_Click;
+            // 
+            // splitContainer3
+            // 
+            splitContainer3.Dock = DockStyle.Fill;
+            splitContainer3.FixedPanel = FixedPanel.Panel2;
+            splitContainer3.IsSplitterFixed = true;
+            splitContainer3.Location = new Point(0, 0);
+            splitContainer3.Margin = new Padding(4);
+            splitContainer3.Name = "splitContainer3";
+            splitContainer3.Orientation = Orientation.Horizontal;
+            // 
+            // splitContainer3.Panel1
+            // 
+            splitContainer3.Panel1.Controls.Add(DebugTextBox1);
+            // 
+            // splitContainer3.Panel2
+            // 
+            splitContainer3.Panel2.BackColor = Color.FromArgb(30, 17, 18);
+            splitContainer3.Panel2MinSize = 10;
+            splitContainer3.Size = new Size(1050, 180);
+            splitContainer3.SplitterDistance = 153;
+            splitContainer3.SplitterWidth = 2;
+            splitContainer3.TabIndex = 1;
+            // 
+            // DebugTextBox1
+            // 
+            DebugTextBox1.AllowDrop = true;
+            DebugTextBox1.AutoScrollMinSize = new Size(2, 15);
+            DebugTextBox1.BackBrush = null;
+            DebugTextBox1.BackColor = Color.FromArgb(30, 17, 18);
+            DebugTextBox1.CaretColor = Color.White;
+            DebugTextBox1.Cursor = Cursors.IBeam;
+            DebugTextBox1.DisabledColor = Color.FromArgb(100, 180, 180, 180);
+            DebugTextBox1.Dock = DockStyle.Fill;
+            DebugTextBox1.Font = new Font("Courier New", 10.5F);
+            DebugTextBox1.ForeColor = Color.FromArgb(255, 255, 128);
+            DebugTextBox1.ImeMode = ImeMode.On;
+            DebugTextBox1.IndentBackColor = Color.FromArgb(30, 17, 18);
+            DebugTextBox1.IsReadLineMode = false;
+            DebugTextBox1.IsReplaceMode = false;
+            DebugTextBox1.Location = new Point(0, 0);
+            DebugTextBox1.Margin = new Padding(4);
+            DebugTextBox1.Name = "DebugTextBox1";
+            DebugTextBox1.Paddings = new Padding(0);
+            DebugTextBox1.SelectionColor = Color.FromArgb(50, 0, 0, 255);
+            DebugTextBox1.ServiceLinesColor = Color.DarkGoldenrod;
+            DebugTextBox1.ShowLineNumbers = false;
+            DebugTextBox1.Size = new Size(1050, 153);
+            DebugTextBox1.TabIndex = 0;
+            DebugTextBox1.KeyDown += DebugTextBox1_KeyDown;
+            // 
+            // imageList1
+            // 
+            imageList1.ColorDepth = ColorDepth.Depth32Bit;
+            imageList1.ImageSize = new Size(16, 16);
+            imageList1.TransparentColor = Color.Black;
+            // 
+            // timerCell
+            // 
+            timerCell.Interval = 10;
+            timerCell.Tick += timerCell_Tick;
+            // 
+            // timerBack
+            // 
+            timerBack.Interval = 10;
+            timerBack.Tick += timerBack_Tick;
+            // 
+            // ScriptEditForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            BackColor = Color.DimGray;
+            ClientSize = new Size(1050, 865);
+            ControlBox = false;
+            Controls.Add(splitContainer1);
+            DoubleBuffered = true;
+            Icon = (Icon)resources.GetObject("$this.Icon");
+            KeyPreview = true;
+            Margin = new Padding(4);
+            MinimumSize = new Size(1047, 837);
+            Name = "ScriptEditForm";
+            StartPosition = FormStartPosition.CenterScreen;
+            FormClosing += Form1_FormClosing;
+            SizeChanged += Form1_SizeChanged;
+            KeyDown += Form1_KeyDown;
+            splitContainer1.Panel1.ResumeLayout(false);
+            splitContainer1.Panel1.PerformLayout();
+            splitContainer1.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit();
+            splitContainer1.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)picMin).EndInit();
+            ((System.ComponentModel.ISupportInitialize)picMax).EndInit();
+            ((System.ComponentModel.ISupportInitialize)picClose).EndInit();
+            ((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
+            panel1.ResumeLayout(false);
+            splitContainer2.Panel1.ResumeLayout(false);
+            splitContainer2.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer2).EndInit();
+            splitContainer2.ResumeLayout(false);
+            contextMenuStripEx1.ResumeLayout(false);
+            splitContainer3.Panel1.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer3).EndInit();
+            splitContainer3.ResumeLayout(false);
+            ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.ImageList imageList1;
+        private System.Windows.Forms.SplitContainer splitContainer1;
+        private System.Windows.Forms.PictureBox pictureBox1;
+        private System.Windows.Forms.PictureBox picClose;
+        private System.Windows.Forms.PictureBox picMin;
+        private System.Windows.Forms.PictureBox picMax;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Panel panel1;
+        private System.Windows.Forms.Timer timerCell;
+        private System.Windows.Forms.Timer timerBack;
+        private System.Windows.Forms.Panel panControlView;
+        private System.Windows.Forms.SplitContainer splitContainer2;
+        private DebugTextBox DebugTextBox1;
+        public FastColoredTextBox fctb;
+        private System.Windows.Forms.SplitContainer splitContainer3;
+        private ContextMenuStripEx contextMenuStripEx1;
+        private System.Windows.Forms.ToolStripMenuItem 澶嶅埗ToolStripMenuItem1;
+        private System.Windows.Forms.ToolStripMenuItem 鍓垏ToolStripMenuItem1;
+        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4;
+        private System.Windows.Forms.ToolStripMenuItem 绮樿创ToolStripMenuItem1;
+        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5;
+        private System.Windows.Forms.ToolStripMenuItem 鍏ㄩ�塗oolStripMenuItem1;
+        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem6;
+        private System.Windows.Forms.ToolStripMenuItem 娓呴櫎ToolStripMenuItem1;
+        private System.Windows.Forms.ToolStripMenuItem 鏂板缓ToolStripMenuItem;
+    }
+}
+
diff --git a/LB_VisionControl/ScriptEditControl/ScriptEditForm.cs b/LB_VisionControl/ScriptEditControl/ScriptEditForm.cs
new file mode 100644
index 0000000..846c3d4
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ScriptEditForm.cs
@@ -0,0 +1,510 @@
+锘縰sing LB_VisionControl.ScriptEditControl.FastColorTextBox;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace LB_VisionControl.ScriptEditControl
+{
+    public partial class ScriptEditForm : Form
+    {
+        public ScriptEditForm()
+        {
+            InitializeComponent();
+            CommConfig.AppLocationPath = Application.StartupPath;
+            UpStyle();
+
+            InitStylesPriority();
+        }
+        private void UpStyle()
+        {
+            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);
+            UpdateStyles();
+        }
+        private void CreatNew()
+        {
+            #region 鍒濆鍖栨暟鎹�
+            fctb.Text = @"/*
+鏃ュ織璁板綍
+鏃堕棿锛�" + DateTime.Now.ToLocalTime() + @"
+鐢ㄦ埛锛�" + Environment.UserName + @"
+璁板綍锛�
+*/
+using System;
+using System.Text;
+class Program
+{
+    static void Main()
+    {
+       //浠g爜
+       
+    }
+}";
+
+            #endregion
+        }
+        private void InitStylesPriority()
+        {
+
+            fctb.ClearUndo();
+            fctb.IsChanged = false;
+
+            CreatNew();
+
+            KeyWordsAuto.CreatMenu(fctb, imageList1);
+            KeysWordCMDAuto.CreatMenu(DebugTextBox1, imageList1);
+        }
+        #region 绯荤粺UI
+        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            try
+            {
+                if (Directory.Exists(CommConfig.BinPath))
+                    Directory.Delete(CommConfig.BinPath, true);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.Message);
+            }
+        }
+        private void Form1_KeyDown(object sender, KeyEventArgs e)
+        {
+            if ((Control.ModifierKeys & Keys.Control) != 0 && e.KeyCode == Keys.Up)
+            { fctb.Focus(); }
+            else if ((Control.ModifierKeys & Keys.Control) != 0 && e.KeyCode == Keys.Down)
+            { DebugTextBox1.Focus(); }
+        }
+
+        private void fctb_TextChanged(object sender, TextChangedEventArgs e)
+        {
+
+        }
+        private void fctb_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (CompliReslut.RowErrorNumber != -1)
+            {
+                fctb[CompliReslut.RowErrorNumber - 1].BackgroundBrush = null;
+                fctb.Invalidate();
+                CompliReslut.RowErrorNumber = -1;
+            }
+        }
+        #endregion
+
+        #region 鍙冲嚮鑿滃崟
+        private void 绮樿创ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            fctb.Paste();
+        }
+
+        private void 澶嶅埗ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            fctb.Copy();
+        }
+
+        private void 鍓垏ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            fctb.Cut();
+
+        }
+
+        private void 鍏ㄩ�塗oolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            fctb.SelectAll();
+        }
+
+        private void 娓呴櫎ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            fctb.Clear();
+        }
+        #endregion
+
+        #region 鍏抽棴鎸夐挳
+        private void picClose_MouseEnter(object sender, EventArgs e)
+        {
+            //picClose.Image = Properties.Resources.close2;
+        }
+
+        private void picClose_MouseLeave(object sender, EventArgs e)
+        {
+            //picClose.Image = Properties.Resources.close1;
+        }
+
+        private void picClose_MouseDown(object sender, MouseEventArgs e)
+        {
+            //picClose.Image = Properties.Resources.close3;
+        }
+
+        private void picClose_MouseUp(object sender, MouseEventArgs e)
+        {
+            this.Close();
+        }
+        #endregion
+
+        #region 鏈�灏忓寲鎸夐挳
+        private void picMin_MouseEnter(object sender, EventArgs e)
+        {
+            //picMin.Image = Properties.Resources.min2;
+        }
+        private void picMin_MouseLeave(object sender, EventArgs e)
+        {
+            //picMin.Image = Properties.Resources.min1;
+        }
+        private void picMin_MouseDown(object sender, MouseEventArgs e)
+        {
+            //picMin.Image = Properties.Resources.min3;
+        }
+        private void picMin_MouseUp(object sender, MouseEventArgs e)
+        {
+           this.WindowState = FormWindowState.Minimized;
+        }
+        #endregion
+
+        #region 鍏ㄥ睆鎸夐挳
+        private void picMax_MouseEnter(object sender, EventArgs e)
+        {
+            if (this.WindowState == FormWindowState.Normal)
+            {
+                //picMax.Image = Properties.Resources.forMax2;
+            }
+            else
+            {
+                //picMax.Image = Properties.Resources.forNor2;
+            }
+        }
+
+        private void picMax_MouseLeave(object sender, EventArgs e)
+        {
+            if (this.WindowState == FormWindowState.Normal)
+            {
+                //picMax.Image = Properties.Resources.forMax1;
+            }
+            else
+            {
+                //picMax.Image = Properties.Resources.forNor1;
+            }
+        }
+
+        private void picMax_MouseDown(object sender, MouseEventArgs e)
+        {
+            if (this.WindowState == FormWindowState.Normal)
+            {
+                //picMax.Image = Properties.Resources.forMax3;
+            }
+            else
+            {
+                //picMax.Image = Properties.Resources.forNor3;
+            }
+        }
+
+        private void picMax_MouseUp(object sender, MouseEventArgs e)
+        {
+            if (this.WindowState == FormWindowState.Normal)
+            {
+                this.WindowState = FormWindowState.Maximized;
+            }
+            else
+            {
+                this.WindowState = FormWindowState.Normal;
+            }
+        }
+        #endregion
+
+        #region 绉诲姩
+        public const int WM_NCLBUTTONDOWN = 0xA1;
+        public const int HT_CAPTION = 0x2;
+        [DllImportAttribute("user32.dll")]
+        public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+        [DllImportAttribute("user32.dll")]
+        public static extern bool ReleaseCapture();
+
+        private void splitContainer1_Panel1_MouseMove(object sender, MouseEventArgs e)
+        {
+            //绉诲姩
+            if (e.Button == MouseButtons.Left)
+            {
+                if (e.X < this.Width)
+                {
+                    ReleaseCapture();
+                    SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
+                }
+            }
+        }
+        private void label1_MouseMove(object sender, MouseEventArgs e)
+        {
+            //绉诲姩
+            if (e.Button == MouseButtons.Left)
+            {
+                if (e.X < this.Width)
+                {
+                    ReleaseCapture();
+                    SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
+                }
+            }
+        }
+        private void Form1_SizeChanged(object sender, EventArgs e)
+        {
+            if (this.WindowState == FormWindowState.Normal)
+            {
+                //picMax.Image = Properties.Resources.forMax1;
+            }
+            else
+            {
+                //picMax.Image = Properties.Resources.forNor1;
+            }
+        }
+
+        #endregion
+
+        #region 鍔ㄧ敾
+        public bool isShow = true;
+        int loadSpeed = 10;
+        public void StartMeun()
+        {
+            if (isShow)
+            {
+                timerBack.Enabled = true;
+            }
+            else
+            {
+                timerCell.Enabled = true;
+            }
+        }
+        private void CellOutputHide()
+        {
+            panel1.Height -= loadSpeed;
+            loadSpeed += loadSpeed;
+            if (panel1.Height <= 30)
+            {
+                timerCell.Enabled = false;
+                panel1.Height = 30;
+                loadSpeed = 10;
+
+                //back
+                timerBack.Enabled = true;
+            }
+        }
+        private void CellOutputShow()
+        {
+            panel1.Height += loadSpeed;
+            loadSpeed += loadSpeed;
+            if (panel1.Height >= 310)
+            {
+                timerCell.Enabled = false;
+                panel1.Height = 310;
+                loadSpeed = 10;
+
+                //OK
+                // picDic.Image = Properties.Resources.rdir1;
+                isShow = false;//鏄剧ず杩囩▼瀹屾垚
+            }
+        }
+
+        private void backOutputHide()
+        {
+            panel1.Left += loadSpeed;
+            loadSpeed += loadSpeed;
+            if (panel1.Left >= this.Width)
+            {
+                timerBack.Enabled = false;
+                panel1.Left = this.Width;
+                loadSpeed = 10;
+
+                //OK
+                //picDic.Image = Properties.Resources.dir1;
+                isShow = true;//鏄剧ず杩囩▼缁撴潫
+            }
+        }
+        private void backOutputShow()
+        {
+            panel1.Left -= loadSpeed;
+            loadSpeed += loadSpeed;
+            if (panel1.Left <= this.Width - panel1.Width - 18)
+            {
+                timerBack.Enabled = false;
+                panel1.Left = this.Width - panel1.Width - 18;
+                loadSpeed = 10;
+
+                //celll
+                timerCell.Enabled = true;
+            }
+        }
+        private void timerCell_Tick(object sender, EventArgs e)
+        {
+            if (isShow)
+            {
+                CellOutputShow();
+            }
+            else
+            {
+                CellOutputHide();
+            }
+        }
+
+        private void timerBack_Tick(object sender, EventArgs e)
+        {
+            if (isShow)
+            {
+                backOutputShow();
+            }
+            else
+            {
+                backOutputHide();
+            }
+        }
+
+        #endregion
+
+
+        public void FileSave()
+        {
+            if (!Directory.Exists(CommConfig.ClassLibPath))
+            {
+                Directory.CreateDirectory(CommConfig.ClassLibPath);
+            }
+            File.WriteAllText(CommConfig.fileName, fctb.Text);
+        }
+
+        #region 鎺у埗鍙�
+        bool stop;
+        string comHead = ">: ";
+        private void StartDebug()
+        {
+            DebugTextBox1.WriteLine("C# Editer v2.0  杞欢  [甯姪璇疯緭鍏ワ細\"?\"]\n");
+            string text = "";
+            stop = false;
+            do
+            {
+                DebugTextBox1.WriteLine(comHead);
+                text = DebugTextBox1.ReadLine();
+                DebugTextBox1.WriteLine(RunCommand(text));
+            } while (!stop);
+        }
+        protected override void OnClosing(CancelEventArgs e)
+        {
+            Stop();
+            base.OnClosing(e);
+        }
+
+        void Stop()
+        {
+            stop = true;
+            DebugTextBox1.IsReadLineMode = false;
+        }
+        protected override void OnShown(EventArgs e)
+        {
+            base.OnShown(e);
+            StartDebug();
+        }
+
+        private string RunCommand(string c)
+        {
+            if (c == "csc" || c.StartsWith("csc "))//杩涘叆CSC鍛戒护妯″紡
+            {
+                return "";
+                //CommandRun m = new CommandRun(this);
+                //return m.RunCsc(c);
+            }
+
+            #region 鍩虹鍛戒护
+            StringBuilder sbr = new StringBuilder();
+            switch (c)
+            {
+                case "exit":
+                    this.Close();
+                    break;
+                case "min":
+                    this.WindowState = FormWindowState.Minimized;
+                    break;
+                case "max":
+                    this.WindowState = FormWindowState.Maximized;
+                    break;
+                case "nor":
+                    this.WindowState = FormWindowState.Normal;
+                    break;
+                case "clear":
+                    fctb.Clear();
+                    break;
+                case "save":
+                    FileSave();
+                    break;
+                case "code":
+                    AddClassFileList();
+                    if (isShow)
+                        StartMeun();
+                    break;
+                case "?":
+                case "help":
+                    AddText("Properties.Resources.help");
+                    if (isShow)
+                        StartMeun();
+                    break;
+                case "test":
+                    AddText("Properties.Resources.TestCode");
+                    if (isShow)
+                        StartMeun();
+                    break;
+                case "hide":
+                    if (!isShow)
+                        StartMeun();
+                    break;
+                case "new":
+                    CreatNew();
+                    break;
+                default:
+                    sbr.AppendLine("unknown command锛�");
+                    break;
+            }
+
+            return sbr.ToString();
+            #endregion
+        }
+        #endregion
+
+
+        #region 娣诲姞UI
+        public void AddCsc()
+        {
+            panControlView.Controls.Clear();
+            ComplieUI cp = new ComplieUI();
+            cp.BackColor = Color.Transparent;
+            cp.fctb = this.fctb;
+            cp.Dock = DockStyle.Fill;
+            panControlView.Controls.Add(cp);
+        }
+        public void AddClassFileList()
+        {
+            panControlView.Controls.Clear();
+            ClassFileList cp = new ClassFileList();
+            cp.BackColor = Color.Transparent;
+            cp.fctb = this.fctb;
+            cp.Dock = DockStyle.Fill;
+            panControlView.Controls.Add(cp);
+        }
+        public void AddText(string txt)
+        {
+            panControlView.Controls.Clear();
+            TextBox tx = new TextBox();
+            tx.Text = txt;
+            tx.Dock = DockStyle.Fill;
+            tx.BorderStyle = BorderStyle.None;
+            tx.BackColor = Color.FromArgb(30, 17, 18);
+            tx.ForeColor = Color.Green;
+            tx.Multiline = true;
+            tx.ScrollBars = ScrollBars.Both;
+            tx.Font = new System.Drawing.Font("寰蒋闆呴粦", 12);
+            panControlView.Controls.Add(tx);
+        }
+        #endregion
+
+        private void DebugTextBox1_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyCode == Keys.Up)
+                e.Handled = true;
+        }
+
+        private void 鏂板缓ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            InitStylesPriority();
+        }
+    }
+
+}
diff --git a/LB_VisionControl/ScriptEditControl/ScriptEditForm.resx b/LB_VisionControl/ScriptEditControl/ScriptEditForm.resx
new file mode 100644
index 0000000..002fc22
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/ScriptEditForm.resx
@@ -0,0 +1,1657 @@
+锘�<?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=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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAACH
+        DwAAjA8AAP1SAACBQAAAfXkAAOmLAAA85QAAGcxzPIV3AAAKOWlDQ1BQaG90b3Nob3AgSUNDIHByb2Zp
+        bGUAAEjHnZZ3VFTXFofPvXd6oc0w0hl6ky4wgPQuIB0EURhmBhjKAMMMTWyIqEBEEREBRZCggAGjoUis
+        iGIhKKhgD0gQUGIwiqioZEbWSnx5ee/l5ffHvd/aZ+9z99l7n7UuACRPHy4vBZYCIJkn4Ad6ONNXhUfQ
+        sf0ABniAAaYAMFnpqb5B7sFAJC83F3q6yAn8i94MAUj8vmXo6U+ng/9P0qxUvgAAyF/E5mxOOkvE+SJO
+        yhSkiu0zIqbGJIoZRomZL0pQxHJijlvkpZ99FtlRzOxkHlvE4pxT2clsMfeIeHuGkCNixEfEBRlcTqaI
+        b4tYM0mYzBXxW3FsMoeZDgCKJLYLOKx4EZuImMQPDnQR8XIAcKS4LzjmCxZwsgTiQ7mkpGbzuXHxArou
+        S49uam3NoHtyMpM4AoGhP5OVyOSz6S4pyalMXjYAi2f+LBlxbemiIluaWltaGpoZmX5RqP+6+Dcl7u0i
+        vQr43DOI1veH7a/8UuoAYMyKarPrD1vMfgA6tgIgd/8Pm+YhACRFfWu/8cV5aOJ5iRcIUm2MjTMzM424
+        HJaRuKC/6386/A198T0j8Xa/l4fuyollCpMEdHHdWClJKUI+PT2VyeLQDf88xP848K/zWBrIieXwOTxR
+        RKhoyri8OFG7eWyugJvCo3N5/6mJ/zDsT1qca5Eo9Z8ANcoISN2gAuTnPoCiEAESeVDc9d/75oMPBeKb
+        F6Y6sTj3nwX9+65wifiRzo37HOcSGExnCfkZi2viawnQgAAkARXIAxWgAXSBITADVsAWOAI3sAL4gWAQ
+        DtYCFogHyYAPMkEu2AwKQBHYBfaCSlAD6kEjaAEnQAc4DS6Ay+A6uAnugAdgBIyD52AGvAHzEARhITJE
+        geQhVUgLMoDMIAZkD7lBPlAgFA5FQ3EQDxJCudAWqAgqhSqhWqgR+hY6BV2ArkID0D1oFJqCfoXewwhM
+        gqmwMqwNG8MM2An2hoPhNXAcnAbnwPnwTrgCroOPwe3wBfg6fAcegZ/DswhAiAgNUUMMEQbigvghEUgs
+        wkc2IIVIOVKHtCBdSC9yCxlBppF3KAyKgqKjDFG2KE9UCIqFSkNtQBWjKlFHUe2oHtQt1ChqBvUJTUYr
+        oQ3QNmgv9Cp0HDoTXYAuRzeg29CX0HfQ4+g3GAyGhtHBWGE8MeGYBMw6TDHmAKYVcx4zgBnDzGKxWHms
+        AdYO64dlYgXYAux+7DHsOewgdhz7FkfEqeLMcO64CBwPl4crxzXhzuIGcRO4ebwUXgtvg/fDs/HZ+BJ8
+        Pb4LfwM/jp8nSBN0CHaEYEICYTOhgtBCuER4SHhFJBLVidbEACKXuIlYQTxOvEIcJb4jyZD0SS6kSJKQ
+        tJN0hHSedI/0ikwma5MdyRFkAXknuZF8kfyY/FaCImEk4SXBltgoUSXRLjEo8UISL6kl6SS5VjJHslzy
+        pOQNyWkpvJS2lIsUU2qDVJXUKalhqVlpirSptJ90snSxdJP0VelJGayMtoybDFsmX+awzEWZMQpC0aC4
+        UFiULZR6yiXKOBVD1aF6UROoRdRvqP3UGVkZ2WWyobJZslWyZ2RHaAhNm+ZFS6KV0E7QhmjvlygvcVrC
+        WbJjScuSwSVzcopyjnIcuUK5Vrk7cu/l6fJu8onyu+U75B8poBT0FQIUMhUOKlxSmFakKtoqshQLFU8o
+        3leClfSVApXWKR1W6lOaVVZR9lBOVd6vfFF5WoWm4qiSoFKmclZlSpWiaq/KVS1TPaf6jC5Ld6In0Svo
+        PfQZNSU1TzWhWq1av9q8uo56iHqeeqv6Iw2CBkMjVqNMo1tjRlNV01czV7NZ874WXouhFa+1T6tXa05b
+        RztMe5t2h/akjpyOl06OTrPOQ12yroNumm6d7m09jB5DL1HvgN5NfVjfQj9ev0r/hgFsYGnANThgMLAU
+        vdR6KW9p3dJhQ5Khk2GGYbPhqBHNyMcoz6jD6IWxpnGE8W7jXuNPJhYmSSb1Jg9MZUxXmOaZdpn+aqZv
+        xjKrMrttTjZ3N99o3mn+cpnBMs6yg8vuWlAsfC22WXRbfLS0suRbtlhOWWlaRVtVWw0zqAx/RjHjijXa
+        2tl6o/Vp63c2ljYCmxM2v9ga2ibaNtlOLtdZzllev3zMTt2OaVdrN2JPt4+2P2Q/4qDmwHSoc3jiqOHI
+        dmxwnHDSc0pwOub0wtnEme/c5jznYuOy3uW8K+Lq4Vro2u8m4xbiVun22F3dPc692X3Gw8Jjncd5T7Sn
+        t+duz2EvZS+WV6PXzAqrFetX9HiTvIO8K72f+Oj78H26fGHfFb57fB+u1FrJW9nhB/y8/Pb4PfLX8U/z
+        /z4AE+AfUBXwNNA0MDewN4gSFBXUFPQm2Dm4JPhBiG6IMKQ7VDI0MrQxdC7MNaw0bGSV8ar1q66HK4Rz
+        wzsjsBGhEQ0Rs6vdVu9dPR5pEVkQObRGZ03WmqtrFdYmrT0TJRnFjDoZjY4Oi26K/sD0Y9YxZ2O8Yqpj
+        ZlgurH2s52xHdhl7imPHKeVMxNrFlsZOxtnF7YmbineIL4+f5rpwK7kvEzwTahLmEv0SjyQuJIUltSbj
+        kqOTT/FkeIm8nhSVlKyUgVSD1ILUkTSbtL1pM3xvfkM6lL4mvVNAFf1M9Ql1hVuFoxn2GVUZbzNDM09m
+        SWfxsvqy9bN3ZE/kuOd8vQ61jrWuO1ctd3Pu6Hqn9bUboA0xG7o3amzM3zi+yWPT0c2EzYmbf8gzySvN
+        e70lbEtXvnL+pvyxrR5bmwskCvgFw9tst9VsR23nbu/fYb5j/45PhezCa0UmReVFH4pZxde+Mv2q4quF
+        nbE7+0ssSw7uwuzi7Rra7bD7aKl0aU7p2B7fPe1l9LLCstd7o/ZeLV9WXrOPsE+4b6TCp6Jzv+b+Xfs/
+        VMZX3qlyrmqtVqreUT13gH1g8KDjwZYa5ZqimveHuIfu1nrUttdp15UfxhzOOPy0PrS+92vG140NCg1F
+        DR+P8I6MHA082tNo1djYpNRU0gw3C5unjkUeu/mN6zedLYYtta201qLj4Ljw+LNvo78dOuF9ovsk42TL
+        d1rfVbdR2grbofbs9pmO+I6RzvDOgVMrTnV32Xa1fW/0/ZHTaqerzsieKTlLOJt/duFczrnZ86nnpy/E
+        XRjrjup+cHHVxds9AT39l7wvXbnsfvlir1PvuSt2V05ftbl66hrjWsd1y+vtfRZ9bT9Y/NDWb9nffsPq
+        RudN65tdA8sHzg46DF645Xrr8m2v29fvrLwzMBQydHc4cnjkLvvu5L2key/vZ9yff7DpIfph4SOpR+WP
+        lR7X/aj3Y+uI5ciZUdfRvidBTx6Mscae/5T+04fx/Kfkp+UTqhONk2aTp6fcp24+W/1s/Hnq8/npgp+l
+        f65+ofviu18cf+mbWTUz/pL/cuHX4lfyr468Xva6e9Z/9vGb5Dfzc4Vv5d8efcd41/s+7P3EfOYH7IeK
+        j3ofuz55f3q4kLyw8Bv3hPP74uYdwgAAAAlwSFlzAAALDAAACwwBP0AiyAAABiZJREFUeF7tnNGR3DYQ
+        RBXBlqo2AYWgEBSCQ3AIDkEhKASFoBAUgkNwCPrfj3P1FXkFdgOYAcnl4KT5eD9tggS7QWCAPfnDy8vL
+        h2QeREhiESGJRYQkFhGSWERIYhEhiUWEJBYRklhESGIRIYlFhCQWEZJYREhiESGJRYQkFhGSWERIYhEh
+        iUWEJBYRklhESGIRIYlFhFFuj/sRvhh8rLT5rWA/RRiFH9AAxv51e9y/3R73n7fH/WWQX0s7tP/79rh/
+        qjzjXcJ+ijAKP6AAIcC8fysGnwHui4DO/IrwVfJzSv6ptGG4TckPvp79FGEUfsAyemEURjV36BnARO7D
+        Xr5W7j/yrM+VNiW4/6YN+ynCKMXNMVLxwKuCWLFMGsGaTvl6Bl8Qt+n2lf0UYZTlxnjQf5UOXIG85AF6
+        gwlTJF/PfK+0K5Hplf0UYRTHqHg2ZwWCqZbvXQKzuQ3TWy+rgbKfIozgGBFXcFYgqAL53iVHF/RqoOyp
+        CF6WioEfGsFZgVgLOhZsblOyq0JjX0XwMMmXsXJWIEcXdCvQaj/ZWxEsJgsDVF90B70FHWHx9Yw1Y/D1
+        r7C/IvRYNnr8oD3g5REsPmMYWtt5Y4rAf8PIw8u2qrgzArH2D9hXcRum1T9QXdABeyxCC0enPWCkYfGU
+        jjlBH3jTeUYg1kDDf+c2JVaF1gyUfRahhVHSWWD0nGFcCUw6674wjPtcYi3oVoXWDJR9FqGGYwT1wHQj
+        G6KTwH3PuPezF/RmoOy1CMzywr0Fr0e19r4Y9B9fUQ/udwlmBr6esWYPvr7k42gge3fiM4QBLMOj+TQa
+        SK96aNGsKgKwppNIfrHfEgCFYS1WLZpzZgCz7ZtKfrLnEgIFsudl5Mw/GGt+j+Qrey4hUCCjizmuP6Pq
+        ORPu40x8Yc8lhCKMPRvBWRbyldkX9E2FZQWyp7qCAWxKJNhBYwptYe0/MMC4TYk1peP+3Gbl9fSXfReh
+        CMQ6LGMwXbEhs2MZytcz1obZHKDsuwhFIKOLoedEdDZ6Jb3nfY4GKr6LUATCN7fAZygPnBgUH/wOJc0D
+        wYLeoHXtxdh3EQ4E0jxAmxRrwbdOpc8IVHwXYQljT4VlzpeTgS+a36Gk9htNiRWoa4Cy9yIsgVgPq/He
+        AukVLZ4CxQrUdVrB3ovwBwXS2/TKn3xW6JXMnkBfYe9F+EMCsX7h8xQovUA9Fdor7L0Iv1Eg6E8La9O7
+        /tbfwtp/oBzmNiVv6xN7L8KBQDyj6kq4fzPx9jda7L0IRSh8EwtXmXcRewbUlbwt+Oy7CAcCcW2ELsKa
+        kiLZLPjsuwhFIL1jhRazHL1bRxqRbCo49l2EIpBeWdfCtRm6gN6RRjSbv/Fl30UoArE2PjVmmLasI41o
+        NhtG9l2EIpC9CyPasUlXYv0G0ts/YJrm6xlrKufrmU1/2XcRKBR+mIcZvpIe3N8ST6XYC3T43dlzESiQ
+        3nlPDxkJk2B99dYaaO3wh3/CZs9FoECsHWmP6KmrBgYK97PEOhC0/izKClRgz0VgjE+0B9pZL3g11hfP
+        1zNHAxXYbxEYRyd6IJThUTPA5lzIQW9B9hwI9rYC7hPeEvZbBObgH1uvPOP/uLCa450arXLYs+5xmxJP
+        oAL7LUKNk44iECpeemREl6Ad+sGbPm8g1oJu/WRr/YrqCVRgr0VoYXyuo8BUvABMqBm6HlMjAFQuvamm
+        1r6GNfVaA8UqcLz92MA+i9Bi6fDRqesZeI3oDSgEztcz1r+y2jUls88i9HB89hF4A+kNJs9PtjxVlgxv
+        CFfYYxEsHJ/u1XgCsTZ0nvmf25R4dvhV2F8RPEwWiicQa0Nn3cOaGXaX9uytCF6Wl+xNA1dhmQmsBZ2v
+        Z6wq0yoImrCvIoywlIK9ufUKPIFMC3sqwijLjTECo76WDKSkuDk+W+wZrgwGpezu6WIG2E8RRuEHLPV4
+        bUd9Frgv7v+ug1hhP0UYhR9AwDRUIHv/97Awf/1XSCgidm2+Zob9FGEUfoATFAPr8QgzfIT9nmE/RUhi
+        ESGJRYQkFhGSWERIYhEhiUWEJBYRklhESGIRIYlFhCQWEZJYREhiESGJRYQkFhGSWERIYhEhiUWEJJb/
+        AQLxxSSvN0IwAAAAAElFTkSuQmCC
+</value>
+  </data>
+  <metadata name="contextMenuStripEx1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>130, 22</value>
+  </metadata>
+  <metadata name="imageList1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 22</value>
+  </metadata>
+  <metadata name="timerCell.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>298, 23</value>
+  </metadata>
+  <metadata name="timerBack.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>415, 23</value>
+  </metadata>
+  <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>62</value>
+  </metadata>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAgIAAAAEAIAAoCAEAZgAAADAwAAABACAAqCUAAI4IAQAgIAAAAQAgAKgQAAA2LgEAICAAAAEA
+        CACoCAAA3j4BABAQAAABACAAaAQAAIZHAQAQEAAAAQAIAGgFAADuSwEAKAAAAIAAAAAAAQAAAQAgAAAA
+        AAAAAAEAxA4AAMQOAAAAAAAAAAAAAP///wD///8A////AP///wD///8A////AAAAAAAAAAABAAAAAgAA
+        AAQAAAAGAAAABwAAAAkAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
+        AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
+        AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
+        AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
+        AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
+        AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
+        AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
+        AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACQAAAAcAAAAGAAAABAAAAAIAAAAB////AP//
+        /wD///8A////AP///wD///8AAAAAAAAAAAIAAAAFAAAACAAAAAwAAAAQAAAAEwAAABUAAAAWAAAAFgAA
+        ABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAA
+        ABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAA
+        ABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAA
+        ABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAA
+        ABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAA
+        ABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAA
+        ABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAA
+        ABUAAAATAAAAEAAAAAwAAAAIAAAABQAAAAL///8A////AP///wD///8A////AP///wAAAAABAAAABAAA
+        AAgAAAAOAAAAFQAAABwAAAAhAAAAJAAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAA
+        ACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAA
+        ACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAA
+        ACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAA
+        ACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAA
+        ACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAA
+        ACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJwAA
+        ACcAAAAnAAAAJwAAACcAAAAnAAAAJwAAACcAAAAnAAAAJAAAACEAAAAcAAAAFQAAAA4AAAAIAAAABP//
+        /wD///8A////AP///wD///8A////AAAAAAEAAAAGAAAADAAAABUAAAAgAAAAKwAAADIAAAA4AAAAPAAA
+        ADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAA
+        ADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAA
+        ADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAA
+        ADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAA
+        ADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAA
+        ADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAA
+        ADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAA
+        ADwAAAA4AAAAMgAAACsAAAAgAAAAFQAAAAwAAAAG////AP///wD///8A////AP///wD///8AAAAAAgAA
+        AAcAAAAQAAAAHAAAACoAAAA4AAAAQwAAAEsAAABQAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAA
+        AFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAA
+        AFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAA
+        AFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAA
+        AFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAA
+        AFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAA
+        AFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUQAA
+        AFEAAABRAAAAUQAAAFEAAABRAAAAUQAAAFEAAABRAAAAUAAAAEsAAABEAAAAOQAAACsAAAAcAAAAEAAA
+        AAf///8A////AP///wD///8A////AP///wAAAAACAAAACAAAABIAAAAhAAAAMgAAAEMAAABRAAAAWgAA
+        AF8AAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAA
+        AGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAA
+        AGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAA
+        AGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAA
+        AGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAA
+        AGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAA
+        AGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAAAGEAAABhAAAAYQAA
+        AGEAAABfAAAAWgAAAFEAAABEAAAAMgAAACEAAAATAAAACf///wD///8A////AP///wD///8A////AAAA
+        AAIAAAAJAAAAFQAAACQAAAA4AAAASwAAAFoAAABkAAAAagAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAA
+        AGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAA
+        AGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAA
+        AGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAA
+        AGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAA
+        AGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAA
+        AGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAA
+        AGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGwAAABsAAAAbAAAAGoAAABkAAAAWgAAAEsAAAA4AAAAJAAA
+        ABUAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGpB5cgpAecH50Gox2VBqwcjga0G4gFuxqF
+        BcAagwXDGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmC
+        BcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmC
+        BcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmC
+        BcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmC
+        BcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmC
+        BcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmC
+        BcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmCBcQZggXEGYIFxBmC
+        BcQZggXEGoMFwxqFBcAAAABfAAAAUAAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP//
+        /wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAA
+        ACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP//
+        /wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAA
+        ADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP//
+        /wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAA
+        AFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP//
+        /wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4G/yKu
+        Bv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKu
+        Bv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKu
+        Bv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKu
+        Bv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKu
+        Bv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKu
+        Bv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKu
+        Bv8irgb/Iq4G/yKuBv8irgb/Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAA
+        AGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8lrA3/JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yax
+        D/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yax
+        D/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yax
+        D/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yax
+        D/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yax
+        D/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yax
+        D/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yaxD/8msQ//JrEP/yexD/8lrQ7/Iq4I/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP//
+        /wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I60J/zuW
+        P/8zfDr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9
+        Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9
+        Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9
+        Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9
+        Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9
+        Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9Ov80fTr/NH06/zR9
+        Ov80fTr/NH06/zR9Ov80fTr/M3s5/zuSQf8lrQ7/Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqE
+        BcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/Now6/w4BGv8PBhv/DwYb/w8GG/8PBhv/DwYb/w8G
+        G/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8G
+        G/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8G
+        G/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8G
+        G/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8G
+        G/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8G
+        G/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8PBhv/DwYb/w8GG/8LABj/M3s6/yax
+        D/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv//
+        /wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOv
+        Cf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGl
+        CJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9
+        Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAA
+        AAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAA
+        AAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8G
+        G/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAA
+        ABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP//
+        /wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAA
+        ACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP//
+        /wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAA
+        ADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP//
+        /wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAA
+        AFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP//
+        /wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEM
+        Hf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAA
+        AGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/Eg8e/xIN
+        Hv8RCx//EQsf/xEKH/8RCR//EQkf/xEJH/8RCh//EQsf/xIMH/8SDR7/EhAe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKu
+        Bv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP//
+        /wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaN
+        Ov8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIQHv8SEB7/Eg8e/xIQHv8TJh3/F04Y/xplFv8aaRX/G3sR/xyAEP8cfxD/HH8Q/xpv
+        E/8aZBb/GV0W/xZDGv8THx3/Egwe/xIPHv8SEB7/EhAe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqE
+        BcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIPHv8SER7/EhQd/xU6Gv8cdBL/HpQM/yGn
+        CP8hqgj/IqwI/yKtCP8irwf/Iq8H/yKvB/8irwf/Iq4H/yKsCP8irAj/IakI/yGoB/8flQz/HHYT/xZH
+        GP8TGR3/EhMe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yax
+        D/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv//
+        /wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOv
+        Cf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIP
+        Hv8RDh7/EhMe/xdMGP8fkw3/Iq4H/yKwB/8irwf/Iq8H/yKvB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irwf/Iq8H/yKvB/8irwf/Iq8H/yChCv8YUxj/Eg0e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/Eg8e/xIPHv8SDx7/Eg8e/xIPHv8SDx7/EhAe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xIP
+        Hv8SDx7/Eg8e/xIPHv8SDx7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGl
+        CJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SDh7/Egwe/xU1Gv8cghD/IrEH/yKxB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/IrAH/xyEEP8RCh//EhEe/xIRHv8SER7/EhEe/xIRHv8SFx7/Ehge/xIXHv8SFx7/Ehge/xIX
+        Hv8SEx7/EhEe/xIRHv8SER7/EhEe/xIRHv8SFR7/Ehge/xIXHv8SFx7/Ehce/xIYHv8SDx7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9
+        Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAA
+        AAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/Eg4e/xEK
+        H/8XThj/IakK/yO4Bf8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irwf/HIEQ/xEKH/8SER7/EhEe/xIR
+        Hv8SER7/Eg0e/xdPGP8abxP/GnAT/xpwE/8acRP/Gm8T/xQxGv8SCx//EhEe/xIRHv8SER7/EhIe/xU+
+        Gv8adhL/Gm8T/xpwE/8acBP/G3QS/xQrG/8SEB7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAA
+        AAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIQHv8RCR//GFMW/yGvCP8jswb/Iq0H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKvB/8cgRD/EQof/xIRHv8SER7/EhEe/xIRHv8RCx//G2sU/yO2Bv8juAX/I7gF/yO5
+        Bf8kwgT/GE8W/xECIP8SER7/EhEe/xIQHv8SDR//F0oX/yXEA/8juAX/I7gF/yO4Bf8kvAT/GWcV/xIT
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8G
+        G/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAA
+        ABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EQof/xhU
+        F/8hrAn/IrIG/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq8H/xyBEP8RCh//EhEe/xIR
+        Hv8SER7/EhEe/xIOHv8WPxr/IqoI/yKvB/8irgf/Iq4H/yS8Bf8bahL/ERAf/xIPHv8SER7/EhEe/xEK
+        H/8VLxr/IrAI/yKwBv8irgf/Iq4H/yKwB/8dghD/EhUd/xIQHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP//
+        /wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIMHv8XRBn/IakJ/yKxBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq8H/yOyBv8jtgX/I7sF/yO8Bf8jvAX/I7wF/yO7Bf8juAX/I7UG/yKy
+        Bv8irwf/Iq4H/yKuB/8irwf/HIEQ/xEKH/8SER7/EhEe/xIRHv8SER7/EhAe/xIXHv8gpAn/Iq8H/yKu
+        B/8irgf/I7YG/x2KD/8TJR3/EQwf/xIRHv8SER7/Egwe/xQoHP8fmA3/I7MG/yKuB/8irgf/Iq8H/yCi
+        Cv8SFR3/EhAe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAA
+        ACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SDx7/Eygc/yCc
+        C/8isgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yO0Bf8isAf/Ho4P/xpw
+        FP8XQBj/FjQY/xY3GP8WNhj/FjwY/xdYFv8bcxP/H5YO/yKxB/8jtQb/IrAH/yKvB/8cgRD/EQof/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/Eg4e/x+SDv8irwf/Iq4H/yKuB/8iswb/IKEL/xUzGv8RCR//EhEe/xIR
+        Hv8SDh7/Ex0e/x2AEf8jtgX/Iq4H/yKuB/8irgf/Iq4H/xQtHP8SEB7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP//
+        /wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xEJH/8bdBL/IrEH/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKwB/8hrAj/GnMT/xQvG/8TGx3/Ehce/xEMH/8RCh//EQof/xEKH/8RCx//EhIe/xIY
+        Hv8THh3/FCwb/xldFv8fmAz/IrAH/xyDEP8RCh//EhEe/xIRHv8SER7/EhEe/xIRHv8SEB7/G3MT/yKv
+        B/8irgf/Iq4H/yKvB/8itAf/Fj4Y/xEIH/8SER7/EhEe/xIQHv8RDh//GFoV/yS8Bf8irgf/Iq4H/yKu
+        B/8irwf/GFgX/xIQHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAA
+        ADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SDB7/FDUb/yCh
+        Cv8isQf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irwf/IJsM/xY/Gv8SEB7/Eg8e/xIO
+        Hv8SDx7/EhEe/xIRHv8SER7/EhEe/xIRHv8SEB7/Eg8e/xIOHv8SDh7/EhMe/xMYHf8XTxj/G2kU/xEL
+        H/8SER7/EhEe/xIRHv8SER7/EhEe/xIQHv8YVhf/Iq8H/yKuB/8irgf/Iq4H/yS8Bf8YUxb/EQwf/xIQ
+        Hv8SER7/EhEe/xEHH/8XQRf/IrUH/yKvB/8irgf/Iq4H/yKvB/8cdRL/Eg8e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP//
+        /wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xEGH/8bcxL/IrEH/yKvB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/IrEH/x6ODf8UKhz/Eg4e/xIQHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhAe/xIQHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUz
+        G/8irgf/Iq4H/yKuB/8irgf/I7cF/xx6Ev8THB7/Eg4e/xIRHv8SER7/EQkf/xU2Gv8gpQr/IrIG/yKu
+        B/8irgf/Iq8H/x6TDP8SDR7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAA
+        AFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SDR7/EyQe/yCX
+        C/8jtAb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKxBv8gnwv/FTYb/xIOHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SEB7/Excd/yCfCv8irwf/Iq4H/yKuB/8jswb/HpMO/xQl
+        Hf8SDR7/EhEe/xIRHv8RCh//FCoc/x6TDv8jtQb/Iq4H/yKuB/8irwf/IaUJ/xIYHf8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP//
+        /wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEM
+        Hf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xEEH/8YVBf/IasJ/yKwBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/IrEH/xdKGP8SDh7/EhAe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SEh7/Eg4e/xEFIP8RAyD/EQQg/xED
+        IP8RCR//HYIR/yKxB/8irgf/Iq4H/yKwBv8hrgn/EyUc/xAAIf8RBCD/EQQg/xEBIP8QBCH/GmgT/yO7
+        Bf8irgf/Iq4H/yKvB/8hqgj/Fkoa/xAAIP8RBCD/EQQg/xEEIP8RAyD/EQkf/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAA
+        AGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EQUg/xxx
+        Ef8jtgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yO2Bf8cfBH/EhQe/xIOHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xENH/8UIxz/GFAW/xlXFP8ZVhT/GVUU/xlYFP8ejw7/IrAG/yKuB/8irgf/Iq4H/yO1
+        B/8baRH/GFIV/xlWFP8ZVhT/GVYU/xhLFf8deg//I7cG/yKuB/8irgf/Iq4H/yKtCP8ehw//GFIV/xlW
+        FP8ZVhT/GVYU/xpZFP8VNRr/EhMe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKu
+        Bv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP//
+        /wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaN
+        Ov8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xINHv8SGR//HogO/yO3Bf8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irwf/IrQH/xY6Gv8RCx//EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EQof/xQwHP8goQz/JcQD/yS9
+        Bf8kvgX/JL0F/yOzBv8irgf/Iq4H/yKuB/8irgf/Iq0H/yO6Bf8kvgX/JL0F/yS9Bf8kvQX/JL8F/yO2
+        Bv8irQf/Iq4H/yKuB/8irgf/Iq4H/yO1Bv8kvgX/JL0F/yS9Bf8kvQX/JMQE/x2DEf8TGR7/Eg8e/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqE
+        BcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EQkf/xQz
+        HP8fmQv/I7QG/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yO0Bf8ejw7/FCId/xIMHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SDh7/ERIg/xx6EP8jugX/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8isQb/H5gN/xMfHP8SDx7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yax
+        D/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv//
+        /wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOv
+        Cf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8RCB//Fj0a/yChC/8isgb/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/I7gF/xtwE/8SFx7/Eg8e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8RBCD/GV8U/yK1
+        Bv8irwf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8isQf/FCAb/xIO
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGl
+        CJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xEG
+        H/8XRxj/IacJ/yKxBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8kvgX/GE0W/xEIIP8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xEFH/8XTBj/IasJ/yKyBv8irwf/Iq8H/yKvB/8irwf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq8H/yKvB/8irwf/Iq8H/yKvB/8irwf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq8H/yKvB/8irwf/Iq8H/yO1Bv8XURf/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9
+        Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAA
+        AAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EQUg/xhSFv8irwj/IrAH/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/IrEG/yGtCf8WPRn/EQgf/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/Egse/xQt
+        HP8aaBX/G3MU/xtwFP8bcBT/G28U/x2FD/8jtAb/Iq4H/yKuB/8irgf/IrAG/x2IEP8bcBT/G3AU/xtw
+        FP8bcBT/G2sV/x6KD/8irgf/Iq8H/yKuB/8irgf/Iq4H/x+VDf8baxX/G3AU/xtwFP8bcBT/G3IU/xdO
+        GP8SEx7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAA
+        AAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8RBSD/GFIW/yKvCP8isAf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8isQb/IawJ/xY9Gf8RCB//EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIQHv8SEB7/EhAe/xIQHv8RCR//FjQZ/yO6
+        Bv8irgf/Iq4H/yKuB/8isgb/GmwU/xITHv8SEB7/EhAe/xIQHv8RBh//Fj8a/yGhCv8isgb/Iq4H/yKu
+        B/8jtAb/HYQO/xEEIP8SEB7/EhAe/xIQHv8SEB7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8G
+        G/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAA
+        ABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xEFIP8YUxb/IrAI/yKwB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKxBv8hrAn/Fj0Z/xEIH/8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xEMH/8VLBv/IKML/yKxBv8irgf/Iq4H/yKwBv8djQ//EhUe/xIQ
+        Hv8SER7/EhEe/xIMHv8SIR7/HpAM/yO1Bv8irgf/Iq4H/yO0Bv8flgv/EyMe/xINHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP//
+        /wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EQYg/xhNF/8irAn/IrEH/yKuB/8irgf/Iq4H/yKuB/8irgf/IrEG/yGrCf8WPBn/EQgf/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/Eg0f/xQj
+        Hf8ejA//I7QG/yKuB/8irgf/Iq8H/yCkCf8TGx3/EhAe/xIRHv8SER7/EhAe/xEIIP8cew//I7YG/yKu
+        B/8irgf/IrEG/yCjCv8XRRn/EQgf/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAA
+        ACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8RBx//F0Aa/yGiC/8isgb/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8isAb/IrII/xZAGP8RBx//EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SDx7/ExYf/xttFP8juQX/Iq4H/yKuB/8irgf/IrAH/xQ4
+        G/8SEB7/EhEe/xIRHv8SER7/EQMg/xpkFP8irwf/Iq8H/yKuB/8irwf/Ia0I/xlbFf8RBR//EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP//
+        /wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xEJH/8WOBr/H50M/yOzBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8kvQX/F00W/xEI
+        H/8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8RCh//GE0W/yO8Bf8irgf/Iq4H/yKuB/8irwf/GWEW/xIQHv8SER7/EhEe/xIRHv8RCB//F0sY/yCm
+        Cf8isQb/Iq4H/yKuB/8jtwb/G3AR/xAAIP8SEh7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAA
+        ADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/Egoe/xQrHP8ekw3/I7QG/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yO5Bf8bbhP/EhYf/xIPHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SEB7/EQgf/xEGH/8RBh//EQYf/xAAIP8VMxr/IrAI/yKxBv8irgf/Iq4H/yKv
+        B/8cfRL/EQUf/xEGH/8RBh//EQYf/xEAIP8TJB7/H5oL/yOyBv8irgf/Iq4H/yO3Bf8dhw7/ERAf/xEB
+        H/8RBh//EQYf/xEGH/8RCR//EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP//
+        /wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SEB7/EAgf/x17Dv8juQX/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I7MG/x6V
+        Df8UJhz/Egwf/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/Eg8e/xIdHv8aZRT/G3YR/xtz
+        Ev8bcxL/G3ES/xx/EP8hpwj/IrAH/yKuB/8irgf/Iq4H/yCgCv8bcxL/G3MS/xtzEv8bcxL/G3MS/xt1
+        E/8gpAr/IrAH/yKuB/8irgf/IrAH/yCmCf8cgBD/G3ES/xtzEv8bcxL/G3QS/xhWF/8SDx7/EhEe/xIR
+        Hv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAA
+        AFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8RAiD/GWIU/yKx
+        CP8irwf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irwf/I7QH/xZCGP8SDR//EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SEB7/EQcg/x6NDP8jtgb/IrAH/yKwB/8isAf/Iq8H/yKtB/8irgf/Iq4H/yKu
+        B/8irgf/Iq8H/yKwB/8isAf/IrAH/yKwB/8isAf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq8H/yKw
+        B/8isAf/IrAH/yKwB/8isQf/Ho8O/xIPHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP//
+        /wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEM
+        Hf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xEIH/8WQRr/IaMK/yKxBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8jtAb/HYcQ/xMdHf8SDx7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8RBR//G3MS/yKx
+        B/8irwf/Iq8H/yKvB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq8H/yKvB/8irwf/Iq8H/yKv
+        B/8irwf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKvB/8irwf/Iq8H/yKwB/8hown/EhAe/xIR
+        Hv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAA
+        AGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/Eg4e/xIW
+        H/8fjg3/I7QG/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKvB/8isgf/F08Y/xINHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xEIH/8ZXBb/IqsI/yKvB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq8H/yGpCP8WRRr/Eg0e/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKu
+        Bv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP//
+        /wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaN
+        Ov8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EQUf/xliFf8irwf/IrAH/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKvB/8gowv/FTAb/xEKH/8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EQof/xZF
+        Gv8isAj/I7sF/yO5Bf8juQX/I7kF/yO3Bf8isQf/Iq0H/yKuB/8irgf/Iq4H/yKvB/8jtgb/I7kF/yO5
+        Bf8juQX/I7kF/yO5Bf8isQb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jtQb/I7kF/yO5Bf8juQX/I7cG/xtw
+        FP8RCh//EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqE
+        BcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SDh7/EiEd/x+ZDP8isQf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKxBv8fmQ3/FC4b/xEF
+        IP8SEB7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SDB7/EQof/xIRHv8SER7/EhEe/xIRHv8SDh7/Eykc/xxxEP8deQ//HXgP/x14D/8ddg//HX8P/yCj
+        Cf8isAb/Iq4H/yKuB/8irwf/IaoI/x2DDv8ddw//HXgP/x14D/8deA//HHYP/yChCv8irwf/Iq4H/yKu
+        B/8irwf/Ia0I/x6JDf8cdQ//HXgP/x14D/8deA//GFYV/xEMH/8SER7/EhEe/xIRHv8PBhv/NH06/yax
+        D/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv//
+        /wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOv
+        Cf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xISHv8RBh//GWMV/yKxBv8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOzBv8fmQz/Fj0Z/xEKIP8RCB//EhAe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIQHv8SCx//EQQg/xMhHv8VNRr/Eg8e/xIRHv8SER7/EhEe/xIS
+        Hv8SDR7/EAIg/xABIP8QASD/EAEg/xAAIP8RCiH/HH0Q/yO5Bf8irgf/Iq4H/yKwB/8gpAn/FDQc/xAA
+        If8QASD/EAEg/xABIP8QACH/G3IT/yKuB/8irgf/Iq4H/yKvBv8itgf/Fz8Y/w8AIv8QASD/EAEg/xAB
+        IP8RBx//EhIe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGl
+        CJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIQHv8THh3/HpEN/yKxB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yO0
+        Bv8hqgj/Gm0S/xQ0HP8RByD/EQMf/xEKH/8SCx7/Egse/xILHv8SCx7/Egsf/xEIH/8RAx//EQcg/xQr
+        HP8YWBX/HYoO/xx+Ef8RCh//EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xEF
+        IP8baRL/I7kF/yKuB/8irgf/IrAH/yKsCP8ZYBX/EQcf/xIRHv8SER7/EhEe/xINHv8YWBf/IqwI/yKu
+        B/8irgf/Iq4H/yS9Bf8aZRL/EQ0f/xIPHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9
+        Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAA
+        AAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIMHv8VPRv/IakJ/yKv
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKzBv8jtwb/H50M/xx4EP8ZXBX/Fj0b/xQw
+        HP8UMBz/FDAc/xQvHP8UMxv/F0gZ/xphFP8cew//H5YM/yKwCP8jtwb/HIQQ/xEKH/8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EQQf/xhSFv8irgj/IrAG/yKuB/8irgf/IrEH/xx5
+        EP8RAyD/EhEe/xIRHv8SER7/Eg8e/xQuHP8hqgj/Iq8H/yKuB/8irgf/I7cG/x2DEP8THx3/Egwe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAA
+        AAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIQHv8XVBf/IrMH/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8jswb/I7UG/yKtCP8goQr/IJwL/yCcC/8gnAv/IJwL/yCdCv8hpQn/Iq4I/yO2
+        Bv8jtAb/IrAH/yKvB/8cgRD/EQof/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8RCB//Fj8a/yChC/8jsgb/Iq4H/yKuB/8jtAb/HosM/xENH/8SEB7/EhEe/xIRHv8SER7/EhIe/x+f
+        Cv8irwf/Iq4H/yKuB/8jtAb/IJgN/xUsG/8RCx//EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8G
+        G/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAA
+        ABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/Eg8e/xIU
+        Hv8ZYRT/IrIH/yKvB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/IrAH/yKx
+        Bv8isgb/IrIG/yKyBv8isgb/IrIG/yKxBv8irwf/Iq4H/yKuB/8irgf/Iq8H/xyBEP8RCh//EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xILHv8TKh3/HpMM/yO0Bv8irgf/Iq4H/yOy
+        Bv8fmQv/FCsc/xILH/8SER7/EhEe/xIRHv8SEB7/HYkP/yKvB/8irgf/Iq4H/yKxBv8hqgn/FTYa/xEJ
+        H/8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP//
+        /wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/Eg4e/xIVHv8ZYRX/IrEH/yKxB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irwf/HIEQ/xEKH/8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xADIP8dew//I7gG/yKuB/8irgf/IrEG/yGmCf8XSxn/EQcf/xIRHv8SER7/EhEe/xIQ
+        Hv8bcRT/Iq8H/yKuB/8irgf/Iq4H/yS9Bf8XQxf/EQgf/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAA
+        ACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/Eg8e/xIRH/8YURj/IaEK/yK0B/8isQb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKvB/8cgRD/EQof/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EQMg/xppE/8isQf/Iq8H/yKu
+        B/8isAf/Iq8I/xlfFP8RBCD/EhEe/xIRHv8SER7/EhAe/xZHGf8isQf/Iq4H/yKuB/8irgf/I7kF/xpp
+        E/8SFR7/Eg8e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP//
+        /wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xEEH/8VMBv/HogP/yGu
+        CP8jtQb/IrEG/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq8H/xyBEP8RCh//EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8RBh//GFYX/yGqCP8isAf/Iq4H/yKvB/8itgb/HHIQ/xEDIP8SER7/EhEe/xIR
+        Hv8SEB7/Exkc/yKtCP8irgf/Iq4H/yKuB/8jtAb/HosP/xMhHf8SDh7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAA
+        ADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhIe/xIJHv8RFB//GFIX/x6MDv8hrAj/I7oF/yO0Bv8isAb/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/IrAG/yOzBv8juQX/HYgP/xEK
+        H/8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xEJH/8WPBr/IaQK/yO3
+        Bf8jswb/I7MG/yS8Bf8eiw3/Ehcf/xINHv8SER7/EhEe/xIQHv8TGR3/H5oM/yO1Bf8jswb/I7MG/yO2
+        Bf8gpQr/FSkb/xIMH/8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP//
+        /wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhIe/xIP
+        Hv8RAx//EiAe/xdNF/8cdBD/H5cM/yGvCP8jugX/I7oF/yO3Bf8jtQb/I7QG/yO0Bv8jtAb/I7QG/yO2
+        Bv8juAX/I7oF/yS8Bf8isgj/IJ4L/xyAD/8XSRf/EQ4f/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/Eg8e/xIVHv8dgw//IKEL/yCcDP8gnAz/IKEL/x2KEP8ULxz/Egoe/xIR
+        Hv8SER7/EhAe/xMWHf8adBP/IJ8L/yCcDP8gnAz/IJ0M/yChDP8VLBv/EQwf/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAA
+        AFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SDB7/EQUf/xEPH/8VMBv/F0UX/xhU
+        Ff8bcBL/HIAQ/x6RDv8flg3/H5UN/x+VDf8flQ3/HokP/xx8Ef8abxL/GVUV/xdJF/8VNxr/Ehoe/xEH
+        H/8SEh7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EQsf/xQr
+        HP8VNhv/FTUb/xU1G/8VNhv/FTMb/xMeHf8SDh7/EhEe/xIRHv8SER7/EhIe/xQnHP8VNRv/FTUb/xU1
+        G/8VNRv/Fjka/xMZHf8SDx7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP//
+        /wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEM
+        Hf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/Eg8e/xEKH/8RBR//EQYg/xIUH/8THh7/FCgc/xQrHP8UKhz/FCoc/xQq
+        HP8TIx3/Ehse/xETH/8RBiD/EQUf/xEJH/8SDR7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SEh7/EQsf/xEJH/8RCR//EQkf/xEJH/8RCh//Eg8e/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/Egwe/xEJH/8RCR//EQkf/xEJH/8RCB//Eg8e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAA
+        AGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/Eg8e/xINHv8SCx//EQsf/xELH/8RCx//EQsf/xIMHv8SDR7/Eg8e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKu
+        Bv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP//
+        /wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaN
+        Ov8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqE
+        BcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yax
+        D/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv//
+        /wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOv
+        Cf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGl
+        CJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9
+        Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAA
+        AAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAA
+        AAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8G
+        G/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAA
+        ABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP//
+        /wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAA
+        ACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP//
+        /wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAA
+        ADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP//
+        /wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAA
+        AFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP//
+        /wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEM
+        Hf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAA
+        AGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKu
+        Bv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP//
+        /wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaN
+        Ov8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqE
+        BcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yax
+        D/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv//
+        /wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOv
+        Cf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGl
+        CJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9
+        Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAA
+        AAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAA
+        AAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8G
+        G/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAA
+        ABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP//
+        /wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAA
+        ACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP//
+        /wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAA
+        ADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP//
+        /wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAA
+        AFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP//
+        /wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEM
+        Hf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAA
+        AGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKu
+        Bv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP//
+        /wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaN
+        Ov8RDB3/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/DwYb/zR9Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqE
+        BcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yax
+        D/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv//
+        /wD///8A////AP///wD///8A////AAAAAAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOv
+        Cf82jTr/EQwd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/w8GG/80fTr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAAABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGl
+        CJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I68J/zaNOv8RDB3/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/DwYb/zR9
+        Ov8msQ//Iq4G/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAA
+        AAr///8A////AP///wD///8A////AP///wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8jrwn/No06/xEMHf8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8PBhv/NH06/yaxD/8irgb/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/GoQFwQAAAGEAAABRAAAAPAAAACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAA
+        AAMhpQiRIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yOvCf82jTr/EAcc/xEMHf8RDB3/EQwd/xEM
+        Hf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEM
+        Hf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEM
+        Hf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEM
+        Hf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEM
+        Hf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEM
+        Hf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/xEMHf8RDB3/EQwd/w4B
+        Gv80fDr/JrEP/yKuBv8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8ahAXBAAAAYQAAAFEAAAA8AAAAJwAA
+        ABYAAAAK////AP///wD///8A////AP///wD///8AAAAAAyGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/I60J/zqZPP82jDr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaN
+        Ov82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaN
+        Ov82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaN
+        Ov82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaN
+        Ov82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaN
+        Ov82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/No06/zaN
+        Ov82jTr/No06/zaNOv82jTr/No06/zaNOv82jTr/Now5/zuXPv8lrQ3/Iq4G/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/xqEBcEAAABhAAAAUQAAADwAAAAnAAAAFgAAAAr///8A////AP///wD///8A////AP//
+        /wAAAAADIaUIkSKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/I64J/yOvCf8jrwn/I68J/yOv
+        Cf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOv
+        Cf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOv
+        Cf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOv
+        Cf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOv
+        Cf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOv
+        Cf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOvCf8jrwn/I68J/yOv
+        Cf8jsAn/I64J/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/GoUFwAAAAF8AAABQAAAAPAAA
+        ACcAAAAWAAAACv///wD///8A////AP///wD///8A////AAAAAAIhpQiRIq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8ahwW9AAAAWgAAAEsAAAA4AAAAJAAAABUAAAAK////AP///wD///8A////AP//
+        /wD///8AAAAAAiGlCJEirgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/xuLBrkAAABRAAAAQwAA
+        ADIAAAAhAAAAEwAAAAn///8A////AP///wD///8A////AP///wAAAAACIacIkCKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/HI8GswAAAEMAAAA4AAAAKgAAABwAAAAQAAAAB////wD///8A////AP//
+        /wD///8A////AAAAAAEhpwiQIq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8dlQarAAAAMgAA
+        ACoAAAAgAAAAFQAAAAwAAAAG////AP///wD///8A////AP///wD///8AAAAAASGnCI8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/x+eBqIAAAAhAAAAHAAAABUAAAANAAAACAAAAAT///8A////AP//
+        /wD///8A////AP///wAAAAAAIqkIjiKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/IKQHnAAA
+        ABIAAAAQAAAADAAAAAgAAAAFAAAAAv///wD///8A////AP///wD///8A////AAAAAAAiqgiNIq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKu
+        B/8irgf/Iq4H/yKuB/8irgf/Iq4H/yKuB/8hqQeXAAAACAAAAAcAAAAGAAAABAAAAAIAAAAB////AP//
+        /wD///8A////AP///wD///8AAAAAACGnCIsiqgiNIqoIjSKqCI0iqQiOIqkIjiKpCI4iqQiOIqkIjiKp
+        CI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKp
+        CI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKp
+        CI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKp
+        CI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKp
+        CI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKp
+        CI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKp
+        CI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKpCI4iqQiOIqkIjiKp
+        CI4AAAACAAAAAgAAAAEAAAABAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD/////////////////////////////
+        ////////////////////////////////////////////////////////////////////////////////
+        //////////////////////////////////////////////////////////////8AAAAAAAAAAAAAAAAA
+        AH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAA
+        AAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAA
+        AAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8A
+        AAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAA
+        AH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAA
+        AAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAA
+        AAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8A
+        AAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAA
+        AH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAA
+        AAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAA
+        AAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8A
+        AAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAA
+        AH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAA
+        AAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAA
+        AAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8A
+        AAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAA
+        AH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAA
+        AAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAA
+        AAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8A
+        AAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAA
+        AH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAA
+        AAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAA
+        AAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8A
+        AAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAA
+        AH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAA
+        AAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAA
+        AAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8A
+        AAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAA
+        AH//AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAA
+        AAAAAAB//wAAAAAAAAAAAAAAAAAAf/8AAAAAAAAAAAAAAAAAAH//AAAAAAAAAAAAAAAAAAB/////////
+        ////////////////////////////////////////////////////////////////////////////////
+        /////////////////////////////////////////////////////////////ygAAAAwAAAAYAAAAAEA
+        IAAAAAAAACQAAMQOAADEDgAAAAAAAAAAAAD///8A+/v7AEhISAEAAAAJAAAAEwAAABgAAAAYAAAAGAAA
+        ABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAA
+        ABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAA
+        ABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAXAAAADwAAAAX///8A+/v7AEhHSAIAAAAUAAAAMgAA
+        AEEAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAABDAAAAQwAA
+        AEMAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAABDAAAAQwAA
+        AEMAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAAA/AAAAKgAAAA////8A+/r7AE1h
+        SRsLPgFdDDoCfgs4Ao8LNwKRCzcCkQs3ApELNwKRCzcCkQs3ApELNwKRCzcCkQs3ApELNwKRCzcCkQs3
+        ApELNwKRCzcCkQs3ApELNwKRCzcCkQs3ApELNwKRCzcCkQs3ApELNwKRCzcCkQs3ApELNwKRCzcCkQs3
+        ApELNwKRCzcCkQs3ApELNwKRCzcCkQs3ApELNwKRCzcCkQs3ApELNwKRCzcCkQs4ApIIJwJ9AAEAQAAA
+        ABf///8A+/j7AFWJS0UeqQPrIqsH+CGqB/khqgf5IaoH+SGqB/khqgf5IaoH+SGqB/khqgf5IaoH+SGq
+        B/khqgf5IaoH+SGqB/khqgf5IaoH+SGqB/khqgf5IaoH+SGqB/khqgf5IaoH+SGqB/khqgf5IaoH+SGq
+        B/khqgf5IaoH+SGqB/khqgf5IaoH+SGqB/khqgf5IaoH+SGqB/khqgf5IaoH+SGqB/khqgf5IaoH+SGt
+        B/kWbgS8AAEARQAAABj///8A+/j7AFWJS0YeqgP0Iq4H/yKuB/8irwf/Iq8G/yKvBv8irwb/Iq8G/yKv
+        Bv8irwb/Iq8G/yKvBv8irwb/Iq8G/yKvBv8irwb/Iq8G/yKvBv8irwb/Iq8G/yKvBv8irwb/Iq8G/yKv
+        Bv8irwb/Iq8G/yKvBv8irwb/Iq8G/yKvBv8irwb/Iq8G/yKvBv8irwb/Iq8G/yKvBv8irwb/Iq8G/yKv
+        Bv8irgf/Iq4H/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yKuCP8lqg7/JaoP/yWq
+        D/8lqg//JaoP/yWqD/8lqg//JaoP/yWqD/8lqg//JaoP/yWqD/8lqg//JaoP/yWqD/8lqg//JaoP/yWq
+        D/8lqg//JaoP/yWqD/8lqg//JaoP/yWqD/8lqg//JaoP/yWqD/8lqg//JaoP/yWqD/8lqg//JaoP/yWq
+        D/8lqg//JaoP/yWqD/8jrQv/Iq4H/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWr
+        Df8kYCX/HDsj/x09I/8dPSP/HT0j/x09I/8dPSP/HT0j/x09I/8dPSP/HT0j/x09I/8dPSP/HT0j/x09
+        I/8dPSP/HT0j/x09I/8dPSP/HT0j/x09I/8dPSP/HT0j/x09I/8dPSP/HT0j/x09I/8dPSP/HT0j/x09
+        I/8dPSP/HT0j/x09I/8dPSP/HT0j/x9EJf8nlhn/Iq8G/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJ
+        S0YeqgPzIq4H/yWrDv8dQSP/EAse/xEOHv8RDh7/EQ4e/xEOHv8RDh7/EQ4e/xEOHv8RDh7/EQ4e/xEO
+        Hv8RDh7/EQ4e/xEOHv8RDh7/EQ4e/xEOHv8RDh7/EQ4e/xEOHv8RDh7/EQ4e/xEOHv8RDh7/EQ4e/xEO
+        Hv8RDh7/EQ4e/xEOHv8RDh7/EQ4e/xEOHv8RDh7/EQ0e/xQXIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAA
+        ABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUaIf8mjhr/IrAG/yKx
+        B/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUa
+        If8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xIPHv8SDh7/Eg4e/xIP
+        Hv8SEB7/EhAe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWr
+        Dv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIQHv8SER7/Ex4c/xUx
+        Gv8WPBj/Fj4Y/xU3Gf8UKBv/Exgd/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJ
+        S0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/Eg8e/xQn
+        G/8aYxL/H5AM/yGiCf8hqAj/IakI/yGmCf8gnAr/HoYO/xY9GP8SEB7/EhIe/xIWHv8SFh7/EhIe/xIR
+        Hv8SFB7/EhYe/xIUHv8SER7/EhEe/xIRHv8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAA
+        ABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SDx7/FTUZ/x+SDP8isAf/IrAH/yKvB/8isQf/IrIG/yKxBv8isQf/IrMH/xpiE/8SDh7/Exsd/xtu
+        Ev8dgQ7/FTMZ/xENH/8WPhj/HYQO/xpmE/8TFx3/EhEe/xIRHv8SER7/EhAe/xUaIf8mjhr/IrAG/yKx
+        B/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIQHv8ULBv/H5MM/yKxB/8irgf/Iq8H/yGnCP8fjwz/HX8O/x2EDf8flwv/IasI/xpi
+        E/8SDh7/EhUe/x2CDv8itQb/GVwU/xEMH/8XPhj/Iq4H/yCcCv8UJRv/EhAe/xIRHv8SER7/EhAe/xUa
+        If8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xITHv8bcRH/IrEH/yKuB/8irwf/Ho0N/xc/GP8THB3/EhMe/xIV
+        Hv8UIhz/F0UX/xY+GP8SEB7/Eg8e/xplE/8iswb/HHcQ/xIQHv8UJBv/IJwK/yKpCP8WOxj/Eg4e/xIQ
+        Hv8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWr
+        Dv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/Eg8e/xQqG/8gngr/Iq8H/yKwB/8glwv/FS8a/xIO
+        Hv8SEB7/EhEe/xIRHv8SEB7/Eg8e/xIRHv8SFR7/Exkd/xhSFf8irwf/H5IM/xQmG/8UIRz/HooN/yKx
+        B/8ZXBT/Exoc/xMZHf8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJ
+        S0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/Eg4e/xdIF/8irQf/Iq4H/yKv
+        B/8ZXBT/Eg8e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIPHv8VMxr/H5EM/yGfCf8irgf/IqsI/yCY
+        Cv8glgr/IaYI/yKvB/8hown/IJcK/x2BDv8THh3/Eg8e/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAA
+        ABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/Eg4e/xlb
+        FP8isAf/Iq8H/yGnCP8VNhn/Eg8e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIQHv8UIxz/HosN/yCa
+        C/8hqAj/Iq8H/yGjCf8gmQv/IJ8K/yKuB/8irAf/IJwL/x6PDf8UKxv/Eg8e/xUaIf8mjhr/IrAG/yKx
+        B/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/Eg4f/xphE/8isQf/Iq8H/yCiCf8UKxv/Eg8e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SEx7/EyEc/xQlHP8dfg//IrIG/xttEv8UIRz/Fj8Y/yGlCP8hown/FjwZ/xQiHP8SFx3/EhAe/xUa
+        If8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/Eg4e/xlZFf8irwf/Iq8H/yGkCf8VLxr/Eg8e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/Eg8e/xILH/8ZWxT/I7MG/xx9D/8SER7/Exkd/x+RDP8irQj/F0EX/xIK
+        H/8SDx7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWr
+        Dv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/Eg4e/xdCF/8iqwj/Iq8H/yKtB/8YTBb/Eg4e/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SEB7/FTIZ/xlaFP8ceQ//Iq8H/yCeCv8aYRP/GV0U/x+X
+        C/8isAf/HYEO/xlbFP8WQBj/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJ
+        S0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/Eg8e/xMlG/8gmgv/IrAH/yKw
+        B/8ehA7/Exsd/xIPHv8SER7/EhEe/xIRHv8SER7/EhEe/xIQHv8SDh7/GEgX/yKxB/8isgb/Iq8H/yKu
+        B/8isQf/IrMG/yKxB/8irgf/Iq8H/yK1Bv8eiQ3/Excd/xUZIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAA
+        ABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIS
+        Hv8bahL/IrAH/yKuB/8irAj/G2oS/xMcHf8SDh7/Eg4e/xIOHv8SDh7/EhUe/xMbHf8SEB7/FCUc/xla
+        E/8aYRL/H5kK/yKwB/8egw7/GlwT/xx0EP8irAf/IaUI/xtpEf8YURX/Exgd/xUZIf8mjhr/IrAG/yKx
+        B/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIQHv8UKhv/H5ML/yKwB/8irgf/Iq0H/x6IDf8ZVRX/F0MY/xdDGP8ZUxX/HX0P/xlX
+        Ff8SDx7/EhAe/xINHv8SDh7/HHQQ/yO0Bv8bahL/Egsf/xQqG/8goAr/IacI/xUyGv8SCx7/EhAe/xUa
+        If8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SEB7/FjsZ/yCXC/8isQf/Iq8H/yKwB/8irwf/IasI/yGr
+        CP8irwf/IrMH/xpiE/8SDx7/EhEe/xIRHv8SDx7/GVcV/yKyBv8ehg3/ExYe/xMcHf8ejgz/IrAH/xhN
+        Fv8SDh7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWr
+        Dv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUvGv8ceg//IaYI/yKw
+        B/8isQb/IrEH/yKxB/8isQb/IrEH/xpfE/8SDx7/EhEe/xIRHv8SDh7/Fj0Y/yGrCP8gnAv/FCQc/xIR
+        Hv8cdBD/I7QG/xtrEv8SEB7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJ
+        S0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIP
+        Hv8SFh3/FjcZ/xldE/8cdhD/HYAP/x1+D/8bcBH/GVgU/xQoG/8SEB7/EhEe/xIRHv8SEB7/Exwd/xhP
+        Fv8YUBb/Ex8c/xIPHv8WNRn/GVYV/xY9Gf8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAA
+        ABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SEB7/Eg8e/xIOHv8SEh7/EhUe/xIUHv8SER7/Eg4e/xIQHv8SER7/EhEe/xIR
+        Hv8SER7/EhAe/xIOHv8SDh7/EhAe/xIRHv8SDx7/Eg4e/xIPHv8SER7/EhAe/xUaIf8mjhr/IrAG/yKx
+        B/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUa
+        If8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWr
+        Dv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJ
+        S0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAA
+        ABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUaIf8mjhr/IrAG/yKx
+        B/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUa
+        If8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWr
+        Dv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJ
+        S0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUaIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAA
+        ABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUaIf8mjhr/IrAG/yKx
+        B/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQyP/EQ4e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUa
+        If8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWrDv8dQiP/EQ0e/xIQ
+        Hv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQ
+        Hv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQ
+        Hv8SEB7/Eg8e/xUZIf8mjhr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJS0YeqgPzIq4H/yWr
+        Dv8gSyX/FRsh/xYeIf8WHiH/Fh4h/xYeIf8WHiH/Fh4h/xYeIf8WHiH/Fh4h/xYeIf8WHiH/Fh4h/xYe
+        If8WHiH/Fh4h/xYeIf8WHiH/Fh4h/xYeIf8WHiH/Fh4h/xYeIf8WHiH/Fh4h/xYeIf8WHiH/Fh4h/xYe
+        If8WHiH/Fh4h/xYeIf8WHiH/Fh0h/xkmJP8nkBr/IrAG/yKxB/8WbwS+AAEARQAAABj///8A+/j7AFWJ
+        S0YeqgPzIq4H/yOtCv8nmxf/JpIY/yaTGP8mkxj/JpMY/yaTGP8mkxj/JpMY/yaTGP8mkxj/JpMY/yaT
+        GP8mkxj/JpMY/yaTGP8mkxj/JpMY/yaTGP8mkxj/JpMY/yaTGP8mkxj/JpMY/yaTGP8mkxj/JpMY/yaT
+        GP8mkxj/JpMY/yaTGP8mkxj/JpMY/yaTGP8mkxj/JpMY/yaUGf8lpw//Iq4H/yKxB/8WbwS8AAEARAAA
+        ABj///8A+/j7AFWJS0UeqgPzIq4H/yKuB/8irwb/IrAG/yKwBv8isAb/IrAG/yKwBv8isAb/IrAG/yKw
+        Bv8isAb/IrAG/yKwBv8isAb/IrAG/yKwBv8isAb/IrAG/yKwBv8isAb/IrAG/yKwBv8isAb/IrAG/yKw
+        Bv8isAb/IrAG/yKwBv8isAb/IrAG/yKwBv8isAb/IrAG/yKwBv8isAb/IrAG/yKwBv8irgf/Iq4H/yOx
+        B/8WcgWzAAEANAAAABP///8A+/j7AFKISEYaqQD2Hq0D/x6tA/8erQP/Hq0D/x6tA/8erQP/Hq0D/x6t
+        A/8erQP/Hq0D/x6tA/8erQP/Hq0D/x6tA/8erQP/Hq0D/x6tA/8erQP/Hq0D/x6tA/8erQP/Hq0D/x6t
+        A/8erQP/Hq0D/x6tA/8erQP/Hq0D/x6tA/8erQP/Hq0D/x6tA/8erQP/Hq0D/x6tA/8erQP/Hq0D/x6t
+        A/8erQP/Hq0D/x+wA/8TdgGjAAAAFwAAAAj///8A/Pr8AIWrfixewUuNYMNNkmDDTZJgw02SYMNNkmDD
+        TZJgw02SYMNNkmDDTZJgw02SYMNNkmDDTZJgw02SYMNNkmDDTZJgw02SYMNNkmDDTZJgw02SYMNNkmDD
+        TZJgw02SYMNNkmDDTZJgw02SYMNNkmDDTZJgw02SYMNNkmDDTZJgw02SYMNNkmDDTZJgw02SYMNNkmDD
+        TZJgw02SYMNNkmDDTZJgw02SYMNNkmHFTZJZoExcSEpIBEhISAH///8A////APz9/AH8/vsA/P77APz+
+        +wD8/vsA/P77APz++wD8/vsA/P77APz++wD8/vsA/P77APz++wD8/vsA/P77APz++wD8/vsA/P77APz+
+        +wD8/vsA/P77APz++wD8/vsA/P77APz++wD8/vsA/P77APz++wD8/vsA/P77APz++wD8/vsA/P77APz+
+        +wD8/vsA/P77APz++wD8/vsA/P77APz++wD8/vsA/P77APz++wD8/fsB+/v7APv7+wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///////8AAP///////wAA////////AAD///////8AAPAAAAAABwAA8AAAAAAHAADwAAAAAAcAAPAA
+        AAAABwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAH
+        AADwAAAAAAcAAPAAAAAABwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAHAADwAAAAAAcAAPAA
+        AAAABwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAH
+        AADwAAAAAAcAAPAAAAAABwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAHAADwAAAAAAcAAPAA
+        AAAABwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAH
+        AAD///////8AAP///////wAA////////AAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAADEDgAAxA4AAAAA
+        AAAAAAAA////AIB/gAEAAAAPAAAAIgAAACUAAAAlAAAAJQAAACUAAAAlAAAAJQAAACUAAAAlAAAAJQAA
+        ACUAAAAlAAAAJQAAACUAAAAlAAAAJQAAACUAAAAlAAAAJQAAACUAAAAlAAAAJQAAACUAAAAlAAAAJQAA
+        ACUAAAAlAAAAIAAAAA7///8Ag46BEAgsAVQIKgJ5CCoCfwgqAn8IKgJ/CCoCfwgqAn8IKgJ/CCoCfwgq
+        An8IKgJ/CCoCfwgqAn8IKgJ/CCoCfwgqAn8IKgJ/CCoCfwgqAn8IKgJ/CCoCfwgqAn8IKgJ/CCoCfwgq
+        An8IKgJ/CCoCfwgqAn8EFAFfAAAAIP///wCKr4M1HKED5CGnB/Ygpwb3IKcG9yCnBvcgpwb3IKcG9yCn
+        Bvcgpwb3IKcG9yCnBvcgpwb3IKcG9yCnBvcgpwb3IKcG9yCnBvcgpwb3IKcG9yCnBvcgpwb3IKcG9yCn
+        Bvcgpwb3IKcG9yCnBvcgpgf3IacH9w9KA5gAAAAk////AIqwgzcdpgPwIq4I/ySoDf8kpw3/JKcN/ySn
+        Df8kpw3/JKcN/ySnDf8kpw3/JKcN/ySnDf8kpw3/JKcN/ySnDf8kpw3/JKcN/ySnDf8kpw3/JKcN/ySn
+        Df8kpw3/JKcN/ySnDf8kpw3/JKcO/yOtCf8isAf/D00DmwAAACT///8AirCDNx2mA+8kqQ3/H1Eh/xky
+        IP8ZMyD/GTMg/xkzIP8ZMyD/GTMg/xkzIP8ZMyD/GTMg/xkzIP8ZMyD/GTMg/xkzIP8ZMyD/GTMg/xkz
+        IP8ZMyD/GTMg/xkzIP8ZMyD/GTMg/xkzIP8bPSL/JJkT/yKxBv8PTQObAAAAJP///wCKsIM3HaYD7ySo
+        Df8aNSD/Eg0e/xIPHv8SDx7/Eg8e/xIPHv8SDx7/Eg8e/xIPHv8SDx7/Eg8e/xIPHv8SDx7/Eg8e/xIP
+        Hv8SDx7/Eg8e/xIPHv8SDx7/Eg8e/xIPHv8SDx7/Eg4e/xUbIP8kkxP/IrEG/w9NA5sAAAAk////AIqw
+        gzcdpgPvJKgN/xo3IP8SDx7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIQHv8SDx7/Eg8e/xIQ
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SEB7/FR0g/ySTE/8isQb/D00DmwAA
+        ACT///8AirCDNx2mA+8kqA3/Gjcg/xIPHv8SER7/EhEe/xIRHv8SER7/EhEe/xIPHv8TFx3/FCkb/xUz
+        Gf8VMRr/FCMb/xIVHv8SER7/EhAe/xIPHv8SER7/EhAe/xIPHv8SER7/EhEe/xIQHv8VHSD/JJMT/yKx
+        Bv8PTQObAAAAJP///wCKsIM3HaYD7ySoDf8aNyD/Eg8e/xIRHv8SER7/EhEe/xIRHv8SEB7/FjoY/x1/
+        Dv8gngr/IacI/yGmCP8gnAr/GVsU/xIRHv8UKBv/FS0a/xISHv8UJxv/FS4a/xITHv8SER7/EhAe/xUd
+        IP8kkxP/IrEG/w9NA5sAAAAk////AIqwgzcdpgPvJKgN/xo3IP8SDx7/EhEe/xIRHv8SER7/Eg8e/xY9
+        GP8gngr/IrIH/yGpCP8fkQv/HowM/yCgCv8cdxD/EhEe/xphE/8fkQz/Ex0d/xpeE/8flAv/FCIc/xIQ
+        Hv8SEB7/FR0g/ySTE/8isQb/D00DmwAAACT///8AirCDNx2mA+8kqA3/Gjcg/xIPHv8SER7/EhEe/xIQ
+        Hv8TGh3/HogN/yKyB/8gmwr/F0UX/xMcHP8TGB3/FCkb/xUzGv8SDx7/F0gX/yGkCf8VMRr/F0MX/yGl
+        Cf8WNxn/Eg4e/xIQHv8VHSD/JJMT/yKxBv8PTQObAAAAJP///wCKsIM3HaYD7ySoDf8aNyD/Eg8e/xIR
+        Hv8SER7/Eg8e/xU1Gf8hpwj/Iq4H/xlTFf8SDh7/EhAe/xIRHv8SEB7/Eg4e/xY9GP8egw7/IqsI/x6D
+        Dv8dfw7/IqsI/x6HDf8bYxL/Exsc/xUcIP8kkxP/IrEG/w9NA5sAAAAk////AIqwgzcdpgPvJKgN/xo3
+        IP8SDx7/EhEe/xIRHv8SDh7/F0cX/yKuB/8hown/FS0a/xIPHv8SER7/EhEe/xIRHv8SDx7/FjcZ/xx4
+        EP8hoQn/IJwK/xx5EP8hoAn/IJ4K/xtuEf8UIRz/FRwg/ySTE/8isQb/D00DmwAAACT///8AirCDNx2m
+        A+8kqA3/Gjcg/xIPHv8SER7/EhEe/xIOHv8XRhf/Iq4H/yCiCf8UKxv/Eg8e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhQe/x18D/8ehw3/Ehgd/xx1EP8ejAz/Exkd/xIQHv8VHSD/JJMT/yKxBv8PTQObAAAAJP//
+        /wCKsIM3HaYD7ySoDf8aNyD/Eg8e/xIRHv8SER7/Eg8e/xUyGv8hpQn/IqwH/xdHF/8SDh7/EhEe/xIR
+        Hv8SER7/EhAe/xMZHf8aZRP/IJgL/yGlCf8ceQ//H5QL/yGmCP8dfA//F0EX/xUbIP8kkxP/IrEG/w9N
+        A5sAAAAk////AIqwgzcdpgPvJKgN/xo3IP8SDx7/EhEe/xIRHv8SEB7/Exkd/x6EDv8isgb/HowN/xUr
+        G/8SEB7/Eg8e/xISHv8TGR3/Excd/xpgE/8ehQ3/IqwH/x6LDf8egg7/IqsI/x6PDP8XShb/FRwg/yST
+        E/8isQb/D00DmwAAACT///8AirCDNx2mA+8kqA3/Gjcg/xIPHv8SER7/EhEe/xIRHv8SDx7/FjwY/yGg
+        Cv8isQf/H5cL/xtsEf8aYhP/HHcP/xplEv8SEh7/Eg8e/xQqGv8hoQr/GVUV/xQkHP8gngr/GV0T/xIO
+        Hv8VHSD/JJMT/yKxBv8PTQObAAAAJP///wCKsIM3HaYD7ySoDf8aNyD/Eg8e/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/F0AY/x+ODP8irQf/IrIG/yKyBv8itAb/HHUQ/xISHv8SEB7/Exod/x+NDP8ccRH/Exgd/x6I
+        Df8ceA//EhIe/xUdIP8kkxP/IrEG/w9NA5sAAAAk////AIqwgzcdpgPvJKgN/xo3IP8SDx7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SDx7/Ex8c/xZCF/8ZWhT/Gl4U/xhQFf8VLBr/EhEe/xIRHv8SEh7/FTQa/xU0
+        Gv8SEx7/FTIa/xY2Gf8SEh7/FR0g/ySTE/8isQb/D00DmwAAACT///8AirCDNx2mA+8kqA3/Gjcg/xIP
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SEB7/Eg4e/xIPHv8SDx7/Eg4e/xIPHv8SER7/EhEe/xIR
+        Hv8SDx7/Eg8e/xIRHv8SDx7/Eg8e/xIQHv8VHSD/JJMT/yKxBv8PTQObAAAAJP///wCKsIM3HaYD7ySo
+        Df8aNyD/Eg8e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUdIP8kkxP/IrEG/w9NA5sAAAAk////AIqw
+        gzcdpgPvJKgN/xo3IP8SDx7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SEB7/FR0g/ySTE/8isQb/D00DmwAA
+        ACT///8AirCDNx2mA+8kqA3/Gjcg/xIPHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIQHv8VHSD/JJMT/yKx
+        Bv8PTQObAAAAJP///wCKsIM3HaYD7ySoDf8aNyD/Eg8e/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhAe/xUd
+        IP8kkxP/IrEG/w9NA5sAAAAk////AIqwgzcdpgPvJKgN/xo3IP8SDx7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SEB7/FR0g/ySTE/8isQb/D00DmwAAACT///8AirCDNx2mA+8kqA3/Gjcg/xIPHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIR
+        Hv8SER7/EhEe/xIQHv8VHSD/JJMT/yKxBv8PTQObAAAAJP///wCKsIM3HaYD7ySoDf8aNiD/Eg4e/xIQ
+        Hv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQ
+        Hv8SEB7/EhAe/xIQHv8SEB7/Eg8e/xUcIP8kkxP/IrEG/w9NA5sAAAAk////AIqwgzcdpgPvJKgN/x1C
+        If8WHiD/Fh8g/xYfIP8WHyD/Fh8g/xYfIP8WHyD/Fh8g/xYfIP8WHyD/Fh8g/xYfIP8WHyD/Fh8g/xYf
+        IP8WHyD/Fh8g/xYfIP8WHyD/Fh8g/xYfIP8WHyD/GCoi/ySVE/8isQb/D00DmwAAACT///8AirCDNx2m
+        A+8jrQn/JJsS/ySVE/8klhP/JJYT/ySWE/8klhP/JJYT/ySWE/8klhP/JJYT/ySWE/8klhP/JJYT/ySW
+        E/8klhP/JJYT/ySWE/8klhP/JJYT/ySWE/8klhP/JJYT/ySWE/8klxP/I6kL/yKwB/8PTgOXAAAAIf//
+        /wCIsIE2GqUA7x+tA/8frgP/H64D/x+uA/8frgP/H64D/x+uA/8frgP/H64D/x+uA/8frgP/H64D/x+u
+        A/8frgP/H64D/x+uA/8frgP/H64D/x+uA/8frgP/H64D/x+uA/8frgP/H64D/x+uA/8frQP/H68D/wxP
+        AH4AAAAO////AMXYwRiP0oJhkdaEZpHWhGaR1oRmkdaEZpHWhGaR1oRmkdaEZpHWhGaR1oRmkdaEZpHW
+        hGaR1oRmkdaEZpHWhGaR1oRmkdaEZpHWhGaR1oRmkdaEZpHWhGaR1oRmkdaEZpHWhGaR1oRmkdaEZpHW
+        hGaS14RniaqCLoCAgAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+        /wD///8A////AP///wD///8A////AP///////////////+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AA
+        AAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AA
+        AAPgAAAD4AAAA+AAAAPgAAAD4AAAA///////////KAAAACAAAABAAAAAAQAIAAAAAAAABAAAxA4AAMQO
+        AAAAAQAAAAAAAAAAAACAf4AAGmMTAP///wAIKgIAHaYDABIPHgAPTQMAj9KCABUrGwAehA4AExodACCc
+        CgDF2MEAiq2DABdEFwAXSRcAH64DAB+TCwAcdw8AI6YLABgqIgAkqQwAGVwUABQjHAAirQcAJJUTABU0
+        GgAbPSIAFh4gABIRHgAEFAEAIKcGABo1IAAfUSEAHowMABY8GAAdfA8AG20RACSaEwCDjoEAGVMVACKx
+        BgAceRAAirCDABx1EACR1oQAF0AYAB1CIQCAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////
+        //////////////////////////8FICAgICAgICAgICAgICAgICAgICAgICAgICAgB////wUWFhQUFBQU
+        FBQUFBQUFBQUFBQUFBQUFBQUFioH////BRYiISEhISEhISEhISEhISEhISEhISEhIRwnKgf///8FFiEG
+        BgYGBgYGBgYGBgYGBgYGBgYGBgYGHRoqB////wUWIQYeHh4eHh4eHgYGHh4eHh4eHh4eHh4dGioH////
+        BRYhBh4eHh4eBh4JGxsYHh4eBh4eBh4eHh0aKgf///8FFiEGHh4eHh4kJQwUFAwXHgkJHhgJHh4eHRoq
+        B////wUWIQYeHh4GJAwqFhIjFC0eAhILFxIYHh4dGioH////BRYhBh4eHgsjKgwPCwsJGwYQFBsPFBsG
+        Hh0aKgf///8FFiEGHh4GGxQZKQYeHh4GJAoWCiUWCgILHRoqB////wUWIQYeHgYPGRQJBh4eHgYbKxQM
+        KxQMJhgdGioH////BRYhBh4eBg8ZFAkGHh4eHh4eJQoLLSMLHh0aKgf///8FFiEGHh4GGxQZDwYeHh4e
+        CwIMFCUSFCUPHRoqB////wUWIQYeHh4LCiojCR4GHgseAgoZIwoWIxAdGioH////BRYhBh4eHgYkFCoS
+        JgITAh4GCRQpGAwXBh0aKgf///8FFiEGHh4eHh4vIxkqKiotHh4LIy0LIyUeHRoqB////wUWIQYeHh4e
+        HgYLDxcXKQkeHh4bGx4bGx4dGioH////BRYhBh4eHh4eHh4GBgYGBh4eHgYGHgYGHh0aKgf///8FFiEG
+        Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHRoqB////wUWIQYeHh4eHh4eHh4eHh4eHh4eHh4eHh4dGioH////
+        BRYhBh4eHh4eHh4eHh4eHh4eHh4eHh4eHh0aKgf///8FFiEGHh4eHh4eHh4eHh4eHh4eHh4eHh4eHRoq
+        B////wUWIQYeHh4eHh4eHh4eHh4eHh4eHh4eHh4dGioH////BRYhBh4eHh4eHh4eHh4eHh4eHh4eHh4e
+        Hh0aKgf///8FFiEGHh4eHh4eHh4eHh4eHh4eHh4eHh4GHRoqB////wUWMB0dHR0dHR0dHR0dHR0dHR0d
+        HR0dHR0VGioH////BRYnGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoWKgf///8FERERERERERERERERERER
+        ERERERERERERERER////////////////////////////////////////////////////////////////
+        ///////////////////////////////////AAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAA
+        AAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAA
+        AAHAAAABwAAAAcAAAAHAAAAD//////////8oAAAAEAAAACAAAAABACAAAAAAAAAEAADEDgAAxA4AAAAA
+        AAAAAAAArrSsDA4pCE0HJAFkByQBYwckAWMHJAFjByQBYwckAWMHJAFjByQBYwckAWMHJAFjByQBYwck
+        AWMHIgFiAgsAN7PPrislmw7YH5UL8h+TC/IfkwvyH5ML8h+TC/IfkwvyH5ML8h+TC/IfkwvyH5ML8h+T
+        C/IflAvyHpcH6wkwAm2z060vJ6AS6BpDHP8XKh7/Fywe/xcsHv8XKx7/Fioe/xcrHv8XLB7/Fywe/xcs
+        Hv8XKx7/GTkd/yGVDfkKNgJxs9OtLyedEucWLB3/Eg0e/xIPHv8SDx7/Ex8c/xQqGv8THRz/Eg8e/xIP
+        Hv8SDx7/Eg4e/xUgHv8gkQ74CjYCcbPTrS8nnRLnFi0d/xIPHv8SER7/GEwW/x+PDP8eig3/G2sR/xUx
+        Gv8WPBj/F0QX/xMaHf8VIB7/IJEO+Ao2AnGz060vJ50S5xYtHf8SDh7/FCUb/x+WC/8ZWhT/FCAc/xQk
+        G/8YUBX/HX4O/x2ADv8YUhX/FiUe/yCQDvgKNgJxs9OtLyedEucWLR3/Eg0e/xY0Gf8gmAv/FCgb/xIO
+        Hv8SDx7/Fz8Y/x6IDf8deg//G24R/xYpHf8gkA74CjYCcbPTrS8nnRLnFi0d/xIOHv8UJBv/H5ML/xhO
+        Ff8TFR3/Excd/xY4Gf8ejQz/HoMO/x6GDf8XOhv/II8O+Ao2AnGz060vJ50S5xYtHf8SDx7/EhEe/xhO
+        Ff8fkQz/HYQO/xtsEf8TGR3/GVkU/xlWFP8baRH/Fiod/yCQDvgKNgJxs9OtLyedEucWLR3/Eg8e/xIR
+        Hv8SER7/FCkb/xc/GP8VLhr/EhEe/xMdHP8THxz/FCMb/xUjHv8gkQ74CjYCcbPTrS8nnRLnFi0d/xIP
+        Hv8SER7/EhEe/xIQHv8SDx7/Eg8e/xIRHv8SEB7/EhAe/xIPHv8VIR7/IJEO+Ao2AnGz060vJ50S5xYt
+        Hf8SDx7/EhEe/xIRHv8SER7/EhEe/xIRHv8SER7/EhEe/xIRHv8SEB7/FSEe/yCRDvgKNgJxs9OtLyed
+        EucWLB3/Eg4e/xIQHv8SEB7/EhAe/xIQHv8SEB7/EhAe/xIQHv8SEB7/Eg8e/xUgHv8gkQ74CjYCcbPT
+        rS8nnhLoGDod/xUgHv8VIR7/FSEe/xUhHv8VIR7/FSEe/xUhHv8VIR7/FSEe/xUhHv8XMB7/IJMN+Qo2
+        AnK107AtLqoW3CifFPMomxXzKJsV8yibFfMomxXzKJsV8yibFfMomxXzKJsV8yibFfMomxXzKJ0V8yin
+        EOsSPAlg5vDlDrnjsUG35a5Ht+auR7fmrke35q5Ht+auR7fmrke35q5Ht+auR7fmrke35q5Ht+auR7fm
+        rke3465FsL6tF///AAD//wAAwAMAAMADAADAAwAAwAMAAMADAADAAwAAwAMAAMADAADAAwAAwAMAAMAD
+        AADAAwAA//8AAP//AAAoAAAAEAAAACAAAAABAAgAAAAAAAABAADEDgAAxA4AAAABAAAAAAAAAgsAAK60
+        rAAdfA8AByQBABUiHQAXPBkAHowNAObw5QC35q4AJ50SAAo2AgAYTRUAEg8eABYsHQCzz64AG2wRABMd
+        HAAelwcAJ6ASACOaDQAWMhsAF0QXABlaFAASPAkAIJEOABIRHgAOKQgAHoMOAC6qFgAonBUAGTodABhT
+        FQCwvq0AH5MLACCPDgC547EAs9OtACinEAAaQxwAtdOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
+        ////////////////////EyEhISEhISEhISEhIRH//xImDQ0NDQ0NDQ0NDR4Y//8JDQwMDBANEAwMDAwE
+        GP//CQ0MGQsGBg8UBRUQBBj//wkNDAQhFgQEHwIbHwQY//8JDQwUEw0MDAUGAg8NGP//CQ0MBCELGRkF
+        BhsbBSL//wkNDBkLIRsPEBYfDw0Y//8JDQwZGQ0FDRkQEAQEGP//CQ0MGRkZDAwZGRkMBBj//wkNDBkZ
+        GRkZGRkZGQQY//8JDQwZGRkZGRkZGQwEGP//CR4EBAQEBAQEBAQEFBj//xwdHR0dHR0dHR0dHR0l////
+        /////////////////////wAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIAB
+        AACAAQAAgAEAAIABAAD//wAA
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionControl/ScriptEditControl/csharp.ico b/LB_VisionControl/ScriptEditControl/csharp.ico
new file mode 100644
index 0000000..5f85a11
--- /dev/null
+++ b/LB_VisionControl/ScriptEditControl/csharp.ico
Binary files differ
diff --git a/LB_VisionControl/UserHSmartWindowControl.Designer.cs b/LB_VisionControl/UserHSmartWindowControl.Designer.cs
new file mode 100644
index 0000000..9bd4448
--- /dev/null
+++ b/LB_VisionControl/UserHSmartWindowControl.Designer.cs
@@ -0,0 +1,151 @@
+锘縩amespace LB_VisionControl
+{
+    partial class UserHSmartWindowControl
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            components = new System.ComponentModel.Container();
+            RightContextMenuStrip = new ContextMenuStrip(components);
+            resizeImageStripMenuItem = new ToolStripMenuItem();
+            autoSizeStripMenuItem = new ToolStripMenuItem();
+            mouseIndexStripMenuItem = new ToolStripMenuItem();
+            BtmStatusStrip = new StatusStrip();
+            StatusLabel = new ToolStripStatusLabel();
+            pnl = new Panel();
+            hWindowControl = new HalconDotNet.HSmartWindowControl();
+            RightContextMenuStrip.SuspendLayout();
+            BtmStatusStrip.SuspendLayout();
+            pnl.SuspendLayout();
+            SuspendLayout();
+            // 
+            // RightContextMenuStrip
+            // 
+            RightContextMenuStrip.Items.AddRange(new ToolStripItem[] { resizeImageStripMenuItem, autoSizeStripMenuItem, mouseIndexStripMenuItem });
+            RightContextMenuStrip.Name = "RightContextMenuStrip";
+            RightContextMenuStrip.Size = new Size(149, 70);
+            // 
+            // resizeImageStripMenuItem
+            // 
+            resizeImageStripMenuItem.Name = "resizeImageStripMenuItem";
+            resizeImageStripMenuItem.Size = new Size(148, 22);
+            resizeImageStripMenuItem.Text = "閲嶆柊缂╂斁鍥惧儚";
+            resizeImageStripMenuItem.Click += resizeImageStripMenuItem_Click;
+            // 
+            // autoSizeStripMenuItem
+            // 
+            autoSizeStripMenuItem.Checked = true;
+            autoSizeStripMenuItem.CheckState = CheckState.Checked;
+            autoSizeStripMenuItem.Name = "autoSizeStripMenuItem";
+            autoSizeStripMenuItem.Size = new Size(148, 22);
+            autoSizeStripMenuItem.Text = "鍥惧儚鑷姩閫傚簲";
+            autoSizeStripMenuItem.Click += autoSizeStripMenuItem_Click;
+            // 
+            // mouseIndexStripMenuItem
+            // 
+            mouseIndexStripMenuItem.Name = "mouseIndexStripMenuItem";
+            mouseIndexStripMenuItem.Size = new Size(148, 22);
+            mouseIndexStripMenuItem.Text = "榧犳爣绱㈠紩鍍忕礌";
+            mouseIndexStripMenuItem.Click += mouseIndexStripMenuItem_Click;
+            // 
+            // BtmStatusStrip
+            // 
+            BtmStatusStrip.Items.AddRange(new ToolStripItem[] { StatusLabel });
+            BtmStatusStrip.Location = new Point(0, 220);
+            BtmStatusStrip.Name = "BtmStatusStrip";
+            BtmStatusStrip.Padding = new Padding(1, 0, 16, 0);
+            BtmStatusStrip.Size = new Size(274, 22);
+            BtmStatusStrip.TabIndex = 44;
+            BtmStatusStrip.Text = "statusStrip1";
+            // 
+            // StatusLabel
+            // 
+            StatusLabel.Name = "StatusLabel";
+            StatusLabel.Size = new Size(0, 17);
+            // 
+            // pnl
+            // 
+            pnl.Controls.Add(hWindowControl);
+            pnl.Dock = DockStyle.Fill;
+            pnl.Location = new Point(0, 0);
+            pnl.Name = "pnl";
+            pnl.Size = new Size(274, 220);
+            pnl.TabIndex = 45;
+            // 
+            // hWindowControl
+            // 
+            hWindowControl.AutoSizeMode = AutoSizeMode.GrowAndShrink;
+            hWindowControl.AutoValidate = AutoValidate.EnableAllowFocusChange;
+            hWindowControl.BackColor = Color.Black;
+            hWindowControl.ContextMenuStrip = RightContextMenuStrip;
+            hWindowControl.Dock = DockStyle.Fill;
+            hWindowControl.HDoubleClickToFitContent = true;
+            hWindowControl.HDrawingObjectsModifier = HalconDotNet.HSmartWindowControl.DrawingObjectsModifier.None;
+            hWindowControl.HImagePart = new Rectangle(0, 88, 2591, 1767);
+            hWindowControl.HKeepAspectRatio = true;
+            hWindowControl.HMoveContent = true;
+            hWindowControl.HZoomContent = HalconDotNet.HSmartWindowControl.ZoomContent.WheelForwardZoomsIn;
+            hWindowControl.Location = new Point(0, 0);
+            hWindowControl.Margin = new Padding(4);
+            hWindowControl.Name = "hWindowControl";
+            hWindowControl.Size = new Size(274, 220);
+            hWindowControl.TabIndex = 43;
+            hWindowControl.WindowSize = new Size(274, 220);
+            hWindowControl.HMouseMove += hWindowControl_HMouseMove;
+            hWindowControl.HMouseDown += hWindowControl_HMouseDown;
+            hWindowControl.HMouseUp += hWindowControl_HMouseUp;
+            // 
+            // UserHSmartWindowControl
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(pnl);
+            Controls.Add(BtmStatusStrip);
+            Margin = new Padding(4);
+            Name = "UserHSmartWindowControl";
+            Size = new Size(274, 242);
+            Load += UserHSmartWindowControl_Load;
+            SizeChanged += UserHSmartWindowControl_SizeChanged;
+            MouseWheel += UserHSmartWindowControl_HMouseWheel;
+            RightContextMenuStrip.ResumeLayout(false);
+            BtmStatusStrip.ResumeLayout(false);
+            BtmStatusStrip.PerformLayout();
+            pnl.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+        private System.Windows.Forms.StatusStrip BtmStatusStrip;
+        private System.Windows.Forms.ToolStripStatusLabel StatusLabel;
+        private ContextMenuStrip RightContextMenuStrip;
+        private ToolStripMenuItem autoSizeStripMenuItem;
+        private ToolStripMenuItem mouseIndexStripMenuItem;
+        private ToolStripMenuItem resizeImageStripMenuItem;
+        private Panel pnl;
+        private HalconDotNet.HSmartWindowControl hWindowControl;
+    }
+}
diff --git a/LB_VisionControl/UserHSmartWindowControl.cs b/LB_VisionControl/UserHSmartWindowControl.cs
new file mode 100644
index 0000000..a1c3acb
--- /dev/null
+++ b/LB_VisionControl/UserHSmartWindowControl.cs
@@ -0,0 +1,1174 @@
+锘縰sing HalconDotNet;
+using System.Diagnostics;
+
+namespace LB_VisionControl
+{
+    public partial class UserHSmartWindowControl : UserControl
+    {
+        public UserHSmartWindowControl()
+        {
+            InitializeComponent();
+
+            // 璁剧疆杞粨榛樿涓虹豢鑹�
+            HOperatorSet.SetColor(hWindowControl.HalconWindow, "green");
+            HOperatorSet.SetLineWidth(hWindowControl.HalconWindow, 5);
+            color = "green";
+            // 鑳屾櫙鑹�
+            hWindowControl.HalconWindow.SetWindowParam("background_color", "gray");
+            // 璁剧疆榛樿瀛椾綋涓� 20鍙� mono瀛椾綋鍔犵矖
+            set_display_font(this.hWindowControl.HalconWindow, 20, "mono", "true", "false");
+        }
+
+        private void UserHSmartWindowControl_Load(object sender, EventArgs e)
+        {
+            // 鍚敤鍙岀紦鍐插噺灏戦棯鐑�
+            this.DoubleBuffered = true;
+            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
+            this.UpdateStyles();
+        }
+
+        /// <summary>
+        /// 鏄惁鑷姩鏀惧ぇ鍒伴�傚悎鍥惧儚
+        /// </summary>
+        public bool bAutoSize = true;
+
+        private HObject _hImage = null;
+        /// <summary>
+        /// 鏄剧ず鍥剧墖(寮傛)
+        /// </summary>
+        public HObject hImage
+        {
+            get
+            {
+                return _hImage;
+            }
+            set
+            {
+                if (value == null)
+                {
+                    _hImage = null;
+                    //ShowHoImage(null, hWindowControl.HalconWindow, bAutoSize);
+                    ShowHoImageAsync(null, hWindowControl.HalconWindow, bAutoSize);
+                    return;
+                }
+
+                // 鑰楁椂鎿嶄綔鍔犻攣閬垮厤琚噴鏀�
+                lock (value)
+                {
+                    try
+                    {
+                        // 娣辨嫹璐濆浘鐗囬伩鍏嶈閲婃斁
+                        //_hImage = value.CopyObj(1, -1);
+                        //ShowHoImage(_hImage, hWindowControl.HalconWindow, bAutoSize);
+                        ShowHoImageAsync(value, hWindowControl.HalconWindow, bAutoSize);
+                    }
+                    catch { }
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鐢诲浘鍙栨秷璇锋眰
+        /// </summary>
+        CancellationTokenSource ctsDrawingTask = new CancellationTokenSource();
+
+        private bool _bAollowDraw = false;
+        /// <summary>
+        /// 鍚敤缁樼敾妯″紡鏍囪
+        /// </summary>
+        public bool bAollowDraw
+        {
+            get { return _bAollowDraw; }
+            set
+            {
+                _bAollowDraw = value;
+                //鍚姩缁樼敾妯″紡闇�瑕佸彇娑堢缉鏀�
+                if (value)
+                {
+                    //// 鍙栨秷寮傛绾跨▼
+                    //ctsDrawingTask.Cancel();
+
+                    //Thread.Sleep(100);
+                    //// 鍒涘缓鏂癈ancellationTokenSource閬垮厤鏃犳硶閲嶅惎
+                    //ctsDrawingTask = new CancellationTokenSource();
+                    //Task task = Task.Run(() => DrawObjectTaskAsync(ctsDrawingTask.Token, RoiType.None), ctsDrawingTask.Token);
+                    HTuple hv_imageWidth = 250; HTuple hv_imageHeight = 250;
+                    if (hImage != null && hImage.IsInitialized())
+                        HOperatorSet.GetImageSize(hImage, out hv_imageWidth, out hv_imageHeight);
+                    switch (enumRoiType)
+                    {
+                        case RoiType.Rectangle2:
+                            if (hRoi == null)
+                                hRoi = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.RECTANGLE2, hv_imageHeight / 2, hv_imageWidth / 2, 0, 400, 400);
+                            hWindowControl.HalconWindow.AttachDrawingObjectToWindow(hRoi);
+                            break;
+                        case RoiType.Circle:
+                            if (hRoi == null)
+                                hRoi = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.CIRCLE, hv_imageHeight / 2, hv_imageWidth / 2, 100);
+                            hWindowControl.HalconWindow.AttachDrawingObjectToWindow(hRoi);
+                            break;
+                        case RoiType.Ellipse:
+                            if (hRoi == null)
+                                hRoi = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.ELLIPSE_SECTOR, 0, 0, 0, hv_imageHeight / 4, hv_imageWidth / 4, 0, Math.PI / 2);
+                            hWindowControl.HalconWindow.AttachDrawingObjectToWindow(hRoi);
+                            break;
+                        case RoiType.Segment:
+                            if (hRoi == null)
+                                hRoi = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.LINE, 0, 0, hv_imageHeight / 4, hv_imageWidth / 4);
+                            hWindowControl.HalconWindow.AttachDrawingObjectToWindow(hRoi);
+                            break;
+                        // 绌哄拰鍏朵粬涓嶈繘琛岀粯鍒�
+                        case RoiType.None:
+                        default:
+                            if (hRoi != null)
+                            {
+                                hRoi.ClearDrawingObject();
+                                hRoi.Dispose();
+                                hRoi = null;
+                            }
+                            break;
+                    }
+                }
+                else
+                {
+                    // 鍙栨秷寮傛绾跨▼
+                    //ctsDrawingTask.Cancel();
+
+                    if (hRoi != null)
+                    {
+                        hRoi.ClearDrawingObject();
+                        hRoi.Dispose();
+                        hRoi = null;
+                    }
+                    Thread.Sleep(100);
+                }
+            }
+        }
+
+        string _color = "green";
+
+        string color
+        {
+            get { return _color; }
+            set
+            {
+                _color = value;
+            }
+        }
+
+        private RoiType enumRoiType = RoiType.None;
+
+        HDrawingObject hRoi = null;
+
+        public Object oRoi
+        {
+            get
+            {
+                if (hRoi == null)
+                    return null;
+                switch (enumRoiType)
+                {
+                    case RoiType.Rectangle2:
+                        {
+                            //鑾峰彇鐭╁舰鍙傛暟鐢熸垚Roi
+                            string[] str = { "row", "column", "phi", "length1", "length2" };
+                            HTuple val = hRoi.GetDrawingObjectParams(str);
+                            //娉ㄦ剰鍙傛暟椤哄簭
+                            return new HRectangle2(val[1], val[0], val[2], (val[3] * 2), (val[4] * 2));
+                        }
+                    case RoiType.Circle:
+                        {
+                            //鑾峰彇鍦嗗舰鍙傛暟鐢熸垚Roi
+                            string[] str = { "row", "column", "radius" };
+                            HTuple val = hRoi.GetDrawingObjectParams(str);
+                            //娉ㄦ剰鍙傛暟椤哄簭
+                            return new HCircle(val[1], val[0], val[2]);
+                        }
+                    case RoiType.Ellipse:
+                        {
+                            //鑾峰彇绾挎鍙傛暟鐢熸垚Roi
+                            string[] str = { "row", "column", "phi", "radius1", "radius2", "start_angle", "end_angle" };
+                            HTuple val = hRoi.GetDrawingObjectParams(str);
+                            //娉ㄦ剰鍙傛暟椤哄簭
+                            return new HEllipse(val[1], val[0], val[2], val[3], val[4], val[5], val[6]);
+                        }
+                    case RoiType.Segment:
+                        {
+                            //鑾峰彇绾挎鍙傛暟鐢熸垚Roi
+                            string[] str = { "row1", "column1", "row2", "column2" };
+                            HTuple val = hRoi.GetDrawingObjectParams(str);
+                            //娉ㄦ剰鍙傛暟椤哄簭
+                            return new HSegment(val[1], val[0], val[3], val[2]);
+                        }
+                    case RoiType.None:
+                    default:
+                        return null;
+                }
+            }
+            set
+            {
+                Type type = value?.GetType();
+
+                if (hRoi != null)
+                {
+                    hRoi.ClearDrawingObject();
+                    hRoi.Dispose();
+                    hRoi = null;
+                }
+
+                if (typeof(HRectangle2) == type)
+                {
+                    enumRoiType = RoiType.Rectangle2;
+                    hRoi = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.RECTANGLE2
+                        , (HTuple)(((HRectangle2)value).Row), (HTuple)(((HRectangle2)value).Column), (HTuple)(((HRectangle2)value).Phi)
+                        , (HTuple)(((HRectangle2)value).SemiLength1), (HTuple)(((HRectangle2)value).SemiLength2));
+                }
+                else if (typeof(HCircle) == type)
+                {
+                    enumRoiType = RoiType.Circle;
+                    hRoi = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.CIRCLE
+                        , (HTuple)(((HCircle)value).Row), (HTuple)(((HCircle)value).Column), (HTuple)(((HCircle)value).Radius));
+                }
+                else if (typeof(HEllipse) == type)
+                {
+                    enumRoiType = RoiType.Segment;
+                    hRoi = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.ELLIPSE_SECTOR
+                        , (HTuple)(((HEllipse)value).Row), (HTuple)(((HEllipse)value).Column), (HTuple)(((HEllipse)value).Phi)
+                        , (HTuple)(((HEllipse)value).Radius1), (HTuple)(((HEllipse)value).Radius2)
+                        , (HTuple)(((HEllipse)value).StartAngle), (HTuple)(((HEllipse)value).EndAngle));
+                }
+                else if (typeof(HSegment) == type)
+                {
+                    enumRoiType = RoiType.Segment;
+                    hRoi = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.LINE
+                        , (HTuple)(((HSegment)value).BeginRow), (HTuple)(((HSegment)value).BeginColumn)
+                        , (HTuple)(((HSegment)value).EndRow), (HTuple)(((HSegment)value).EndColumn));
+                }
+                else
+                {
+                    enumRoiType = RoiType.None;
+                    if (hRoi != null)
+                    {
+                        hRoi.ClearDrawingObject();
+                        hRoi.Dispose();
+                        hRoi = null;
+                    }
+                }
+
+
+                if (hRoi != null && bAollowDraw)
+                {
+                    //鎶婄粯鍒跺璞¢噸鏂版樉绀哄埌halcon绐楀彛涓�
+                    hWindowControl.HalconWindow.AttachDrawingObjectToWindow(hRoi);
+                }
+            }
+        }
+
+        static int winRow, winCol, winWidth, winHeight, partWidth, partHeight;
+        static HTuple imgWidth, imgHeight;
+
+        /// <summary>
+        /// 鏄剧ず鍥剧墖(寮傛)
+        /// </summary>
+        /// <param name="ho_image"></param>
+        /// <param name="hWindow"></param>
+        /// <param name="autoSize"></param>
+        public async void ShowHoImageAsync(HObject ho_image, HWindow hWindow, bool autoSize = true)
+        {
+            if (ho_image == null || !ho_image.IsInitialized())
+                HOperatorSet.ClearWindow(hWindow);
+            else
+                await ShowImageAsync(hWindow, ho_image, autoSize);
+        }
+
+        /// <summary>
+        /// 鏄剧ず鍥剧墖(鍚屾)
+        /// </summary>
+        /// <param name="ho_image"></param>
+        /// <param name="autoSize"></param>
+        public void ShowHoImage(HObject ho_image, bool autoSize = true)
+        {
+            _hImage = ho_image;
+            HOperatorSet.ClearWindow(hWindowControl.HalconWindow);
+
+            if (ho_image == null)
+                return;
+
+            try
+            {
+                if (autoSize && bAutoSize)
+                {
+                    HOperatorSet.GetImageSize(ho_image, out HTuple imgWidth, out HTuple imgHeight);
+                    if (imgWidth.Length > 0)
+                    {
+                        hWindowControl.HalconWindow.GetWindowExtents(out int winRow, out int winCol, out int winWidth, out int winHeight);
+                        double partWidth, partHeight;
+
+                        if (winWidth < winHeight)
+                        {
+                            partWidth = imgWidth;
+                            partHeight = imgWidth * winHeight / winWidth;
+                        }
+                        else
+                        {
+                            partWidth = imgHeight * winWidth / winHeight;
+                            partHeight = imgHeight;
+                        }
+
+                        //璁$畻姣斾緥
+                        double scale = Math.Max(1.0 * imgWidth.D / winWidth, 1.0 * imgHeight.D / winHeight);
+                        double w = winWidth * scale;
+                        double h = winHeight * scale;
+
+                        double row1 = -(h - imgHeight.D) / 2;
+                        double col1 = -(w - imgWidth.D) / 2;
+                        double row2 = imgHeight.D + (h - imgHeight.D) / 2;
+                        double col2 = imgWidth.D + (w - imgWidth.D) / 2;
+
+                        //灞呬腑绛夋瘮渚�
+                        hWindowControl.HalconWindow.SetPart(row1, col1, row2, col2);
+                    }
+                }
+                HOperatorSet.DispObj(ho_image, hWindowControl.HalconWindow);
+            }
+            catch (HOperatorException ex)
+            {
+                Debug.WriteLine($"銆恵DateTime.Now:HH:mm:ss.fff}銆戦敊璇秷鎭�: {ex.Message}");
+                Debug.WriteLine($"銆恵DateTime.Now:HH:mm:ss.fff}銆戦敊璇唬鐮�: {ex.GetErrorCode()}");
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"銆恵DateTime.Now:HH:mm:ss.fff}銆慐rror displaying image: {ex.Message}");
+            }
+            return;
+        }
+
+        private async Task<bool> ShowImageAsync(HWindow hWindow, HObject ho_image, bool autoSize = true)
+        {
+            return await Task.Run(() =>
+            {
+                if (ho_image == null || !ho_image.IsInitialized())
+                {
+                    try
+                    {
+                        HOperatorSet.ClearWindow(hWindow);
+                    }
+                    catch { return false; }
+                    return true;
+                }
+
+                try
+                {
+                    HOperatorSet.ClearWindow(hWindow);
+
+                    if (autoSize)
+                    {
+                        HOperatorSet.GetImageSize(ho_image, out HTuple imgWidth, out HTuple imgHeight);
+                        if (imgWidth.Length > 0)
+                        {
+                            hWindow.GetWindowExtents(out int winRow, out int winCol, out int winWidth, out int winHeight);
+                            double partWidth, partHeight;
+
+                            if (winWidth < winHeight)
+                            {
+                                partWidth = imgWidth;
+                                partHeight = imgWidth * winHeight / winWidth;
+                            }
+                            else
+                            {
+                                partWidth = imgHeight * winWidth / winHeight;
+                                partHeight = imgHeight;
+                            }
+
+                            //璁$畻姣斾緥
+                            double scale = Math.Max(1.0 * imgWidth.D / winWidth, 1.0 * imgHeight.D / winHeight);
+                            double w = winWidth * scale;
+                            double h = winHeight * scale;
+
+                            double row1 = -(h - imgHeight.D) / 2;
+                            double col1 = -(w - imgWidth.D) / 2;
+                            double row2 = imgHeight.D + (h - imgHeight.D) / 2;
+                            double col2 = imgWidth.D + (w - imgWidth.D) / 2;
+
+                            //灞呬腑绛夋瘮渚�
+                            hWindow.SetPart(row1, col1, row2, col2);
+                        }
+                    }
+
+                    HOperatorSet.DispObj(ho_image, hWindow);
+                }
+                catch { return false; }
+                return true;
+            });
+        }
+
+        public HWindow GetHalconWindow()
+        {
+            return this.hWindowControl.HalconWindow;
+        }
+
+        public void ClearObj()
+        {
+            try
+            {
+                HOperatorSet.ClearWindow(hWindowControl.HalconWindow);
+            }
+            catch { }
+        }
+
+        public void ShowObj(HObject ho_object)
+        {
+            try
+            {
+                if (ho_object != null && ho_object.IsInitialized())
+                    HOperatorSet.DispObj(ho_object, this.hWindowControl.HalconWindow);
+            }
+            catch { }
+        }
+
+        public void DispObj(HObject ho_object, string color)
+        {
+            try
+            {
+                if (ho_object != null && ho_object.IsInitialized())
+                {
+                    SetColor(color);
+                    HOperatorSet.DispObj(ho_object, this.hWindowControl.HalconWindow);
+                }
+            }
+            catch { }
+        }
+
+        public void DispObj(HObject ho_object, bool result = true)
+        {
+            try
+            {
+                if (ho_object != null && ho_object.IsInitialized())
+                {
+                    string color = result ? "green" : "red";
+                    SetColor(color);
+                    HOperatorSet.DispObj(ho_object, this.hWindowControl.HalconWindow);
+                }
+            }
+            catch { }
+        }
+
+        public void ShowMsg(string msg, double x = 0, double y = 0, string color = "green")
+        {
+            try
+            {
+                SetColor(color);
+                disp_message(this.hWindowControl.HalconWindow, msg, "image", (HTuple)y, (HTuple)x, color, "true");
+            }
+            catch { }
+        }
+
+        public void ShowMsg(string msg, bool result, double x = 0, double y = 0, int size = 0)
+        {
+            try
+            {
+                if (size > 0)
+                    set_display_font(this.hWindowControl.HalconWindow, size, "mono", "true", "false");
+                string color = result ? "green" : "red";
+                SetColor(color);
+                disp_message(this.hWindowControl.HalconWindow, msg, "image", (HTuple)y, (HTuple)x, result ? "green" : "red", "true");
+            }
+            catch { }
+        }
+
+        public void SetColor(string color = "")
+        {
+            try
+            {
+                if (color.TrimEnd() == "")
+                {
+                    color = GetRandomColor();
+                    //color = this.color;
+                }
+
+                if (this.color != color)
+                {
+                    HOperatorSet.SetColor(this.hWindowControl.HalconWindow, color);
+                    this.color = color;
+                }
+            }
+            catch { }
+        }
+
+        /// <summary>
+        /// 鐢熸垚Halcon闅忔満棰滆壊
+        /// </summary>
+        /// <returns></returns>
+        public string GetRandomColor()
+        {
+            // 鑾峰彇褰撳墠鏃堕棿鐨勬绉掓暟浣滀负绉嶅瓙
+            int seed = DateTime.Now.Millisecond;
+
+            // 浣跨敤绉嶅瓙鍒涘缓 Random 瀹炰緥
+            Random random = new Random(seed);
+
+            // 鐢熸垚闅忔満鏁�
+            int randomNumber = random.Next(0, 18);
+
+            // 寤舵椂闅忔満鏃堕棿鍙樻洿闅忔満绉嶅瓙
+            Thread.Sleep(randomNumber);
+
+            string[] strsColors = new string[]
+            {
+                "red", "green","blue", "cyan", "magenta",
+                "yellow", "dim gray", "gray","light gray", "medium slate blue", "coral", "slate blue",
+                "spring green", "orange red", "orange", "dark olive green","pink", "forest green", "cadet blue"
+            };
+            if (randomNumber <= strsColors.Length)
+                return strsColors[randomNumber];
+            else
+                return strsColors[0];
+        }
+
+        public void SetFont(HTuple hv_Size, string hv_Font = "mono", string hv_Bold = "true", string hv_Slant = "false")
+        {
+            set_display_font(this.hWindowControl.HalconWindow, hv_Size, hv_Font, hv_Bold, hv_Slant);
+        }
+
+        /// <summary>
+        /// 璁剧疆绗﹀彿澶у皬
+        /// </summary>
+        /// <param name="hv_WindowHandle"></param>
+        /// <param name="hv_Size"></param>
+        /// <param name="hv_Font"></param>
+        /// <param name="hv_Bold"></param>
+        /// <param name="hv_Slant"></param>
+        public static void set_display_font(HTuple hv_WindowHandle, HTuple hv_Size, string hv_Font = "mono", string hv_Bold = "true", string hv_Slant = "false")
+        {
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_OS = new HTuple(), hv_Fonts = new HTuple();
+            HTuple hv_Style = new HTuple(), hv_Exception = new HTuple();
+            HTuple hv_AvailableFonts = new HTuple(), hv_Fdx = new HTuple();
+            HTuple hv_Indices = new HTuple();
+            HTuple hv_Font_COPY_INP_TMP = new HTuple(hv_Font);
+            HTuple hv_Size_COPY_INP_TMP = new HTuple(hv_Size);
+
+            // Initialize local and output iconic variables 
+            try
+            {
+                //This procedure sets the text font of the current window with
+                //the specified attributes.
+                //
+                //Input parameters:
+                //WindowHandle: The graphics window for which the font will be set
+                //Size: The font size. If Size=-1, the default of 16 is used.
+                //Bold: If set to 'true', a bold font is used
+                //Slant: If set to 'true', a slanted font is used
+                //
+                hv_OS.Dispose();
+                HOperatorSet.GetSystem("operating_system", out hv_OS);
+                if ((int)((new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(new HTuple()))).TupleOr(
+                    new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(-1)))) != 0)
+                {
+                    hv_Size_COPY_INP_TMP.Dispose();
+                    hv_Size_COPY_INP_TMP = 16;
+                }
+                if ((int)(new HTuple(((hv_OS.TupleSubstr(0, 2))).TupleEqual("Win"))) != 0)
+                {
+                    //Restore previous behaviour
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Size = ((1.13677 * hv_Size_COPY_INP_TMP)).TupleInt()
+                                ;
+                            hv_Size_COPY_INP_TMP.Dispose();
+                            hv_Size_COPY_INP_TMP = ExpTmpLocalVar_Size;
+                        }
+                    }
+                }
+                else
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Size = hv_Size_COPY_INP_TMP.TupleInt()
+                                ;
+                            hv_Size_COPY_INP_TMP.Dispose();
+                            hv_Size_COPY_INP_TMP = ExpTmpLocalVar_Size;
+                        }
+                    }
+                }
+                if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("Courier"))) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Courier";
+                    hv_Fonts[1] = "Courier 10 Pitch";
+                    hv_Fonts[2] = "Courier New";
+                    hv_Fonts[3] = "CourierNew";
+                    hv_Fonts[4] = "Liberation Mono";
+                }
+                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("mono"))) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Consolas";
+                    hv_Fonts[1] = "Menlo";
+                    hv_Fonts[2] = "Courier";
+                    hv_Fonts[3] = "Courier 10 Pitch";
+                    hv_Fonts[4] = "FreeMono";
+                    hv_Fonts[5] = "Liberation Mono";
+                }
+                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("sans"))) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Luxi Sans";
+                    hv_Fonts[1] = "DejaVu Sans";
+                    hv_Fonts[2] = "FreeSans";
+                    hv_Fonts[3] = "Arial";
+                    hv_Fonts[4] = "Liberation Sans";
+                }
+                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("serif"))) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Times New Roman";
+                    hv_Fonts[1] = "Luxi Serif";
+                    hv_Fonts[2] = "DejaVu Serif";
+                    hv_Fonts[3] = "FreeSerif";
+                    hv_Fonts[4] = "Utopia";
+                    hv_Fonts[5] = "Liberation Serif";
+                }
+                else
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple(hv_Font_COPY_INP_TMP);
+                }
+                hv_Style.Dispose();
+                hv_Style = "";
+                if ((int)(new HTuple(((HTuple)hv_Bold).TupleEqual("true"))) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Style = hv_Style + "Bold";
+                            hv_Style.Dispose();
+                            hv_Style = ExpTmpLocalVar_Style;
+                        }
+                    }
+                }
+                else if ((int)(new HTuple(((HTuple)hv_Bold).TupleNotEqual("false"))) != 0)
+                {
+                    hv_Exception.Dispose();
+                    hv_Exception = "Wrong value of control parameter Bold";
+                    throw new HalconException(hv_Exception);
+                }
+                if ((int)(new HTuple(((HTuple)hv_Slant).TupleEqual("true"))) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Style = hv_Style + "Italic";
+                            hv_Style.Dispose();
+                            hv_Style = ExpTmpLocalVar_Style;
+                        }
+                    }
+                }
+                else if ((int)(new HTuple(((HTuple)hv_Slant).TupleNotEqual("false"))) != 0)
+                {
+                    hv_Exception.Dispose();
+                    hv_Exception = "Wrong value of control parameter Slant";
+                    throw new HalconException(hv_Exception);
+                }
+                if ((int)(new HTuple(hv_Style.TupleEqual(""))) != 0)
+                {
+                    hv_Style.Dispose();
+                    hv_Style = "Normal";
+                }
+                hv_AvailableFonts.Dispose();
+                HOperatorSet.QueryFont(hv_WindowHandle, out hv_AvailableFonts);
+                hv_Font_COPY_INP_TMP.Dispose();
+                hv_Font_COPY_INP_TMP = "";
+                for (hv_Fdx = 0; (int)hv_Fdx <= (int)((new HTuple(hv_Fonts.TupleLength())) - 1); hv_Fdx = (int)hv_Fdx + 1)
+                {
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_AvailableFonts.TupleFind(
+                            hv_Fonts.TupleSelect(hv_Fdx));
+                    }
+                    if ((int)(new HTuple((new HTuple(hv_Indices.TupleLength())).TupleGreater(
+                        0))) != 0)
+                    {
+                        if ((int)(new HTuple(((hv_Indices.TupleSelect(0))).TupleGreaterEqual(0))) != 0)
+                        {
+                            hv_Font_COPY_INP_TMP.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Font_COPY_INP_TMP = hv_Fonts.TupleSelect(
+                                    hv_Fdx);
+                            }
+                            break;
+                        }
+                    }
+                }
+                if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual(""))) != 0)
+                {
+                    throw new HalconException("Wrong value of control parameter Font");
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_Font = (((hv_Font_COPY_INP_TMP + "-") + hv_Style) + "-") + hv_Size_COPY_INP_TMP;
+                        hv_Font_COPY_INP_TMP.Dispose();
+                        hv_Font_COPY_INP_TMP = ExpTmpLocalVar_Font;
+                    }
+                }
+                HOperatorSet.SetFont(hv_WindowHandle, hv_Font_COPY_INP_TMP);
+
+                hv_Font_COPY_INP_TMP.Dispose();
+                hv_Size_COPY_INP_TMP.Dispose();
+                hv_OS.Dispose();
+                hv_Fonts.Dispose();
+                hv_Style.Dispose();
+                hv_Exception.Dispose();
+                hv_AvailableFonts.Dispose();
+                hv_Fdx.Dispose();
+                hv_Indices.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Font_COPY_INP_TMP.Dispose();
+                hv_Size_COPY_INP_TMP.Dispose();
+                hv_OS.Dispose();
+                hv_Fonts.Dispose();
+                hv_Style.Dispose();
+                hv_Exception.Dispose();
+                hv_AvailableFonts.Dispose();
+                hv_Fdx.Dispose();
+                hv_Indices.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        public static void disp_message(HTuple hv_WindowHandle, HTuple hv_String, HTuple hv_CoordSystem, HTuple hv_Row, HTuple hv_Column, HTuple hv_Color, HTuple hv_Box)
+        {
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_GenParamName = new HTuple(), hv_GenParamValue = new HTuple();
+            HTuple hv_Color_COPY_INP_TMP = new HTuple(hv_Color);
+            HTuple hv_Column_COPY_INP_TMP = new HTuple(hv_Column);
+            HTuple hv_CoordSystem_COPY_INP_TMP = new HTuple(hv_CoordSystem);
+            HTuple hv_Row_COPY_INP_TMP = new HTuple(hv_Row);
+
+            try
+            {
+                if ((int)((new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(new HTuple()))).TupleOr(
+                    new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(new HTuple())))) != 0)
+                {
+
+                    hv_Color_COPY_INP_TMP.Dispose();
+                    hv_Column_COPY_INP_TMP.Dispose();
+                    hv_CoordSystem_COPY_INP_TMP.Dispose();
+                    hv_Row_COPY_INP_TMP.Dispose();
+                    hv_GenParamName.Dispose();
+                    hv_GenParamValue.Dispose();
+
+                    return;
+                }
+                if ((int)(new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(-1))) != 0)
+                {
+                    hv_Row_COPY_INP_TMP.Dispose();
+                    hv_Row_COPY_INP_TMP = 12;
+                }
+                if ((int)(new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(-1))) != 0)
+                {
+                    hv_Column_COPY_INP_TMP.Dispose();
+                    hv_Column_COPY_INP_TMP = 12;
+                }
+                //
+                //Convert the parameter Box to generic parameters.
+                hv_GenParamName.Dispose();
+                hv_GenParamName = new HTuple();
+                hv_GenParamValue.Dispose();
+                hv_GenParamValue = new HTuple();
+                if ((int)(new HTuple((new HTuple(hv_Box.TupleLength())).TupleGreater(0))) != 0)
+                {
+                    if ((int)(new HTuple(((hv_Box.TupleSelect(0))).TupleEqual("false"))) != 0)
+                    {
+                        //Display no box
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "box");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    "false");
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    else if ((int)(new HTuple(((hv_Box.TupleSelect(0))).TupleNotEqual(
+                        "true"))) != 0)
+                    {
+                        //Set a color other than the default.
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "box_color");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    hv_Box.TupleSelect(0));
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                }
+                if ((int)(new HTuple((new HTuple(hv_Box.TupleLength())).TupleGreater(1))) != 0)
+                {
+                    if ((int)(new HTuple(((hv_Box.TupleSelect(1))).TupleEqual("false"))) != 0)
+                    {
+                        //Display no shadow.
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "shadow");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    "false");
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    else if ((int)(new HTuple(((hv_Box.TupleSelect(1))).TupleNotEqual(
+                        "true"))) != 0)
+                    {
+                        //Set a shadow color other than the default.
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "shadow_color");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    hv_Box.TupleSelect(1));
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                }
+                //Restore default CoordSystem behavior.
+                if ((int)(new HTuple(hv_CoordSystem_COPY_INP_TMP.TupleNotEqual("window"))) != 0)
+                {
+                    hv_CoordSystem_COPY_INP_TMP.Dispose();
+                    hv_CoordSystem_COPY_INP_TMP = "image";
+                }
+                //
+                if ((int)(new HTuple(hv_Color_COPY_INP_TMP.TupleEqual(""))) != 0)
+                {
+                    //disp_text does not accept an empty string for Color.
+                    hv_Color_COPY_INP_TMP.Dispose();
+                    hv_Color_COPY_INP_TMP = new HTuple();
+                }
+                //
+                //HOperatorSet.DispText(hv_WindowHandle, hv_String, hv_CoordSystem_COPY_INP_TMP,
+                //    hv_Row_COPY_INP_TMP, hv_Column_COPY_INP_TMP, hv_Color_COPY_INP_TMP, hv_GenParamName,hv_GenParamValue);
+                HOperatorSet.SetTposition(hv_WindowHandle, hv_Row_COPY_INP_TMP, hv_Column_COPY_INP_TMP);
+                HOperatorSet.WriteString(hv_WindowHandle, hv_String);
+                hv_Color_COPY_INP_TMP.Dispose();
+                hv_Column_COPY_INP_TMP.Dispose();
+                hv_CoordSystem_COPY_INP_TMP.Dispose();
+                hv_Row_COPY_INP_TMP.Dispose();
+                hv_GenParamName.Dispose();
+                hv_GenParamValue.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Color_COPY_INP_TMP.Dispose();
+                hv_Column_COPY_INP_TMP.Dispose();
+                hv_CoordSystem_COPY_INP_TMP.Dispose();
+                hv_Row_COPY_INP_TMP.Dispose();
+                hv_GenParamName.Dispose();
+                hv_GenParamValue.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // 璁板綍鎺т欢杩愯鐘舵��
+        private bool bMouseOnLeftButton = false, bMouseOnRightButton = false;
+
+        private void hWindowControl_HMouseDown(object sender, HMouseEventArgs e)
+        {
+            try
+            {
+                switch (e.Button)
+                {
+                    case MouseButtons.Left:
+                        bMouseOnLeftButton = true;
+                        break;
+                    case MouseButtons.Right:
+                        bMouseOnRightButton = true;
+                        break;
+                    case MouseButtons.Middle:
+                        break;
+                    default:
+                        break;
+                }
+            }
+            catch { }
+        }
+
+        private void hWindowControl_HMouseUp(object sender, HMouseEventArgs e)
+        {
+            try
+            {
+                switch (e.Button)
+                {
+                    case MouseButtons.Left:
+                        bMouseOnLeftButton = false;
+                        break;
+                    case MouseButtons.Right:
+                        bMouseOnRightButton = false;
+                        break;
+                    case MouseButtons.Middle:
+                        break;
+                    default:
+                        break;
+                }
+            }
+            catch { }
+        }
+
+        HTuple positionRow = new HTuple();
+        HTuple positionColumn = new HTuple();
+        private void hWindowControl_HMouseMove(object sender, HMouseEventArgs e)
+        {
+            if (hImage == null)
+            {
+                return;
+            }
+            if (mouseIndexStripMenuItem.Checked)
+            {
+                //this.BeginInvoke(new Action(() =>
+                //{
+                try
+                {
+                    HOperatorSet.GetMposition(hWindowControl.HalconWindow, out HTuple positionRow, out HTuple positionColumn, out HTuple button_state);
+                    if (this.positionRow.Length == 0 || this.positionColumn.Length == 0)
+                    {
+                        this.positionRow = positionRow;
+                        this.positionColumn = positionColumn;
+                    }
+
+                    if (this.positionRow.D != positionRow.D || this.positionColumn.D != positionColumn.D)
+                    {
+                        this.positionRow = positionRow;
+                        this.positionColumn = positionColumn;
+                    }
+                }
+                catch { }
+                //}));
+            }
+        }
+
+        private static readonly object _lock = new object();
+        /// <summary>
+        /// 榧犳爣绱㈠紩鍙栨秷璇锋眰
+        /// </summary>
+        CancellationTokenSource ctsIndexTask = new CancellationTokenSource();
+
+        public bool _bGetIndex = false;
+        /// <summary>
+        /// 鍚敤榧犳爣绱㈠紩妯″紡鏍囪
+        /// </summary>
+        public bool bGetIndex
+        {
+            get { return _bGetIndex; }
+            set
+            {
+                _bGetIndex = value;
+                //鍚姩缁樼敾妯″紡闇�瑕佸彇娑堢缉鏀�
+                if (value)
+                {
+                    // 鍒涘缓鏂癈ancellationTokenSource閬垮厤鏃犳硶閲嶅惎
+                    ctsIndexTask = new CancellationTokenSource();
+                    Task.Run(() => GetIndexTaskAsync(ctsIndexTask.Token), ctsIndexTask.Token);
+                }
+                else
+                    ctsIndexTask.Cancel();
+            }
+        }
+
+        private void GetIndexTaskAsync(CancellationToken token)
+        {
+            while (true)
+            {
+                // 绛夊緟涓�娈垫椂闂村悗鍐嶆妫�鏌�
+                System.Threading.Thread.Sleep(500); // 0.5绉掗挓
+
+                if (!_bGetIndex || ctsIndexTask.IsCancellationRequested)
+                {
+                    if (this.StatusLabel.Text != string.Empty)
+                        this.StatusLabel.Text = string.Empty;
+                    return;
+                }
+
+                if (hImage != null)
+                {
+                    try
+                    {
+                        lock (_lock)
+                        {
+                            // 鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                HOperatorSet.CountChannels(hImage, out HTuple hv_Channels);
+                                if (hv_Channels.TupleInt() != 1)
+                                {
+                                    HOperatorSet.Rgb1ToGray(hImage, out HObject ho_ImageGray);
+                                    HOperatorSet.Decompose3(hImage, out HObject ho_ImageR, out HObject ho_ImageG, out HObject ho_ImageB);
+                                    HOperatorSet.TransFromRgb(ho_ImageR, ho_ImageG, ho_ImageB, out HObject ho_ImageH, out HObject ho_ImageS, out HObject ho_ImageV, "hsv");
+                                    try
+                                    {
+                                        if (positionRow.Length > 0)
+                                        {
+                                            HOperatorSet.GetGrayval(ho_ImageGray, positionRow, positionColumn, out HTuple GrayValue);
+                                            HOperatorSet.GetGrayval(ho_ImageR, positionRow, positionColumn, out HTuple RValue);
+                                            HOperatorSet.GetGrayval(ho_ImageG, positionRow, positionColumn, out HTuple GValue);
+                                            HOperatorSet.GetGrayval(ho_ImageB, positionRow, positionColumn, out HTuple BValue);
+                                            HOperatorSet.GetGrayval(ho_ImageH, positionRow, positionColumn, out HTuple HValue);
+                                            HOperatorSet.GetGrayval(ho_ImageS, positionRow, positionColumn, out HTuple SValue);
+                                            HOperatorSet.GetGrayval(ho_ImageV, positionRow, positionColumn, out HTuple VValue);
+                                            this.BeginInvoke(new Action(() =>
+                                            {
+                                                if (positionRow.Length > 0)
+                                                {
+                                                    this.StatusLabel.Text = $"Row:{positionRow},Column:{positionColumn},鐏板害鍊納GrayValue.D:F0}," +
+                                                      $"RGB({RValue.D:F0},{GValue.D:F0},{BValue.D:F0})," +
+                                                      $"HSV({HValue.D:F0},{SValue.D:F0},{VValue.D:F0})";
+                                                }
+                                            }));
+                                        }
+                                    }
+                                    catch { }
+                                    ho_ImageR.Dispose(); ho_ImageG.Dispose(); ho_ImageB.Dispose();
+                                    ho_ImageH.Dispose(); ho_ImageS.Dispose(); ho_ImageV.Dispose();
+                                    ho_ImageGray.Dispose();
+                                }
+                                else
+                                {
+                                    HOperatorSet.Rgb1ToGray(hImage, out HObject ho_ImageGray);
+                                    try
+                                    {
+                                        if (positionRow.Length > 0)
+                                        {
+                                            HOperatorSet.GetGrayval(ho_ImageGray, positionRow, positionColumn, out HTuple GrayValue);
+
+                                            //HOperatorSet.GenRectangle1(out HObject ho_Rectangle, positionRow - 5, positionColumn - 5, positionRow + 5, positionColumn + 5);
+                                            //HOperatorSet.Intensity(ho_Rectangle, ho_ImageGray, out HTuple GrayValue, out HTuple hv_Deviation);
+                                            this.BeginInvoke(new Action(() =>
+                                            {
+                                                if (positionRow.Length > 0)
+                                                    this.StatusLabel.Text = $"Row:{positionRow},Column:{positionColumn},鐏板害鍊納GrayValue.D:F0}";
+                                            }));
+                                        }
+                                    }
+                                    catch { }
+                                    ho_ImageGray.Dispose();
+                                }
+                            }
+                        }
+                    }
+                    catch { }
+                }
+            }
+        }
+
+        private void UserHSmartWindowControl_HMouseWheel(object sender, MouseEventArgs e)
+        {
+            hWindowControl.HSmartWindowControl_MouseWheel(sender, e);
+        }
+
+        private void UserHSmartWindowControl_SizeChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (imgWidth == null || imgHeight == null
+                    || imgWidth.Length == 0 || imgHeight.Length == 0)
+                    return;
+            }
+            catch { }
+        }
+
+        private void autoSizeStripMenuItem_Click(object sender, EventArgs e)
+        {
+            autoSizeStripMenuItem.Checked = !autoSizeStripMenuItem.Checked;
+            bAutoSize = !bAutoSize;
+        }
+
+        private void mouseIndexStripMenuItem_Click(object sender, EventArgs e)
+        {
+            mouseIndexStripMenuItem.Checked = !mouseIndexStripMenuItem.Checked;
+            bGetIndex = !bGetIndex;
+        }
+
+        private void resizeImageStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ShowHoImage(hImage);
+        }
+    }
+}
diff --git a/LB_VisionControl/UserHSmartWindowControl.resx b/LB_VisionControl/UserHSmartWindowControl.resx
new file mode 100644
index 0000000..29b82e3
--- /dev/null
+++ b/LB_VisionControl/UserHSmartWindowControl.resx
@@ -0,0 +1,126 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema 
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="RightContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>157, 17</value>
+  </metadata>
+  <metadata name="BtmStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionControl/UserItem.Designer.cs b/LB_VisionControl/UserItem.Designer.cs
new file mode 100644
index 0000000..582babc
--- /dev/null
+++ b/LB_VisionControl/UserItem.Designer.cs
@@ -0,0 +1,58 @@
+锘縩amespace LB_VisionControl
+{
+    partial class UserItem
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            uiContextMenuStrip1 = new ContextMenuStrip();
+            uiContextMenuStrip1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // uiContextMenuStrip1
+            // 
+            uiContextMenuStrip1.BackColor = Color.FromArgb(243, 249, 255);
+            uiContextMenuStrip1.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiContextMenuStrip1.Name = "uiContextMenuStrip1";
+            uiContextMenuStrip1.Size = new Size(181, 70);
+            uiContextMenuStrip1.ItemClicked += uiContextMenuStrip1_ItemClicked;
+            // 
+            // UserItem
+            // 
+            //AutoScaleMode = AutoScaleMode.None;
+            ContextMenuStrip = uiContextMenuStrip1;
+            Name = "UserItem";
+            Size = new Size(310, 100);
+            Paint += UserItem_Paint;
+            uiContextMenuStrip1.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ContextMenuStrip uiContextMenuStrip1;
+    }
+}
diff --git a/LB_VisionControl/UserItem.cs b/LB_VisionControl/UserItem.cs
new file mode 100644
index 0000000..f2c0f2a
--- /dev/null
+++ b/LB_VisionControl/UserItem.cs
@@ -0,0 +1,135 @@
+锘縰sing System.Drawing;
+using System.Xml.Linq;
+using static System.Net.Mime.MediaTypeNames;
+using static System.Windows.Forms.AxHost;
+
+namespace LB_VisionControl
+{
+    public enum State { None, Pass, Error, Warn };
+
+    public partial class UserItem : PictureBox
+    {
+        // 瀹氫箟涓�涓鎵樺拰浜嬩欢
+        public delegate void MenuItem1ClickedHandler(string name, string text);
+        public event MenuItem1ClickedHandler MenuItem1ClickedEvent;
+
+        // 瀹氫箟涓�涓鎵樺拰浜嬩欢
+        public delegate void MenuItem2ClickedHandler(string name, string text);
+        public event MenuItem2ClickedHandler MenuItem2ClickedEvent;
+
+        // 瀹氫箟涓�涓鎵樺拰浜嬩欢
+        public delegate void MenuItem3ClickedHandler(string name, string text);
+        public event MenuItem3ClickedHandler MenuItem3ClickedEvent;
+
+        // 瀹氫箟涓�涓鎵樺拰浜嬩欢
+        public delegate void MenuItem4ClickedHandler(string name, string text);
+        public event MenuItem4ClickedHandler MenuItem4ClickedEvent;
+
+        // 瀹氫箟涓�涓鎵樺拰浜嬩欢
+        public delegate void MenuItem5ClickedHandler(string name, string text);
+        public event MenuItem5ClickedHandler MenuItem5ClickedEvent;
+
+        // 瀹氫箟涓�涓鎵樺拰浜嬩欢
+        public delegate void MenuItem6ClickedHandler(string name, string text);
+        public event MenuItem6ClickedHandler MenuItem6ClickedEvent;
+
+        public State state = State.None;
+
+        public UserItem()
+        {
+            InitializeComponent();
+        }
+
+        public UserItem(string[] arrMenuItems)
+        {
+            InitializeComponent();
+            if (arrMenuItems.Length <= 0)
+                return;
+
+            uiContextMenuStrip1.Items.Clear();
+            ToolStripItem[] toolStripItems = new ToolStripItem[arrMenuItems.Length];
+            for (int i = 0; i < arrMenuItems.Length; i++)
+            {
+                ToolStripMenuItem ToolStripMenuItem = new ToolStripMenuItem();
+                ToolStripMenuItem.Name = $"ToolStripMenuItem{i}";
+                ToolStripMenuItem.Size = new Size(180, 22);
+                ToolStripMenuItem.Text = arrMenuItems[i];
+                toolStripItems[i] = ToolStripMenuItem;
+            }
+
+            uiContextMenuStrip1.Items.AddRange(toolStripItems);
+        }
+
+        public void UserItem_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
+        {
+            // 缁樺埗濉厖妞渾锛堜娇鐢ㄥ潗鏍囧拰澶у皬鍙傛暟锛�
+            // 缁樺埗涓�涓渾鐢ㄤ簬鏄剧ず鐘舵��
+            switch (state)
+            {
+                case State.None:
+                    e.Graphics.FillEllipse(Brushes.Black, 10, 10, 15, 15);
+                    break;
+                case State.Pass:
+                    e.Graphics.FillEllipse(Brushes.DarkGreen, 10, 10, 15, 15);
+                    break;
+                case State.Error:
+                    e.Graphics.FillEllipse(Brushes.MediumVioletRed, 10, 10, 15, 15);
+                    break;
+                case State.Warn:
+                    e.Graphics.FillEllipse(Brushes.Yellow, 10, 10, 15, 15);
+                    break;
+            }
+
+            // 缁樺埗鑳屾櫙鐭╁舰鏄剧ずName
+            RectangleF bgRect = new RectangleF(35, 0, Width, 40);
+            e.Graphics.FillRectangle(Brushes.AliceBlue, bgRect);
+            e.Graphics.DrawString(Name, Font, Brushes.Black, bgRect);
+
+            // 缁樺埗鑳屾櫙鐭╁舰鏄剧ずText
+            RectangleF btRect = new RectangleF(10, 40, Width, Height - 40);
+            e.Graphics.FillRectangle(Brushes.AliceBlue, btRect);
+            e.Graphics.DrawString(Text, Font, Brushes.Black, btRect);
+        }
+
+        private void uiContextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
+        {
+            // 鑾峰彇琚偣鍑荤殑鑿滃崟椤�
+            ToolStripMenuItem clickedItem = e.ClickedItem as ToolStripMenuItem;
+
+            if (clickedItem != null)
+            {
+                // 鏍规嵁琚偣鍑荤殑鑿滃崟椤规墽琛屼笉鍚岀殑鎿嶄綔
+                switch (clickedItem.Name)
+                {
+                    case "ToolStripMenuItem0":
+                        // 鎵ц鑿滃崟椤�0鐨勯�昏緫
+                        MenuItem1ClickedEvent?.Invoke(Name, Text);
+                        break;
+                    case "ToolStripMenuItem1":
+                        // 鎵ц鑿滃崟椤�1鐨勯�昏緫
+                        MenuItem2ClickedEvent?.Invoke(Name, Text);
+                        break;
+                    case "ToolStripMenuItem2":
+                        // 鎵ц鑿滃崟椤�2鐨勯�昏緫
+                        MenuItem3ClickedEvent?.Invoke(Name, Text);
+                        break;
+                    case "ToolStripMenuItem3":
+                        // 鎵ц鑿滃崟椤�3鐨勯�昏緫
+                        MenuItem4ClickedEvent?.Invoke(Name, Text);
+                        break;
+                    case "ToolStripMenuItem4":
+                        // 鎵ц鑿滃崟椤�4鐨勯�昏緫
+                        MenuItem5ClickedEvent?.Invoke(Name, Text);
+                        break;
+                    case "ToolStripMenuItem5":
+                        // 鎵ц鑿滃崟椤�5鐨勯�昏緫
+                        MenuItem6ClickedEvent?.Invoke(Name, Text);
+                        break;
+                    default:
+                        // 鎵ц鍏朵粬鎿嶄綔
+                        break;
+                }
+            }
+        }
+    }
+}
diff --git a/LB_VisionControl/UserItem.resx b/LB_VisionControl/UserItem.resx
new file mode 100644
index 0000000..8e32e05
--- /dev/null
+++ b/LB_VisionControl/UserItem.resx
@@ -0,0 +1,123 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema 
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="uiContextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionControl/UserPictureBox.cs b/LB_VisionControl/UserPictureBox.cs
new file mode 100644
index 0000000..efd3d29
--- /dev/null
+++ b/LB_VisionControl/UserPictureBox.cs
@@ -0,0 +1,481 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Drawing.Drawing2D;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Diagnostics;
+using static System.Net.Mime.MediaTypeNames;
+
+namespace LB_VisionControl
+{
+    public class UserPictureBox : PictureBox, IDisposable
+    {
+        public UserPictureBox(Control parent)
+        {
+            Point location = Point.Empty;
+            Size size = parent.ClientSize;
+            _zoomMatrix = new Matrix();
+            _rect = new Rectangle(0, 0, size.Width, size.Height);
+            this.Location = location;
+            this.Size = size;
+            this.SizeMode = PictureBoxSizeMode.Zoom;
+            this.parent = parent;
+            RegisterEvent();
+        }
+
+        #region 鍙橀噺
+        Control parent { get; set; }
+
+        private Bitmap _currentImage = null;
+        private readonly object _syncLock = new object();
+
+        public Bitmap Image
+        {
+            get => _currentImage;
+            set
+            {
+                //// 鏍规嵁棣栧厛璁剧疆鐨勫浘鍍忓ぇ灏忔潵璁$畻缂╂斁姣斾緥
+                //try
+                //{
+                //    if (_currentImage == null)
+                //    {
+                //        _imgWidth = value.Width;
+                //        _imgHeight = value.Height;
+
+                //        // 璁$畻鑷�傚簲缂╂斁姣斾緥
+                //        float zoomX = (float)parent.ClientSize.Width / _imgWidth;
+                //        float zoomY = (float)parent.ClientSize.Height / _imgHeight;
+                //        _zoom = Math.Min(zoomX, zoomY); // 鍙栬緝灏忕殑姣斾緥淇濊瘉瀹屽叏鏄剧ず
+                //    }
+                //}
+                //catch { }
+
+                lock (_syncLock)
+                {
+                    try
+                    {
+                        // 閲婃斁鐜版湁璧勬簮
+                        DisposeCurrentImage();
+
+                        if (value != null)
+                        {
+                            // 鍒涘缓鏂板浘鍍忓壇鏈�
+                            //_currentImage = new Bitmap(value);
+                            SetBackImage(value);
+                        }
+                        Refresh();
+                    }
+                    catch (Exception ex)
+                    {
+                        // 璁板綍閿欒鎴栧鐞嗗紓甯�
+                        Debug.WriteLine($"銆恵DateTime.Now:HH:mm:ss.fff}銆戝浘鍍忚缃け璐�: {ex.Message}");
+                        DisposeCurrentImage();
+                    }
+                }
+            }
+        }
+
+        private void DisposeCurrentImage()
+        {
+            try
+            {
+                if (_tBrush != null)
+                {
+                    _tBrush.Dispose();
+                    _tBrush = null;
+                }
+
+                if (_currentImage != null)
+                {
+                    _currentImage.Dispose();
+                    _currentImage = null;
+                }
+            }
+            catch { }
+        }
+
+        /// <summary>
+        /// 鐢ㄤ簬鍐呴儴婵�娲绘槸鍚﹂噸缁�
+        /// </summary>
+        private bool _mEnable = true;
+
+        /// <summary>
+        /// 鑳屾櫙绾圭悊鐢诲埛(璁剧疆鍥惧儚鍚庝細灏嗗浘鍍忚浆鎹㈡垚绾圭悊鐢诲埛锛屽洜涓哄~鍏呯敾鍒风殑閫熷害瑕佹瘮缁樺埗鍥惧儚鐨勯�熷害蹇緱澶�)
+        /// </summary>
+        private TextureBrush _tBrush;
+
+        /// <summary>
+        /// 鎺т欢鐨勭煩褰㈠尯鍩�
+        /// </summary>
+        private Rectangle _rect = new Rectangle();
+
+        /// <summary>
+        /// 鍥惧儚瀹藉害
+        /// </summary>
+        private int _imgWidth = 1;
+
+        /// <summary>
+        /// 鍥惧儚楂樺害
+        /// </summary>
+        private int _imgHeight = 1;
+
+        /// <summary>
+        /// 鎸変笅骞崇Щ閿紝榧犳爣鍦ㄦ帶浠朵笂鐨勬í鍧愭爣
+        /// </summary>
+        private float _mouseDownX = 0.0f;
+
+        /// <summary>
+        /// 鎸変笅骞崇Щ閿紝榧犳爣鍦ㄦ帶浠朵笂鐨勭旱鍧愭爣
+        /// </summary>
+        private float _mouseDownY = 0.0f;
+
+        /// <summary>
+        /// 缂╂斁绯绘暟
+        /// </summary>
+        private float _zoom = 1.0f;
+
+        /// <summary>
+        /// 鍥剧墖宸︿笂瑙扻杞寸殑鍋忕Щ閲�
+        /// </summary>
+        private float _imgX = 0.0f;
+        /// <summary>
+        /// 鍥剧墖宸︿笂瑙扽杞寸殑鍋忕Щ閲�
+        /// </summary>
+        private float _imgY = 0.0f;
+
+        /// <summary>
+        /// 鎸変笅骞崇Щ閿紝璁板綍褰撳墠鐨刜imgX
+        /// </summary>
+        private float _imgStartX = 0.0f;
+
+        /// <summary>
+        /// 鎸変笅骞崇Щ閿紝璁板綍褰撳墠鐨刜imgY
+        /// </summary>
+        private float _imgStartY = 0.0f;
+
+        /// <summary>
+        /// 褰撳墠鐨勭缉鏀剧煩闃�
+        /// </summary>
+        private Matrix _zoomMatrix = new Matrix();
+
+        /// <summary>
+        /// 鏈�灏忕缉鏀惧�嶇巼
+        /// </summary>
+        private float _minZoom = 0.05f;
+
+        /// <summary>
+        /// 鏈�澶х缉鏀惧�嶇巼
+        /// </summary>
+        private float _maxZoom = 50.0f;
+
+        /// <summary>
+        /// 姣忔榧犳爣婊氳疆鏃讹紝缂╂斁绯绘暟鐨勫閲忓��
+        /// </summary>
+        private float _mouseZoomDV = 0.05f;
+
+        /// <summary>
+        /// 骞崇Щ鎸夐敭
+        /// </summary>
+        private MouseButtons _translateBtn = MouseButtons.Left;
+
+        /// <summary>
+        /// 鎸囩ず鏄惁姝e湪鎵ц骞崇Щ鎿嶄綔
+        /// </summary>
+        private bool _inTranslate = false;
+        #endregion
+
+        #region 灞炴��
+        /// <summary>
+        /// 鑾峰彇鏄惁姝e湪鎵ц骞崇Щ鎿嶄綔
+        /// </summary>
+        public bool InTranslate
+        {
+            get { return _inTranslate; }
+            protected set
+            {
+                if (value != _inTranslate)
+                {
+                    _inTranslate = value;
+                    if (value)
+                    {
+                        OnStartTranslate();
+                    }
+                    else
+                    {
+                        OnStopTranslate();
+                    }
+                }
+            }
+        }
+        #endregion
+
+        #region 鏂规硶
+        /// <summary>
+        /// 娉ㄥ唽浜嬩欢
+        /// </summary>
+        public void RegisterEvent()
+        {
+            //this.MouseDoubleClick += new MouseEventHandler(_ctrl_MouseDoubleClick);
+            this.MouseDown += new MouseEventHandler(_ctrl_MouseDown);
+            this.MouseMove += new MouseEventHandler(_ctrl_MouseMove);
+            this.MouseUp += new MouseEventHandler(_ctrl_MouseUp);
+            this.MouseEnter += new EventHandler(_ctrl_MouseEnter);
+            this.MouseWheel += new MouseEventHandler(_ctrl_MouseWheel);
+            this.Paint += new PaintEventHandler(_ctrl_Paint);
+
+            this.MouseDoubleClick += new MouseEventHandler(_ctrl_MouseDoubleDown);
+        }
+
+        /// <summary>
+        /// 閲婃斁鑳屾櫙绾圭悊鐢诲埛
+        /// </summary>
+        protected virtual void tBrushDispose()
+        {
+            if (_tBrush != null)
+            {
+                _tBrush.Dispose();
+                _tBrush = null;
+            }
+        }
+
+        /// <summary>
+        /// 閲婃斁璧勬簮
+        /// </summary>
+        public new void Dispose()
+        {
+            tBrushDispose();
+            if (_zoomMatrix != null)
+            {
+                _zoomMatrix.Dispose();
+                _zoomMatrix = null;
+            }
+            if (this != null)
+                base.Dispose();
+        }
+
+        /// <summary>
+        /// 璁剧疆鑳屾櫙鍥惧儚
+        /// </summary>
+        /// <param name="img"></param>
+        public void SetBackImage(Bitmap img)
+        {
+            _mEnable = false;
+
+            tBrushDispose();        //閲婃斁褰撳墠绾圭悊
+            if (img != null)
+            {
+                _imgWidth = img.Width;
+                _imgHeight = img.Height;
+
+                //褰撳浘鍍忕殑姘村钩鍒嗚鲸鐜囧拰鍨傜洿鍒嗚鲸鐜囦笉涓�96鏃讹紝灏嗗浘鍍忚浆鎹㈡垚绾圭悊鐢诲埛涔嬪悗浼氬鑷村浘鍍忚嚜鍔ㄨ瑁佸壀鎺変竴閮ㄥ垎
+                if (img.VerticalResolution != 96 || img.HorizontalResolution != 96)
+                {
+                    //閲嶆柊瀹炰緥鍖栦竴寮犲浘鐗囦箣鍚庯紝鏂板浘鐗囩殑姘村钩鍒嗚鲸鐜囧拰鍨傜洿鍒嗚鲸鐜囦細鑷姩璋冩暣涓�96
+                    using (Bitmap bmp = new Bitmap(img))
+                    {
+                        _tBrush = new TextureBrush(img, WrapMode.Clamp);
+                    }
+                }
+                else
+                    _tBrush = new TextureBrush(img, WrapMode.Clamp);
+            }
+            else
+            {
+                _imgWidth = 1;
+                _imgHeight = 1;
+            }
+            NormalMatrix();
+            _mEnable = true;
+
+            ZoomImage(parent.ClientSize.Height / 2, parent.ClientSize.Width / 2, _zoom);
+        }
+
+        /// <summary>
+        /// 缂╂斁鍥惧儚
+        /// </summary>
+        /// <param name="x">缂╂斁鐨勪腑蹇冪偣X</param>
+        /// <param name="y">缂╂斁鐨勪腑蹇冪偣Y</param>
+        /// <param name="zoom">缂╂斁绯绘暟</param>
+        protected void ZoomImage(int x, int y, float zoom)
+        {
+            if (zoom >= _maxZoom)
+                zoom = _maxZoom;
+            else if (zoom < _minZoom)
+                zoom = _minZoom;
+            float oldX = x / _zoom;
+            float oldY = y / _zoom;
+            _zoom = zoom;
+            _imgX = x / zoom - oldX + _imgX;
+            _imgY = y / zoom - oldY + _imgY;
+            _zoomMatrix.Reset();
+            _zoomMatrix.Scale(zoom, zoom);
+            _zoomMatrix.Translate(_imgX, _imgY);
+            this.Refresh();
+        }
+
+
+        /// <summary>
+        /// 褰掍竴鍖栧綋鍓嶇煩闃�
+        /// </summary>
+        protected virtual void NormalMatrix()
+        {
+            //_zoom = 1.0f;
+            //_imgX = 0.0f;
+            //_imgY = 0.0f;
+            //_zoomMatrix.Reset();
+            //_zoomMatrix.Scale(_zoom, _zoom);
+            //_zoomMatrix.Translate(_imgX, _imgY);
+
+            _zoomMatrix = new Matrix();
+        }
+
+        #endregion
+
+        #region 鎺т欢浜嬩欢
+        private void _ctrl_Paint(object sender, PaintEventArgs e)
+        {
+            if (_mEnable)
+            {
+                Graphics g = e.Graphics;
+                g.InterpolationMode = InterpolationMode.HighQualityBicubic;         //璁剧疆鎻掑�兼ā寮�
+                if (_tBrush != null)
+                {
+                    g.Transform = _zoomMatrix;                                      //璁剧疆鍙樻崲鐭╅樀
+                    g.FillRectangle(_tBrush, 0, 0, _imgWidth, _imgHeight);
+                }
+            }
+        }
+
+        private void _ctrl_MouseWheel(object sender, MouseEventArgs e)
+        {
+            if (_mEnable)
+            {
+                if (e.Delta >= 0)
+                    ZoomImage(e.X, e.Y, _zoom + _mouseZoomDV);
+                else
+                    ZoomImage(e.X, e.Y, _zoom - _mouseZoomDV);
+            }
+        }
+
+        private void _ctrl_MouseEnter(object sender, EventArgs e)
+        {
+            //涓烘帶浠惰缃劍鐐癸紝鍥犱负鍙湁鎺т欢鏈夌劍鐐规墠鑳戒负鎺т欢瑙﹀彂榧犳爣婊氳疆浜嬩欢
+            this.Focus();
+        }
+
+        private void _ctrl_MouseUp(object sender, MouseEventArgs e)
+        {
+            if (_mEnable)
+            {
+                if (e.Button == _translateBtn)
+                {
+                    InTranslate = false;
+                }
+            }
+        }
+
+        private void _ctrl_MouseMove(object sender, MouseEventArgs e)
+        {
+            if (_mEnable)
+            {
+                if (_inTranslate)
+                {
+                    float deltaX = e.X - _mouseDownX;
+                    float deltaY = e.Y - _mouseDownY;
+                    _imgX = _imgStartX + (deltaX / _zoom);
+                    _imgY = _imgStartY + (deltaY / _zoom);
+                    _zoomMatrix.Reset();
+                    _zoomMatrix.Scale(_zoom, _zoom);
+                    _zoomMatrix.Translate(_imgX, _imgY);
+                    this.Refresh();
+                }
+            }
+        }
+
+        private void _ctrl_MouseDoubleDown(object sender, MouseEventArgs e)
+        {
+            if (_mEnable && _currentImage != null)
+            {
+                Bitmap Image = _currentImage.Clone() as Bitmap;
+                DisposeCurrentImage();
+                this.Image = Image;
+            }
+        }
+
+        private void _ctrl_MouseDown(object sender, MouseEventArgs e)
+        {
+            if (_mEnable)
+            {
+                if (e.Button == _translateBtn)
+                {
+                    _mouseDownX = e.X;
+                    _mouseDownY = e.Y;
+                    _imgStartX = _imgX;
+                    _imgStartY = _imgY;
+                    InTranslate = true;
+                }
+            }
+        }
+
+        //private void _ctrl_MouseDoubleClick(object sender, MouseEventArgs e)
+        //{
+        //    this.BeginInvoke(new Action(() =>
+        //    {
+        //        try
+        //        {
+        //            // 灏� Image 淇濆瓨涓轰复鏃舵枃浠�
+        //            string tempFilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".jpg");
+        //            this.Image.Save(tempFilePath, System.Drawing.Imaging.ImageFormat.Jpeg);
+
+        //            // 浣跨敤榛樿鍥剧墖鏌ョ湅鍣ㄦ墦寮�涓存椂鍥剧墖
+        //            Process.Start(tempFilePath);
+
+        //            Thread.Sleep(1000);
+        //            // 鍦ㄦ搷浣滅郴缁熸墦寮�鍥剧墖鍚庯紝浣犲彲浠ラ�夋嫨鍒犻櫎涓存椂鏂囦欢锛堝彲閫夛級
+        //            File.Delete(tempFilePath); // 濡傛灉甯屾湜鍦ㄦ墦寮�鍚庡垹闄や复鏃舵枃浠讹紝鍙栨秷娉ㄩ噴姝よ
+        //        }
+        //        catch { }
+        //    }));
+        //}
+
+        #endregion
+
+        #region 鑷畾涔変簨浠�
+
+        /// <summary>
+        /// 鍦ㄥ紑濮嬪钩绉绘椂鍙戠敓
+        /// </summary>
+        public event EventHandler StartTranslate;
+
+        /// <summary>
+        /// 鍦ㄧ粨鏉熷钩绉绘椂鍙戠敓
+        /// </summary>
+        public event EventHandler StopTranslate;
+
+        /// <summary>
+        /// 瑙﹀彂寮�濮嬪钩绉讳簨浠�
+        /// </summary>
+        protected virtual void OnStartTranslate()
+        {
+            if (StartTranslate != null)
+            {
+                StartTranslate(this, EventArgs.Empty);
+            }
+        }
+
+        /// <summary>
+        /// 瑙﹀彂缁撴潫骞崇Щ浜嬩欢
+        /// </summary>
+        protected virtual void OnStopTranslate()
+        {
+            if (StopTranslate != null)
+            {
+                StopTranslate(this, EventArgs.Empty);
+            }
+        }
+
+        #endregion
+    }
+}
diff --git a/LB_VisionControl/ref/halcondotnet.dll b/LB_VisionControl/ref/halcondotnet.dll
new file mode 100644
index 0000000..bb41201
--- /dev/null
+++ b/LB_VisionControl/ref/halcondotnet.dll
Binary files differ
diff --git a/LB_VisionFlowNode/FlowConnection.cs b/LB_VisionFlowNode/FlowConnection.cs
new file mode 100644
index 0000000..c686cae
--- /dev/null
+++ b/LB_VisionFlowNode/FlowConnection.cs
@@ -0,0 +1,49 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionFlowNode
+{
+    public class FlowConnection
+    {
+        [JsonProperty]
+        public string Id { get; set; } = Guid.NewGuid().ToString();
+
+        [JsonIgnore]
+        public FlowNode StartNode { get; set; }
+        [JsonProperty]
+        public string StartNodeId { get; set; }
+
+        [JsonIgnore]
+        public FlowNode EndNode { get; set; }
+        [JsonProperty]
+        public string EndNodeId { get; set; }
+
+        [JsonProperty]
+        public int BranchIndex { get; set; } = -1;
+        [JsonProperty]
+        public string BranchName { get { return $"Branch{BranchIndex}"; } }
+
+        [JsonProperty]
+        public bool IsParallel { get; set; }
+
+        public Color LineColor { get; set; } = Color.Black;
+        public float LineWidth { get; set; } = 2f;
+        public bool IsDashed { get; set; }
+
+
+        public FlowConnection() { }
+
+        public FlowConnection(FlowNode startNode, FlowNode endNode, int branchIndex)
+        {
+            StartNode = startNode;
+            EndNode = endNode;
+            StartNodeId = startNode?.Id;
+            EndNodeId = endNode?.Id;
+            BranchIndex = branchIndex;
+        }
+    }
+}
diff --git a/LB_VisionFlowNode/FlowEnum.cs b/LB_VisionFlowNode/FlowEnum.cs
new file mode 100644
index 0000000..ab440a5
--- /dev/null
+++ b/LB_VisionFlowNode/FlowEnum.cs
@@ -0,0 +1,40 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionFlowNode
+{
+    public enum NodeType
+    {
+        Normal,      // 鏅�氳妭鐐�
+        Switch,      // 鍒嗘敮鑺傜偣锛堜簩閫変竴锛�
+        Begin,       // 寮�濮嬭妭鐐�
+        End,          // 缁撴潫鑺傜偣聽
+        MultiBranch, // 澶氬垎鏀妭鐐�
+        Parallel,    // 骞惰鍒嗘敮鑺傜偣
+        Join        // 姹囪仛鍒嗘敮鑺傜偣锛堢瓑寰呮墍鏈夊垎鏀畬鎴愶級
+    }
+
+    public enum PanelMode
+    {
+        Normal, // 姝e父妯″紡
+        DraggingNode, // 鎷栨嫿鑺傜偣
+        CreatingConnection, // 鍒涘缓杩炵嚎
+        Run // 杩愯妯″紡
+    }
+
+    public enum EdgePosition
+    {
+        None,
+        Top,
+        Bottom,
+        Left,
+        Right,
+        TopLeft,
+        TopRight,
+        BottomLeft,
+        BottomRight
+    }
+}
diff --git a/LB_VisionFlowNode/FlowNode.cs b/LB_VisionFlowNode/FlowNode.cs
new file mode 100644
index 0000000..f4007fa
--- /dev/null
+++ b/LB_VisionFlowNode/FlowNode.cs
@@ -0,0 +1,239 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionFlowNode
+{
+    [Serializable]
+    public class FlowNode
+    {
+        // 鐢ㄤ簬鏍囪瘑鑺傜偣鐨勫敮涓�ID
+        [JsonProperty]
+        public string Id { get; set; } = Guid.NewGuid().ToString();
+
+        [JsonProperty]
+        public bool Result { get; set; } = true;
+
+        [JsonProperty]
+        public bool Break { get; set; } = false;
+
+        [JsonProperty]
+        public NodeType NodeType { get; set; } = NodeType.Normal;
+
+        [JsonProperty]
+        public string Text { get; set; } = "鍚嶇О";
+
+        [JsonProperty]
+        public string Description { get; set; } = "鎻忚堪";
+
+        [JsonProperty]
+        public string NextNodeId { get; set; }
+
+        [JsonIgnore]
+        public FlowNode NextNode { get; set; } = null;
+
+        #region 鍒嗘敮娴佺▼鐩稿叧
+        /// <summary>
+        /// 澶氬垎鏀拰骞惰鑺傜偣鐨勫垎鏀妭鐐归泦鍚堛�怟ey: 鍒嗘敮鍚嶇О, Value: 鎵�閾炬帴鐨勫垎鏀妭鐐瑰悕绉般��
+        /// </summary>
+        public ConcurrentDictionary<string, string> BranchNodes { get; set; }
+            = new ConcurrentDictionary<string, string>();
+
+        [JsonProperty]
+        public string BranchIndex { get; set; } = "0";
+
+        // 鍒嗘敮鏉′欢锛堝彲閫夛級
+        public Func<bool> BranchCondition { get; set; }
+
+        // 瓒呮椂璁剧疆锛堢敤浜庡苟琛屾墽琛岋級
+        public int TimeoutMilliseconds { get; set; } = 60000;
+        #endregion
+
+        public int X { get; set; } = 0;
+
+        public int Y { get; set; } = 0;
+
+        public int Width { get; set; } = 100;
+
+        public int Height { get; set; } = 40;
+
+        public Point LeftPoint
+        {
+            get { return new Point(X - Width / 2, Y); }
+        }
+
+        public Point RightPoint
+        {
+            get { return new Point(X + Width / 2, Y); }
+        }
+
+        public Point BtmPoint
+        {
+            get { return new Point(X, Y + Height / 2); }
+        }
+
+        public Point TopPoint
+        {
+            get { return new Point(X, Y - Height / 2); }
+        }
+
+        public Rectangle GetBounds()
+        {
+            return new Rectangle(X - Width / 2, Y - Height / 2, Width, Height);
+        }
+
+        public Color GetColor()
+        {
+            if (Break)
+                return Color.Gray;
+            return Result ? Color.LightGreen : Color.MediumVioletRed;
+        }
+
+        public List<Point> GetConnectionPoints()
+        {
+            List<Point> points = new List<Point>() { };
+            switch (NodeType)
+            {
+                case NodeType.Begin:
+                    points.Add(BtmPoint);
+                    break;
+                case NodeType.End:
+                    points.Add(TopPoint);
+                    break;
+                case NodeType.Switch:
+                    points.Add(TopPoint);
+                    points.Add(LeftPoint);
+                    points.Add(RightPoint);
+                    break;
+                case NodeType.MultiBranch:
+                case NodeType.Parallel:
+                    points.Add(TopPoint);
+                    int branchCount = BranchNodes.Count;
+                    if (branchCount == 0)
+                        break;
+                    int spacing = Width / (branchCount + 1);
+                    for (int i = 1; i <= branchCount; i++)
+                        points.Add(new Point(X - Width / 2 + i * spacing, Y + Height / 2));
+                    break;
+                case NodeType.Join:
+                case NodeType.Normal:
+                    points.Add(TopPoint);
+                    points.Add(BtmPoint);
+                    break;
+                default: break;
+            }
+            return points;
+        }
+
+        public Point GetBranchPoints(int index)
+        {
+            List<Point> points = new List<Point>() { };
+            switch (NodeType)
+            {
+                case NodeType.Begin:
+                    points.Add(BtmPoint);
+                    break;
+                case NodeType.End:
+                    break;
+                case NodeType.Switch:
+                    points.Add(LeftPoint);
+                    points.Add(RightPoint);
+                    break;
+                case NodeType.MultiBranch:
+                case NodeType.Parallel:
+                    int branchCount = BranchNodes.Count;
+                    if (branchCount == 0)
+                        break;
+                    int spacing = Width / (branchCount + 1);
+                    for (int i = 1; i <= branchCount; i++)
+                        points.Add(new Point(X - Width / 2 + i * spacing, Y + Height / 2));
+                    break;
+                case NodeType.Join:
+                case NodeType.Normal:
+                    points.Add(BtmPoint);
+                    break;
+                default: break;
+            }
+
+            if (index >= 0 && index < points.Count)
+                return points[index];
+            else
+                return new Point(-1, -1);
+        }
+
+        public List<Point> GetBranchPoints()
+        {
+            List<Point> points = new List<Point>() { };
+            switch (NodeType)
+            {
+                case NodeType.Begin:
+                    points.Add(BtmPoint);
+                    break;
+                case NodeType.End:
+                    break;
+                case NodeType.Switch:
+                    points.Add(LeftPoint);
+                    points.Add(RightPoint);
+                    break;
+                case NodeType.MultiBranch:
+                case NodeType.Parallel:
+                    int branchCount = BranchNodes.Count;
+                    if (branchCount == 0)
+                        break;
+                    int spacing = Width / (branchCount + 1);
+                    for (int i = 1; i <= branchCount; i++)
+                        points.Add(new Point(X - Width / 2 + i * spacing, Y + Height / 2));
+                    break;
+                case NodeType.Join:
+                case NodeType.Normal:
+                    points.Add(BtmPoint);
+                    break;
+                default: break;
+            }
+            return points;
+        }
+
+        public FlowNode() { }
+
+        public FlowNode(NodeType nodeType, Point location, string text, string description, int width = 100, int height = 40)
+        {
+            NodeType = nodeType;
+            X = location.X;
+            Y = location.Y;
+            Width = width;
+            Height = height;
+            Text = text;
+            Description = description;
+        }
+
+        public static Point[] GetDiamondPoints(Rectangle bounds)
+        {
+            int centerX = bounds.X + bounds.Width / 2;
+            int centerY = bounds.Y + bounds.Height / 2;
+
+            return new Point[]{ new Point(centerX, bounds.Y), new Point(bounds.Right, centerY)
+                , new Point(centerX, bounds.Bottom), new Point(bounds.X, centerY)};
+        }
+    }
+
+    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
+    public class NodeAttribute : Attribute
+    {
+        public string Name { get; }
+        public string Category { get; }
+        public string Group { get; }
+        public string Description { get; }
+
+        public NodeAttribute(string name, string category, string group, string description)
+        {
+            Name = name;
+            Category = category;
+            Group = group;
+            Description = description;
+        }
+    }
+}
diff --git a/LB_VisionFlowNode/FlowNodeEditor.Designer.cs b/LB_VisionFlowNode/FlowNodeEditor.Designer.cs
new file mode 100644
index 0000000..96781ea
--- /dev/null
+++ b/LB_VisionFlowNode/FlowNodeEditor.Designer.cs
@@ -0,0 +1,133 @@
+锘縩amespace LB_VisionFlowNode
+{
+    partial class FlowNodeEditor
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FlowNodeEditor));
+            tsp_Top = new ToolStrip();
+            btn_Run = new ToolStripButton();
+            btn_Clear = new ToolStripButton();
+            btn_Save = new ToolStripButton();
+            btn_Load = new ToolStripButton();
+            pnl_FlowNodeEditor = new Panel();
+            tsp_Top.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tsp_Top
+            // 
+            tsp_Top.BackColor = Color.FromArgb(39, 51, 63);
+            tsp_Top.Items.AddRange(new ToolStripItem[] { btn_Run, btn_Clear, btn_Save, btn_Load });
+            tsp_Top.Location = new Point(0, 0);
+            tsp_Top.Name = "tsp_Top";
+            tsp_Top.Size = new Size(460, 28);
+            tsp_Top.TabIndex = 14;
+            tsp_Top.Text = "toolStrip1";
+            // 
+            // btn_Run
+            // 
+            btn_Run.DisplayStyle = ToolStripItemDisplayStyle.Text;
+            btn_Run.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            btn_Run.ForeColor = SystemColors.Control;
+            btn_Run.Image = (Image)resources.GetObject("btn_Run.Image");
+            btn_Run.ImageTransparentColor = Color.Magenta;
+            btn_Run.Name = "btn_Run";
+            btn_Run.Size = new Size(78, 25);
+            btn_Run.Text = "杩愯娴嬭瘯";
+            btn_Run.Click += btn_Run_Click;
+            // 
+            // btn_Clear
+            // 
+            btn_Clear.DisplayStyle = ToolStripItemDisplayStyle.Text;
+            btn_Clear.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            btn_Clear.ForeColor = SystemColors.Control;
+            btn_Clear.Image = (Image)resources.GetObject("btn_Clear.Image");
+            btn_Clear.ImageTransparentColor = Color.Magenta;
+            btn_Clear.Name = "btn_Clear";
+            btn_Clear.Size = new Size(78, 25);
+            btn_Clear.Text = "娓呯┖鑺傜偣";
+            btn_Clear.Click += btn_Clear_Click;
+            // 
+            // btn_Save
+            // 
+            btn_Save.DisplayStyle = ToolStripItemDisplayStyle.Text;
+            btn_Save.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            btn_Save.ForeColor = SystemColors.Control;
+            btn_Save.Image = (Image)resources.GetObject("btn_Save.Image");
+            btn_Save.ImageTransparentColor = Color.Magenta;
+            btn_Save.Name = "btn_Save";
+            btn_Save.Size = new Size(110, 25);
+            btn_Save.Text = "淇濆瓨鎵�鏈夎妭鐐�";
+            btn_Save.Click += btn_Save_Click;
+            // 
+            // btn_Load
+            // 
+            btn_Load.DisplayStyle = ToolStripItemDisplayStyle.Text;
+            btn_Load.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            btn_Load.ForeColor = SystemColors.Control;
+            btn_Load.Image = (Image)resources.GetObject("btn_Load.Image");
+            btn_Load.ImageTransparentColor = Color.Magenta;
+            btn_Load.Name = "btn_Load";
+            btn_Load.Size = new Size(110, 25);
+            btn_Load.Text = "鍔犺浇鎵�鏈夎妭鐐�";
+            btn_Load.Click += btn_Load_Click;
+            // 
+            // pnl_FlowNodeEditor
+            // 
+            pnl_FlowNodeEditor.AutoScroll = true;
+            pnl_FlowNodeEditor.BackColor = Color.FromArgb(39, 51, 63);
+            pnl_FlowNodeEditor.Dock = DockStyle.Fill;
+            pnl_FlowNodeEditor.Location = new Point(0, 28);
+            pnl_FlowNodeEditor.MinimumSize = new Size(261, 61);
+            pnl_FlowNodeEditor.Name = "pnl_FlowNodeEditor";
+            pnl_FlowNodeEditor.Size = new Size(460, 301);
+            pnl_FlowNodeEditor.TabIndex = 15;
+            // 
+            // FlowNodeEditor
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(pnl_FlowNodeEditor);
+            Controls.Add(tsp_Top);
+            Name = "FlowNodeEditor";
+            Size = new Size(460, 329);
+            tsp_Top.ResumeLayout(false);
+            tsp_Top.PerformLayout();
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+        private FlowPanel pnl_Main;
+        private ToolStrip tsp_Top;
+        private ToolStripButton btn_Run;
+        private ToolStripButton btn_Clear;
+        private ToolStripButton btn_Save;
+        private ToolStripButton btn_Load;
+        private Panel pnl_FlowNodeEditor;
+    }
+}
diff --git a/LB_VisionFlowNode/FlowNodeEditor.cs b/LB_VisionFlowNode/FlowNodeEditor.cs
new file mode 100644
index 0000000..21cd083
--- /dev/null
+++ b/LB_VisionFlowNode/FlowNodeEditor.cs
@@ -0,0 +1,71 @@
+锘縩amespace LB_VisionFlowNode
+{
+    public partial class FlowNodeEditor : UserControl
+    {
+        public FlowNodeEditor()
+        {
+            InitializeComponent();
+        }
+
+        private void btn_Run_Click(object sender, EventArgs e)
+        {
+            pnl_Main.Run(out _);
+        }
+
+        private void btn_Clear_Click(object sender, EventArgs e)
+        {
+            pnl_Main.ClearNodes();
+        }
+
+        private void btn_Load_Click(object sender, EventArgs e)
+        {
+            using (OpenFileDialog openFileDialog = new OpenFileDialog())
+            {
+                // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+                openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+                                                    // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+                openFileDialog.Filter = "Ini Files (*.json)|*.json|All Files (*.*)|*.*";
+                // 鏄剧ず鏂囦欢瀵硅瘽妗�
+                DialogResult result = openFileDialog.ShowDialog();
+
+                // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+                if (result == DialogResult.OK)
+                {
+                    // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                    string[] selectedFiles = openFileDialog.FileNames;
+                    if (selectedFiles.Length > 0)
+                        pnl_Main.Load(selectedFiles[0]);
+                }
+            }
+        }
+
+        private void btn_Save_Click(object sender, EventArgs e)
+        {
+            // 鍒涘缓 SaveFileDialog 瀹炰緥
+            using (SaveFileDialog saveFileDialog = new SaveFileDialog())
+            {
+                // 璁剧疆瀵硅瘽妗嗘爣棰�
+                saveFileDialog.Title = "淇濆瓨鏂囦欢";
+
+                // 璁剧疆榛樿璺緞
+                saveFileDialog.InitialDirectory = Application.StartupPath;
+
+                // 璁剧疆鏂囦欢绫诲瀷杩囨护鍣�
+                saveFileDialog.Filter = "鏂囨湰鏂囦欢 (*.json)|*.json|鎵�鏈夋枃浠� (*.*)|*.*";
+
+                // 璁剧疆榛樿鏂囦欢鍚�
+                saveFileDialog.FileName = "panel.json";
+
+                // 鏄剧ず瀵硅瘽妗嗗苟妫�鏌ョ敤鎴锋槸鍚︾偣鍑讳簡淇濆瓨鎸夐挳
+                if (saveFileDialog.ShowDialog() == DialogResult.OK)
+                {
+                    // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠惰矾寰�
+                    string fullPath = saveFileDialog.FileName;
+                    pnl_Main.Save(fullPath);
+                }
+            }
+
+
+        }
+    }
+}
diff --git a/LB_VisionFlowNode/FlowNodeEditor.resx b/LB_VisionFlowNode/FlowNodeEditor.resx
new file mode 100644
index 0000000..a6f16d2
--- /dev/null
+++ b/LB_VisionFlowNode/FlowNodeEditor.resx
@@ -0,0 +1,160 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="tsp_Top.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>185, 17</value>
+  </metadata>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="btn_Run.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACNSURBVDhPY/j27dt/SjADiHByciILoxjw4f1HkjDJBjy/
+        dfL/iW5TME2WASe6Tf4fqpUCG0KWARAXmBB2waSzr/4vuPQawwB0jNWArH0v/ksvfATGhAzBMABZMzGG
+        oBig07ASQzM2Q0Ds1hMvMQ1A14SOQRpBGMYHuZYkA7BhkKspMgCEqWcAJZiBUgAABzX8nOIkzeMAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+  <data name="btn_Clear.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACNSURBVDhPY/j27dt/SjADiHByciILoxjw4f1HkjDJBjy/
+        dfL/iW5TME2WASe6Tf4fqpUCG0KWARAXmBB2waSzr/4vuPQawwB0jNWArH0v/ksvfATGhAzBMABZMzGG
+        oBig07ASQzM2Q0Ds1hMvMQ1A14SOQRpBGMYHuZYkA7BhkKspMgCEqWcAJZiBUgAABzX8nOIkzeMAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+  <data name="btn_Save.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACNSURBVDhPY/j27dt/SjADiHByciILoxjw4f1HkjDJBjy/
+        dfL/iW5TME2WASe6Tf4fqpUCG0KWARAXmBB2waSzr/4vuPQawwB0jNWArH0v/ksvfATGhAzBMABZMzGG
+        oBig07ASQzM2Q0Ds1hMvMQ1A14SOQRpBGMYHuZYkA7BhkKspMgCEqWcAJZiBUgAABzX8nOIkzeMAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+  <data name="btn_Load.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACNSURBVDhPY/j27dt/SjADiHByciILoxjw4f1HkjDJBjy/
+        dfL/iW5TME2WASe6Tf4fqpUCG0KWARAXmBB2waSzr/4vuPQawwB0jNWArH0v/ksvfATGhAzBMABZMzGG
+        oBig07ASQzM2Q0Ds1hMvMQ1A14SOQRpBGMYHuZYkA7BhkKspMgCEqWcAJZiBUgAABzX8nOIkzeMAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionFlowNode/FlowPanel.cs b/LB_VisionFlowNode/FlowPanel.cs
new file mode 100644
index 0000000..eb8c279
--- /dev/null
+++ b/LB_VisionFlowNode/FlowPanel.cs
@@ -0,0 +1,1463 @@
+锘縰sing System.Collections.Concurrent;
+using System.Diagnostics;
+using System.Xml.Linq;
+
+namespace LB_VisionFlowNode
+{
+    public class FlowPanel : Panel, IMessageFilter
+    {
+        #region 绉佹湁鍙橀噺
+        private PanelMode PanelMode = PanelMode.Normal;
+
+        private Point mousePosition;
+        private Point mouseRightStartLocation;
+        private Point mouseLeftStartLocation;
+        private Point dragStartPoint;
+
+        private int connectStartNodeBranchIndex = -1;
+        private FlowNode connectStartNode = null;
+
+        private FlowNode selectedNode = null;
+        private FlowConnection selectedConnection = null;
+        private int selectedBranchIndex = -1;
+
+        /// <summary>
+        /// nodes鐨勭储寮曚负鑺傜偣鍚嶇О
+        /// </summary>
+        private ConcurrentDictionary<string, FlowNode> nodes
+            = new ConcurrentDictionary<string, FlowNode>();
+
+        public ConcurrentDictionary<string, FlowNode> GetAllNodes() { return nodes; }
+
+        /// <summary>
+        /// connections鐨勭储寮曚负璧风偣鑺傜偣鍚嶇О(鍒嗘敮鑺傜偣浼氬鍔爗-Branch connectStartNodeBranchIndex})
+        /// </summary>
+        private ConcurrentDictionary<string, FlowConnection> connections
+            = new ConcurrentDictionary<string, FlowConnection>();
+
+        private ContextMenuStrip rContextMenu = null;
+
+        private bool messageFilterInstalled = false;
+
+        #endregion
+
+        #region 澶栭儴璋冪敤浜嬩欢
+        /// <summary>
+        /// 鏂板鑺傜偣(name,class)
+        /// </summary>
+        public Action<string, string> AddNodeAction;
+
+        /// <summary>
+        /// 鏂板鍒嗘敮
+        /// </summary>
+        public Action<string> AddBranchAction;
+
+        /// <summary>
+        /// 閲嶅懡鍚嶈妭鐐�
+        /// </summary>
+        public Action<string, string> RenameNodeAction;
+
+        /// <summary>
+        /// 鍒犻櫎鑺傜偣
+        /// </summary>
+        public Action<string> DeleteNodeAction;
+
+        /// <summary>
+        /// 鍒犻櫎鑺傜偣
+        /// </summary>
+        public Action<string> DeleteBranchAction;
+
+        /// <summary>
+        /// 缂栬緫鑺傜偣
+        /// </summary>
+        public Action<string> EditNodeAction;
+
+        /// <summary>
+        /// 杈撳叆杈撳嚭鑺傜偣
+        /// </summary>
+        public Action<string> InAndOutNodeAction;
+        #endregion
+
+        public FlowPanel()
+        {
+            // 鍚敤鍙岀紦鍐插拰鑷畾涔夌粯鍒�
+            this.SetStyle(ControlStyles.AllPaintingInWmPaint |
+              ControlStyles.UserPaint |
+              ControlStyles.DoubleBuffer |
+              ControlStyles.ResizeRedraw, true);
+
+            this.UpdateStyles();
+
+            this.BackColor = Color.White;
+            this.Font = new Font("瀹嬩綋", 9F);
+            this.Paint += OnPaint;
+            this.MouseDoubleClick += OnMouseDoubleClick;
+            this.MouseDown += OnMouseDown;
+            this.MouseMove += OnMouseMove;
+            this.MouseUp += OnMouseUp;
+
+            this.GotFocus += (s, e) => InstallMessageFilter();
+            this.LostFocus += (s, e) => RemoveMessageFilter();
+            this.MouseDown += (s, e) => this.Focus();
+
+            rContextMenu = new ContextMenuStrip();
+            this.ContextMenuStrip = rContextMenu;
+
+            this.AutoScroll = false; // 绂佺敤鑷姩婊氬姩
+        }
+
+        public readonly IFlowContext Context = null;
+
+        public FlowPanel(IFlowContext context) : this()
+        {
+            this.Context = context;
+        }
+
+        // 瀹氫箟濮旀墭绫诲瀷
+        private delegate void NodeHandler(FlowNode node);
+
+        // 浣跨敤濮旀墭瀛楀吀
+        private Dictionary<string, NodeHandler> _nodeHandlers = new Dictionary<string, NodeHandler>();
+
+        private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
+
+        string NodesMsg = string.Empty;
+
+        private async Task<bool> ExecuteFlowAsync(FlowNode startNode, ExecutionContext ExecutionContext)
+        {
+            string strRunTime = $"杩愯鏃堕棿璁板綍\r\n";
+            // 鍋囪 nameWidth 鏄姩鎬佽绠楃殑鍒楀锛堟瘮濡� 20锛�
+            int nameWidth = 30; //姝ラ鍚嶇О灏忎簬20涓垪瀹�
+            var formatString = "{0,-" + nameWidth + "}{1,-10}";
+            try
+            {
+                var currentNode = startNode;
+                string nextNodeName = string.Empty;
+                DateTime StartTime = DateTime.Now;
+                while (currentNode != null && !_cancellationTokenSource.IsCancellationRequested)
+                {
+
+                    await ExecuteNodeAsync(currentNode, ExecutionContext);
+
+                    // 闃叉姝诲惊鐜紝杩愯鏃堕棿瓒呰繃60绉掑垯寮哄埗缁堟
+                    if ((DateTime.Now - StartTime).TotalSeconds > 1000000000)
+                    {
+                        _cancellationTokenSource.Cancel();
+                        NodesMsg = $"鎵ц鎵�鏈夎妭鐐硅秴杩�10s";
+                        return false;
+                    }
+
+                    // 鎵ц瀹屽綋鍓嶈妭鐐瑰悗浜ゆ崲鍒颁笅涓�涓妭鐐硅繍琛�
+                    switch (currentNode.NodeType)
+                    {
+                        case NodeType.End:
+                            return GetResult(ExecutionContext);
+                        case NodeType.Switch:
+                        case NodeType.MultiBranch:
+                            if (currentNode.BranchNodes.ContainsKey($"{currentNode.Text}-Branch{currentNode.BranchIndex}"))
+                            {
+                                nextNodeName = currentNode.BranchNodes[$"{currentNode.Text}-Branch{currentNode.BranchIndex}"];
+
+                                if (nextNodeName == null || !nodes.ContainsKey(nextNodeName))
+                                {
+                                    return GetResult(ExecutionContext);
+                                }
+                                else
+                                    currentNode = nodes[nextNodeName];
+                            }
+                            else
+                            {
+                                return GetResult(ExecutionContext);
+                            }
+                            break;
+                        case NodeType.Parallel:
+                            // 骞惰鎵ц澶氬垎鏀�(鐩磋嚦褰撳墠branch閮借蛋鍒颁簡Join姹囪仛鍒嗘敮鑺傜偣锛堢瓑寰呮墍鏈夊垎鏀畬鎴愶級)
+                            currentNode = await ExecuteParallelBranches(currentNode, ExecutionContext);
+                            break;
+                        case NodeType.Join:
+                        default:
+                            if (currentNode.BranchNodes.ContainsKey($"{currentNode.Text}-Branch0"))
+                                nextNodeName = currentNode.BranchNodes[$"{currentNode.Text}-Branch0"];
+                            else
+                                return GetResult(ExecutionContext);
+
+                            if (nextNodeName == null || !nodes.ContainsKey(nextNodeName))
+                                return GetResult(ExecutionContext);
+                            else
+                                currentNode = nodes[nextNodeName];
+                            break;
+                    }
+                }
+
+                return GetResult(ExecutionContext);
+            }
+            catch (Exception ex) { NodesMsg = $"鎵ц娴佺▼鍙戠敓鎰忓,{ex.Message}銆恵ex.StackTrace}銆�"; return false; }
+        }
+
+        private async Task<FlowNode> ExecuteParallelBranches(FlowNode ParallelNode, ExecutionContext ExecutionContext)
+        {
+            try
+            {
+                var currentNode = ParallelNode;
+                string nextNodeName = string.Empty;
+                DateTime StartTime = DateTime.Now;
+                while (currentNode != null && !_cancellationTokenSource.IsCancellationRequested)
+                {
+                    // 闃叉姝诲惊鐜紝杩愯鏃堕棿瓒呰繃10绉掑垯寮哄埗缁堟
+                    if ((DateTime.Now - StartTime).TotalSeconds > 10)
+                    {
+                        _cancellationTokenSource.Cancel();
+                        NodesMsg = $"{currentNode.Text},骞惰寮�濮嬭繍琛岃秴杩�10s";
+                        return null;
+                    }
+
+                    // 鎵ц瀹屽綋鍓嶈妭鐐瑰悗浜ゆ崲鍒颁笅涓�涓妭鐐硅繍琛�
+                    switch (currentNode.NodeType)
+                    {
+                        case NodeType.End:
+                            return null;
+                        case NodeType.Switch:
+                        case NodeType.MultiBranch:
+                            await ExecuteNodeAsync(currentNode, ExecutionContext);
+                            if (currentNode.BranchNodes.ContainsKey($"{currentNode.Text}-Branch{currentNode.BranchIndex}"))
+                            {
+                                nextNodeName = currentNode.BranchNodes[$"{currentNode.Text}-Branch{currentNode.BranchIndex}"];
+
+                                if (nextNodeName == null || !nodes.ContainsKey(nextNodeName))
+                                    return null;
+                                else
+                                    currentNode = nodes[nextNodeName];
+                            }
+                            else
+                                return null;
+                            break;
+                        case NodeType.Parallel:
+                            // 骞惰鎵ц澶氬垎鏀�(鐩磋嚦褰撳墠branch閮借蛋鍒颁簡Join姹囪仛鍒嗘敮鑺傜偣锛堢瓑寰呮墍鏈夊垎鏀畬鎴愶級)
+                            var parallelTasks = new List<Task<FlowNode>>();
+
+                            foreach (var branch in currentNode.BranchNodes)
+                            {
+                                if (!nodes.ContainsKey(branch.Value))
+                                    return null;
+                                else
+                                {
+                                    parallelTasks.Add(Task.Run(async () =>
+                                    {
+                                        return await ExecuteParallelBranches(nodes[branch.Value], ExecutionContext); ;
+                                    }));
+                                }
+                            }
+
+                            // 绛夊緟鎵�鏈夊苟琛屼换鍔″畬鎴愭垨瓒呮椂
+                            var timeoutTask = Task.Delay(currentNode.TimeoutMilliseconds, _cancellationTokenSource.Token);
+                            var completedTask = await Task.WhenAny(Task.WhenAll(parallelTasks), timeoutTask);
+
+                            if (completedTask == timeoutTask)
+                            {
+                                NodesMsg = $"骞惰鎵ц瓒呮椂:{currentNode.Text}";
+                                return null;
+                            }
+
+                            var JoinNodes = await Task.WhenAll(parallelTasks);
+
+                            // 鎵惧埌JoinNodes绗竴涓笉涓簄ull鐨勮妭鐐逛綔涓轰笅涓�涓妭鐐�
+                            return JoinNodes.FirstOrDefault(node => node != null);
+                        case NodeType.Join:
+                            await ExecuteNodeAsync(currentNode, ExecutionContext);
+                            nextNodeName = currentNode.BranchNodes[$"{currentNode.Text}-Branch0"];
+
+                            if (nextNodeName == null || !nodes.ContainsKey(nextNodeName))
+                                return null;
+                            else
+                                return nodes[nextNodeName];
+                        default:
+                            await ExecuteNodeAsync(currentNode, ExecutionContext);
+                            nextNodeName = currentNode.BranchNodes[$"{currentNode.Text}-Branch0"];
+
+                            if (nextNodeName == null || !nodes.ContainsKey(nextNodeName))
+                                return null;
+                            else
+                                currentNode = nodes[nextNodeName];
+                            break;
+                    }
+                }
+
+                return null;
+            }
+            catch { return null; }
+        }
+
+        private bool GetResult(ExecutionContext ExecutionContext)
+        {
+            if (ExecutionContext.BranchResults.Values.Contains(false))
+                return false;
+            else
+                return true;
+        }
+
+        private async Task ExecuteNodeAsync(FlowNode currentNode, ExecutionContext context)
+        {
+            if (currentNode == null) return;
+
+            // 鎵ц褰撳墠鑺傜偣
+            context.CurrentconnectStartNodeBranchIndex = currentNode.BranchIndex;
+            context.CurrentBranchName = $"{currentNode.Text}-Branch{currentNode.BranchIndex}";
+            bool result = Context.ExecuteNode(currentNode);
+#if DEBUG
+            Debug.WriteLine($"鎵ц鑺傜偣[{currentNode.Text}],缁撴灉涓簕result}");
+#endif
+            context.BranchResults.TryAdd(context.CurrentBranchName, currentNode.Result);
+            currentNode.Result = result;
+        }
+
+        public bool Run(out string msg)
+        {
+            NodesMsg = string.Empty;
+            if (nodes == null || nodes.Count <= 0 || Context == null)
+            {
+                msg = "鏈厤缃妭鐐规垨涓婁笅鏂囷紝鏃犳硶杩愯";
+                return false;
+            }
+
+            var beginNodes = nodes.AsParallel()
+                     .Where(n => n.Value.Text == "寮�濮�")
+                     .ToList();
+
+            if (beginNodes.Count > 0)
+            {
+                _cancellationTokenSource.Cancel();
+                _cancellationTokenSource = new CancellationTokenSource();
+                bool result = Task.Run(() =>
+                    ExecuteFlowAsync(beginNodes[0].Value, new ExecutionContext())
+                ).Result;
+
+                if (result)
+                    msg = string.Empty;
+                else
+                    msg = NodesMsg;
+                return result;
+            }
+
+            msg = "鏈壘鍒板紑濮嬭妭鐐�";
+            return false;
+        }
+
+        private void AddNode(FlowNode node)
+        {
+            // 鍚嶇О閲嶅鍒欐坊鍔�(鍓湰)
+            string nodeName = node.Text;
+
+            while (nodes.Any(n => n.Value.Text == nodeName))
+            {
+                nodeName += "(Copy)";
+            }
+
+            node.Text = nodeName;
+            if (this.nodes.TryAdd(nodeName, node))
+                AddNodeAction?.Invoke(nodeName, node.Description);
+
+            this.Invalidate();
+        }
+
+        public void ClearNodes()
+        {
+            this.nodes.Clear();
+            this.connections.Clear();
+            this.Invalidate();
+        }
+
+        string filePath = string.Empty;
+
+        public bool Load(string filePath)
+        {
+            try
+            {
+                PanelMode = PanelMode.Run;
+
+                nodes.Clear();
+                connections.Clear();
+
+                string json = File.ReadAllText(filePath);
+                // 鍙嶅簭鍒楀寲
+                var (deserializedNodes, deserializedConnections) = FlowSerializer.Deserialize(json);
+                nodes = deserializedNodes;
+                connections = deserializedConnections;
+
+                PanelMode = PanelMode.Normal;
+                this.filePath = filePath;
+                return true;
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show($"鍔犺浇澶辫触: {ex.Message}", "寮傚父");
+                return false;
+            }
+        }
+
+        public bool Save(string filePath)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(filePath))
+                    return true;
+
+                PanelMode = PanelMode.Run;
+
+                string json = FlowSerializer.Serialize(nodes, connections);
+                File.WriteAllText(filePath, json);
+
+                PanelMode = PanelMode.Normal;
+                return true;
+            }
+            catch { return false; }
+        }
+
+        #region 绉佹湁鍑芥暟
+
+        #region 妫�娴嬬偣鍑绘槸鍚﹀湪鑺傜偣涓�
+        private FlowNode GetNodeAt(Point location)
+        {
+            foreach (var node in nodes)
+            {
+                if (node.Value.GetBounds().Contains(location))
+                    return node.Value;
+            }
+            return null;
+        }
+        #endregion
+
+        #region 妫�娴嬬偣鍑绘槸鍚﹀湪杩炴帴绾夸笂
+        public FlowConnection GetConnectionAt(Point mousePoint)
+        {
+            foreach (var connection in connections)
+            {
+                if (IsPointNearConnection(mousePoint, connection.Value))
+                    return connection.Value;
+            }
+            return null;
+        }
+
+        private bool IsPointNearConnection(Point point, FlowConnection connection, int tolerance = 3)
+        {
+            if (connection == null || connection.StartNode == null || connection.EndNode == null)
+                return false;
+
+            Point[] points = GetConnectionAllPoints(connection);
+
+            // 妫�鏌ユ瘡涓嚎娈�
+            for (int i = 0; i < points.Length - 1; i++)
+            {
+                if (IsPointNearLine(point, points[i], points[i + 1]))
+                    return true;
+            }
+            return false;
+        }
+
+        // 鍒ゆ柇鐐规槸鍚﹂潬杩戠嚎娈�
+        private bool IsPointNearLine(Point point, Point lineStart, Point lineEnd, int tolerance = 3)
+        {
+            // 璁$畻鐐瑰埌绾挎鐨勮窛绂�
+            double distance = PointToLineDistance(point, lineStart, lineEnd);
+            return distance <= tolerance;
+        }
+
+        // 璁$畻鐐瑰埌绾挎鐨勮窛绂�
+        private double PointToLineDistance(Point point, Point lineStart, Point lineEnd)
+        {
+            double lineLengthSquared = Math.Pow(lineEnd.X - lineStart.X, 2) + Math.Pow(lineEnd.Y - lineStart.Y, 2);
+
+            if (lineLengthSquared == 0) // 绾挎闀垮害涓�0
+                return Distance(point, lineStart);
+
+            // 璁$畻鎶曞奖姣斾緥
+            double t = Math.Max(0, Math.Min(1,
+                ((point.X - lineStart.X) * (lineEnd.X - lineStart.X) +
+                 (point.Y - lineStart.Y) * (lineEnd.Y - lineStart.Y)) / lineLengthSquared));
+
+            // 璁$畻鎶曞奖鐐�
+            Point projection = new Point(
+                (int)(lineStart.X + t * (lineEnd.X - lineStart.X)),
+                (int)(lineStart.Y + t * (lineEnd.Y - lineStart.Y))
+            );
+
+            // 杩斿洖鐐瑰埌鎶曞奖鐐圭殑璺濈
+            return Distance(point, projection);
+        }
+        #endregion
+
+        #region 妫�娴嬬偣鍑绘槸鍚﹀湪鍒嗘敮涓�
+
+        private int GetBranchAt(Point location)
+        {
+            foreach (var connection in connections)
+            {
+                if (IsPointNearConnection(location, connection.Value))
+                    return connection.Value.BranchIndex;
+            }
+            return -1;
+        }
+
+        private FlowNode OnNodeBranch(Point location, out int index)
+        {
+            index = -1;
+            foreach (var node in nodes.Values)
+            {
+                index = GetPointIndexNearLocation(location, node.GetBranchPoints());
+                if (index != -1)
+                    return node;
+            }
+            return null;
+        }
+
+        /// <summary>
+        /// 妫�娴嬮紶鏍囦綅缃槸鍚﹀湪鐐瑰垪琛ㄤ腑鐨勪换鎰忕偣闄勮繎锛屽苟杩斿洖璇ョ偣鐨勭储寮�
+        /// </summary>
+        /// <param name="mousePoint">榧犳爣浣嶇疆</param>
+        /// <param name="points">鐐瑰垪琛�</param>
+        /// <param name="tolerance">瀹瑰樊鑼冨洿锛堝儚绱狅級</param>
+        /// <returns>鎵惧埌鐨勭偣鐨勭储寮曪紝濡傛灉娌℃壘鍒拌繑鍥�-1</returns>
+        public int GetPointIndexNearLocation(Point mousePoint, List<Point> points, float tolerance = 8f)
+        {
+            if (points == null || points.Count == 0)
+                return -1;
+
+            for (int i = 0; i < points.Count; i++)
+            {
+                if (IsPointNearPoint(mousePoint, points[i], tolerance))
+                    return i;
+            }
+
+            return -1;
+        }
+
+        /// <summary>
+        /// 鍒ゆ柇涓や釜鐐规槸鍚﹀湪瀹瑰樊鑼冨洿鍐呮帴杩�
+        /// </summary>
+        private bool IsPointNearPoint(Point point1, Point point2, float tolerance)
+        {
+            float distance = Distance(point1, point2);
+            return distance <= tolerance;
+        }
+
+        /// <summary>
+        /// 璁$畻涓ょ偣涔嬮棿鐨勮窛绂�
+        /// </summary>
+        private float Distance(Point p1, Point p2)
+        {
+            return (float)Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2));
+        }
+        #endregion
+
+        #region 缁樺埗鐩稿叧
+        /// <summary>
+        /// 缁樺埗鑺傜偣
+        /// </summary>
+        /// <param name="g"></param>
+        /// <param name="node"></param>
+        private void DrawNode(Graphics g, FlowNode node)
+        {
+            // 缁樺埗鑺傜偣鑳屾櫙
+            Color background = node.GetColor();
+            using (Brush brush = new SolidBrush(background))
+            {
+                switch (node.NodeType)
+                {
+                    case NodeType.Switch:
+                    case NodeType.MultiBranch:
+                        g.FillPolygon(brush, FlowNode.GetDiamondPoints(node.GetBounds()));
+                        break;
+                    case NodeType.Begin:
+                    case NodeType.End:
+                    case NodeType.Parallel:
+                    case NodeType.Join:
+                        g.FillEllipse(brush, node.GetBounds());
+                        break;
+                    default:
+                        g.FillRectangle(brush, node.GetBounds());
+                        break;
+                }
+            }
+
+聽 聽 聽 聽 聽 聽聽// 缁樺埗杈规
+            if (node == selectedNode)
+            {
+                Color borderColor = Color.Coral;
+                int borderWidth = 3;
+
+                using (Pen pen = new Pen(borderColor, borderWidth))
+                {
+                    switch (node.NodeType)
+                    {
+                        case NodeType.Switch:
+                        case NodeType.MultiBranch:
+                            g.DrawPolygon(pen, FlowNode.GetDiamondPoints(node.GetBounds()));
+                            break;
+                        case NodeType.Begin:
+                        case NodeType.End:
+                        case NodeType.Parallel:
+                        case NodeType.Join:
+                            g.DrawEllipse(pen, node.GetBounds());
+                            break;
+                        default:
+                            g.DrawRectangle(pen, node.GetBounds());
+                            break;
+                    }
+                }
+            }
+
+聽 聽 聽 聽 聽 聽聽// 缁樺埗鏂囨湰
+聽 聽 聽 聽 聽 聽聽using (StringFormat sf = new StringFormat())
+            {
+                sf.Alignment = StringAlignment.Center;
+                sf.LineAlignment = StringAlignment.Center;
+                using (Brush textBrush = new SolidBrush(Color.Black))
+                {
+                    g.DrawString(node.Text, this.Font, textBrush, node.GetBounds(), sf);
+                }
+            }
+
+            // 缁樺埗杩炴帴鐐�
+聽 聽 聽 聽 聽 聽聽using (Brush brush = new SolidBrush(Color.Coral))
+            {
+                foreach (var point in node.GetConnectionPoints())
+                    g.FillEllipse(brush, point.X - 2, point.Y - 2, 4, 4);
+            }
+        }
+
+        /// <summary>
+        /// 缁樺埗杩炴帴绾�
+        /// </summary>
+        /// <param name="g"></param>
+        /// <param name="connection"></param>
+        private void DrawConnection(Graphics g, FlowConnection connection, Pen pen)
+        {
+            if (connection == null || connection.StartNode == null || connection.EndNode == null)
+                return;
+
+            Point[] allPoints = GetConnectionAllPoints(connection);
+
+            if (allPoints.Length > 2)
+            {
+                // 缁樺埗鎶樼嚎
+                g.DrawLines(pen, allPoints);
+                // 鍦ㄦ渶鍚庝竴娈电嚎娈典笂缁樺埗绠ご
+                DrawArrow(g, pen, allPoints[allPoints.Length - 2], allPoints[allPoints.Length - 1]);
+            }
+            else if (allPoints.Length == 2)
+            {
+                // 浠庝笂寰�涓嬬洿鎺ョ粯鍒剁洿绾�
+                g.DrawLine(pen, allPoints[0], allPoints[1]);
+                DrawArrow(g, pen, allPoints[0], allPoints[1]);
+            }
+            return;
+        }
+
+        /// <summary>
+        /// 鑾峰彇杩炴帴绾跨殑鎵�鏈夌偣
+        /// </summary>
+        /// <param name="connection"></param>
+        /// <returns></returns>
+        Point[] GetConnectionAllPoints(FlowConnection connection)
+        {
+            if (connection.StartNode == null || connection.EndNode == null)
+                return new Point[] { };
+
+            Point startPoint = connection.StartNode.BtmPoint;
+            Point endPoint = connection.EndNode.TopPoint;
+
+            switch (connection.StartNode.NodeType)
+            {
+                case NodeType.Switch:
+                    if (connection.BranchIndex == 0)
+                    {
+                        // connectStartNodeBranchIndex涓篠tartNode鐨勫乏杈�
+                        startPoint = connection.StartNode.LeftPoint;
+                        if (endPoint.X > startPoint.X || startPoint.Y > endPoint.Y)
+                        {
+                            return new Point[]
+                            {
+                                startPoint,
+                                new Point(startPoint.X - 10, startPoint.Y),
+                                new Point(startPoint.X - 10, endPoint.Y - 10),
+                                new Point(endPoint.X, endPoint.Y - 10) ,
+                                endPoint
+                            };
+                        }
+                        else
+                        {
+                            return new Point[]
+                            {
+                                startPoint,
+                                new Point(endPoint.X, startPoint.Y),
+                                endPoint
+                            };
+                        }
+                    }
+                    else if (connection.BranchIndex == 1)
+                    {
+                        // connectStartNodeBranchIndex涓篠tartNode鐨勫彸杈�
+                        startPoint = connection.StartNode.RightPoint;
+                        if (endPoint.X < startPoint.X || startPoint.Y > endPoint.Y)
+                        {
+                            return new Point[]
+                            {
+                                startPoint,
+                                new Point(startPoint.X + 10, startPoint.Y),
+                                new Point(startPoint.X + 10, endPoint.Y - 10),
+                                new Point(endPoint.X, endPoint.Y - 10) ,
+                                endPoint
+                            };
+                        }
+                        else
+                        {
+                            return new Point[]
+                            {
+                                startPoint,
+                                new Point(endPoint.X, startPoint.Y),
+                                endPoint
+                            };
+                        }
+                    }
+                    break;
+                case NodeType.MultiBranch:
+                case NodeType.Parallel:
+                    // 澶氬垎鏀妭鐐癸細浣跨敤鍒嗘敮绱㈠紩鑾峰彇杩炴帴鐐�
+                    if (connection.BranchIndex >= 0 && connection.BranchIndex < connection.StartNode.BranchNodes.Count)
+                        return CalculateMultiBranchConnectionPath(
+                            connection.StartNode.GetBranchPoints(connection.BranchIndex)
+                            , endPoint, connection.StartNode, connection.EndNode);
+                    break;
+                default:
+                    startPoint = connection.StartNode.BtmPoint;
+                    return CalculateMultiBranchConnectionPath(startPoint, endPoint, connection.StartNode, connection.EndNode);
+            }
+            return new Point[] { };
+        }
+
+        /// <summary>
+        /// 涓婁笅杩炴帴鐨勮妭鐐硅矾寰勮绠�
+        /// </summary>
+        /// <param name="startPoint"></param>
+        /// <param name="endPoint"></param>
+        /// <param name="connectStartNodeBranchIndex"></param>
+        /// <returns></returns>
+        private Point[] CalculateMultiBranchConnectionPath(Point startPoint, Point endPoint
+            , FlowNode StartNode, FlowNode EndNode)
+        {
+            if (startPoint.Y > endPoint.Y)
+            {
+                if (startPoint.X > endPoint.X)
+                    return new Point[]
+                    {
+                        startPoint,
+                        new Point(startPoint.X, startPoint.Y + 10),
+                        new Point(startPoint.X - StartNode.Width, startPoint.Y + 10),
+                        new Point(startPoint.X - StartNode.Width, endPoint.Y - 10),
+                        new Point(endPoint.X, endPoint.Y - 10),
+                        endPoint
+                    };
+                else
+                    return new Point[]
+                    {
+                        startPoint,
+                        new Point(startPoint.X, startPoint.Y + 10),
+                        new Point(startPoint.X + StartNode.Width, startPoint.Y + 10),
+                        new Point(startPoint.X + StartNode.Width, endPoint.Y - 10),
+                        new Point(endPoint.X, endPoint.Y - 10),
+                        endPoint
+                    };
+            }
+            else if (startPoint.X != endPoint.X)
+            {
+                return new Point[]
+                {
+                    startPoint,
+                    new Point(startPoint.X, (startPoint.Y + endPoint.Y) / 2),
+                    new Point(endPoint.X, (startPoint.Y + endPoint.Y) / 2),
+                    endPoint
+                };
+            }
+            else
+            {
+                return new Point[]
+                {
+                    startPoint,
+                    endPoint
+                };
+            }
+        }
+
+        /// <summary>
+        /// 缁樺埗绠ご
+        /// </summary>
+        /// <param name="g"></param>
+        /// <param name="pen"></param>
+        /// <param name="start"></param>
+        /// <param name="end"></param>
+        private void DrawArrow(Graphics g, Pen pen, Point start, Point end)
+        {
+            // 璁$畻绠ご鏂瑰悜
+            double dx = end.X - start.X;
+            double dy = end.Y - start.Y;
+            double angle = Math.Atan2(dy, dx);
+
+            int arrowLength = 8;  // 澧炲姞绠ご闀垮害
+            double arrowAngle = Math.PI / 6;  // 30搴﹁
+
+            // 璁$畻绠ご鐨勪袱涓鐐�
+            Point arrowPoint1 = new Point(
+                (int)(end.X - arrowLength * Math.Cos(angle - arrowAngle)),
+                (int)(end.Y - arrowLength * Math.Sin(angle - arrowAngle)));
+
+            Point arrowPoint2 = new Point(
+              (int)(end.X - arrowLength * Math.Cos(angle + arrowAngle)),
+              (int)(end.Y - arrowLength * Math.Sin(angle + arrowAngle)));
+
+            // 缁樺埗绠ご
+            using (Pen arrowPen = new Pen(pen.Color, pen.Width))
+            {
+                g.DrawLine(arrowPen, end, arrowPoint1);
+                g.DrawLine(arrowPen, end, arrowPoint2);
+
+                // 鍙�夛細濉厖绠ご锛堝疄蹇冪澶达級
+                Point[] arrowPoints = { end, arrowPoint1, arrowPoint2 };
+                using (Brush arrowBrush = new SolidBrush(pen.Color))
+                {
+                    g.FillPolygon(arrowBrush, arrowPoints);
+                }
+            }
+        }
+        #endregion
+
+        #region 閿洏鐩稿叧
+        protected override void OnKeyDown(KeyEventArgs e)
+        {
+            base.OnKeyDown(e);
+
+            switch (e.KeyCode)
+            {
+                case Keys.Delete:
+                    if (selectedNode != null)
+                    {
+                        RemoveNode(selectedNode);
+                        selectedNode = null;
+                        e.Handled = true;
+                        return;
+                    }
+
+                    if (selectedConnection != null)
+                    {
+                        RemoveConnection(selectedConnection, selectedBranchIndex);
+                        selectedConnection = null;
+                        e.Handled = true;
+                        return;
+                    }
+                    break;
+                case Keys.Escape:
+                    selectedConnection = null;
+                    selectedNode = null;
+                    Invalidate();
+                    e.Handled = true;
+                    return;
+            }
+
+            Save(filePath);
+            return;
+        }
+
+        private void InstallMessageFilter()
+        {
+            if (!messageFilterInstalled)
+            {
+                Application.AddMessageFilter(this);
+                messageFilterInstalled = true;
+            }
+        }
+
+        private void RemoveMessageFilter()
+        {
+            if (messageFilterInstalled)
+            {
+                Application.RemoveMessageFilter(this);
+                messageFilterInstalled = false;
+            }
+        }
+
+        public bool PreFilterMessage(ref Message m)
+        {
+            const int WM_KEYDOWN = 0x100;
+            const int WM_KEYUP = 0x101;
+
+            // 鍙湪Panel鏈夌劍鐐规椂澶勭悊娑堟伅
+            if (this.Focused && (m.Msg == WM_KEYDOWN || m.Msg == WM_KEYUP))
+            {
+                Keys keyData = (Keys)(int)m.WParam;
+
+                if (m.Msg == WM_KEYDOWN)
+                {
+                    var e = new KeyEventArgs(keyData);
+                    OnKeyDown(e);
+                    return e.Handled;
+                }
+            }
+
+            return false;
+        }
+        #endregion
+
+        #region 鍐呴儴浜嬩欢(閲嶇粯/榧犳爣)
+        private void OnPaint(object sender, PaintEventArgs e)
+        {
+            Graphics g = e.Graphics;
+            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
+
+            // 缁樺埗鑺傜偣
+            foreach (var node in nodes.Values)
+                DrawNode(g, node);
+
+            // 缁樺埗杩炴帴绾�
+            foreach (var connection in connections.Values)
+            {
+                if (connection == selectedConnection)
+                    DrawConnection(g, connection, new Pen(Color.Coral, connection.LineWidth));
+                else
+                    DrawConnection(g, connection, new Pen(connection.LineColor, connection.LineWidth));
+            }
+
+            // 缁樺埗涓存椂杩炴帴绾�
+            if (this.PanelMode == PanelMode.CreatingConnection && connectStartNode != null)
+            {
+                using (Pen tempPen = new Pen(Color.Coral, 2))
+                {
+                    tempPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
+
+                    // 铏氭嫙鑺傜偣鐢ㄤ簬缁樺埗杩炴帴绾跨粓鐐�
+                    FlowNode virtualEndNode = new FlowNode(NodeType.Normal
+                                , new Point(mousePosition.X, mousePosition.Y + connectStartNode.Height / 2)
+                                , "virtualNode", "virtualNode", connectStartNode.Width, connectStartNode.Height);
+                    DrawConnection(g, new FlowConnection(connectStartNode, virtualEndNode, connectStartNodeBranchIndex), tempPen);
+                }
+            }
+        }
+
+        private void OnMouseDoubleClick(object sender, MouseEventArgs e)
+        {
+            switch (e.Button)
+            {
+                case MouseButtons.Left:
+                    {
+                        FlowNode clickedNode = GetNodeAt(e.Location);
+
+                        if (clickedNode != null)
+                        {
+                            try
+                            {
+                                EditNodeAction?.Invoke(clickedNode.Text);
+                            }
+                            catch { }
+                        }
+                    }
+                    break;
+                case MouseButtons.Right:
+                default:
+                    break;
+            }
+        }
+
+        private void OnMouseDown(object sender, MouseEventArgs e)
+        {
+            PanelMode = PanelMode.Normal;
+            selectedNode = GetNodeAt(e.Location);
+            selectedBranchIndex = GetBranchAt(e.Location);
+            switch (e.Button)
+            {
+                case MouseButtons.Left:
+                    FlowNode isConnectingNode = OnNodeBranch(e.Location, out connectStartNodeBranchIndex);
+                    selectedConnection = GetConnectionAt(e.Location);
+                    mouseLeftStartLocation = e.Location;
+                    // 鐐瑰嚮鍦ㄨ竟鐣屼笂骞舵湭鐐瑰嚮鍦ㄨ妭鐐逛笂锛岃繘鍏ュ垽鏂槸鍚﹁繘鍏ヨ繛鎺ョ嚎妯″紡
+                    if (isConnectingNode != null && selectedNode == null)
+                    {
+                        // 鍙兘浠庤繛鎺ョ偣寮�濮嬭繛绾� 娌℃湁閫変腑鑺傜偣 閫変腑浜嗚繛鎺ョ偣
+                        if (connectStartNodeBranchIndex < 0)
+                            return;
+
+                        PanelMode = PanelMode.CreatingConnection;
+                        connectStartNode = isConnectingNode;
+                        this.Invalidate();
+                        return;
+                    }
+
+                    // 鐐瑰嚮鍦ㄨ妭鐐逛笂锛岄澶囪繘鍏ユ嫋鍔ㄨ妭鐐规ā寮�
+                    if (selectedNode != null)
+                    {
+                        this.PanelMode = PanelMode.DraggingNode;
+                        dragStartPoint = e.Location;
+                        return;
+                    }
+                    break;
+                case MouseButtons.Right:
+                    rContextMenu.Items.Clear();
+                    mouseRightStartLocation = e.Location;
+                    if (selectedNode == null && Context != null)
+                    {
+                        // 娌℃湁閫変腑鑺傜偣鏃讹紝鏄剧ず鍔ㄦ�佽妭鐐硅彍鍗�
+                        var categorizedItems = Context.GetCategorizedMenuItems(ContextMenuItem_Click);
+
+                        foreach (var category in categorizedItems)
+                        {
+                            // 鍒涘缓绫诲埆涓嬫媺鑿滃崟
+                            var categoryMenu = new ToolStripMenuItem(category.Key);
+
+                            // 娣诲姞璇ョ被鍒殑鎵�鏈夎彍鍗曢」
+                            foreach (var menuItem in category.Value)
+                            {
+                                categoryMenu.DropDownItems.Add(menuItem);
+                            }
+
+                            rContextMenu.Items.Add(categoryMenu);
+                        }
+                    }
+                    else if (selectedNode != null)
+                    {
+                        if (selectedNode.NodeType == NodeType.Begin
+                            || selectedNode.NodeType == NodeType.End)
+                        {
+                            rContextMenu.Items.Clear();
+                            return;
+                        }
+                        var renameItem = new ToolStripMenuItem("缂栬緫");
+                        renameItem.Click += (s, ev) => EditInAndOutNode();
+                        rContextMenu.Items.Add(renameItem);
+
+                        var deleteItem = new ToolStripMenuItem("閲嶅懡鍚�");
+                        deleteItem.Click += (s, ev) => RenameNode();
+                        rContextMenu.Items.Add(deleteItem);
+
+                        if (selectedNode.NodeType == NodeType.Normal
+                            || selectedNode.NodeType == NodeType.Switch
+                            || selectedNode.NodeType == NodeType.MultiBranch)
+                        {
+                            var breakItem = new ToolStripMenuItem("绂佺敤");
+                            breakItem.Checked = selectedNode.Break;
+                            breakItem.Click += (s, ev) => BreakNode();
+                            rContextMenu.Items.Add(breakItem);
+                        }
+
+                        if (selectedNode.NodeType == NodeType.Parallel
+                            || selectedNode.NodeType == NodeType.MultiBranch)
+                        {
+                            var addBranchItem = new ToolStripMenuItem("娣诲姞鍒嗘敮");
+                            addBranchItem.Click += (s, ev) => AddBranch();
+                            rContextMenu.Items.Add(addBranchItem);
+
+                            var removeBranchItem = new ToolStripMenuItem("绉婚櫎鍒嗘敮");
+                            removeBranchItem.Click += (s, ev) => RemoveBranch();
+                            rContextMenu.Items.Add(removeBranchItem);
+                        }
+                    }
+                    break;
+                default:
+                    selectedNode = null;
+                    break;
+            }
+            this.Invalidate();
+        }
+
+        private void OnMouseUp(object sender, MouseEventArgs e)
+        {
+            try
+            {
+                switch (e.Button)
+                {
+                    case MouseButtons.Left:
+                        switch (this.PanelMode)
+                        {
+                            case PanelMode.CreatingConnection:
+                                FlowNode connectEndNode = GetNodeAt(e.Location);
+
+                                if (connectEndNode == null)
+                                {
+                                    connectStartNode = null;
+                                    connectStartNodeBranchIndex = -1;
+                                    return;
+                                }
+
+                                // 瀹屾垚杩炵嚎鎿嶄綔鍚庨渶瑕佸垽鏂杩炴帴绾挎墍杩炴帴鐨勮捣濮嬭妭鐐瑰拰缁堢偣鑺傜偣鏄惁宸茬粡琚繛鎺�
+                                foreach (var conn in connections.Values)
+                                {
+                                    // 宸茬粡瀛樺湪璇ヨ繛鎺ョ嚎
+                                    if (conn.StartNode == connectStartNode
+                                        && conn.EndNode == connectEndNode)
+                                    {
+                                        connectStartNode = null;
+                                        connectStartNodeBranchIndex = -1;
+                                        return;
+                                    }
+
+                                    // 杩炴帴绾跨殑璧风偣宸茬粡杩炴帴浜嗗叾浠栬妭鐐癸紝鍒欐柇寮�涔嬪墠鐨勮繛鎺�
+                                    switch (conn.StartNode.NodeType)
+                                    {
+                                        // 鍒嗘敮鑺傜偣閫昏緫鍗曠嫭澶勭悊
+                                        case NodeType.Switch:
+                                            if (conn.StartNode == connectStartNode && connectStartNodeBranchIndex >= 0
+                                                && conn.BranchIndex == connectStartNodeBranchIndex)
+                                            {
+                                                RemoveConnection(conn, connectStartNodeBranchIndex);
+                                                break;
+                                            }
+                                            break;
+                                        // 澶氬垎鏀妭鐐归�昏緫鍗曠嫭澶勭悊
+                                        case NodeType.MultiBranch:
+                                        case NodeType.Parallel:
+                                            if (conn.StartNode == connectStartNode && connectStartNodeBranchIndex >= 0
+                                                && conn.BranchIndex == connectStartNodeBranchIndex)
+                                            {
+                                                // 鏂紑涔嬪墠鐨勮繛鎺�
+                                                RemoveConnection(conn, connectStartNodeBranchIndex);
+                                                break;
+                                            }
+                                            break;
+                                        default:
+                                            if (conn.StartNode == connectStartNode)
+                                            {
+                                                // 鏂紑涔嬪墠鐨勮繛鎺�
+                                                RemoveConnection(conn, connectStartNodeBranchIndex);
+                                                break;
+                                            }
+                                            break;
+                                    }
+                                }
+
+                                // 纭繚杩炴帴鐨勮捣鐐瑰拰缁堢偣閮戒笉涓虹┖涓斾笉鐩稿悓锛屽垱寤鸿繛鎺ョ嚎
+                                if (connectStartNode != null
+                                    //&& connectEndNode != null
+                                    && connectEndNode != connectStartNode && connectStartNodeBranchIndex >= 0)
+                                    ConnectAsBranch(connectStartNode, connectEndNode, connectStartNodeBranchIndex);
+
+                                connectStartNode = null;
+                                connectStartNodeBranchIndex = -1;
+                                break;
+                            case PanelMode.DraggingNode:
+                                // 瀹屾垚鎷栧姩鎿嶄綔鍚庣殑閫昏緫
+                                break;
+                        }
+                        break;
+                    case MouseButtons.Right:
+                    default:
+                        break;
+                }
+            }
+            catch { }
+            finally
+            {
+                PanelMode = PanelMode.Normal;
+                this.Invalidate();
+                Save(filePath);
+            }
+
+        }
+
+        private void OnMouseMove(object sender, MouseEventArgs e)
+        {
+            mousePosition = e.Location;
+            switch (this.PanelMode)
+            {
+                case PanelMode.CreatingConnection:
+                    // 缁樺埗涓存椂杩炴帴绾块�昏緫鍦╬aint
+                    //this.Cursor = Cursors.Cross;
+                    break;
+                case PanelMode.DraggingNode:
+                    // 缁樺埗鎷栧姩鑺傜偣閫昏緫鍦╬aint,褰撳墠鍙槸淇敼琚�
+                    int deltaX = e.X - dragStartPoint.X;
+                    int deltaY = e.Y - dragStartPoint.Y;
+                    if (selectedNode != null)
+                    {
+                        selectedNode.X += deltaX;
+                        selectedNode.Y += deltaY;
+                    }
+                    dragStartPoint = e.Location;
+                    this.Cursor = Cursors.Hand;
+                    break;
+                case PanelMode.Normal:
+                    FlowNode isConnectingNode = OnNodeBranch(e.Location, out int index);
+
+                    // 鐐瑰嚮鍦ㄨ竟鐣屼笂骞舵湭鐐瑰嚮鍦ㄨ妭鐐逛笂锛岃繘鍏ュ垽鏂槸鍚﹁繘鍏ヨ繛鎺ョ嚎妯″紡
+                    if (isConnectingNode != null && selectedNode == null && index >= 0)
+                        this.Cursor = Cursors.Cross;
+                    else
+                        this.Cursor = Cursors.Default;
+                    break;
+            }
+            this.Invalidate();
+        }
+
+        private void ContextMenuItem_Click(object sender, EventArgs e)
+        {
+            if (sender is ToolStripMenuItem menuItem && menuItem.Tag is string description)
+            {
+                // 鍙兘鏈変竴涓紑濮嬭妭鐐�
+                if (description == "寮�濮�"
+                    && nodes.Any(n => n.Value.Text == "寮�濮�"))
+                    return;
+
+                // 鍙兘鏈変竴涓粨鏉熻妭鐐�
+                if (description == "缁撴潫"
+                    && nodes.Any(n => n.Value.Text == "缁撴潫"))
+                    return;
+
+                // 鑾峰彇榧犳爣浣嶇疆
+                Point mousePoint = mouseRightStartLocation;
+
+                // 鍚嶇О閲嶅鍒欐坊鍔�(鍓湰)
+                string nodeName = description;
+                while (nodes.Any(n => n.Value.Text == nodeName))
+                    nodeName += "(Copy)";
+
+                FlowNode newNode = new FlowNode();
+                switch (description)
+                {
+                    case "寮�濮�":
+                        newNode = new FlowNode(NodeType.Begin, mousePoint, nodeName, description);
+                        break;
+                    case "缁撴潫":
+                        newNode = new FlowNode(NodeType.End, mousePoint, nodeName, description);
+                        break;
+                    case "鍒嗘敮":
+                        newNode = new FlowNode(NodeType.Switch, mousePoint, nodeName, description);
+                        newNode.BranchNodes.TryAdd($"{newNode.Text}-Branch0", string.Empty);
+                        break;
+                    case "澶氬垎鏀�":
+                        newNode = new FlowNode(NodeType.MultiBranch, mousePoint, nodeName, description);
+                        break;
+                    case "骞惰鍒嗘敮寮�濮�":
+                        newNode = new FlowNode(NodeType.Parallel, mousePoint, nodeName, description);
+                        break;
+                    case "骞惰鍒嗘敮缁撴潫":
+                        newNode = new FlowNode(NodeType.Join, mousePoint, nodeName, description);
+                        break;
+                    default:
+                        newNode = new FlowNode(NodeType.Normal, mousePoint, nodeName, description);
+                        break;
+                }
+                //鍒嗘敮鑺傜偣榛樿娣诲姞涓や釜鍒嗘敮
+                newNode.BranchNodes.TryAdd($"{newNode.Text}-Branch{newNode.BranchNodes.Count}", string.Empty);
+
+                if (nodes.TryAdd(newNode.Text, newNode))
+                {
+                    AddNodeAction?.Invoke(newNode.Text, description);
+                    Debug.WriteLine($"銆恵DateTime.Now:HH:mm:ss.fff}銆戝垱寤轰簡鏂拌妭鐐�: {description}");
+                }
+
+            }
+            Save(filePath);
+        }
+        #endregion
+
+        #region 鍏朵粬鍑芥暟
+        private void RemoveNode(FlowNode selectedNode)
+        {
+            try
+            {
+                foreach (var conn in connections)
+                {
+                    if (conn.Value == null)
+                        continue;
+
+                    if (conn.Value.StartNode == selectedNode || conn.Value.EndNode == selectedNode)
+                    {
+                        RemoveConnection(conn.Value, -1);
+                        //connections.TryRemove(conn);
+                        //break;
+                    }
+                }
+
+                if (this.nodes.Remove(selectedNode.Text, out _))
+                    DeleteNodeAction?.Invoke(selectedNode.Text);
+
+                Save(filePath);
+                this.Invalidate();
+            }
+            catch { }
+        }
+
+        private void EditInAndOutNode()
+        {
+            try
+            {
+                PanelMode = PanelMode.Run;
+                if (selectedNode == null)
+                    return;
+                InAndOutNodeAction?.Invoke(selectedNode.Text);
+            }
+            catch { }
+            finally { PanelMode = PanelMode.Normal; }
+        }
+
+        private void RenameNode()
+        {
+            try
+            {
+                PanelMode = PanelMode.Run;
+                if (selectedNode == null)
+                    return;
+
+                RenameForm renameForm = new RenameForm(selectedNode.Text, true);
+                renameForm.ShowDialog();
+                if (renameForm.bRename)
+                {
+                    if (nodes.Any(n => n.Value.Text == renameForm.strNewName))
+                    {
+                        MessageBox.Show("宸插瓨鍦ㄥ悓鍚嶈妭鐐癸紝璇蜂慨鏀瑰悗閲嶈瘯!", "寮傚父");
+                        return;
+                    }
+
+                    nodes.TryRemove(renameForm.strOriName, out _);
+                    selectedNode.Text = renameForm.strNewName;
+                    nodes.TryAdd(selectedNode.Text, selectedNode);
+
+                    if (connections.TryRemove(renameForm.strOriName, out FlowConnection conn)
+                        && conn != null)
+                        connections.TryAdd(selectedNode.Text, conn);
+
+                    foreach (var node in nodes.Values)
+                    {
+                        foreach (var branch in node.BranchNodes)
+                        {
+                            if (branch.Key.StartsWith($"{renameForm.strOriName}-Branch"))
+                            {
+                                var newKey = branch.Key.Replace(renameForm.strOriName, renameForm.strNewName);
+                                node.BranchNodes.TryRemove(branch.Key, out var value);
+                                node.BranchNodes.TryAdd(newKey, value);
+                            }
+                            else if (branch.Value == renameForm.strOriName)
+                            {
+                                var newValue = branch.Value.Replace(renameForm.strOriName, renameForm.strNewName);
+                                node.BranchNodes.TryRemove(branch.Key, out _);
+                                node.BranchNodes.TryAdd(branch.Key, newValue);
+                            }
+                        }
+                    }
+                    this.Invalidate();
+                    RenameNodeAction?.Invoke(renameForm.strOriName, renameForm.strNewName);
+                }
+            }
+            catch { }
+            finally { PanelMode = PanelMode.Normal; }
+        }
+
+        private void RemoveConnection(FlowConnection selectedConnection, int BranchIndex)
+        {
+            foreach (var conn in connections)
+            {
+                if (conn.Value == selectedConnection)
+                {
+                    connections.TryRemove(conn);
+                    //selectedConnection.StartNode.BranchNodes
+                    //    .TryRemove($"{selectedConnection.StartNode.Text}-Branch{BranchIndex}", out _);
+
+                    if (selectedConnection.StartNode.BranchNodes.ContainsKey($"{selectedConnection.StartNode.Text}-Branch{selectedConnection.BranchIndex}"))
+                        selectedConnection.StartNode.BranchNodes[$"{selectedConnection.StartNode.Text}-Branch{selectedConnection.BranchIndex}"] = null;
+                    break;
+                }
+            }
+            this.Invalidate();
+        }
+
+        public void ConnectAsBranch(FlowNode parentNode, FlowNode branchNode, int connectStartNodeBranchIndex)
+        {
+            //// 纭繚鍒嗘敮鑺傜偣娉ㄥ唽鍒颁富闆嗗悎
+            //RegisterNode(branchNode);
+
+            // 鏇存柊鍒嗘敮寮曠敤
+            string branchName = $"{parentNode.Text}-Branch{connectStartNodeBranchIndex}";
+            if (parentNode != null && branchNode != null)
+            {
+                // 鏇存柊 BranchNodes 瀛楀吀
+                parentNode.BranchNodes.AddOrUpdate(branchName,
+                    (branchNode.Text),
+                    (key, existing) => (branchNode.Text));
+            }
+
+            // 鍒涘缓杩炴帴绾�
+            var connection = new FlowConnection(parentNode, branchNode, connectStartNodeBranchIndex);
+
+            // 鍘熸潵鐨勮繛鎺ョ嚎琚浛鎹负鏂扮殑杩炴帴绾�
+            if (connections.ContainsKey(branchName))
+                connections[branchName] = connection;
+            else
+                connections.TryAdd(branchName, connection);
+
+            // 鍘熸潵鐨勮繛鎺ヨ妭鐐硅鏇挎崲涓烘柊鐨勮妭鐐�
+            if (parentNode.BranchNodes.ContainsKey(branchName))
+                parentNode.BranchNodes[branchName] = branchNode.Text;
+            else
+                parentNode.BranchNodes.TryAdd(branchName, branchNode.Text);
+
+            Save(filePath);
+        }
+
+        private void BreakNode()
+        {
+            PanelMode = PanelMode.Run;
+            if (selectedNode == null)
+                return;
+            try
+            {
+                selectedNode.Break = !selectedNode.Break;
+            }
+            catch { }
+            finally { PanelMode = PanelMode.Normal; Save(filePath); }
+        }
+
+        private void AddBranch()
+        {
+            PanelMode = PanelMode.Run;
+            if (selectedNode == null)
+                return;
+            try
+            {
+                selectedNode.BranchNodes.TryAdd($"{selectedNode.Text}-Branch{selectedNode.BranchNodes.Count}", string.Empty);
+                AddBranchAction?.Invoke(selectedNode.Text);
+            }
+            catch { }
+            finally { PanelMode = PanelMode.Normal; Save(filePath); }
+        }
+
+        private void RemoveBranch()
+        {
+            PanelMode = PanelMode.Run;
+            if (selectedNode == null)
+                return;
+            try
+            {
+                int index = selectedNode.BranchNodes.Count - 1;
+                selectedNode.BranchNodes.TryRemove($"{selectedNode.Text}-Branch{index}", out _);
+                connections.TryRemove($"{selectedNode.Text}-Branch{index}", out _);
+                DeleteBranchAction?.Invoke(selectedNode.Text);
+            }
+            catch { }
+            finally { PanelMode = PanelMode.Normal; Save(filePath); }
+        }
+        #endregion
+
+        #endregion
+    }
+
+    public class ExecutionContext
+    {
+        public string CurrentconnectStartNodeBranchIndex { get; set; } = "";
+        public string CurrentBranchName { get; set; }
+        public ConcurrentDictionary<string, bool> BranchResults { get; set; } = new ConcurrentDictionary<string, bool>();
+
+        public ExecutionContext Clone()
+        {
+            return new ExecutionContext
+            {
+                CurrentconnectStartNodeBranchIndex = CurrentconnectStartNodeBranchIndex,
+                CurrentBranchName = CurrentBranchName,
+                BranchResults = new ConcurrentDictionary<string, bool>(BranchResults)
+            };
+        }
+    }
+}
diff --git a/LB_VisionFlowNode/FlowSerializer.cs b/LB_VisionFlowNode/FlowSerializer.cs
new file mode 100644
index 0000000..1e986fa
--- /dev/null
+++ b/LB_VisionFlowNode/FlowSerializer.cs
@@ -0,0 +1,73 @@
+锘縰sing Newtonsoft.Json;
+using System.Collections.Concurrent;
+
+namespace LB_VisionFlowNode
+{
+    // 搴忓垪鍖栫鐞嗙被
+    public static class FlowSerializer
+    {
+        public static string Serialize(ConcurrentDictionary<string, FlowNode> nodes
+            , ConcurrentDictionary<string, FlowConnection> connections)
+        {
+            var data = new FlowData
+            {
+                Nodes = nodes,
+                Connections = connections
+            };
+
+            var settings = new JsonSerializerSettings
+            {
+                Formatting = Formatting.Indented,
+                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
+
+            };
+
+            return JsonConvert.SerializeObject(data, settings);
+        }
+
+        public static (ConcurrentDictionary<string, FlowNode>, ConcurrentDictionary<string, FlowConnection>) Deserialize(string json)
+        {
+            var settings = new JsonSerializerSettings { };
+
+            var data = JsonConvert.DeserializeObject<FlowData>(json, settings);
+            var nodeDictionary = data.Nodes.ToDictionary(n => n.Value.Id);
+
+            // 閲嶅缓杩炴帴鍏崇郴
+            foreach (var connection in data.Connections)
+            {
+                if (nodeDictionary.TryGetValue(connection.Value.StartNodeId, out var startNode))
+                    connection.Value.StartNode = startNode.Value;
+
+                if (nodeDictionary.TryGetValue(connection.Value.EndNodeId, out var endNode))
+                    connection.Value.EndNode = endNode.Value;
+            }
+
+            //// 閲嶅缓 NextNode 鍏崇郴
+            //foreach (var node in data.Nodes)
+            //{
+            //    foreach (var branchNodeName in node.Value.BranchNodes.Values)
+            //    {
+            //        if (!string.IsNullOrEmpty(branchNodeName) &&
+            //                nodeDictionary.TryGetValue(branchNodeName, out var nextNode))
+            //        {
+            //            node.Value.NextNode = nextNode.Value;
+            //        }
+            //    }
+            //}
+
+            return (data.Nodes, data.Connections);
+        }
+    }
+
+    // 鍖呰绫荤敤浜庡簭鍒楀寲
+    public class FlowData
+    {
+        [JsonProperty("Nodes")]
+        public ConcurrentDictionary<string, FlowNode> Nodes { get; set; }
+            = new ConcurrentDictionary<string, FlowNode>();
+
+        [JsonProperty("Connections")]
+        public ConcurrentDictionary<string, FlowConnection> Connections { get; set; }
+            = new ConcurrentDictionary<string, FlowConnection>();
+    }
+}
diff --git a/LB_VisionFlowNode/IFlowContext.cs b/LB_VisionFlowNode/IFlowContext.cs
new file mode 100644
index 0000000..4ca3882
--- /dev/null
+++ b/LB_VisionFlowNode/IFlowContext.cs
@@ -0,0 +1,680 @@
+锘縰sing LB_VisionProcesses;
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text.Json.Nodes;
+using System.Threading;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.TreeView;
+
+namespace LB_VisionFlowNode
+{
+    /// <summary>
+    /// 鎻掍欢鑺傜偣鏂规硶淇℃伅
+    /// </summary>
+    public class PluginNodeMethodInfo
+    {
+        public string DisplayName { get; set; }
+        public string FullTypeName { get; set; }
+        public string Category { get; set; }
+        public string Group { get; set; }
+        public string Description { get; set; }
+    }
+    public abstract class IFlowContext
+    {
+        public readonly Dictionary<string, MethodInfo> _nodeMethods
+            = new Dictionary<string, MethodInfo>();
+
+        public readonly Dictionary<string, List<MethodInfo>> _groupedMethods
+            = new Dictionary<string, List<MethodInfo>>();
+
+        public readonly Dictionary<string, Func<FlowNode, bool>> _nodeDelegates
+            = new Dictionary<string, Func<FlowNode, bool>>();
+
+        // 鑷姩鐢熸垚鐨勬彃浠惰妭鐐规柟娉曚俊鎭�
+        public readonly Dictionary<string, PluginNodeMethodInfo> _pluginNodeMethods
+            = new Dictionary<string, PluginNodeMethodInfo>();
+
+        // 鍔ㄦ�佹柟娉曠殑鍖呰锛堢敤浜庢ā鎷烳ethodInfo锛�
+        private readonly Dictionary<string, DynamicMethodWrapper> _dynamicMethodWrappers
+            = new Dictionary<string, DynamicMethodWrapper>();
+
+        // 鏄惁宸茶嚜鍔ㄧ敓鎴愭彃浠惰妭鐐�
+        private bool _pluginNodesGenerated = false;
+
+        // 鍔ㄦ�佹柟娉曞寘瑁呯被
+        public class DynamicMethodWrapper
+        {
+            public string DisplayName { get; set; }
+            public string Category { get; set; }
+            public string Group { get; set; }
+            public string Description { get; set; }
+            public Func<FlowNode, bool> Execute { get; set; }
+            // 妯℃嫙MethodInfo鐨勫繀瑕佸睘鎬�
+            public string Name => DisplayName;
+        }
+
+        public void InitializeMethods()
+        {
+            // 1. 鍏堝鐞嗚嚜韬殑Node鐗规�ф柟娉�
+            var methods = GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);
+            foreach (var method in methods)
+            {
+                var nodeAttr = method.GetCustomAttribute<NodeAttribute>();
+                if (nodeAttr != null)
+                {
+                    // 浣跨敤鎻忚堪浣滀负閿��
+                    _nodeMethods[nodeAttr.Description] = method;
+
+                    // 鎸夌粍鍒嗙被
+                    if (!_groupedMethods.ContainsKey(nodeAttr.Group))
+                    {
+                        _groupedMethods[nodeAttr.Group] = new List<MethodInfo>();
+                    }
+                    _groupedMethods[nodeAttr.Group].Add(method);
+                }
+            }
+
+            // 2. 鑷姩涓篒Process宸ュ叿鐢熸垚鍔ㄦ�佽妭鐐规柟娉�
+            GeneratePluginNodeMethods();
+        }
+
+        /// <summary>
+        /// 鑷姩涓篒Process宸ュ叿鐢熸垚鑺傜偣鏂规硶锛堟牳蹇冩柟娉曪級
+        /// </summary>
+        private void GeneratePluginNodeMethods()
+        {
+            if (_pluginNodesGenerated)
+                return;
+            try
+            {
+                // 纭繚IProcess鐨勬彃浠剁鐞嗗櫒宸插垵濮嬪寲
+                if (IProcess.dicProcesses == null || IProcess.dicProcesses.Count == 0)
+                {
+                    var _ = IProcess.dicProcesses; // 瑙﹀彂鍒濆鍖�
+                }
+                // 娓呯┖鐜版湁鐨勬彃浠惰妭鐐规柟娉�
+                _pluginNodeMethods.Clear();
+                _dynamicMethodWrappers.Clear();
+                // 閬嶅巻鎵�鏈塈Process宸ュ叿
+                foreach (var processKvp in IProcess.dicProcesses)
+                {
+                    string toolName = processKvp.Key;
+                    string className = processKvp.Value;
+                    // 鑾峰彇宸ュ叿鐨勫垎绫�
+                    string category = GetCategoryForTool(toolName);
+                    string group = GetGroupForCategory(category); // 鏍规嵁鍒嗙被纭畾缁�
+                    string description = $"{toolName}";
+
+                    // 鍒涘缓鎻掍欢鑺傜偣鏂规硶淇℃伅
+                    var pluginNode = new PluginNodeMethodInfo
+                    {
+                        DisplayName = toolName,
+                        FullTypeName = className,
+                        Category = category,
+                        Group = group,
+                        Description = description
+                    };
+                    _pluginNodeMethods[toolName] = pluginNode;
+
+                    // 鍒涘缓鍔ㄦ�佹墽琛屽鎵�
+                    Func<FlowNode, bool> executeDelegate = (node) =>
+                    {
+                        try
+                        {
+                            // 鍒涘缓IProcess瀹炰緥
+                            IProcess process = IProcess.CreateProcess(toolName);
+                            if (process == null)
+                            {
+                                Debug.WriteLine($"鏃犳硶鍒涘缓宸ュ叿瀹炰緥: {toolName}");
+                                node.Result = false;
+                                return false;
+                            }
+
+                            // 鍒濆鍖栬繍琛屽弬鏁�
+                            process.InitRunParams();
+
+                            // 鎵ц宸ュ叿鐨凴un鏂规硶
+                            bool runResult = process.Run();
+
+                            // 璁剧疆鑺傜偣缁撴灉
+                            node.Result = runResult;
+                            node.BranchIndex = "0"; // 榛樿鍒嗘敮
+
+                            // 閲婃斁璧勬簮
+                            process.Dispose();
+
+                            Debug.WriteLine($"鎻掍欢宸ュ叿 {toolName} 鎵ц瀹屾垚锛岀粨鏋�: {runResult}");
+                            return runResult;
+                        }
+                        catch (Exception ex)
+                        {
+                            Debug.WriteLine($"鎻掍欢宸ュ叿 {toolName} 鎵ц澶辫触: {ex.Message}");
+                            node.Result = false;
+                            return false;
+                        }
+                    };
+
+                    // 鍒涘缓鍔ㄦ�佹柟娉曞寘瑁�
+                    var dynamicMethod = new DynamicMethodWrapper
+                    {
+                        DisplayName = toolName,
+                        Category = category,
+                        Group = group,
+                        Description = description,
+                        Execute = executeDelegate
+                    };
+                    _dynamicMethodWrappers[description] = dynamicMethod;
+
+                    // ********** 鍏抽敭锛氬皢鍔ㄦ�佹柟娉曟坊鍔犲埌_nodeMethods鍜宊groupedMethods **********
+                    // 鏂瑰紡锛氱敓鎴愬姩鎬丮ethodInfo锛堜娇鐢‥mit锛夛紝鎴栬�呮ā鎷燂紙杩欓噷鐢‥mit鐢熸垚鐪熷疄鐨凪ethodInfo锛�
+                    MethodInfo dynamicMethodInfo = CreateDynamicMethod(toolName, group, description);
+
+                    // 娣诲姞鍒癬nodeMethods锛堥敭鏄痙escription锛�
+                    _nodeMethods[description] = dynamicMethodInfo;
+
+                    // 娣诲姞鍒癬groupedMethods
+                    if (!_groupedMethods.ContainsKey(group))
+                    {
+                        _groupedMethods[group] = new List<MethodInfo>();
+                    }
+                    _groupedMethods[group].Add(dynamicMethodInfo);
+
+                    // 娣诲姞鍒癬nodeDelegates
+                    _nodeDelegates[description] = executeDelegate;
+
+                    Debug.WriteLine($"鑷姩鐢熸垚鎻掍欢鑺傜偣: {toolName} (鍒嗙被: {category}, 缁�: {group})");
+                }
+
+                _pluginNodesGenerated = true;
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"鑷姩鐢熸垚鎻掍欢鑺傜偣鏂规硶澶辫触: {ex.Message}");
+            }
+        }
+
+        /// <summary>
+        /// 浣跨敤Reflection.Emit鐢熸垚鍔ㄦ�丮ethodInfo锛屾ā鎷烴ode鐗规�ф柟娉�
+        /// </summary>
+        /// <param name="toolName">宸ュ叿鍚嶇О</param>
+        /// <param name="group">缁勫悕</param>
+        /// <param name="description">鎻忚堪</param>
+        /// <returns>鍔ㄦ�佺敓鎴愮殑MethodInfo</returns>
+        private MethodInfo CreateDynamicMethod(string toolName, string group, string description)
+        {
+            // 1. 瀹氫箟鍔ㄦ�佹柟娉曠殑鍙傛暟鍜岃繑鍥炵被鍨�
+            Type flowNodeType = typeof(FlowNode);
+            DynamicMethod dynamicMethod = new DynamicMethod(
+                toolName,                  // 鏂规硶鍚�
+                typeof(void),               // 杩斿洖绫诲瀷锛堝拰鍘熸湁Node鏂规硶涓�鑷达級
+                new[] { typeof(FlowNode) }, // 鍙傛暟绫诲瀷
+                GetType(),                  // 鎵�灞炵被鍨�
+                true);                      // 璺宠繃JIT鍙鎬ф鏌�
+
+            // 2. 鐢熸垚IL浠g爜锛岃皟鐢ㄥ姩鎬佸鎵�
+            ILGenerator il = dynamicMethod.GetILGenerator();
+            // 鍔犺浇鍙傛暟锛團lowNode锛�
+            il.Emit(OpCodes.Ldarg_1); // 娉ㄦ剰锛氬疄渚嬫柟娉曠殑绗竴涓弬鏁版槸this锛圠darg_0锛夛紝杩欓噷鍔ㄦ�佹柟娉曟槸闈欐�佺殑锛屾墍浠darg_0鏄疐lowNode
+                                      // 璋冪敤濮旀墭锛堣繖閲岀畝鍖栵紝鐩存帴璁剧疆Result涓簍rue锛�
+            il.Emit(OpCodes.Ldflda, flowNodeType.GetProperty("Result").GetSetMethod());
+            il.Emit(OpCodes.Ldc_I4_1);
+            il.Emit(OpCodes.Callvirt, flowNodeType.GetProperty("Result").GetSetMethod());
+            // 璁剧疆BranchIndex
+            il.Emit(OpCodes.Ldarg_1);
+            il.Emit(OpCodes.Ldflda, flowNodeType.GetProperty("BranchIndex").GetSetMethod());
+            il.Emit(OpCodes.Ldstr, "0");
+            il.Emit(OpCodes.Callvirt, flowNodeType.GetProperty("BranchIndex").GetSetMethod());
+            // 杩斿洖
+            il.Emit(OpCodes.Ret);
+
+            // 3. 灏咲ynamicMethod鍖呰涓篗ethodInfo锛圖ynamicMethod缁ф壙鑷狹ethodInfo锛�
+            return dynamicMethod;
+        }
+
+        /// <summary>
+        /// 鏍规嵁宸ュ叿鍚嶇О鎺ㄦ柇鍒嗙被锛堝畬鍠勯�昏緫锛�
+        /// </summary>
+        private string GetCategoryForTool(string toolName)
+        {
+            if (string.IsNullOrWhiteSpace(toolName))
+                return "鏈垎绫�";
+
+            toolName = toolName.ToLower();
+
+            if (toolName.Contains("鐩告満") || toolName.Contains("鍙栧浘"))
+                return "鐩告満宸ュ叿";
+            else if (toolName.Contains("閫氳") || toolName.Contains("command"))
+                return "閫氳宸ュ叿";
+            else if (toolName.Contains("opencvsharp"))
+                return "OpencvSharp绠楁硶";
+            else if (toolName.Contains("halcon"))
+                return "Halcon绠楁硶";
+            else if (toolName.Contains("yolo") || toolName.Contains("tensorrt") ||
+                     toolName.Contains("ocr") || toolName.Contains("deeplearning") || toolName.Contains("澶фā鍨�"))
+                return "娣卞害瀛︿範";
+            else if (toolName.Contains("鍥惧儚澶勭悊") || toolName.Contains("鐐逛簯") ||
+                     toolName.Contains("绾跨嚎浜ょ偣"))
+                return "鍥惧儚澶勭悊宸ュ叿";
+            else if (toolName.Contains("娴嬭瘯") || toolName.Contains("妫�鏌�") ||
+                     toolName.Contains("绔彛") || toolName.Contains("灞忓箷") ||
+                     toolName.Contains("宸ュ簭") || toolName.Contains("杞骇"))
+                return "鑷畾涔夊伐鍏�";
+            else if (toolName.Contains("鑴氭湰") || toolName.Contains("鍒嗘敮") ||
+                     toolName.Contains("寤舵椂") || toolName.Contains("缁樺埗"))
+                return "宸ュ叿";
+            else if (toolName.Contains("鍥哄畾璺熼殢") || toolName.Contains("fixture"))
+                return "宸ュ叿";
+            else
+                return "鎻掍欢宸ュ叿";
+        }
+
+        /// <summary>
+        /// 鏍规嵁鍒嗙被纭畾缁勫悕
+        /// </summary>
+        private string GetGroupForCategory(string category)
+        {
+            switch (category)
+            {
+                case "閫氳宸ュ叿":
+                    return "Basic";
+                case "绠楁硶":
+                    return "Basic";
+                case "娣卞害瀛︿範":
+                    return "Basic";
+                case "鍥惧儚澶勭悊宸ュ叿":
+                    return "Basic";
+                case "鑷畾涔夊伐鍏�":
+                    return "Basic";
+                case "宸ュ叿":
+                    return "Basic";
+                default:
+                    return "Plugin";
+            }
+        }
+
+        public void InitializeDelegates()
+        {
+            // 1. 澶勭悊鑷韩鐨凬ode鏂规硶
+            foreach (var kvp in _nodeMethods)
+            {
+                var method = kvp.Value;
+                var parameters = method.GetParameters();
+
+                //濡傛灉鏄姩鎬佹柟娉曪紙DynamicMethod锛夛紝璺宠繃锛堝凡缁忓湪GeneratePluginNodeMethods涓坊鍔犱簡濮旀墭锛�
+                if (method is DynamicMethod)
+                {
+                    // 浠庡姩鎬佹柟娉曞寘瑁呬腑鑾峰彇瀵瑰簲鐨勫鎵�
+                    if (_dynamicMethodWrappers.TryGetValue(kvp.Key, out var wrapper))
+                    {
+                        // 鐩存帴浣跨敤鍖呰涓殑Execute濮旀墭
+                        _nodeDelegates[kvp.Key] = wrapper.Execute;
+                    }
+                    else
+                    {
+                        // 濡傛灉娌℃湁鎵惧埌鍖呰锛屽垱寤轰竴涓粯璁ょ殑鎵ц濮旀墭
+                        _nodeDelegates[kvp.Key] = (node) =>
+                        {
+                            Debug.WriteLine($"鎵ц鍔ㄦ�佹柟娉�: {kvp.Key}");
+                            node.Result = true;
+                            node.BranchIndex = "0";
+                            return true;
+                        };
+                    }
+                    continue;
+                }
+
+                if (parameters.Length == 0)
+                {
+                    var action = (Action)Delegate.CreateDelegate(typeof(Action), this, method);
+                    _nodeDelegates[kvp.Key] = (node) => { action(); return node.Result; };
+                }
+                else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(FlowNode))
+                {
+                    var action = (Action<FlowNode>)Delegate.CreateDelegate(typeof(Action<FlowNode>), this, method);
+                    _nodeDelegates[kvp.Key] = (node) => { action(node); return node.Result; };
+                }
+            }
+
+            // 2. 纭繚鍔ㄦ�佹柟娉曠殑濮旀墭宸叉坊鍔狅紙GeneratePluginNodeMethods涓凡澶勭悊锛�
+        }
+
+        public virtual bool ExecuteNode(FlowNode node)
+        {
+            if (string.IsNullOrEmpty(node.Description))
+                return false;
+
+            // 浼樺厛妫�鏌ュ姩鎬佸鎵�
+            if (_nodeDelegates.TryGetValue(node.Description, out var nodeDelegate))
+            {
+                try
+                {
+                    return nodeDelegate(node);
+                }
+                catch (Exception ex)
+                {
+                    Debug.WriteLine($"鎵ц鑺傜偣澶辫触: {ex.Message}");
+                    return false;
+                }
+            }
+
+            // 鍏煎鍘熸湁閫昏緫
+            return false;
+        }
+
+        public Dictionary<string, MethodInfo> GetAvailableNodes()
+        {
+            return _nodeMethods.ToDictionary(
+                kvp => kvp.Key,
+                kvp => kvp.Value
+            );
+        }
+
+        // 鑾峰彇鎸夌粍鍒嗙粍鐨勫彲鐢ㄨ妭鐐癸紙鍖呭惈鍔ㄦ�佺敓鎴愮殑鎻掍欢鑺傜偣锛�
+        public Dictionary<string, List<ToolStripMenuItem>> GetGroupedMenuItems(EventHandler clickHandler)
+        {
+            var groupedMenuItems = new Dictionary<string, List<ToolStripMenuItem>>();
+
+            foreach (var group in _groupedMethods)
+            {
+                var menuItems = new List<ToolStripMenuItem>();
+
+                foreach (var method in group.Value)
+                {
+                    string menuText;
+                    string toolTip;
+
+                    // 鍒ゆ柇鏄潤鎬佹柟娉曡繕鏄姩鎬佹柟娉�
+                    if (method is DynamicMethod dynamicMethod)
+                    {
+                        // 鍔ㄦ�佹柟娉曪紙鎻掍欢宸ュ叿锛�
+                        var pluginNode = _pluginNodeMethods.Values.FirstOrDefault(p => p.DisplayName == dynamicMethod.Name);
+                        menuText = pluginNode?.DisplayName ?? dynamicMethod.Name;
+                        toolTip = pluginNode?.Description ?? $"鍔ㄦ�佸伐鍏�: {dynamicMethod.Name}";
+                    }
+                    else
+                    {
+                        // 闈欐�佹柟娉曪紙鍘熸湁Node鐗规�ф柟娉曪級
+                        var nodeAttr = method.GetCustomAttribute<NodeAttribute>();
+                        menuText = nodeAttr?.Name ?? method.Name;
+                        toolTip = nodeAttr?.Description ?? method.Name;
+                    }
+
+                    var menuItem = new ToolStripMenuItem
+                    {
+                        Text = menuText,
+                        Tag = menuText, // 瀛樺偍鎻忚堪浣滀负鏍囪瘑
+                        ToolTipText = toolTip
+                    };
+
+                    if (clickHandler != null)
+                    {
+                        menuItem.Click += clickHandler;
+                    }
+
+                    menuItems.Add(menuItem);
+                }
+
+                groupedMenuItems[group.Key] = menuItems;
+            }
+
+            return groupedMenuItems;
+        }
+
+        // 鑾峰彇鎸夌被鍒垎缁勭殑鑿滃崟椤癸紙鍖呭惈鍔ㄦ�佺敓鎴愮殑鎻掍欢鑺傜偣锛�
+        public Dictionary<string, List<ToolStripMenuItem>> GetCategorizedMenuItems(EventHandler clickHandler)
+        {
+            var categorizedMethods = new Dictionary<string, List<MethodInfo>>();
+
+            // 1. 澶勭悊鍘熸湁Node鏂规硶
+            foreach (var method in _nodeMethods.Values.Where(m => !(m is DynamicMethod)))
+            {
+                var nodeAttr = method.GetCustomAttribute<NodeAttribute>();
+                if (nodeAttr == null) continue;
+
+                if (!categorizedMethods.ContainsKey(nodeAttr.Category))
+                {
+                    categorizedMethods[nodeAttr.Category] = new List<MethodInfo>();
+                }
+                categorizedMethods[nodeAttr.Category].Add(method);
+            }
+
+            // 2. 澶勭悊鍔ㄦ�佹彃浠舵柟娉�
+            foreach (var pluginNode in _pluginNodeMethods.Values)
+            {
+                if (!categorizedMethods.ContainsKey(pluginNode.Category))
+                {
+                    categorizedMethods[pluginNode.Category] = new List<MethodInfo>();
+                }
+
+                // 鎵惧埌瀵瑰簲鐨勫姩鎬丮ethodInfo
+                var dynamicMethod = _nodeMethods.Values
+                    .OfType<DynamicMethod>()
+                    .FirstOrDefault(m => m.Name == pluginNode.DisplayName);
+
+                if (dynamicMethod != null)
+                {
+                    categorizedMethods[pluginNode.Category].Add(dynamicMethod);
+                }
+            }
+
+            // 鐢熸垚鑿滃崟椤�
+            var categorizedMenuItems = new Dictionary<string, List<ToolStripMenuItem>>();
+            foreach (var category in categorizedMethods)
+            {
+                var menuItems = new List<ToolStripMenuItem>();
+
+                foreach (var method in category.Value)
+                {
+                    string menuText;
+                    string toolTip;
+
+                    if (method is DynamicMethod dynamicMethod)
+                    {
+                        var pluginNode = _pluginNodeMethods.Values.FirstOrDefault(p => p.DisplayName == dynamicMethod.Name);
+                        menuText = pluginNode?.DisplayName ?? dynamicMethod.Name;
+                        toolTip = pluginNode?.Description ?? $"鍔ㄦ�佸伐鍏�: {dynamicMethod.Name}";
+                    }
+                    else
+                    {
+                        var nodeAttr = method.GetCustomAttribute<NodeAttribute>();
+                        menuText = nodeAttr?.Name ?? method.Name;
+                        toolTip = $"{nodeAttr?.Group} - {nodeAttr?.Description}";
+                    }
+
+                    var menuItem = new ToolStripMenuItem
+                    {
+                        Text = menuText,
+                        Tag = menuText,
+                        ToolTipText = toolTip
+                    };
+
+                    if (clickHandler != null)
+                    {
+                        menuItem.Click += clickHandler;
+                    }
+
+                    menuItems.Add(menuItem);
+                }
+
+                categorizedMenuItems[category.Key] = menuItems;
+            }
+
+            return categorizedMenuItems;
+        }
+
+        // 鍘熸湁Node鏂规硶
+        [Node("寮�濮�", "鎺у埗", "Logic", "寮�濮�")]
+        public virtual void 寮�濮�(FlowNode node) { node.Result = true; }
+
+        [Node("缁撴潫", "鎺у埗", "Logic", "缁撴潫")]
+        public virtual void 缁撴潫(FlowNode node) { node.Result = true; }
+
+        [Node("鍒嗘敮", "鎺у埗", "Logic", "鍒嗘敮")]
+        public virtual void 鍒嗘敮(FlowNode node) { node.Result = true; }
+
+        [Node("澶氬垎鏀�", "鎺у埗", "Logic", "澶氬垎鏀�")]
+        public virtual void 澶氬垎鏀�(FlowNode node) { node.Result = true; }
+
+        [Node("骞惰鍒嗘敮寮�濮�", "鎺у埗", "Logic", "骞惰鍒嗘敮寮�濮�")]
+        public virtual void 骞惰鍒嗘敮寮�濮�(FlowNode node)
+        {
+            string ProcessName = node.Text;
+            node.BranchIndex = "-1";
+            try
+            {
+                for (int i = 0; i < node.BranchNodes.Count; i++)
+                {
+                    if (i == 0)
+                        node.BranchIndex = "0;";
+                    else
+                        node.BranchIndex += $"{i.ToString()};";
+                }
+                node.Result = true;
+            }
+            catch { node.Result = false; }
+        }
+
+        [Node("骞惰鍒嗘敮缁撴潫", "鎺у埗", "Logic", "骞惰鍒嗘敮缁撴潫")]
+        public virtual void 骞惰鍒嗘敮缁撴潫(FlowNode node) { node.Result = true; }
+    }
+
+    public class FlowContext : IFlowContext
+    {
+        /// <summary>
+        /// 杩愯鏍囪
+        /// </summary>
+        public bool bRuning = false;
+
+        /// <summary>
+        /// 杩愯瀹屾垚
+        /// </summary>
+        public bool bCompleted = true;
+
+        /// <summary>
+        /// 杩愯缁撴灉
+        /// </summary>
+        public bool Result = false;
+
+        /// <summary>
+        /// 杩愯娑堟伅
+        /// </summary>
+        public string Msg = string.Empty;
+
+        /// <summary>
+        /// 杩愯鏃堕棿
+        /// </summary>
+        public double RunTime = 0;
+
+        /// <summary>
+        /// 寮�濮嬫椂闂�
+        /// </summary>
+        public DateTime StartTime = DateTime.Now;
+
+        public FlowContext()
+        {
+            InitializeMethods();
+            InitializeDelegates();
+        }
+
+        // 缁熶竴鐨勫姩鎬佽妭鐐规墽琛岃緟鍔╂柟娉曪紙鍙�夛級
+        private void RunNodeAsync(FlowNode node)
+        {
+            // 璋冪敤鍩虹被鐨凟xecuteNode
+            node.Result = ExecuteNode(node);
+            if (node.Result)
+            {
+                Debug.WriteLine($"{node.Text} 杩愯瀹屾垚");
+            }
+            else
+            {
+                Msg += $"[{node.Text}] 杩愯澶辫触";
+                Result = false;
+            }
+        }
+
+        // 閲嶅啓鍘熸湁Node鏂规硶锛屾坊鍔犱笟鍔¢�昏緫
+        [Node("寮�濮�", "鎺у埗", "Logic", "寮�濮�")]
+        public override void 寮�濮�(FlowNode node)
+        {
+            StartTime = DateTime.Now;
+            RunTime = 0;
+
+            Result = true;
+            bRuning = true;
+            bCompleted = false;
+            Msg = string.Empty;
+            node.Result = true;
+        }
+
+        [Node("缁撴潫", "鎺у埗", "Logic", "缁撴潫")]
+        public override void 缁撴潫(FlowNode node)
+        {
+            bRuning = false;
+            bCompleted = true;
+
+            if (Result)
+                Msg = "杩愯鎴愬姛";
+
+            RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
+            node.Result = true;
+        }
+
+        [Node("鍒嗘敮", "鎺у埗", "Logic", "鍒嗘敮")]
+        public override void 鍒嗘敮(FlowNode node)
+        {
+            string ProcessName = node.Text;
+            node.BranchIndex = "-1";
+            node.Result = true;
+            try
+            {
+                if (node.Break)
+                {
+                    node.BranchIndex = "0";
+                    node.Result = true;
+                    return;
+                }
+
+                node.BranchIndex = 0.ToString();
+                Debug.WriteLine($"{ProcessName},鍒嗘敮{node.BranchIndex}杩愯瀹屾垚");
+            }
+            catch (Exception ex)
+            {
+                node.Result = false;
+                Result &= false;
+                Msg = $"[{ProcessName}]杩愯鍙戠敓鎰忓,{ex.Message}";
+            }
+        }
+
+        [Node("澶氬垎鏀�", "鎺у埗", "Logic", "澶氬垎鏀�")]
+        public override void 澶氬垎鏀�(FlowNode node)
+        {
+            string ProcessName = node.Text;
+            node.BranchIndex = "-1";
+            node.Result = true;
+            try
+            {
+                if (node.Break)
+                {
+                    node.BranchIndex = "0";
+                    node.Result = true;
+                    return;
+                }
+
+                node.BranchIndex = 0.ToString();
+                Debug.WriteLine($"{ProcessName},鍒嗘敮{node.BranchIndex}杩愯瀹屾垚");
+            }
+            catch (Exception ex)
+            {
+                node.Result = false;
+                Result &= false;
+                Msg = $"[{ProcessName}]杩愯鍙戠敓鎰忓,{ex.Message}";
+            }
+        }
+
+        // 淇濈暀鍘熸湁娴嬭瘯鏂规硶锛堝彲閫夛紝涔熷彲浠ョЩ闄わ紝鐢卞姩鎬佺敓鎴愭浛浠o級
+        [Node("娴嬭瘯宸ュ叿", "绠楁硶", "Basic", "娴嬭瘯宸ュ叿")]
+        public void 娴嬭瘯宸ュ叿(FlowNode node) { RunNodeAsync(node); }
+    }
+
+}
diff --git a/LB_VisionFlowNode/LB_VisionFlowNode.csproj b/LB_VisionFlowNode/LB_VisionFlowNode.csproj
new file mode 100644
index 0000000..a54b92e
--- /dev/null
+++ b/LB_VisionFlowNode/LB_VisionFlowNode.csproj
@@ -0,0 +1,28 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Library</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <Nullable>enable</Nullable>
+    <UseWindowsForms>true</UseWindowsForms>
+    <ImplicitUsings>enable</ImplicitUsings>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
+    <PackageReference Include="ReaLTaiizor" Version="3.8.1.4" />
+    <PackageReference Include="SunnyUI" Version="3.9.0" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\LB_SmartVisionCommon\LB_SmartVisionCommon.csproj" />
+    <ProjectReference Include="..\LB_VisionProcesses\LB_VisionProcesses.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Update="RenameForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+  </ItemGroup>
+
+</Project>
\ No newline at end of file
diff --git a/LB_VisionFlowNode/MainForm.Designer.cs b/LB_VisionFlowNode/MainForm.Designer.cs
new file mode 100644
index 0000000..5169370
--- /dev/null
+++ b/LB_VisionFlowNode/MainForm.Designer.cs
@@ -0,0 +1,101 @@
+锘縩amespace LB_VisionFlowNode
+{
+    partial class MainForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
+            flowNodeEditor = new FlowNodeEditor();
+            themeForm = new ReaLTaiizor.Forms.ThemeForm();
+            panel = new ReaLTaiizor.Controls.Panel();
+            themeForm.SuspendLayout();
+            panel.SuspendLayout();
+            SuspendLayout();
+            // 
+            // flowNodeEditor
+            // 
+            flowNodeEditor.Dock = DockStyle.Fill;
+            flowNodeEditor.Location = new Point(5, 5);
+            flowNodeEditor.Name = "flowNodeEditor";
+            flowNodeEditor.Size = new Size(770, 361);
+            flowNodeEditor.TabIndex = 0;
+            // 
+            // themeForm
+            // 
+            themeForm.BackColor = Color.FromArgb(32, 41, 50);
+            themeForm.Controls.Add(panel);
+            themeForm.Dock = DockStyle.Fill;
+            themeForm.Font = new Font("Microsoft Sans Serif", 9F);
+            themeForm.Image = (Image)resources.GetObject("themeForm.Image");
+            themeForm.Location = new Point(0, 0);
+            themeForm.Name = "themeForm";
+            themeForm.Padding = new Padding(10, 70, 10, 9);
+            themeForm.RoundCorners = true;
+            themeForm.Sizable = true;
+            themeForm.Size = new Size(800, 450);
+            themeForm.SmartBounds = true;
+            themeForm.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            themeForm.TabIndex = 1;
+            themeForm.Text = "鎷栨媺鎷芥祦绋嬭妭鐐圭紪杈戝櫒";
+            // 
+            // panel
+            // 
+            panel.BackColor = Color.FromArgb(39, 51, 63);
+            panel.Controls.Add(flowNodeEditor);
+            panel.Dock = DockStyle.Fill;
+            panel.EdgeColor = Color.FromArgb(32, 41, 50);
+            panel.Location = new Point(10, 70);
+            panel.Name = "panel";
+            panel.Padding = new Padding(5);
+            panel.Size = new Size(780, 371);
+            panel.SmoothingType = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
+            panel.TabIndex = 1;
+            panel.Text = "panel1";
+            // 
+            // MainForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(800, 450);
+            Controls.Add(themeForm);
+            FormBorderStyle = FormBorderStyle.None;
+            MinimumSize = new Size(261, 61);
+            Name = "MainForm";
+            Text = "鎷栨媺鎷芥祦绋嬭妭鐐圭紪杈戝櫒";
+            TransparencyKey = Color.Fuchsia;
+            themeForm.ResumeLayout(false);
+            panel.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private FlowNodeEditor flowNodeEditor;
+        private ReaLTaiizor.Forms.ThemeForm themeForm;
+        private ReaLTaiizor.Controls.Panel panel;
+    }
+}
diff --git a/LB_VisionFlowNode/MainForm.cs b/LB_VisionFlowNode/MainForm.cs
new file mode 100644
index 0000000..2955743
--- /dev/null
+++ b/LB_VisionFlowNode/MainForm.cs
@@ -0,0 +1,10 @@
+namespace LB_VisionFlowNode
+{
+    public partial class MainForm : Form
+    {
+        public MainForm()
+        {
+            InitializeComponent();
+        }
+    }
+}
diff --git a/LB_VisionFlowNode/MainForm.resx b/LB_VisionFlowNode/MainForm.resx
new file mode 100644
index 0000000..d3dab5c
--- /dev/null
+++ b/LB_VisionFlowNode/MainForm.resx
@@ -0,0 +1,286 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="themeForm.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAIAAAB7GkOtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAACVUSURBVHhe7dXLDnD/OYbhb1RnQP1L5yZodRe7gUTsK6k2StJo42Boi3AE9gRnRChBgqGx4gCu
+        +e/NnTwr12jNVlbe+/nw8z/8vWlf+dxHab/1kz+Y9tUvfCLNL2r58mc/SvvGT38y7Yuf+njaB5PaYlJb
+        POkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkW
+        k9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9ri
+        F7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY
+        1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT
+        2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJS
+        WzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYA
+        xzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzp
+        FpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa
+        4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1
+        mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQW
+        k9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9pi
+        Uls2AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2
+        AMc86RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc8
+        6RaT2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT
+        2uIXtZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIX
+        tZjUFpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjU
+        FpPaYlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPa
+        YlJbNgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJb
+        NgDHPOkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbNgDH
+        POkWk9riF7WY1BaT2mJSWzYAxzzpFpPa4he1mNQWk9piUls2AMc86RaT2uIXtZjUFpPaYlJbPnznz7+V
+        9rWf+ME0T6LlF3/k+9K+/lOfTPuVT308zYto+c+//aO0DcAxk9piUltMaotJbfEiWkxqywbgmEltMakt
+        JrXFpLZ4ES0mtWUDcMyktpjUFpPaYlJbvIgWk9qyAThmUltMaotJbTGpLV5Ei0lt2QAcM6ktJrXFpLaY
+        1BYvosWktmwAjpnUFpPaYlJbTGqLF9FiUls2AMdMaotJbTGpLSa1xYtoMaktG4BjJrXFpLaY1BaT2uJF
+        tJjUlg3AMZPaYlJbTGqLSW3xIlpMassG4JhJbTGpLSa1xaS2eBEtJrVlA3DMpLaY1BaT2mJSW7yIFpPa
+        sgE4ZlJbTGqLSW0xqS1eRItJbdkAHDOpLSa1xaS2mNQWL6LFpLZsAI6Z1BaT2mJSW0xqixfRYlJbNgDH
+        TGqLSW0xqS0mtcWLaDGpLRuAYya1xaS2mNQWk9riRbSY1JYNwDGT2mJSW0xqi0lt8SJaTGrLBuCYSW0x
+        qS0mtcWktngRLSa1ZQNwzKS2mNQWk9piUlu8iBaT2rIBOGZSW0xqi0ltMaktXkSLSW3ZABwzqS0mtcWk
+        tpjUFi+ixaS2bACOmdQWk9piUltMaosX0WJSWzYAx0xqi0ltMaktJrXFi2gxqS0bgGMmtcWktpjUFpPa
+        4kW0mNSWDcAxk9piUltMaotJbfEiWkxqywbgmEltMaktJrXFpLZ4ES0mtWUDcMyktpjUFpPaYlJbvIgW
+        k9qyAThmUltMaotJbTGpLV5Ei0lt2QAcM6ktJrXFpLaY1BYvosWktmwAjpnUFpPaYlJbTGqLF9FiUls2
+        AMdMaotJbTGpLSa1xYtoMaktG4BjJrXFpLaY1BaT2uJFtJjUlg3AMZPaYlJbTGqLSW3xIlpMassG4JhJ
+        bTGpLSa1xaS2eBEtJrVlA3DMpLaY1BaT2mJSW7yIFpPasgE4ZlJbTGqLSW0xqS1eRItJbdkAHDOpLSa1
+        xaS2mNQWL6LFpLZsAI6Z1BaT2mJSW0xqixfRYlJbNgDHTGqLSW0xqS0mtcWLaDGpLRuAYya1xaS2mNQW
+        k9riRbSY1JYNwDGT2mJSW0xqi0lt8SJaTGrLBuCYSW0xqS0mtcWktngRLSa1ZQNwzKS2mNQWk9piUlu8
+        iBaT2rIBOGZSW0xqi0ltMaktXkSLSW3ZABwzqS0mtcWktpjUFi+ixaS2bACOmdQWk9piUltMaosX0WJS
+        WzYAx0xqi0ltMaktJrXFi2gxqS0bgGMmtcWktpjUFpPa4kW0mNSWDcAxk9piUltMaotJbfEiWkxqywbg
+        mEltMaktJrXFpLZ4ES0mtWUDcMyktpjUFpPaYlJbvIgWk9qyAThmUltMaotJbTGpLV5Ei0lt2QAcM6kt
+        JrXFpLaY1BYvosWktmwAjpnUFpPaYlJbTGqLF9FiUls2AMdMaotJbTGpLSa1xYtoMaktG4BjJrXFpLaY
+        1BaT2uJFtJjUlg3AMZPaYlJbTGqLSW3xIlpMassG4JhJbTGpLSa1xaS2eBEtJrVlA3DMpLaY1BaT2mJS
+        W7yIFpPasgE4ZlJbTGqLSW0xqS1eRItJbdkAHDOpLSa1xaS2mNQWL6LFpLZsAI6Z1BaT2mJSW0xqixfR
+        YlJbNgDHTGqLSW0xqS0mtcWLaDGpLR9+88d/IO1Ln/n+NE+ixUlo8aTnpV///CfSfuMLbRuAYya1xaS2
+        mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qy
+        AThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYlk9piUls2AMdMaotJbTFJ
+        85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNw
+        zKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYl
+        k9piUls2AMdMaotJbTFJ85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJ
+        bTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1
+        xaS2bACOmdQWk9pikuYlk9piUls2AMdMaotJbTFJ85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9pi
+        UltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJ
+        bdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYlk9piUls2AMdMaotJbTFJ85JJbTGpLRuAYya1xaS2
+        mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qy
+        AThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYlk9piUls2AMdMaotJbTFJ
+        85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNw
+        zKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYl
+        k9piUls2AMdMaotJbTFJ85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9piUltM0rxkUltMassG4JhJ
+        bTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJbdkAHDOpLSa1xSTNSya1
+        xaS2bACOmdQWk9pikuYlk9piUls2AMdMaotJbTFJ85JJbTGpLRuAYya1xaS2mKR5yaS2mNSWDcAxk9pi
+        UltM0rxkUltMassG4JhJbTGpLSZpXjKpLSa1ZQNwzKS2mNQWkzQvmdQWk9qyAThmUltMaotJmpdMaotJ
+        bdkAHDOpLSa1xSTNSya1xaS2bACOmdQWk9pikuYlk9piUls+/Otf/X7a/8WfH/rYx9L8Iy1//8e/k/aj
+        3/M9af/73e+m/eff/mHaBuD4Makt/pEWk9piUltMaotJbdkAHD8mtcU/0mJSW0xqi0ltMaktG4Djx6S2
+        +EdaTGqLSW0xqS0mtWUDcPyY1Bb/SItJbTGpLSa1xaS2bACOH5Pa4h9pMaktJrXFpLaY1JYNwPFjUlv8
+        Iy0mtcWktpjUFpPasgE4fkxqi3+kxaS2mNQWk9piUls2AMePSW3xj7SY1BaT2mJSW0xqywbg+DGpLf6R
+        FpPaYlJbTGqLSW3ZABw/JrXFP9JiUltMaotJbTGpLRuA48ektvhHWkxqi0ltMaktJrVlA3D8mNQW/0iL
+        SW0xqS0mtcWktmwAjh+T2uIfaTGpLSa1xaS2mNSWDcDxY1Jb/CMtJrXFpLaY1BaT2rIBOH5Maot/pMWk
+        tpjUFpPaYlJbNgDHj0lt8Y+0mNQWk9piUltMassG4PgxqS3+kRaT2mJSW0xqi0lt2QAcPya1xT/SYlJb
+        TGqLSW0xqS0bgOPHpLb4R1pMaotJbTGpLSa1ZQNw/JjUFv9Ii0ltMaktJrXFpLZsAI4fk9riH2kxqS0m
+        tcWktpjUlg3A8WNSW/wjLSa1xaS2mNQWk9qyATh+TGqLf6TFpLaY1BaT2mJSWzYAx49JbfGPtJjUFpPa
+        YlJbTGrLBuD4Makt/pEWk9piUltMaotJbdkAHD8mtcU/0mJSW0xqi0ltMaktG4Djx6S2+EdaTGqLSW0x
+        qS0mtWUDcPyY1Bb/SItJbTGpLSa1xaS2bACOH5Pa4h9pMaktJrXFpLaY1JYNwPFjUlv8Iy0mtcWktpjU
+        FpPasgE4fkxqi3+kxaS2mNQWk9piUls2AMePSW3xj7SY1BaT2mJSW0xqywbg+DGpLf6RFpPaYlJbTGqL
+        SW3ZABw/JrXFP9JiUltMaotJbTGpLRuA48ektvhHWkxqi0ltMaktJrVlA3D8mNQW/0iLSW0xqS0mtcWk
+        tmwAjh+T2uIfaTGpLSa1xaS2mNSWDcDxY1Jb/CMtJrXFpLaY1BaT2rIBOH5Maot/pMWktpjUFpPaYlJb
+        NgDHj0lt8Y+0mNQWk9piUltMassG4PgxqS3+kRaT2mJSW0xqi0lt2QAcPya1xT/SYlJbTGqLSW0xqS0b
+        gOPHpLb4R1pMaotJbTGpLSa1ZQNw/JjUFv9Ii0ltMaktJrXFpLZsAI4fk9riH2kxqS0mtcWktpjUlg3A
+        8WNSW/wjLSa1xaS2mNQWk9qyATh+TGqLf6TFpLaY1BaT2mJSWzYAx49JbfGPtJjUFpPaYlJbTGrLBuD4
+        Makt/pEWk9piUltMaotJbdkAHD8mtcU/0mJSW0xqi0ltMaktG4Djx6S2+EdaTGqLSW0xqS0mtWUDcPyY
+        1Bb/SItJbTGpLSa1xaS2bACOH5Pa4h9pMaktJrXFpLaY1JYNwPFjUlv8Iy0mtcWktpjUFpPasgE4fkxq
+        i3+kxaS2mNQWk9piUls2AMePSW3xj7SY1BaT2mJSW0xqywbg+DGpLf6RFpPaYlJbTGqLSW3ZABw/JrXF
+        P9JiUltMaotJbTGpLRuA48ektvhHWkxqi0ltMaktJrVlA3D8mNQW/0iLSW0xqS0mtcWktmwAjh+T2uIf
+        aTGpLSa1xaS2mNSWDcDxY1Jb/CMtJrXFpLaY1BaT2rIBOH5Maot/pMWktpjUFpPaYlJbPviq5d/+9Jtp
+        //Rn30r7r7/7o7R//+s/SPuXv/h22n/95e+l/cOf/G7aBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqL
+        SW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWk
+        tpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJb
+        TGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0b
+        gGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnU
+        FpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqL
+        SW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWk
+        tpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJb
+        TGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0b
+        gGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnU
+        FpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqL
+        SW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWk
+        tpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJb
+        TGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0b
+        gGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnU
+        FpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqL
+        SW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWk
+        tpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJb
+        TGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0b
+        gGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnU
+        FpPaYlJbTGqLSW0xqS0ffv3zn0j7xz/7Ztp3/vxbab/8qY+nfTHun//i22n/8Td/mPaVz32UtgE4ZlJb
+        TGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0m
+        tcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPa
+        YlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0x
+        qS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwA
+        jpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJb
+        TGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0m
+        tcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPa
+        YlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0x
+        qS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwA
+        jpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJb
+        TGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0m
+        tcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPa
+        YlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0x
+        qS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwA
+        jpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJb
+        TGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0m
+        tcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPa
+        YlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwAjpnUFpPaYlJbTGqLSW0x
+        qS0bgGMmtcWktpjUFpPaYlJbTGrLBuCYSW0xqS0mtcWktpjUFpPasgE4ZlJbTGqLSW0xqS0mtcWktmwA
+        jpnUFpPaYlJbTGqLSW0xqS0bgGMmtcWktpjUFpPaYlJbTGrLhy995vvT/KSWL3+27bv/899z6Euf+SjN
+        i2j51U9/PG0DcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUD
+        cMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmk
+        tngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNw
+        zKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2
+        eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DM
+        pLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4
+        ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyk
+        tpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngR
+        LSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2
+        mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEt
+        JrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaY
+        pHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0m
+        tWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpik
+        ecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1
+        ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5
+        yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVl
+        A3DMpLaYpHnJpLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJ
+        pLZ4ES0mtWUDcMyktpikecmktngRLSa1ZQNwzKS2mKR5yaS2eBEtJrVlA3DMpLaYpHnJpLZ4ES0mteXD
+        N37hx9J++5c+k/a1n/1U2lc+94m0X/vsR2lf/7lPp331Z354Dm0AjpnUFpPaYlJbTGqLSZqXNgDHTGqL
+        SW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpik
+        eWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0xqS0maV7aABwzqS0mtcWktpjUFpM0L20AjpnUFpPa
+        YlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPS
+        BuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0xqS0maV7aABwzqS0mtcWk
+        tpjUFpM0L20AjpnUFpPaYlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3A
+        MZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0x
+        qS0maV7aABwzqS0mtcWktpjUFpM0L20AjpnUFpPaYlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMm
+        tcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJb
+        TNK8tAE4ZlJbTGqLSW0xqS0maV7aABwzqS0mtcWktpjUFpM0L20AjpnUFpPaYlJbTGqLSZqXNgDHTGqL
+        SW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpik
+        eWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0xqS0maV7aABwzqS0mtcWktpjUFpM0L20AjpnUFpPa
+        YlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPS
+        BuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0xqS0maV7aABwzqS0mtcWk
+        tpjUFpM0L20AjpnUFpPaYlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMmtcWktpjUFpPaYpLmpQ3A
+        MZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJbTNK8tAE4ZlJbTGqLSW0x
+        qS0maV7aABwzqS0mtcWktpjUFpM0L20AjpnUFpPaYlJbTGqLSZqXNgDHTGqLSW0xqS0mtcUkzUsbgGMm
+        tcWktpjUFpPaYpLmpQ3AMZPaYlJbTGqLSW0xSfPSBuCYSW0xqS0mtcWktpikeWkDcMyktpjUFpPaYlJb
+        TNK8tAE4ZlJbTGqLSW0xqS0maV76fzfth9drmQBzAAAAAElFTkSuQmCC
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionFlowNode/Program.cs b/LB_VisionFlowNode/Program.cs
new file mode 100644
index 0000000..1b5b1bc
--- /dev/null
+++ b/LB_VisionFlowNode/Program.cs
@@ -0,0 +1,17 @@
+namespace LB_VisionFlowNode
+{
+    internal static class Program
+    {
+        /// <summary>
+        ///  The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            // To customize application configuration such as set high DPI settings or default font,
+            // see https://aka.ms/applicationconfiguration.
+            //ApplicationConfiguration.Initialize();
+            Application.Run(new MainForm());
+        }
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionFlowNode/RenameForm.Designer.cs b/LB_VisionFlowNode/RenameForm.Designer.cs
new file mode 100644
index 0000000..980de61
--- /dev/null
+++ b/LB_VisionFlowNode/RenameForm.Designer.cs
@@ -0,0 +1,261 @@
+锘縩amespace LB_VisionFlowNode
+{
+    partial class RenameForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RenameForm));
+            theme_RenameForm = new ReaLTaiizor.Forms.ThemeForm();
+            tlp_RenameMain = new Sunny.UI.UITableLayoutPanel();
+            tlp_RenameInput = new Sunny.UI.UITableLayoutPanel();
+            lb_OriginalName = new ReaLTaiizor.Controls.BigLabel();
+            bl_NewName = new ReaLTaiizor.Controls.BigLabel();
+            txt_OriginalName = new ReaLTaiizor.Controls.AloneTextBox();
+            txt_NewName = new ReaLTaiizor.Controls.AloneTextBox();
+            tlp_RenameOperator = new Sunny.UI.UITableLayoutPanel();
+            btn_Rename = new ReaLTaiizor.Controls.Button();
+            btn_Cancel = new ReaLTaiizor.Controls.Button();
+            theme_RenameForm.SuspendLayout();
+            tlp_RenameMain.SuspendLayout();
+            tlp_RenameInput.SuspendLayout();
+            tlp_RenameOperator.SuspendLayout();
+            SuspendLayout();
+            // 
+            // theme_RenameForm
+            // 
+            theme_RenameForm.BackColor = Color.FromArgb(32, 41, 50);
+            theme_RenameForm.Controls.Add(tlp_RenameMain);
+            theme_RenameForm.Dock = DockStyle.Fill;
+            theme_RenameForm.Font = new Font("Microsoft Sans Serif", 9F);
+            theme_RenameForm.Image = (Image)resources.GetObject("theme_RenameForm.Image");
+            theme_RenameForm.Location = new Point(0, 0);
+            theme_RenameForm.Name = "theme_RenameForm";
+            theme_RenameForm.Padding = new Padding(10, 70, 10, 9);
+            theme_RenameForm.RoundCorners = true;
+            theme_RenameForm.Sizable = true;
+            theme_RenameForm.Size = new Size(461, 260);
+            theme_RenameForm.SmartBounds = true;
+            theme_RenameForm.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            theme_RenameForm.TabIndex = 0;
+            theme_RenameForm.Text = "閲嶅懡鍚嶈缃�";
+            // 
+            // tlp_RenameMain
+            // 
+            tlp_RenameMain.ColumnCount = 1;
+            tlp_RenameMain.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tlp_RenameMain.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tlp_RenameMain.Controls.Add(tlp_RenameInput, 0, 0);
+            tlp_RenameMain.Controls.Add(tlp_RenameOperator, 0, 1);
+            tlp_RenameMain.Dock = DockStyle.Fill;
+            tlp_RenameMain.Location = new Point(10, 70);
+            tlp_RenameMain.Name = "tlp_RenameMain";
+            tlp_RenameMain.RowCount = 2;
+            tlp_RenameMain.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tlp_RenameMain.RowStyles.Add(new RowStyle(SizeType.Absolute, 60F));
+            tlp_RenameMain.Size = new Size(441, 181);
+            tlp_RenameMain.TabIndex = 0;
+            tlp_RenameMain.TagString = null;
+            // 
+            // tlp_RenameInput
+            // 
+            tlp_RenameInput.ColumnCount = 4;
+            tlp_RenameInput.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tlp_RenameInput.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tlp_RenameInput.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tlp_RenameInput.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tlp_RenameInput.Controls.Add(lb_OriginalName, 1, 0);
+            tlp_RenameInput.Controls.Add(bl_NewName, 1, 1);
+            tlp_RenameInput.Controls.Add(txt_OriginalName, 2, 0);
+            tlp_RenameInput.Controls.Add(txt_NewName, 2, 1);
+            tlp_RenameInput.Dock = DockStyle.Fill;
+            tlp_RenameInput.Location = new Point(3, 3);
+            tlp_RenameInput.Name = "tlp_RenameInput";
+            tlp_RenameInput.RowCount = 2;
+            tlp_RenameInput.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+            tlp_RenameInput.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+            tlp_RenameInput.Size = new Size(435, 115);
+            tlp_RenameInput.TabIndex = 0;
+            tlp_RenameInput.TagString = null;
+            // 
+            // lb_OriginalName
+            // 
+            lb_OriginalName.AutoSize = true;
+            lb_OriginalName.BackColor = Color.Transparent;
+            lb_OriginalName.Dock = DockStyle.Fill;
+            lb_OriginalName.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            lb_OriginalName.ForeColor = SystemColors.Control;
+            lb_OriginalName.Location = new Point(103, 0);
+            lb_OriginalName.Name = "lb_OriginalName";
+            lb_OriginalName.Size = new Size(94, 57);
+            lb_OriginalName.TabIndex = 0;
+            lb_OriginalName.Text = "鍘熷悕绉帮細";
+            lb_OriginalName.TextAlign = ContentAlignment.MiddleRight;
+            // 
+            // bl_NewName
+            // 
+            bl_NewName.AutoSize = true;
+            bl_NewName.BackColor = Color.Transparent;
+            bl_NewName.Dock = DockStyle.Fill;
+            bl_NewName.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            bl_NewName.ForeColor = SystemColors.Control;
+            bl_NewName.Location = new Point(103, 57);
+            bl_NewName.Name = "bl_NewName";
+            bl_NewName.Size = new Size(94, 58);
+            bl_NewName.TabIndex = 1;
+            bl_NewName.Text = "鏂板悕绉帮細";
+            bl_NewName.TextAlign = ContentAlignment.MiddleRight;
+            // 
+            // txt_OriginalName
+            // 
+            txt_OriginalName.BackColor = Color.FromArgb(32, 41, 50);
+            txt_OriginalName.Dock = DockStyle.Fill;
+            txt_OriginalName.EnabledCalc = true;
+            txt_OriginalName.Font = new Font("Microsoft YaHei UI", 12F);
+            txt_OriginalName.ForeColor = SystemColors.WindowText;
+            txt_OriginalName.Location = new Point(203, 3);
+            txt_OriginalName.MaxLength = 32767;
+            txt_OriginalName.MultiLine = false;
+            txt_OriginalName.Name = "txt_OriginalName";
+            txt_OriginalName.ReadOnly = true;
+            txt_OriginalName.Size = new Size(129, 51);
+            txt_OriginalName.TabIndex = 2;
+            txt_OriginalName.TextAlign = HorizontalAlignment.Center;
+            txt_OriginalName.UseSystemPasswordChar = false;
+            // 
+            // txt_NewName
+            // 
+            txt_NewName.BackColor = Color.FromArgb(32, 41, 50);
+            txt_NewName.Dock = DockStyle.Fill;
+            txt_NewName.EnabledCalc = true;
+            txt_NewName.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
+            txt_NewName.ForeColor = Color.FromArgb(124, 133, 142);
+            txt_NewName.Location = new Point(203, 60);
+            txt_NewName.MaxLength = 32767;
+            txt_NewName.MultiLine = false;
+            txt_NewName.Name = "txt_NewName";
+            txt_NewName.ReadOnly = false;
+            txt_NewName.Size = new Size(129, 52);
+            txt_NewName.TabIndex = 3;
+            txt_NewName.TextAlign = HorizontalAlignment.Center;
+            txt_NewName.UseSystemPasswordChar = false;
+            // 
+            // tlp_RenameOperator
+            // 
+            tlp_RenameOperator.ColumnCount = 5;
+            tlp_RenameOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tlp_RenameOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tlp_RenameOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
+            tlp_RenameOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tlp_RenameOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 101F));
+            tlp_RenameOperator.Controls.Add(btn_Rename, 1, 0);
+            tlp_RenameOperator.Controls.Add(btn_Cancel, 3, 0);
+            tlp_RenameOperator.Dock = DockStyle.Fill;
+            tlp_RenameOperator.Location = new Point(3, 124);
+            tlp_RenameOperator.Name = "tlp_RenameOperator";
+            tlp_RenameOperator.RowCount = 1;
+            tlp_RenameOperator.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tlp_RenameOperator.Size = new Size(435, 54);
+            tlp_RenameOperator.TabIndex = 1;
+            tlp_RenameOperator.TagString = null;
+            // 
+            // btn_Rename
+            // 
+            btn_Rename.BackColor = Color.Transparent;
+            btn_Rename.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_Rename.Cursor = Cursors.Hand;
+            btn_Rename.Dock = DockStyle.Fill;
+            btn_Rename.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Rename.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_Rename.Font = new Font("Microsoft Sans Serif", 12F);
+            btn_Rename.Image = null;
+            btn_Rename.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_Rename.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_Rename.Location = new Point(103, 3);
+            btn_Rename.Name = "btn_Rename";
+            btn_Rename.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Rename.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_Rename.Size = new Size(86, 48);
+            btn_Rename.TabIndex = 0;
+            btn_Rename.Text = "閲嶅懡鍚�";
+            btn_Rename.TextAlignment = StringAlignment.Center;
+            btn_Rename.Click += btn_Rename_Click;
+            // 
+            // btn_Cancel
+            // 
+            btn_Cancel.BackColor = Color.Transparent;
+            btn_Cancel.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_Cancel.Cursor = Cursors.Hand;
+            btn_Cancel.Dock = DockStyle.Fill;
+            btn_Cancel.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Cancel.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_Cancel.Font = new Font("Microsoft Sans Serif", 12F);
+            btn_Cancel.Image = null;
+            btn_Cancel.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_Cancel.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_Cancel.Location = new Point(245, 3);
+            btn_Cancel.Name = "btn_Cancel";
+            btn_Cancel.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Cancel.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_Cancel.Size = new Size(86, 48);
+            btn_Cancel.TabIndex = 1;
+            btn_Cancel.Text = "鍙栨秷";
+            btn_Cancel.TextAlignment = StringAlignment.Center;
+            // 
+            // RenameForm
+            // 
+            AutoScaleDimensions = new SizeF(96F, 96F);
+            AutoScaleMode = AutoScaleMode.Dpi;
+            ClientSize = new Size(461, 260);
+            Controls.Add(theme_RenameForm);
+            FormBorderStyle = FormBorderStyle.None;
+            MinimumSize = new Size(261, 61);
+            Name = "RenameForm";
+            Text = "閲嶅懡鍚嶈缃�";
+            TransparencyKey = Color.Fuchsia;
+            theme_RenameForm.ResumeLayout(false);
+            tlp_RenameMain.ResumeLayout(false);
+            tlp_RenameInput.ResumeLayout(false);
+            tlp_RenameInput.PerformLayout();
+            tlp_RenameOperator.ResumeLayout(false);
+            ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private ReaLTaiizor.Forms.ThemeForm theme_RenameForm;
+        private Sunny.UI.UITableLayoutPanel tlp_RenameMain;
+        private Sunny.UI.UITableLayoutPanel tlp_RenameInput;
+        private Sunny.UI.UITableLayoutPanel tlp_RenameOperator;
+        private ReaLTaiizor.Controls.BigLabel lb_OriginalName;
+        private ReaLTaiizor.Controls.BigLabel bl_NewName;
+        private ReaLTaiizor.Controls.Button btn_Rename;
+        private ReaLTaiizor.Controls.Button btn_Cancel;
+        private ReaLTaiizor.Controls.AloneTextBox txt_OriginalName;
+        private ReaLTaiizor.Controls.AloneTextBox txt_NewName;
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionFlowNode/RenameForm.cs b/LB_VisionFlowNode/RenameForm.cs
new file mode 100644
index 0000000..a921123
--- /dev/null
+++ b/LB_VisionFlowNode/RenameForm.cs
@@ -0,0 +1,62 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_VisionFlowNode
+{
+    public partial class RenameForm : Form
+    {
+        // 瀹氫箟涓�涓鎵樺拰浜嬩欢
+        public delegate void UpdateStringHandler(string oriString, string newString);
+        public event UpdateStringHandler UpdateStringEvent;
+        public bool bRename = false;
+        public string strOriName { get; set; }
+        public string strNewName { get; set; }
+
+        public bool bCheckBan = true;
+        public RenameForm(string strOrigin = "", bool bCheckBan = true)
+        {
+            InitializeComponent();
+            // 绂佹淇敼绐楀彛澶у皬
+            this.FormBorderStyle = FormBorderStyle.FixedDialog;
+            this.txt_OriginalName.Text = strOrigin;
+            this.txt_NewName.Text = strOrigin;
+            this.bCheckBan = bCheckBan;
+        }
+        List<string> banStr = new List<string>() { ",", ".", "\\", "/", ":", "*", "?", "\"", "<", ">", "|", "\0" };
+
+        private void btn_Rename_Click(object sender, EventArgs e)
+        {
+            if (string.IsNullOrEmpty(this.txt_NewName.Text.Trim()))
+            {
+                MessageBox.Show("鍚嶇О涓嶅厑璁镐负绌�", "寮傚父");
+                return;
+            }
+
+            if (bCheckBan)
+            {
+                foreach (string str in banStr)
+                {
+                    if (this.txt_NewName.Text.Contains(str))
+                    {
+                        MessageBox.Show("鍚嶇О涓嶅厑璁稿嚭鐜�, . \\ / : * ? \" < > | 绛夊瓧绗�", "寮傚父");
+                        return;
+                    }
+                }
+            }
+
+            // 瑙﹀彂浜嬩欢锛岄�氱煡鐖剁獥浣撴洿鏂皊tring
+            UpdateStringEvent?.Invoke(this.txt_OriginalName.Text, this.txt_NewName.Text);
+            bRename = true;
+            strOriName = this.txt_OriginalName.Text;
+            strNewName = this.txt_NewName.Text;
+            this.Close();
+        }
+    }
+}
diff --git a/LB_VisionFlowNode/RenameForm.resx b/LB_VisionFlowNode/RenameForm.resx
new file mode 100644
index 0000000..9282447
--- /dev/null
+++ b/LB_VisionFlowNode/RenameForm.resx
@@ -0,0 +1,139 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="theme_RenameForm.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        vgAADr4B6kKxwAAAAt9JREFUSEvtVc9rU0EQflGrUqtVa0l2J01siGZ3XpoKKQgqVr3oxYuK4KH0UFDB
+        P0Dx4g8UxJsHbz2LeCiCF0ElatWa7E4SoVLoQa+iUkS0Vq2tzEuiyctre9CDBwe+03zvm9lvZ+c5zv/4
+        k7DZbMtYKrzZutH9FuUp0nCBUF4uIpwpaBigNGRuOc5y/3dLRi4eX21c2GNRDlsUk6Tgs0X4QQjzDIMw
+        ZxBeWy2P2qzTQjoSH8fONr9OUITKmXA3IVwnhPc1wXqwOGmwFmFfrt9ZYVzYaxWUrIYbeR125x0n5Bf1
+        ghOUjvSRhiemrtsGKPhOGu6QG9HnHGdZMSV3GAUva4W5UFFF+wOLFFQ0TQjW69AvjDBvUcywZUbFBPOL
+        LvQSAvl5XsFUV1+D+GhPbAOhHFlInO+AEK4yj/nlTKybtMgF8SsWyruPk5HOmn7IoBwkFNN+crWjTzw9
+        tUvMK9lhEG4uaGP1tEbLk55VE6mOtRbhnp9UgZgmDRfLmfAaFp9MJlfxmBolvjZzG2FQPir1xtc7PMuk
+        4I2fQEp8I5TXuAEW526KCEesElNN3GC8IyWyDrnyoEEx01idvZUjxTofC1tiCZ6SAKFAFLhBFw45Rolj
+        3vjVEzRMlFU0XRPnebdaXiGEWb/QIpglFwa8E/Cl/E6IL4RwnOe8VuBFj0xZhFcBIgujcoLDTgnlNoPw
+        tpYwCM/qreEwWgw1nXIJGCWmjIbtjs0m2i3Kh1XxOavhrP8lWoRLfoEloUTebhWbKisC4YRnkxbTeYwe
+        qBfnMDo6VJmqAKEg8GkVnP5lM1vCr48QPpKO7PYX4E54TRCKD0Gv1w+2ueDKrgYRSnf1ecsK5WBDoho5
+        7GzjDUoazvNLJiUeWA1PCcUYKRg1CPctwm2LMFxyxU6/zZ5VZRS7eC08T25c15BsjBD/A2xWtDLPJhLt
+        3jbIitZxxJWL/oC8+9CROKW6pD/3t6N5n/+r8RMPp2HDn8xmcgAAAABJRU5ErkJggg==
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithm.cs b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithm.cs
new file mode 100644
index 0000000..0c95831
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithm.cs
@@ -0,0 +1,5656 @@
+锘縰sing HalconDotNet;
+using Microsoft.Extensions.Logging.Abstractions;
+using LB_VisionProcesses.Alogrithms.Halcon;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Serialization;
+using OpenCvSharp;
+using OpenCvSharp.XFeatures2D;
+using System;
+using System.Collections.Generic;
+using System.Data.Common;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Reflection.Metadata;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics.X86;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Xml.Linq;
+using ZXing;
+using ZXing.Common;
+using ZXing.Windows.Compatibility;
+using static System.Collections.Specialized.BitVector32;
+using static System.Net.Mime.MediaTypeNames;
+using static System.Resources.ResXFileRef;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
+using Extensions = OpenCvSharp.Extensions;
+using Point = OpenCvSharp.Point;
+using LB_VisionControl;
+
+namespace LB_VisionProcesses.Alogrithms
+{
+    public class TAlgorithm : IProcess
+    {
+        /// <summary>
+        /// 璇诲啓閿�
+        /// </summary>
+        public readonly object lockObj = new object();
+
+        /// <summary>
+        /// 瑁佸垏鍥剧墖涓篽oDomainImage(淇濈暀鍘熷潗鏍囩郴,鍏朵綑濉厖涓虹┖)
+        /// </summary>
+        /// <returns></returns>
+        public virtual bool ReduceDomainImage(object InputImage, ref object image)
+        {
+            image = null;
+            if (InputImage == null)
+            {
+                image = null;
+                Msg = "杈撳叆鍥剧墖涓虹┖";
+                Result = false;
+                return false;
+            }
+
+            lock (InputImage)
+            {
+                try
+                {
+                    if (InputImage is Bitmap)
+                    {
+                        TAlgorithm.Bitmap2Mat((Bitmap)InputImage, out Mat src);
+
+                        if (Params.Fixture == null)
+                            Params.Fixture = new Fixture();
+                        else if (dicFixtures.ContainsKey(Params.Fixture.strName))
+                            Params.Fixture = dicFixtures[Params.Fixture.strName];
+
+                        switch (Params.ROI?.GetType().Name)
+                        {
+                            case "HRectangle2":
+                                // 1. 瀹氫箟鏃嬭浆鐭╁舰锛堜腑蹇冪偣銆佸ぇ灏忋�佽搴︼級
+                                RotatedRect rotatedRect = new RotatedRect(
+                                    new Point2f(Convert.ToSingle(Params.ROI.X + Params.Fixture.X)
+                                    , Convert.ToSingle(Params.ROI.Y + Params.Fixture.Y)), // 涓績鍧愭爣
+                                    new Size2f(Convert.ToSingle(((HRectangle2)Params.ROI).Width)
+                                    , Convert.ToSingle(((HRectangle2)Params.ROI).Height)),  // 瀹藉害鍜岄珮搴�
+                                     Convert.ToSingle(((HRectangle2)Params.ROI).Angle + Params.Fixture.Angle)                   // 鏃嬭浆瑙掑害锛堝害锛�
+                                );
+
+                                // 2. 鑾峰彇鏃嬭浆鐭╁舰鐨�4涓《鐐�
+                                Point2f[] vertices = rotatedRect.Points();
+                                // 3. 淇瓒呭嚭杈圭晫鐨勭偣鍧愭爣锛堝叧閿楠わ級
+                                Point2f[] clampedPoints = vertices.Select(p =>
+                                {
+                                    float x = Clamp(p.X, 0, src.Width - 1);
+                                    float y = Clamp(p.Y, 0, src.Height - 1);
+                                    return new Point2f(x, y);
+                                }).ToArray();
+                                Rect boundingRect = Cv2.BoundingRect(clampedPoints);
+
+                                // 4. 鍒涘缓涓庡師鍥惧ぇ灏忕浉鍚岀殑Mat锛屽苟鍒濆鍖栨棤鏁堝��
+                                image = new Mat(src.Size(), src.Type());
+                                ((Mat)image).SetTo(TAlgorithm.GetInvalidValueForMat(src)); // 鍏ㄩ儴鍒濆鍖栦负鏃犳晥鍊�
+
+                                // 5. 鍒涘缓閬僵锛氬湪result涓婄粯鍒舵棆杞煩褰紙鐧借壊濉厖锛�
+                                using (Mat cropped = new Mat(src, boundingRect))
+                                {
+                                    cropped.CopyTo(new Mat(((Mat)image), boundingRect));
+                                }
+
+                                break;
+                            case "HCircle":
+                                // 1. 瀹氫箟鍦嗗舰锛堝渾蹇冦�佸崐寰勶級
+                                Point center = new Point(Params.ROI.X + Params.Fixture.X
+                                    , Params.ROI.Y + Params.Fixture.Y);
+                                int radius = Convert.ToInt16(((HCircle)Params.ROI).Radius);
+
+                                // 2. 鍒涘缓涓庡師鍥惧ぇ灏忕浉鍚岀殑Mat锛屽苟鍒濆鍖栨棤鏁堝��
+                                image = new Mat(src.Size(), src.Type());
+                                ((Mat)image).SetTo(TAlgorithm.GetInvalidValueForMat(src)); // 鍏ㄩ儴鍒濆鍖栦负鏃犳晥鍊�
+
+                                // 3. 鍒涘缓鍦嗗舰閬僵
+                                using (Mat mask = Mat.Zeros(src.Rows, src.Cols, MatType.CV_8UC1))
+                                {
+                                    Cv2.Circle(mask, center, radius, Scalar.White, -1);
+                                    src.CopyTo(((Mat)image), mask);
+                                }
+                                break;
+                            case "ROI":
+                            default:
+                                image = ((Bitmap)InputImage)?.Clone();
+                                return true;
+                        }
+                        TAlgorithm.Mat2Bitmap((Mat)image, out Bitmap bmp);
+                        image = bmp;
+                        return true;
+                    }
+                    else if (InputImage is HObject ho_image)
+                    {
+                        if (!ho_image.IsInitialized())
+                            return false;
+
+                        if (Params.Fixture == null)
+                            Params.Fixture = new Fixture();
+
+                        HObject hoDomainImage = null;
+
+                        switch (Params.ROI?.GetType().Name)
+                        {
+                            case "HRectangle2":
+                                HOperatorSet.GenRectangle2(out HObject hRectangle2, (HTuple)(Params.ROI.Row + Params.Fixture.Row), (HTuple)(Params.ROI.Column + Params.Fixture.Column)
+                                    , (HTuple)(Params.ROI.Phi + Params.Fixture.Phi), (HTuple)((HRectangle2)Params.ROI).SemiLength1, (HTuple)((HRectangle2)Params.ROI).SemiLength2);
+                                HOperatorSet.ReduceDomain(ho_image, hRectangle2, out hoDomainImage);
+                                break;
+                            case "HCircle":
+                                HOperatorSet.GenCircle(out HObject hCircle, (HTuple)(Params.ROI.Row + Params.Fixture.Row), (HTuple)(Params.ROI.Column + Params.Fixture.Column)
+                                    , (HTuple)((HCircle)Params.ROI).Radius);
+                                HOperatorSet.ReduceDomain(ho_image, hCircle, out hoDomainImage);
+                                break;
+                            case "ROI":
+                            default:
+                                image = ho_image.CopyObj(1, -1);
+                                return true;
+                        }
+
+                        image = hoDomainImage;
+                        return true;
+                    }
+                    else if (InputImage is Mat)
+                    {
+                        Mat src = ((Mat)InputImage);
+
+                        if (Params.Fixture == null)
+                            Params.Fixture = new Fixture();
+                        switch (Params.ROI?.GetType().Name)
+                        {
+                            case "HRectangle2":
+                                // 1. 瀹氫箟鏃嬭浆鐭╁舰锛堜腑蹇冪偣銆佸ぇ灏忋�佽搴︼級
+                                RotatedRect rotatedRect = new RotatedRect(
+                                    new Point2f(Convert.ToSingle(Params.ROI.X + Params.Fixture.X)
+                                    , Convert.ToSingle(Params.ROI.Y + Params.Fixture.Y)), // 涓績鍧愭爣
+                                    new Size2f(Convert.ToSingle(((HRectangle2)Params.ROI).Width)
+                                    , Convert.ToSingle(((HRectangle2)Params.ROI).Height)),  // 瀹藉害鍜岄珮搴�
+                                     Convert.ToSingle(((HRectangle2)Params.ROI).Angle + Params.Fixture.Angle)                   // 鏃嬭浆瑙掑害锛堝害锛�
+                                );
+
+                                // 2. 鑾峰彇鏃嬭浆鐭╁舰鐨�4涓《鐐�
+                                Point2f[] vertices = rotatedRect.Points();
+                                // 3. 淇瓒呭嚭杈圭晫鐨勭偣鍧愭爣锛堝叧閿楠わ級
+                                Point2f[] clampedPoints = vertices.Select(p =>
+                                {
+                                    float x = Clamp(p.X, 0, src.Width - 1);
+                                    float y = Clamp(p.Y, 0, src.Height - 1);
+                                    return new Point2f(x, y);
+                                }).ToArray();
+                                Rect boundingRect = Cv2.BoundingRect(clampedPoints);
+
+                                // 4. 鍒涘缓涓庡師鍥惧ぇ灏忕浉鍚岀殑Mat锛屽苟鍒濆鍖栨棤鏁堝��
+                                image = new Mat(src.Size(), src.Type());
+                                ((Mat)image).SetTo(TAlgorithm.GetInvalidValueForMat(src)); // 鍏ㄩ儴鍒濆鍖栦负鏃犳晥鍊�
+
+                                // 5. 鍒涘缓閬僵锛氬湪result涓婄粯鍒舵棆杞煩褰紙鐧借壊濉厖锛�
+                                using (Mat cropped = new Mat(src, boundingRect))
+                                {
+                                    cropped.CopyTo(new Mat(((Mat)image), boundingRect));
+                                }
+
+                                break;
+                            case "HCircle":
+                                // 1. 瀹氫箟鍦嗗舰锛堝渾蹇冦�佸崐寰勶級
+                                Point center = new Point(Params.ROI.X + Params.Fixture.X
+                                    , Params.ROI.Y + Params.Fixture.Y);
+                                int radius = Convert.ToInt16(((HCircle)Params.ROI).Radius);
+
+                                // 2. 鍒涘缓涓庡師鍥惧ぇ灏忕浉鍚岀殑Mat锛屽苟鍒濆鍖栨棤鏁堝��
+                                image = new Mat(src.Size(), src.Type());
+                                ((Mat)image).SetTo(TAlgorithm.GetInvalidValueForMat(src)); // 鍏ㄩ儴鍒濆鍖栦负鏃犳晥鍊�
+
+                                // 3. 鍒涘缓鍦嗗舰閬僵
+                                using (Mat mask = Mat.Zeros(src.Rows, src.Cols, MatType.CV_8UC1))
+                                {
+                                    Cv2.Circle(mask, center, radius, Scalar.White, -1);
+                                    src.CopyTo(((Mat)image), mask);
+                                }
+                                break;
+                            case "ROI":
+                            default:
+                                image = ((Mat)InputImage)?.Clone();
+                                return true;
+                        }
+                        return true;
+                    }
+                    else
+                    {
+                        image = null;
+                        Msg = $"杈撳叆鏍煎紡涓嶆纭畕InputImage.GetType()}";
+                        Result = false;
+                        return false;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    image = null;
+                    Msg = $"瑁佸壀鍖哄煙澶辫触,鍘熷洜鏄�:{ex.ToString()}";
+                    Result = false;
+                    return false;
+                }
+            }
+        }
+
+        public override void Dispose()
+        {
+            if (InputImage != null)
+            {
+                if (InputImage is HObject)
+                    ((HObject)InputImage).Dispose();
+                else if (InputImage is Mat)
+                    ((Mat)InputImage).Dispose();
+                else if (InputImage is Bitmap)
+                    ((Bitmap)InputImage).Dispose();
+
+                InputImage = null;
+            }
+
+            if (OutputImage != null)
+            {
+                if (OutputImage is HObject)
+                    ((HObject)OutputImage).Dispose();
+                else if (OutputImage is Mat)
+                    ((Mat)OutputImage).Dispose();
+                else if (OutputImage is Bitmap)
+                    ((Bitmap)OutputImage).Dispose();
+
+                OutputImage = null;
+            }
+
+            if (Record != null)
+            {
+                Record.Dispose();
+                Record = null;
+            }
+        }
+
+        public override object Clone()
+        {
+            try
+            {
+                var obj = (TAlgorithm)MemberwiseClone(); // 娴呮嫹璐�
+
+                // 鎵嬪姩澶勭悊寮曠敤绫诲瀷
+                if (InputImage != null)
+                {
+                    if (InputImage is HObject ho_image && ho_image.IsInitialized())
+                        obj.InputImage = ho_image.CopyObj(1, -1);
+                    else if (InputImage is Mat mat && !mat.Empty())
+                        obj.InputImage = mat.Clone();
+                    else if (InputImage is Bitmap bitmap)
+                        obj.InputImage = bitmap.Clone();
+                }
+
+                return obj;
+            }
+            catch { return (TAlgorithm)MemberwiseClone(); }
+        }
+
+        public override void InitRunParams()
+        {
+            Result = true;
+            bCompleted = false;
+            Msg = "";
+            OutputImage = null;
+
+            if (Record != null)
+                Record.Dispose();
+        }
+
+        public override bool Run()
+        {
+            DateTime StartTime = DateTime.Now;
+
+            InitRunParams();
+            HOperatorSet.GenEmptyObj(out HObject EmptyObj);
+            OutputImage = EmptyObj;
+
+            // 鍒涘缓骞跺惎鍔ㄤ换鍔�
+            Task.Factory.StartNew(() => { TAlgorithmMain(); });
+
+            while ((DateTime.Now - StartTime).TotalMilliseconds <= MaxTimeOut)
+            {
+                if (bCompleted)
+                {
+                    RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
+                    return Result;
+                }
+
+                Thread.Sleep(30);
+            }
+
+            Msg = "杩愯瓒呮椂";
+            Result = false;
+            RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
+            return false;
+        }
+
+        /// <summary>
+        /// 绠楀瓙閫昏緫
+        /// </summary>
+        public virtual void TAlgorithmMain()
+        {
+            bCompleted = true;
+            Debug.WriteLine("浠诲姟瀹屾垚");
+        }
+
+        /// <summary>
+        /// 鍔犺浇绠楁硶
+        /// </summary>
+        /// <param name="fullPath">瀹屾暣璺緞甯�.json</param>
+        /// <returns></returns>
+        public override bool Load(string fullPath = "")
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                if (!fullPath.Contains(".json"))
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+                if (string.IsNullOrEmpty(fullPath) || fullPath.Trim() == "")
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                string directoryPath = Path.GetDirectoryName(fullPath);
+                strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+
+                if (!File.Exists(fullPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    Save(directoryPath);
+                    return true;
+                }
+
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+                Params = JsonConvert.DeserializeObject<ProcessParams>(strJson);
+                if (Params == null)
+                    return false;
+
+                Params.FixDeserializedData();
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨绠楁硶
+        /// </summary>
+        /// <param name="filePath">涓嶅甫.json</param>
+        /// <returns></returns>
+        public override bool Save(string filePath = "")
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(filePath) || filePath.Trim() == "")
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                string strJson = string.Empty;
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Newtonsoft.Json.Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+                strJson = JsonConvert.SerializeObject(Params, settings);
+
+                Params = JsonConvert.DeserializeObject<ProcessParams>(strJson);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                if (!Directory.Exists(filePath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(filePath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+                File.WriteAllText(filePath + "//" + strProcessName + ".json", strJson, Encoding.UTF8);
+                return true;
+            }
+            catch { return false; }
+        }
+
+        #region 鑷畾涔夌殑绠楁硶
+        // 閫氱敤鐗堟湰鐨� Clamp 鏂规硶
+        public static T Clamp<T>(T value, T min, T max) where T : IComparable<T>
+        {
+            if (value.CompareTo(min) < 0)
+                return min;
+            else if (value.CompareTo(max) > 0)
+                return max;
+            else
+                return value;
+        }
+
+        public static void Bitmap2HObject(Bitmap bmp, out HObject image)
+        {
+            BitmapData srcBmpData;
+
+            try
+            {
+                if (bmp == null || bmp.Width == 0 || bmp.Height == 0)
+                {
+                    image = null;
+                    return;
+                }
+
+                lock (bmp)
+                {
+                    switch (bmp.PixelFormat)
+                    {
+                        case PixelFormat.Format24bppRgb:
+                            srcBmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
+
+                            int width = bmp.Width;
+                            int height = bmp.Height;
+                            int stride = srcBmpData.Stride;
+
+                            if (stride == width * 3)
+                                HOperatorSet.GenImageInterleaved(out image, srcBmpData.Scan0, "bgr", bmp.Width, bmp.Height, 0, "byte", 0, 0, 0, 0, -1, 0);
+                            else
+                                image = HandleStrideAlignmentBest(srcBmpData.Scan0, width, height, stride);
+
+                            bmp.UnlockBits(srcBmpData);
+                            break;
+                        default:
+                            srcBmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
+                            HOperatorSet.GenImage1(out image, "byte", bmp.Width, bmp.Height, srcBmpData.Scan0);
+                            bmp.UnlockBits(srcBmpData);
+                            break;
+                    }
+                }
+                return;
+            }
+            catch
+            {
+                image = null;
+                return;
+            }
+        }
+
+        private static HObject HandleStrideAlignmentBest(IntPtr scan0, int width, int height, int stride)
+        {
+            int expectedStride = width * 3;
+            byte[] alignedData = new byte[width * height * 3];
+
+            unsafe
+            {
+                byte* srcPtr = (byte*)scan0;
+                fixed (byte* dstPtr = alignedData)
+                {
+                    // 浣跨敤鏈�蹇�熺殑澶嶅埗鏂规硶
+
+                    // .NET Core 3.0+ 浣跨敤 Buffer.MemoryCopy
+                    for (int y = 0; y < height; y++)
+                    {
+                        Buffer.MemoryCopy(
+                            srcPtr + y * stride,
+                            dstPtr + y * expectedStride,
+                            expectedStride,
+                            expectedStride
+                        );
+                    }
+                    HOperatorSet.GenImageInterleaved(out HObject ho_img, new IntPtr(dstPtr), "bgr", width, height, 0, "byte", width, height, 0, 0, -1, 0);
+                    return ho_img;
+                }
+            }
+        }
+
+        public static unsafe void HObject2Bitmap(HObject hObject, out Bitmap bmp)
+        {
+            try
+            {
+                if (hObject == null || !hObject.IsInitialized())
+                {
+                    bmp = null;
+                    return;
+                }
+
+                // 鑾峰彇鍥惧儚淇℃伅
+                HOperatorSet.GetImageSize(hObject, out HTuple width, out HTuple height);
+                HOperatorSet.CountChannels(hObject, out HTuple channels);
+
+                if (channels.I == 1)
+                {
+                    // 鐏板害鍥惧鐞�
+                    HTuple ptr, type;
+                    HOperatorSet.GetImagePointer1(hObject, out ptr, out type, out width, out height);
+
+                    bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
+
+                    // 璁剧疆鐏板害璋冭壊鏉�
+                    ColorPalette palette = bmp.Palette;
+                    for (int i = 0; i < 256; i++)
+                        palette.Entries[i] = Color.FromArgb(i, i, i);
+                    bmp.Palette = palette;
+
+                    // 鐩存帴鍐呭瓨鎷疯礉
+                    BitmapData bmpData = bmp.LockBits(
+                        new Rectangle(0, 0, width, height),
+                        ImageLockMode.WriteOnly,
+                        PixelFormat.Format8bppIndexed);
+
+                    Buffer.MemoryCopy(
+                      (void*)ptr.L,
+                      (void*)bmpData.Scan0,
+                      width * height,
+                      width * height);
+
+                    bmp.UnlockBits(bmpData);
+                    return;
+                }
+                else
+                {
+                    // 褰╄壊鍥惧鐞嗭紙BGR椤哄簭锛�
+                    HTuple ptrR, ptrG, ptrB, type;
+                    HOperatorSet.GetImagePointer3(hObject, out ptrR, out ptrG, out ptrB, out type, out width, out height);
+
+                    bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
+                    BitmapData bmpData = bmp.LockBits(
+                        new Rectangle(0, 0, width, height),
+                        ImageLockMode.WriteOnly,
+                        PixelFormat.Format24bppRgb);
+
+                    byte* dstPtr = (byte*)bmpData.Scan0;
+                    byte* srcR = (byte*)ptrR.L;
+                    byte* srcG = (byte*)ptrG.L;
+                    byte* srcB = (byte*)ptrB.L;
+
+                    Parallel.For(0, height.I, y =>
+                    {
+                        int srcOffset = y * width;
+                        int dstOffset = y * bmpData.Stride;
+
+                        for (int x = 0; x < width; x++)
+                        {
+                            dstPtr[dstOffset + x * 3] = srcB[srcOffset + x];     // B
+                            dstPtr[dstOffset + x * 3 + 1] = srcG[srcOffset + x]; // G
+                            dstPtr[dstOffset + x * 3 + 2] = srcR[srcOffset + x]; // R
+                        }
+                    });
+
+                    bmp.UnlockBits(bmpData);
+                    return;
+                }
+            }
+            catch
+            {
+                bmp = null;
+                return;
+            }
+        }
+
+        public static void Mat2HObject(Mat mat, out HObject image)
+        {
+            try
+            {
+                if (mat == null || mat.Empty())
+                {
+                    image = null;
+                    return;
+                }
+
+                if (mat.Type() == MatType.CV_8UC3) // 褰╄壊鍥惧儚 (BGR)
+                {
+                    HOperatorSet.GenImageInterleaved(
+                        out image,
+                        mat.Data,
+                        "bgr",
+                        mat.Width,
+                        mat.Height,
+                        0,
+                        "byte",
+                        0, 0, 0, 0, -1, 0);
+                }
+                else if (mat.Type() == MatType.CV_8UC1) // 鐏板害鍥惧儚
+                {
+                    HOperatorSet.GenImage1(
+                        out image,
+                        "byte",
+                        mat.Width,
+                        mat.Height,
+                        mat.Data);
+                }
+                else
+                {
+                    throw new ArgumentException($"Mat2HObject涓嶆敮鎸佺殑鍥惧儚鏍煎紡锛歿mat.Type()}");
+                }
+                return;
+            }
+            catch
+            {
+                image = null;
+                return;
+            }
+        }
+
+        public static void HObject2Mat(HObject image, out Mat mat)
+        {
+            try
+            {
+                if (image == null || !image.IsInitialized())
+                {
+                    mat = null;
+                    return;
+                }
+
+                // 鑾峰彇鍥惧儚绫诲瀷淇℃伅
+                HOperatorSet.CountChannels(image, out HTuple channels);
+
+                // 鏍规嵁閫氶亾鏁伴�夋嫨涓嶅悓鐨勫鐞嗘柟寮�
+                if (channels.I == 1)
+                {
+                    mat = ConvertGrayImage(image);
+                }
+                else if (channels.I == 3)
+                {
+                    mat = ConvertColorImage(image);
+                }
+                else
+                {
+                    mat = null;
+                    return;
+                }
+            }
+            catch
+            {
+                mat = null;
+                return;
+            }
+        }
+
+        public static Mat ConvertColorImage(HObject colorimage)
+        {
+            // 鑾峰彇Halcon鍥惧儚鎸囬拡
+            HOperatorSet.GetImagePointer3(colorimage,
+                out HTuple ptrR, out HTuple ptrG, out HTuple ptrB,
+                out HTuple type, out HTuple width, out HTuple height);
+
+            // 鍒涘缓OpenCV Mat锛堟敞鎰廈GR椤哄簭锛�
+            Mat mat = new Mat(height.I, width.I, MatType.CV_8UC3);
+
+            unsafe
+            {
+                byte* matPtr = (byte*)mat.Data;
+                byte[] r = new byte[width * height];
+                byte[] g = new byte[width * height];
+                byte[] b = new byte[width * height];
+
+                // 浠嶩alcon鎷疯礉鏁版嵁
+                Marshal.Copy(ptrR.IP, r, 0, r.Length);
+                Marshal.Copy(ptrG.IP, g, 0, g.Length);
+                Marshal.Copy(ptrB.IP, b, 0, b.Length);
+
+                // 濉厖Mat锛圚alcon鐨凴GB 鈫� OpenCV鐨凚GR锛�
+                for (int i = 0; i < height; i++)
+                {
+                    for (int j = 0; j < width; j++)
+                    {
+                        int idx = i * width + j;
+                        matPtr[i * mat.Step() + j * 3] = b[idx];     // B
+                        matPtr[i * mat.Step() + j * 3 + 1] = g[idx]; // G
+                        matPtr[i * mat.Step() + j * 3 + 2] = r[idx]; // R
+                    }
+                }
+            }
+            return mat;
+        }
+
+        public static Mat ConvertGrayImage(HObject grayImage)
+        {
+            // 鑾峰彇鍗曢�氶亾鍥惧儚鎸囬拡
+            HOperatorSet.GetImagePointer1(grayImage, out HTuple ptrGray,
+                out HTuple type, out HTuple width, out HTuple height);
+
+            // 鍒涘缓OpenCV鐏板害Mat
+            Mat mat = new Mat(height.I, width.I, MatType.CV_8UC1);
+
+            //鑾峰彇鍥惧儚鏁版嵁鎬诲瓧鑺傛暟
+            int totalBytes = width.I * height.I;
+            // 浣跨敤闈炴墭绠″唴瀛樺鍒�
+            unsafe
+            {
+                Buffer.MemoryCopy(
+                    (void*)ptrGray.IP,     // 婧愭寚閽� (Halcon)
+                    (void*)mat.Data,       // 鐩爣鎸囬拡 (OpenCV)
+                    totalBytes,            // 鐩爣缂撳啿鍖哄ぇ灏�
+                    totalBytes             // 瑕佸鍒剁殑瀛楄妭鏁�
+                );
+            }
+            // 鎷疯礉鏁版嵁
+            //Marshal.Copy(ptrGray.IP, mat.Data, 0, width.I * height.I);
+
+            return mat;
+        }
+
+        public static void Bitmap2Mat(Bitmap bmp, out Mat image)
+        {
+            try
+            {
+                if (bmp == null)
+                {
+                    image = null;
+                    return;
+                }
+
+                image = Extensions.BitmapConverter.ToMat(bmp);
+                return;
+            }
+            catch
+            {
+                image = null;
+                return;
+            }
+        }
+
+        public static void Mat2Bitmap(Mat mat, out Bitmap image)
+        {
+            try
+            {
+                if (mat == null)
+                {
+                    image = null;
+                    return;
+                }
+
+                image = Extensions.BitmapConverter.ToBitmap(mat);
+            }
+            catch
+            {
+                image = null;
+                return;
+            }
+        }
+
+        public static void Bitmap2BinaryBitmap(Bitmap bitmap, out BinaryBitmap binarybitmap)
+        {
+            BinaryBitmap bbmp;
+            try
+            {
+                if (bitmap != null)
+                {
+                    LuminanceSource source = new BitmapLuminanceSource(bitmap);
+                    //var binarizer = new GlobalHistogramBinarizer(source);
+                    var binarizer = new HybridBinarizer(source); // 鎴栬�呯敤杩欎釜
+                    bbmp = new BinaryBitmap(binarizer);
+                    binarybitmap = bbmp;
+                }
+                else
+                {
+                    binarybitmap = null;
+                }
+            }
+            catch
+            {
+                binarybitmap = null;
+            }
+        }
+
+        public static void BinaryBitmap2Bitmap(BinaryBitmap binarybitmap, out Bitmap bitmap)
+        {
+            try
+            {
+                if (binarybitmap != null)
+                {
+                    BitMatrix bitmatrix = binarybitmap.BlackMatrix;
+                    bitmap = new Bitmap(bitmatrix.Width, bitmatrix.Height);
+                    for (int i = 0; i < bitmatrix.Width; i++)
+                    {
+                        for (int j = 0; j < bitmatrix.Height; j++)
+                            bitmap.SetPixel(i, j, bitmatrix[i, j] ? Color.Black : Color.White);
+                    }
+                }
+                else
+                {
+                    bitmap = null;
+                }
+            }
+            catch
+            {
+                bitmap = null;
+            }
+        }
+
+        public static void DeepImage2PointsCloud(HObject image, out HTuple pointsCloud)
+        {
+            // Stack for temporary objects 
+            HObject[] OTemp = new HObject[20];
+
+            // Local iconic variables 
+
+            HObject ho_ImageZ, ho_ImageX, ho_ImageY, ho_Region;
+            HObject ho_ImageReduced, ho_Z, ho_ImageScaled;
+
+            // Local control variables 
+
+            HTuple hv_xResolution = new HTuple(), hv_yResolution = new HTuple();
+            HTuple hv_zResolution = new HTuple(), hv_ScaleFactor = new HTuple();
+            HTuple hv_WindowHandle = new HTuple(), hv_Width = new HTuple();
+            HTuple hv_Height = new HTuple(), hv_Min = new HTuple();
+            HTuple hv_Max = new HTuple(), hv_Range = new HTuple();
+            HTuple hv_factor = new HTuple(), hv_ScaleZ = new HTuple();
+            HTuple hv_zScale = new HTuple();
+            HTuple hv_Instructions = new HTuple(), hv_PoseOut = new HTuple();
+            pointsCloud = new HTuple();
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_ImageZ);
+            HOperatorSet.GenEmptyObj(out ho_ImageX);
+            HOperatorSet.GenEmptyObj(out ho_ImageY);
+            HOperatorSet.GenEmptyObj(out ho_Region);
+            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
+            HOperatorSet.GenEmptyObj(out ho_Z);
+            HOperatorSet.GenEmptyObj(out ho_ImageScaled);
+            try
+            {
+                //璇诲彇娣卞害鍥�
+                ho_ImageZ.Dispose();
+                ho_ImageZ = image;
+
+                //纭畾xyz鐨勬樉绀哄垎杈ㄧ巼锛屽嵆纭畾缂╂斁鍥犲瓙
+                hv_xResolution.Dispose();
+                hv_xResolution = 1;
+                hv_yResolution.Dispose();
+                hv_yResolution = 1;
+                hv_zResolution.Dispose();
+                hv_zResolution = 1;
+                //纭畾缂╂斁鍥犲瓙
+                hv_ScaleFactor.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_ScaleFactor = new HTuple();
+                    hv_ScaleFactor = hv_ScaleFactor.TupleConcat(hv_xResolution, hv_yResolution, hv_zResolution);
+                }
+                //鑾峰彇绐楀彛鍙ユ焺
+                if (HDevWindowStack.IsOpen())
+                {
+                    hv_WindowHandle = HDevWindowStack.GetActive();
+                }
+                //鑾峰彇鍥惧儚澶у皬
+                hv_Width.Dispose(); hv_Height.Dispose();
+                HOperatorSet.GetImageSize(ho_ImageZ, out hv_Width, out hv_Height);
+
+
+                //鐢熸垚X鏇查潰鍥惧儚
+                ho_ImageX.Dispose();
+                HOperatorSet.GenImageSurfaceFirstOrder(out ho_ImageX, "real", 0, 1, 0, 0, 0,
+                    hv_Width, hv_Height);
+                //鐢熸垚Y鏇查潰鍥惧儚
+                ho_ImageY.Dispose();
+                HOperatorSet.GenImageSurfaceFirstOrder(out ho_ImageY, "real", 1, 0, 0, 0, 0,
+                    hv_Width, hv_Height);
+
+
+                //瀵规繁搴﹀浘杩涜澶勭悊婊ゆ尝澶勭悊
+
+                //鑾峰彇娣卞害鍥炬渶灏忓�� Min 鍜屾渶澶у�� Max锛屼互鍙婅寖鍥� Range
+                hv_Min.Dispose(); hv_Max.Dispose(); hv_Range.Dispose();
+                HOperatorSet.MinMaxGray(ho_ImageZ, ho_ImageZ, 0, out hv_Min, out hv_Max, out hv_Range);
+
+                //濡傛灉鏈�灏忓�煎皬浜�0锛屽垯鍥惧儚涔�1锛屽姞-min锛屽嵆淇濇寔鏈�浣庡�间负0
+                if ((int)(new HTuple(hv_Min.TupleLess(0.0))) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HObject ExpTmpOutVar_0;
+                        HOperatorSet.ScaleImage(ho_ImageZ, out ExpTmpOutVar_0, 1.0, -hv_Min);
+                        ho_ImageZ.Dispose();
+                        ho_ImageZ = ExpTmpOutVar_0;
+                    }
+                }
+                //鑾峰彇鏂版繁搴﹀浘鐨勬渶灏忓�� Min 鍜屾渶澶у�� Max锛屼互鍙婅寖鍥� Range
+                hv_Min.Dispose(); hv_Max.Dispose(); hv_Range.Dispose();
+                HOperatorSet.MinMaxGray(ho_ImageZ, ho_ImageZ, 0, out hv_Min, out hv_Max, out hv_Range);
+                // 妫�鏌in鍜孧ax鐨勫��
+                Debug.WriteLine($"Min: {hv_Min.D}, Max: {hv_Max.D}");
+                //闃堝�兼彁鍙栵紙鏍稿績锛�
+                ho_Region.Dispose();
+                HOperatorSet.Threshold(ho_ImageZ, out ho_Region
+                    , hv_Max.D < 1.0 ? 0 : 1, hv_Max);
+                //鑾峰彇鍖哄煙鍥惧儚
+                ho_ImageReduced.Dispose();
+                HOperatorSet.ReduceDomain(ho_ImageZ, ho_Region, out ho_ImageReduced);
+                //杞疄鏁板浘
+                ho_Z.Dispose();
+                HOperatorSet.ConvertImageType(ho_ImageReduced, out ho_Z, "real");
+                //鑾峰彇鏂版繁搴﹀浘鐨勬渶灏忓�� Min 鍜屾渶澶у�� Max锛屼互鍙婅寖鍥� Range
+                hv_Min.Dispose(); hv_Max.Dispose(); hv_Range.Dispose();
+                HOperatorSet.MinMaxGray(ho_Z, ho_Z, 0, out hv_Min, out hv_Max, out hv_Range);
+                //璁$畻缂╂斁鍥犲瓙 factor = xResolution / zResolution锛岀劧鍚庤绠� Z 鏂瑰悜涓婄殑缂╂斁姣斾緥 ScaleZ = 1 / factor
+                hv_factor.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_factor = hv_xResolution / hv_zResolution;
+                }
+                hv_ScaleZ.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_ScaleZ = 1 / hv_factor;
+                }
+                //杈撳嚭
+                hv_zScale.Dispose();
+                hv_zScale = new HTuple(hv_ScaleZ);
+                //灏� Z 鎸夌収缂╂斁姣斾緥 ScaleZ 杩涜缂╂斁锛屽苟瀛樺偍鍦� ImageScaled 涓�
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    ho_ImageScaled.Dispose();
+                    HOperatorSet.ScaleImage(ho_Z, out ho_ImageScaled, hv_ScaleZ, (-hv_ScaleZ) * hv_Min);
+                }
+
+                //鎶奨,Y,Z鍥惧儚鎷熷悎涓�3D鐐逛簯妯″瀷
+                pointsCloud.Dispose();
+                HOperatorSet.XyzToObjectModel3d(ho_ImageX, ho_ImageY, ho_ImageScaled, out pointsCloud);
+                //HOperatorSet.WriteObjectModel3d(hv_ObjectModel3D, "om3", "test", new HTuple(),
+                //    new HTuple());
+                if (hv_Instructions == null)
+                    hv_Instructions = new HTuple();
+                hv_Instructions[0] = "";
+
+                //objectModel3D = hv_ObjectModel3D.Clone();
+                //// 鎸佷箙鍖栫敓鎴愮殑3D妯″瀷
+                //HOperatorSet.WriteObjectModel3d(objectModel3D, "om3", "pcl.om3", new HTuple(), new HTuple());
+                //// 鎻愮ず鐢熸垚3D妯″瀷鎴愬姛
+                //MessageBox.Show("鐢熸垚3D妯″瀷OK");
+
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_ImageZ.Dispose();
+                ho_ImageX.Dispose();
+                ho_ImageY.Dispose();
+                ho_Region.Dispose();
+                ho_ImageReduced.Dispose();
+                ho_Z.Dispose();
+                ho_ImageScaled.Dispose();
+
+                hv_xResolution.Dispose();
+                hv_yResolution.Dispose();
+                hv_zResolution.Dispose();
+                hv_ScaleFactor.Dispose();
+                hv_WindowHandle.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_Min.Dispose();
+                hv_Max.Dispose();
+                hv_Range.Dispose();
+                hv_factor.Dispose();
+                hv_ScaleZ.Dispose();
+                hv_zScale.Dispose();
+                hv_Instructions.Dispose();
+                hv_PoseOut.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+            finally
+            {
+                ho_ImageZ.Dispose();
+                ho_ImageX.Dispose();
+                ho_ImageY.Dispose();
+                ho_Region.Dispose();
+                ho_ImageReduced.Dispose();
+                ho_Z.Dispose();
+                ho_ImageScaled.Dispose();
+
+                hv_xResolution.Dispose();
+                hv_yResolution.Dispose();
+                hv_zResolution.Dispose();
+                hv_ScaleFactor.Dispose();
+                hv_WindowHandle.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_Min.Dispose();
+                hv_Max.Dispose();
+                hv_Range.Dispose();
+                hv_factor.Dispose();
+                hv_ScaleZ.Dispose();
+                hv_zScale.Dispose();
+                hv_Instructions.Dispose();
+                hv_PoseOut.Dispose();
+            }
+        }
+
+        public static void DeepImage2PointsCloud(HObject image, out HTuple pointsCloud
+            , double XScale = 1, double YScale = 1, double ZScale = 1, int ZOffset = 0
+            , int InvalidValue = 0, int minColor = 0, int maxColor = 180, double grayPercent = 0.8)
+        {
+            // Stack for temporary objects 
+            HObject[] OTemp = new HObject[20];
+
+            // Local iconic variables 
+            HObject ho_ImageH;
+            HObject ho_ImageZ, ho_ImageX, ho_ImageY, ho_Region;
+            HObject ho_ImageReduced, ho_Z, ho_ImageScaled;
+
+            // Local control variables 
+
+            HTuple hv_xResolution = new HTuple(), hv_yResolution = new HTuple();
+            HTuple hv_zResolution = new HTuple(), hv_ScaleFactor = new HTuple();
+            HTuple hv_WindowHandle = new HTuple(), hv_Width = new HTuple();
+            HTuple hv_Height = new HTuple(), hv_Min = new HTuple();
+            HTuple hv_Max = new HTuple(), hv_Range = new HTuple();
+            HTuple hv_factor = new HTuple(), hv_ScaleZ = new HTuple();
+            HTuple hv_zScale = new HTuple();
+            HTuple hv_Instructions = new HTuple(), hv_PoseOut = new HTuple();
+            pointsCloud = new HTuple();
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_ImageH);
+            HOperatorSet.GenEmptyObj(out ho_ImageZ);
+            HOperatorSet.GenEmptyObj(out ho_ImageX);
+            HOperatorSet.GenEmptyObj(out ho_ImageY);
+            HOperatorSet.GenEmptyObj(out ho_Region);
+            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
+            HOperatorSet.GenEmptyObj(out ho_Z);
+            HOperatorSet.GenEmptyObj(out ho_ImageScaled);
+            try
+            {
+                //鑾峰彇鍘熷浘鍍�
+                ho_ImageH.Dispose();
+                HOperatorSet.CopyImage(image, out ho_ImageH);
+
+                hv_Width.Dispose(); hv_Height.Dispose();
+                HOperatorSet.GetImageSize(image, out hv_Width, out hv_Height);
+
+                //璇诲彇娣卞害鍥�
+                ho_ImageZ.Dispose();
+                HOperatorSet.GetDomain(ho_ImageH, out HObject ho_ImageDomain);
+
+                //鑾峰彇娣卞害鍥炬渶灏忓�� Min 鍜屾渶澶у�� Max锛屼互鍙婅寖鍥� Range
+                hv_Min.Dispose(); hv_Max.Dispose(); hv_Range.Dispose();
+                HOperatorSet.MinMaxGray(ho_ImageDomain, ho_ImageH, 0, out hv_Min, out hv_Max, out hv_Range);
+
+                // 妫�鏌in鍜孧ax鐨勫��
+                Debug.WriteLine($"Min: {hv_Min.D}, Max: {hv_Max.D}");
+                //濡傛灉鏈�灏忓�煎皬浜�0锛屽垯鍥惧儚涔�1锛屽姞-min锛屽嵆淇濇寔鏈�浣庡�间负0
+                //if ((int)(new HTuple(hv_Min.TupleLess(0.0))) != 0)
+                //{
+                //    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                //    {
+                //        HObject ExpTmpOutVar_0;
+                //        HOperatorSet.ScaleImage(ho_ImageZ, out ExpTmpOutVar_0, 1.0, -hv_Min);
+                //        ho_ImageZ.Dispose();
+                //        ho_ImageZ = ExpTmpOutVar_0;
+                //    }
+                //}
+
+                //闃堝�兼彁鍙栵紙鏍稿績锛�
+                ho_Region.Dispose();
+                HOperatorSet.Threshold(ho_ImageH, out ho_Region
+                    , hv_Min.D > 0 && InvalidValue > 0 ? InvalidValue : 0, hv_Max);
+
+                //杞疄鏁板浘
+                HOperatorSet.ConvertImageType(ho_ImageH, out ho_ImageH, "real");
+
+                //灏� Z 鎸夌収缂╂斁姣斾緥 ScaleZ 杩涜缂╂斁锛屽苟瀛樺偍鍦� ImageScaled 涓�
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    ho_ImageScaled.Dispose();
+                    HOperatorSet.ScaleImage(ho_ImageH, out ho_ImageScaled, ZScale, ZScale * ZOffset);
+                }
+
+                //鑾峰彇鏂版繁搴﹀浘鐨勬渶灏忓�� Min 鍜屾渶澶у�� Max锛屼互鍙婅寖鍥� Range
+                hv_Min.Dispose(); hv_Max.Dispose(); hv_Range.Dispose();
+                HOperatorSet.MinMaxGray(ho_Region, ho_ImageScaled, 0, out hv_Min, out hv_Max, out hv_Range);
+
+                //灏嗛珮搴﹀浘杞负HSV鏍煎紡鐨勫浘鍍�
+                double k = (maxColor - minColor) * 1.0 / (hv_Max.D - hv_Min.D);
+                double b = maxColor - k * hv_Min.D * 1.0;
+                HOperatorSet.ReduceDomain(ho_ImageScaled, ho_Region, out HObject ho_ImageZOut);
+                //
+                HOperatorSet.ScaleImage(ho_ImageZOut, out HObject ho_ImageZOutScaled, k, b);
+                HOperatorSet.ConvertImageType(ho_ImageZOutScaled, out HObject ho_ImageZByte, "byte");
+                HOperatorSet.GenImageProto(ho_ImageZByte, out HObject ho_ImageZProto, 255);
+                HOperatorSet.TransToRgb(ho_ImageZByte, ho_ImageZProto, ho_ImageZProto
+                    , out HObject H, out HObject S, out HObject V, "hsv");
+                HOperatorSet.Compose3(H, S, V, out HObject HSV);
+
+                //鐢熸垚X鏇查潰鍥惧儚
+                ho_ImageX.Dispose();
+                HOperatorSet.GenImageSurfaceFirstOrder(out ho_ImageX, "real", 0, XScale, 0, 0, 0,
+                    hv_Width, hv_Height);
+                //鐢熸垚Y鏇查潰鍥惧儚
+                ho_ImageY.Dispose();
+                HOperatorSet.GenImageSurfaceFirstOrder(out ho_ImageY, "real", YScale, 0, 0, 0, 0,
+                    hv_Width, hv_Height);
+
+                //鎶奨,Y,Z鍥惧儚鎷熷悎涓�3D鐐逛簯妯″瀷
+                pointsCloud.Dispose();
+                HOperatorSet.XyzToObjectModel3d(ho_ImageX, ho_ImageY, ho_ImageZOut, out pointsCloud);
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_ImageZ.Dispose();
+                ho_ImageX.Dispose();
+                ho_ImageY.Dispose();
+                ho_Region.Dispose();
+                ho_ImageReduced.Dispose();
+                ho_Z.Dispose();
+                ho_ImageScaled.Dispose();
+
+                hv_xResolution.Dispose();
+                hv_yResolution.Dispose();
+                hv_zResolution.Dispose();
+                hv_ScaleFactor.Dispose();
+                hv_WindowHandle.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_Min.Dispose();
+                hv_Max.Dispose();
+                hv_Range.Dispose();
+                hv_factor.Dispose();
+                hv_ScaleZ.Dispose();
+                hv_zScale.Dispose();
+                hv_Instructions.Dispose();
+                hv_PoseOut.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+            finally
+            {
+                ho_ImageH.Dispose();
+                ho_ImageZ.Dispose();
+                ho_ImageX.Dispose();
+                ho_ImageY.Dispose();
+                ho_Region.Dispose();
+                ho_ImageReduced.Dispose();
+                ho_Z.Dispose();
+                ho_ImageScaled.Dispose();
+
+                hv_xResolution.Dispose();
+                hv_yResolution.Dispose();
+                hv_zResolution.Dispose();
+                hv_ScaleFactor.Dispose();
+                hv_WindowHandle.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_Min.Dispose();
+                hv_Max.Dispose();
+                hv_Range.Dispose();
+                hv_factor.Dispose();
+                hv_ScaleZ.Dispose();
+                hv_zScale.Dispose();
+                hv_Instructions.Dispose();
+                hv_PoseOut.Dispose();
+            }
+        }
+
+        public static void PointsCloud2DeepImage(HTuple pointsCloud, out HObject image, double Resolution = 1.0)
+        {
+            HOperatorSet.GenEmptyObj(out image);
+            image = null;
+            try
+            {
+                HOperatorSet.GetObjectModel3dParams(pointsCloud, "point_coord_z", out HTuple hv_z);
+                HOperatorSet.GetObjectModel3dParams(pointsCloud, "point_coord_y", out HTuple hv_y);
+                HOperatorSet.GetObjectModel3dParams(pointsCloud, "point_coord_x", out HTuple hv_x);
+
+                HOperatorSet.TupleMin(hv_x, out HTuple hv_Min);
+                HTuple hv_xTemp = hv_x - hv_Min;
+                hv_x = hv_xTemp;
+                hv_xTemp = ((hv_x / Resolution)).TupleInt();
+                hv_x.Dispose();
+                hv_x = hv_xTemp;
+
+                HOperatorSet.TupleMin(hv_y, out hv_Min);
+                HTuple hv_yTemp = hv_y - hv_Min;
+                hv_y = hv_yTemp;
+                hv_yTemp = ((hv_y / Resolution)).TupleInt();
+                hv_y.Dispose();
+                hv_y = hv_yTemp;
+
+                HOperatorSet.TupleMin(hv_z, out hv_Min);
+                HTuple hv_zTemp = hv_z - hv_Min;
+                hv_z.Dispose();
+                hv_z = hv_zTemp;
+
+                HOperatorSet.TupleMax(hv_x, out HTuple hv_xMax);
+                HOperatorSet.TupleMax(hv_y, out HTuple hv_yMax);
+                HOperatorSet.GenImageConst(out image, "real", hv_xMax + 1, hv_yMax + 1);
+                HOperatorSet.SetGrayval(image, hv_y, hv_x, hv_z);
+
+                //hoperatorset.getimagesize(ho_image, out htuple hv_width, out htuple hv_height);
+                //hoperatorset.genrectangle1(out hobject ho_rectangle, 0, 0, hv_height - 1, hv_width - 1);
+                //hoperatorset.getregionpoints(ho_rectangle, out htuple hv_rows, out htuple hv_columns);
+                //hoperatorset.getgrayval(ho_image, hv_rows, hv_columns, out htuple hv_z);
+            }
+            catch { image = null; }
+        }
+
+        /// <summary>
+        /// 璁$畻涓ょ偣鐨勮窛绂�
+        /// </summary>
+        /// <param name="startPoint"></param>
+        /// <param name="endPoint"></param>
+        /// <returns></returns>
+        public static double GetDistanceP2P(HPoint startPoint, HPoint endPoint)
+        {
+            try
+            {
+                return Math.Sqrt(Math.Pow(startPoint.X - endPoint.X, 2) + Math.Pow(startPoint.Y - endPoint.Y, 2));
+            }
+            catch { return 9994; }
+        }
+
+        public static double GetDistanceP2P(Point startPoint, Point endPoint)
+        {
+            return GetDistanceP2P(new HPoint(startPoint), new HPoint(endPoint));
+        }
+
+        public static double DistanceP2P(double startX, double startY, double endX, double endY)
+        {
+            return GetDistanceP2P(new HPoint(startX, startY), new HPoint(endX, endY));
+        }
+
+        /// <summary>
+        /// 鑾峰彇涓ょ偣鐨勪腑鐐�
+        /// </summary>
+        /// <param name="startPoint"></param>
+        /// <param name="endPoint"></param>
+        /// <returns></returns>
+        public static HPoint GetMidPoint(HPoint startPoint, HPoint endPoint)
+        {
+            return new HPoint((startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2);
+        }
+
+        public static Point GetMidPoint(Point startPoint, Point endPoint)
+        {
+            return new Point((startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2);
+        }
+
+        public static System.Drawing.Point GetMidPoint(System.Drawing.Point startPoint, System.Drawing.Point endPoint)
+        {
+            return new System.Drawing.Point((startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2);
+        }
+
+        /// <summary>
+        /// 鍒ゆ柇鐐规槸鍚﹀湪绾挎涓�
+        /// </summary>
+        /// <param name="point"></param>
+        /// <param name="segment"></param>
+        /// <returns></returns>
+        public static bool IsPointOnSegment(HPoint pt, HSegment segment, double tolerance = 1e-3)
+        {
+            // 璁$畻鐩寸嚎鏂圭▼鐨勭郴鏁�
+            double A = segment.EndY - segment.StartX;
+            double B = segment.StartX - segment.EndX;
+            double C = segment.EndX * segment.StartY - segment.StartX * segment.EndY;
+
+            // 璁$畻鐐瑰埌鐩寸嚎鐨勮窛绂�
+            double distance = Math.Abs(A * pt.X + B * pt.Y + C) / Math.Sqrt(A * A + B * B);
+
+            // 鍏佽涓�涓緢灏忕殑璇樊
+            if (distance < tolerance)
+            {
+                // 鍒ゆ柇鐐规槸鍚﹀湪鐩寸嚎娈佃寖鍥村唴
+                if (Math.Min(segment.StartX, segment.EndX) <= pt.X && pt.X <= Math.Max(segment.StartX, segment.EndX)
+                 && Math.Min(segment.StartY, segment.EndY) <= pt.Y && pt.Y <= Math.Max(segment.StartY, segment.EndY))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public static bool IsPointOnSegment(double px, double py, double x1, double y1, double x2, double y2)
+        {
+            return IsPointOnSegment(new HPoint(px, py), new HSegment(x1, y1, x2, y2));
+        }
+
+        /// <summary>
+        /// 鍒ゆ柇鐐规槸鍚﹀湪鐭╁舰杈归檮杩�
+        /// </summary>
+        /// <param name="pt"></param>
+        /// <param name="rect"></param>
+        /// <param name="tolerance"></param>
+        /// <returns></returns>
+        static bool IsPointNearRectangleSilde(System.Drawing.Point pt, Rectangle rect, double tolerance = 100)
+        {
+            try
+            {
+                // 濡傛灉鐐圭殑 X 鍧愭爣绛変簬鐭╁舰鐨勫乏杈� (rect.Left) 鎴栧彸杈� (rect.Right)锛屽苟涓� Y 鍧愭爣鍦ㄧ煩褰㈢殑涓婁笅杈圭晫涔嬮棿锛岄偅涔堢偣鍦ㄧ煩褰㈢殑鍨傜洿杈圭晫涓娿��
+                // 濡傛灉鐐圭殑 Y 鍧愭爣绛変簬鐭╁舰鐨勪笂杈�(rect.Top) 鎴栦笅杈�(rect.Bottom)锛屽苟涓� X 鍧愭爣鍦ㄧ煩褰㈢殑宸﹀彸杈圭晫涔嬮棿锛岄偅涔堢偣鍦ㄧ煩褰㈢殑姘村钩杈圭晫涓娿��
+                return (Math.Abs(pt.X - rect.Left) <= tolerance || Math.Abs(pt.X - rect.Right) <= tolerance) && pt.Y >= rect.Top + tolerance && pt.Y <= rect.Bottom - tolerance
+                    || (Math.Abs(pt.Y - rect.Top) <= tolerance || Math.Abs(pt.Y - rect.Bottom) <= tolerance) && pt.X >= rect.Left - tolerance && pt.X <= rect.Right + tolerance;
+
+            }
+            catch { return false; }
+        }
+
+        public static bool IsPointNearRectangleSilde(HPoint pt, HRectangle2 rect, double tolerance = 100)
+        {
+            return IsPointNearRectangleSilde(new System.Drawing.Point((int)pt.X, (int)pt.Y), new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height), tolerance);
+        }
+
+        /// <summary>
+        /// 鍒ゆ柇鐐规槸鍚﹀湪鐐归檮杩�
+        /// </summary>
+        /// <param name="pt1"></param>
+        /// <param name="pt2"></param>
+        /// <param name="tolerance"></param>
+        /// <returns></returns>
+        public static bool IsPointNearPoint(HPoint pt1, HPoint pt2, double tolerance = 100)
+        {
+            if (GetDistanceP2P(pt1, pt2) <= tolerance)
+                return true;
+            return false;
+        }
+
+        public static bool IsPointNearPoint(Point pt1, Point pt2, double tolerance = 100)
+        {
+            if (GetDistanceP2P(pt1, pt2) <= tolerance)
+                return true;
+            return false;
+        }
+
+        public static bool IsPointNearPoint(double x1, double y1, double x2, double y2, int tolerance = 100)
+        {
+            return IsPointNearPoint(new HPoint(x1, y1), new HPoint(x2, y2), tolerance);
+        }
+
+        /// <summary>
+        /// 鍒ゆ柇鐐规槸鍚﹀湪鐭╁舰瑙掍笂
+        /// </summary>
+        /// <param name="pt"></param>
+        /// <param name="rect"></param>
+        /// <param name="corner"></param>
+        /// <param name="tolerance"></param>
+        /// <returns></returns>
+        public static bool IsPointNearRectangleCorner(Point pt, Rectangle rect, out string corner, double tolerance = 10)
+        {
+            try
+            {
+                //鎸夐『鏃堕拡鍘诲尮閰嶈浣�
+                Point LeftTopPoint = new Point(rect.Left, rect.Top);
+                if (IsPointNearPoint(LeftTopPoint, pt, tolerance))
+                {
+                    corner = "LeftTop";
+                    return true;
+                }
+
+                Point RightTopPoint = new Point(rect.Right, rect.Top);
+                if (IsPointNearPoint(RightTopPoint, pt, tolerance))
+                {
+                    corner = "RightTop";
+                    return true;
+                }
+
+                Point RightBtmPoint = new Point(rect.Right, rect.Bottom);
+                if (IsPointNearPoint(RightBtmPoint, pt, tolerance))
+                {
+                    corner = "RightBtm";
+                    return true;
+                }
+
+                Point LeftBtmPoint = new Point(rect.Left, rect.Bottom);
+                if (IsPointNearPoint(LeftBtmPoint, pt, tolerance))
+                {
+                    corner = "LeftBtm";
+                    return true;
+                }
+
+                corner = "";
+                return false;
+            }
+            catch { corner = ""; return false; }
+        }
+
+        public static bool IsPointNearRectangleCorner(HPoint pt, HRectangle2 rect, out string corner, double tolerance = 10)
+        {
+            try
+            {
+                //鎸夐『鏃堕拡鍘诲尮閰嶈浣�
+                var rectCorners = rect.Corners;
+                HPoint LeftTopPoint = rectCorners[0];
+                if (IsPointNearPoint(LeftTopPoint, pt, tolerance))
+                {
+                    corner = "LeftTop";
+                    return true;
+                }
+
+                HPoint RightTopPoint = rectCorners[1];
+                if (IsPointNearPoint(RightTopPoint, pt, tolerance))
+                {
+                    corner = "RightTop";
+                    return true;
+                }
+
+                HPoint RightBtmPoint = rectCorners[2];
+                if (IsPointNearPoint(RightBtmPoint, pt, tolerance))
+                {
+                    corner = "RightBtm";
+                    return true;
+                }
+
+                HPoint LeftBtmPoint = rectCorners[3];
+                if (IsPointNearPoint(LeftBtmPoint, pt, tolerance))
+                {
+                    corner = "LeftBtm";
+                    return true;
+                }
+
+                corner = "";
+                return false;
+            }
+            catch { corner = ""; return false; }
+        }
+
+        /// <summary>
+        /// 璁$畻涓ょ嚎鐨勪氦鐐�
+        /// </summary>
+        /// <param name="p1">绾�1璧峰鐐�</param>
+        /// <param name="p2"></param>
+        /// <param name="p3">绾�2璧峰鐐�</param>
+        /// <param name="p4"></param>
+        /// <returns></returns>
+        public static Point2d? GetLineIntersection(Point2d p1, Point2d p2, Point2d p3, Point2d p4, bool bOnSegment = false)
+        {
+            // 鐩寸嚎1鐨勫悜閲�
+            double x1 = p1.X, y1 = p1.Y;
+            double x2 = p2.X, y2 = p2.Y;
+
+            // 鐩寸嚎2鐨勫悜閲�
+            double x3 = p3.X, y3 = p3.Y;
+            double x4 = p4.X, y4 = p4.Y;
+
+            // 璁$畻鍒嗘瘝
+            double denominator = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
+
+            // 濡傛灉鍒嗘瘝涓�0锛岃鏄庝袱绾垮钩琛屾垨閲嶅悎
+            if (denominator == 0)
+                return null;
+
+            // 璁$畻ua鍜寀b
+            double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator;
+            double ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator;
+
+            //濡傛灉ua鍜寀b鍦�0鍜�1涔嬮棿锛岃鏄庝氦鐐瑰湪涓ゆ潯绾挎涓�
+            if (bOnSegment && !(ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1))
+                return null; // 浜ょ偣涓嶅湪绾挎涓�
+
+
+            // 璁$畻浜ょ偣鍧愭爣
+            double x = x1 + ua * (x2 - x1);
+            double y = y1 + ua * (y2 - y1);
+
+            return new Point2d(x, y);
+        }
+        #endregion
+
+        #region Halcon
+        // Chapter: Graphics / Output
+        // Short Description: Display 3D object models 
+        public static void visualize_object_model_3d(HTuple hv_WindowHandle, HTuple hv_ObjectModel3D,
+            HTuple hv_CamParam, HTuple hv_PoseIn, HTuple hv_GenParamName, HTuple hv_GenParamValue,
+            HTuple hv_Title, HTuple hv_Label, HTuple hv_Information, out HTuple hv_PoseOut)
+        {
+            // Local iconic variables 
+
+            HObject ho_Image = null, ho_ImageDump = null;
+
+            // Local control variables 
+
+            HTuple ExpTmpLocalVar_gDispObjOffset = new HTuple();
+            HTuple ExpTmpLocalVar_gLabelsDecor = new HTuple(), ExpTmpLocalVar_gInfoDecor = new HTuple();
+            HTuple ExpTmpLocalVar_gInfoPos = new HTuple(), ExpTmpLocalVar_gTitlePos = new HTuple();
+            HTuple ExpTmpLocalVar_gTitleDecor = new HTuple(), ExpTmpLocalVar_gTerminationButtonLabel = new HTuple();
+            HTuple ExpTmpLocalVar_gAlphaDeselected = new HTuple();
+            HTuple ExpTmpLocalVar_gIsSinglePose = new HTuple(), ExpTmpLocalVar_gUsesOpenGL = new HTuple();
+            HTuple hv_Scene3DTest = new HTuple(), hv_Scene3D = new HTuple();
+            HTuple hv_WindowHandleBuffer = new HTuple(), hv_TrackballSize = new HTuple();
+            HTuple hv_VirtualTrackball = new HTuple(), hv_MouseMapping = new HTuple();
+            HTuple hv_WaitForButtonRelease = new HTuple(), hv_MaxNumModels = new HTuple();
+            HTuple hv_WindowCenteredRotation = new HTuple(), hv_NumModels = new HTuple();
+            HTuple hv_SelectedObject = new HTuple(), hv_ClipRegion = new HTuple();
+            HTuple hv_CPLength = new HTuple(), hv_RowNotUsed = new HTuple();
+            HTuple hv_ColumnNotUsed = new HTuple(), hv_Width = new HTuple();
+            HTuple hv_Height = new HTuple(), hv_WPRow1 = new HTuple();
+            HTuple hv_WPColumn1 = new HTuple(), hv_WPRow2 = new HTuple();
+            HTuple hv_WPColumn2 = new HTuple(), hv_CamParamValue = new HTuple();
+            HTuple hv_CamWidth = new HTuple(), hv_CamHeight = new HTuple();
+            HTuple hv_Scale = new HTuple(), hv_Indices = new HTuple();
+            HTuple hv_DispBackground = new HTuple(), hv_Mask = new HTuple();
+            HTuple hv_Center = new HTuple(), hv_PoseEstimated = new HTuple();
+            HTuple hv_Poses = new HTuple(), hv_HomMat3Ds = new HTuple();
+            HTuple hv_Sequence = new HTuple(), hv_Font = new HTuple();
+            HTuple hv_Exception = new HTuple(), hv_OpenGLInfo = new HTuple();
+            HTuple hv_DummyObjectModel3D = new HTuple(), hv_CameraIndexTest = new HTuple();
+            HTuple hv_PoseTest = new HTuple(), hv_InstanceIndexTest = new HTuple();
+            HTuple hv_MinImageSize = new HTuple(), hv_TrackballRadiusPixel = new HTuple();
+            HTuple hv_Ascent = new HTuple(), hv_Descent = new HTuple();
+            HTuple hv_TextWidth = new HTuple(), hv_TextHeight = new HTuple();
+            HTuple hv_NumChannels = new HTuple(), hv_ColorImage = new HTuple();
+            HTuple hv_CameraIndex = new HTuple(), hv_AllInstances = new HTuple();
+            HTuple hv_SetLight = new HTuple(), hv_LightParam = new HTuple();
+            HTuple hv_LightPosition = new HTuple(), hv_LightKind = new HTuple();
+            HTuple hv_LightIndex = new HTuple(), hv_PersistenceParamName = new HTuple();
+            HTuple hv_PersistenceParamValue = new HTuple(), hv_AlphaOrig = new HTuple();
+            HTuple hv_I = new HTuple(), hv_ParamName = new HTuple();
+            HTuple hv_ParamValue = new HTuple(), hv_ParamNameTrunk = new HTuple();
+            HTuple hv_Instance = new HTuple(), hv_HomMat3D = new HTuple();
+            HTuple hv_Qx = new HTuple(), hv_Qy = new HTuple(), hv_Qz = new HTuple();
+            HTuple hv_TBCenter = new HTuple(), hv_TBSize = new HTuple();
+            HTuple hv_ButtonHold = new HTuple(), hv_VisualizeTB = new HTuple();
+            HTuple hv_MaxIndex = new HTuple(), hv_TrackballCenterRow = new HTuple();
+            HTuple hv_TrackballCenterCol = new HTuple(), hv_GraphEvent = new HTuple();
+            HTuple hv_Exit = new HTuple(), hv_GraphButtonRow = new HTuple();
+            HTuple hv_GraphButtonColumn = new HTuple(), hv_GraphButton = new HTuple();
+            HTuple hv_ButtonReleased = new HTuple(), hv_e = new HTuple();
+            HTuple hv_CamParam_COPY_INP_TMP = new HTuple(hv_CamParam);
+            HTuple hv_GenParamName_COPY_INP_TMP = new HTuple(hv_GenParamName);
+            HTuple hv_GenParamValue_COPY_INP_TMP = new HTuple(hv_GenParamValue);
+            HTuple hv_Label_COPY_INP_TMP = new HTuple(hv_Label);
+            HTuple hv_PoseIn_COPY_INP_TMP = new HTuple(hv_PoseIn);
+
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_Image);
+            HOperatorSet.GenEmptyObj(out ho_ImageDump);
+            hv_PoseOut = new HTuple();
+            try
+            {
+                //The procedure visualize_object_model_3d can be used to display
+                //one or more 3d object models and to interactively modify
+                //the object poses by using the mouse.
+                //
+                //The pose can be modified by moving the mouse while
+                //pressing a mouse button. The default settings are:
+                //
+                // Rotate: Left mouse button
+                // Zoom: Shift + Left mouse button (or Center mouse button)
+                // Pan: Ctrl + Left mouse button
+                //
+                //Furthermore, it is possible to select and deselect objects,
+                //to decrease the mouse sensitivity, and to toggle the
+                //inspection mode (see the description of the generic parameter
+                //'inspection_mode' below):
+                //
+                // (De-)select object(s): Right mouse button
+                // Low mouse sensitivity: Alt + mouse button
+                // Toggle inspection mode: Ctrl + Alt + Left mouse button
+                //
+                //In GenParamName and GenParamValue all generic Parameters
+                //of disp_object_model_3d are supported.
+                //
+                //**********************************************************
+                //Define global variables
+                //**********************************************************
+                //
+                //global def tuple gDispObjOffset
+                //global def tuple gLabelsDecor
+                //global def tuple gInfoDecor
+                //global def tuple gInfoPos
+                //global def tuple gTitlePos
+                //global def tuple gTitleDecor
+                //global def tuple gTerminationButtonLabel
+                //global def tuple gAlphaDeselected
+                //global def tuple gIsSinglePose
+                //global def tuple gUsesOpenGL
+                //
+                //**********************************************************
+                //Initialize Handles to enable correct handling in error case
+                //**********************************************************
+                hv_Scene3DTest.Dispose();
+                hv_Scene3DTest = new HTuple();
+                hv_Scene3D.Dispose();
+                hv_Scene3D = new HTuple();
+                hv_WindowHandleBuffer.Dispose();
+                hv_WindowHandleBuffer = new HTuple();
+
+                //**********************************************************
+                //Some user defines that may be adapted if desired
+                //**********************************************************
+                //
+                //TrackballSize defines the diameter of the trackball in
+                //the image with respect to the smaller image dimension.
+                hv_TrackballSize.Dispose();
+                hv_TrackballSize = 0.8;
+                //
+                //VirtualTrackball defines the type of virtual trackball that
+                //shall be used ('shoemake' or 'bell').
+                hv_VirtualTrackball.Dispose();
+                hv_VirtualTrackball = "shoemake";
+                //VirtualTrackball := 'bell'
+                //
+                //Functionality of mouse buttons
+                //    1: Left mouse button
+                //    2: Middle mouse button
+                //    4: Right mouse button
+                //    5: Left+Right mouse button
+                //  8+x: Shift + mouse button
+                // 16+x: Ctrl + mouse button
+                // 48+x: Ctrl + Alt + mouse button
+                //in the order [Translate, Rotate, Scale, ScaleAlternative1, ScaleAlternative2, SelectObjects, ToggleSelectionMode]
+                hv_MouseMapping.Dispose();
+                hv_MouseMapping = new HTuple();
+                hv_MouseMapping[0] = 17;
+                hv_MouseMapping[1] = 1;
+                hv_MouseMapping[2] = 2;
+                hv_MouseMapping[3] = 5;
+                hv_MouseMapping[4] = 9;
+                hv_MouseMapping[5] = 4;
+                hv_MouseMapping[6] = 49;
+                //
+                //The labels of the objects appear next to their projected
+                //center. With gDispObjOffset a fixed offset is added
+                //                  R,  C
+                ExpTmpLocalVar_gDispObjOffset = new HTuple();
+                ExpTmpLocalVar_gDispObjOffset[0] = -30;
+                ExpTmpLocalVar_gDispObjOffset[1] = 0;
+                HDevelopExport.ExpSetGlobalVar_gDispObjOffset(ExpTmpLocalVar_gDispObjOffset);
+                //
+                //Customize the decoration of the different text elements
+                //              Color,   Box
+                ExpTmpLocalVar_gInfoDecor = new HTuple();
+                ExpTmpLocalVar_gInfoDecor[0] = "white";
+                ExpTmpLocalVar_gInfoDecor[1] = "false";
+                HDevelopExport.ExpSetGlobalVar_gInfoDecor(ExpTmpLocalVar_gInfoDecor);
+                ExpTmpLocalVar_gLabelsDecor = new HTuple();
+                ExpTmpLocalVar_gLabelsDecor[0] = "white";
+                ExpTmpLocalVar_gLabelsDecor[1] = "false";
+                HDevelopExport.ExpSetGlobalVar_gLabelsDecor(ExpTmpLocalVar_gLabelsDecor);
+                ExpTmpLocalVar_gTitleDecor = new HTuple();
+                ExpTmpLocalVar_gTitleDecor[0] = "black";
+                ExpTmpLocalVar_gTitleDecor[1] = "true";
+                HDevelopExport.ExpSetGlobalVar_gTitleDecor(ExpTmpLocalVar_gTitleDecor);
+                //
+                //Customize the position of some text elements
+                //  gInfoPos has one of the values
+                //  {'UpperLeft', 'LowerLeft', 'UpperRight'}
+                ExpTmpLocalVar_gInfoPos = "LowerLeft";
+                HDevelopExport.ExpSetGlobalVar_gInfoPos(ExpTmpLocalVar_gInfoPos);
+                //  gTitlePos has one of the values
+                //  {'UpperLeft', 'UpperCenter', 'UpperRight'}
+                ExpTmpLocalVar_gTitlePos = "UpperLeft";
+                HDevelopExport.ExpSetGlobalVar_gTitlePos(ExpTmpLocalVar_gTitlePos);
+                //Alpha value (=1-transparency) that is used for visualizing
+                //the objects that are not selected
+                ExpTmpLocalVar_gAlphaDeselected = 0.3;
+                HDevelopExport.ExpSetGlobalVar_gAlphaDeselected(ExpTmpLocalVar_gAlphaDeselected);
+                //Customize the label of the continue button
+                ExpTmpLocalVar_gTerminationButtonLabel = " Continue ";
+                HDevelopExport.ExpSetGlobalVar_gTerminationButtonLabel(ExpTmpLocalVar_gTerminationButtonLabel);
+                //Define if the continue button responds to a single click event or
+                //if it responds only if the mouse button is released while being placed
+                //over the continue button.
+                //'true':  Wait until the continue button has been released.
+                //         This should be used to avoid unwanted continuations of
+                //         subsequent calls of visualize_object_model_3d, which can
+                //         otherwise occur if the mouse button remains pressed while the
+                //         next visualization is active.
+                //'false': Continue the execution already if the continue button is
+                //         pressed. This option allows a fast forwarding through
+                //         subsequent calls of visualize_object_model_3d.
+                hv_WaitForButtonRelease.Dispose();
+                hv_WaitForButtonRelease = "true";
+                //Number of 3D Object models that can be selected and handled individually.
+                //If there are more models passed then this number, some calculations
+                //are performed differently and the individual selection and handling
+                //of models is not supported anymore. Note that the value of MaxNumModels
+                //can be overwritten with the generic parameter max_num_selectable_models.
+                hv_MaxNumModels.Dispose();
+                hv_MaxNumModels = 1000;
+                //Defines the default for the initial state of the rotation center:
+                //(1) The rotation center is fixed in the center of the image and lies
+                //    on the surface of the object.
+                //(2) The rotation center lies in the center of the object.
+                hv_WindowCenteredRotation.Dispose();
+                hv_WindowCenteredRotation = 2;
+                //
+                //**********************************************************
+                //
+                //Initialize some values
+                hv_NumModels.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_NumModels = new HTuple(hv_ObjectModel3D.TupleLength()
+                        );
+                }
+                hv_SelectedObject.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_SelectedObject = HTuple.TupleGenConst(
+                        hv_NumModels, 1);
+                }
+                //
+                //Apply some system settings
+                // dev_get_preferences(...); only in hdevelop
+                // dev_set_preferences(...); only in hdevelop
+                // dev_get_preferences(...); only in hdevelop
+                // dev_set_preferences(...); only in hdevelop
+                hv_ClipRegion.Dispose();
+                HOperatorSet.GetSystem("clip_region", out hv_ClipRegion);
+                HOperatorSet.SetSystem("clip_region", "false");
+                HDevelopExport.dev_update_off();
+                //
+                //Check if GenParamName matches GenParamValue
+                if ((int)new HTuple(new HTuple(hv_GenParamName_COPY_INP_TMP.TupleLength()
+                    ).TupleNotEqual(new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleLength()
+                    ))) != 0)
+                {
+                    throw new HalconException("Number of generic parameters does not match number of generic parameter values");
+                }
+                //
+                try
+                {
+                    //
+                    //Refactor camera parameters to fit to window size
+                    //
+                    hv_CPLength.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_CPLength = new HTuple(hv_CamParam_COPY_INP_TMP.TupleLength()
+                            );
+                    }
+                    hv_RowNotUsed.Dispose(); hv_ColumnNotUsed.Dispose(); hv_Width.Dispose(); hv_Height.Dispose();
+                    HOperatorSet.GetWindowExtents(hv_WindowHandle, out hv_RowNotUsed, out hv_ColumnNotUsed,
+                        out hv_Width, out hv_Height);
+                    hv_WPRow1.Dispose(); hv_WPColumn1.Dispose(); hv_WPRow2.Dispose(); hv_WPColumn2.Dispose();
+                    HOperatorSet.GetPart(hv_WindowHandle, out hv_WPRow1, out hv_WPColumn1, out hv_WPRow2,
+                        out hv_WPColumn2);
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.SetPart(hv_WindowHandle, 0, 0, hv_Height - 1, hv_Width - 1);
+                    }
+                    if ((int)new HTuple(hv_CPLength.TupleEqual(0)) != 0)
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            HDevelopExport.gen_cam_par_area_scan_division(0.06, 0, 8.5e-6, 8.5e-6, hv_Width / 2, hv_Height / 2,
+                                hv_Width, hv_Height, out hv_CamParam_COPY_INP_TMP);
+                        }
+                    }
+                    else
+                    {
+                        hv_CamParamValue.Dispose();
+                        HDevelopExport.get_cam_par_data(hv_CamParam_COPY_INP_TMP, new HTuple("sx").TupleConcat(
+                            "sy").TupleConcat("cx").TupleConcat("cy").TupleConcat("image_width").TupleConcat(
+                            "image_height"), out hv_CamParamValue);
+                        hv_CamWidth.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_CamWidth = hv_CamParamValue.TupleSelect(
+                                4).TupleReal();
+                        }
+                        hv_CamHeight.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_CamHeight = hv_CamParamValue.TupleSelect(
+                                5).TupleReal();
+                        }
+                        hv_Scale.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Scale = (hv_Width / hv_CamWidth).TupleConcat(
+                                hv_Height / hv_CamHeight).TupleMin();
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "sx", hv_CamParamValue.TupleSelect(
+                                0) / hv_Scale, out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "sy", hv_CamParamValue.TupleSelect(
+                                1) / hv_Scale, out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "cx", hv_CamParamValue.TupleSelect(
+                                2) * hv_Scale, out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "cy", hv_CamParamValue.TupleSelect(
+                                3) * hv_Scale, out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "image_width", (hv_CamParamValue.TupleSelect(
+                                4) * hv_Scale).TupleInt(), out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "image_height", (hv_CamParamValue.TupleSelect(
+                                5) * hv_Scale).TupleInt(), out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                    }
+                    //
+                    //Check the generic parameters for max_num_selectable_models
+                    //(Note that the default is set above to MaxNumModels := 1000)
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                            "max_num_selectable_models");
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        if ((int)hv_GenParamValue_COPY_INP_TMP.TupleSelect(hv_Indices.TupleSelect(
+                            0)).TupleIsNumber() != 0)
+                        {
+                            if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                hv_Indices.TupleSelect(0)).TupleNumber().TupleInt().TupleLess(
+                                1)) != 0)
+                            {
+                                //Wrong parameter value: Only integer values greater than 0 are allowed
+                                throw new HalconException("Wrong value for parameter 'max_num_selectable_models' (must be an integer value greater than 0)");
+                            }
+                        }
+                        else
+                        {
+                            //Wrong parameter value: Only integer values greater than 0 are allowed
+                            throw new HalconException("Wrong value for parameter 'max_num_selectable_models' (must be an integer value greater than 0)");
+                        }
+                        hv_MaxNumModels.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_MaxNumModels = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                hv_Indices.TupleSelect(0)).TupleNumber().TupleInt();
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    //
+                    //Check the generic parameters for window_centered_rotation
+                    //(Note that the default is set above to WindowCenteredRotation := 2)
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                            "inspection_mode");
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(hv_Indices.TupleSelect(
+                            0)).TupleEqual("surface")) != 0)
+                        {
+                            hv_WindowCenteredRotation.Dispose();
+                            hv_WindowCenteredRotation = 1;
+                        }
+                        else if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                            hv_Indices.TupleSelect(0)).TupleEqual("standard")) != 0)
+                        {
+                            hv_WindowCenteredRotation.Dispose();
+                            hv_WindowCenteredRotation = 2;
+                        }
+                        else
+                        {
+                            //Wrong parameter value, use default value
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    //
+                    //Check the generic parameters for disp_background
+                    //(The former parameter name 'use_background' is still supported
+                    // for compatibility reasons)
+                    hv_DispBackground.Dispose();
+                    hv_DispBackground = "false";
+                    if ((int)new HTuple(new HTuple(hv_GenParamName_COPY_INP_TMP.TupleLength()
+                        ).TupleGreater(0)) != 0)
+                    {
+                        hv_Mask.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Mask = hv_GenParamName_COPY_INP_TMP.TupleEqualElem(
+                                "disp_background").TupleOr(hv_GenParamName_COPY_INP_TMP.TupleEqualElem(
+                                "use_background"));
+                        }
+                        hv_Indices.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Indices = hv_Mask.TupleFind(
+                                1);
+                        }
+                    }
+                    else
+                    {
+                        hv_Indices.Dispose();
+                        hv_Indices = -1;
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        hv_DispBackground.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_DispBackground = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                hv_Indices.TupleSelect(0));
+                        }
+                        if ((int)new HTuple(hv_DispBackground.TupleNotEqual("true")).TupleAnd(
+                            new HTuple(hv_DispBackground.TupleNotEqual("false"))) != 0)
+                        {
+                            //Wrong parameter value: Only 'true' and 'false' are allowed
+                            throw new HalconException("Wrong value for parameter 'disp_background' (must be either 'true' or 'false')");
+                        }
+                        //Note that the background is handled explicitly in this procedure
+                        //and therefore, the parameter is removed from the list of
+                        //parameters and disp_background is always set to true (see below)
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    //
+                    //Read and check the parameter Label for each object
+                    if ((int)new HTuple(new HTuple(hv_Label_COPY_INP_TMP.TupleLength()).TupleEqual(
+                        0)) != 0)
+                    {
+                        //no labels set -> leave as []
+                    }
+                    else if ((int)new HTuple(new HTuple(hv_Label_COPY_INP_TMP.TupleLength()
+                        ).TupleEqual(1)) != 0)
+                    {
+                        //a single label set for all models
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_Label = HTuple.TupleGenConst(
+                                    hv_NumModels, hv_Label_COPY_INP_TMP);
+                                hv_Label_COPY_INP_TMP.Dispose();
+                                hv_Label_COPY_INP_TMP = ExpTmpLocalVar_Label;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        if ((int)new HTuple(new HTuple(hv_Label_COPY_INP_TMP.TupleLength()).TupleNotEqual(
+                            hv_NumModels)) != 0)
+                        {
+                            //Number of elements in Label does not match
+                            //the number of object models.
+                            throw new HalconException(new HTuple(new HTuple("Number of elements in Label (") + new HTuple(hv_Label_COPY_INP_TMP.TupleLength()
+                                )) + ") does not match the number of object models(" + hv_NumModels + ").");
+                        }
+                    }
+                    //Convert labels into strings
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Label = "" + hv_Label_COPY_INP_TMP;
+                            hv_Label_COPY_INP_TMP.Dispose();
+                            hv_Label_COPY_INP_TMP = ExpTmpLocalVar_Label;
+                        }
+                    }
+                    //
+                    //Read and check the parameter PoseIn for each object
+                    hv_Center.Dispose();
+                    HDevelopExport.get_object_models_center(hv_ObjectModel3D, out hv_Center);
+                    if ((int)new HTuple(hv_Center.TupleEqual(new HTuple())) != 0)
+                    {
+                        hv_Center.Dispose();
+                        hv_Center = new HTuple();
+                        hv_Center[0] = 0;
+                        hv_Center[1] = 0;
+                        hv_Center[2] = 0;
+                    }
+                    if ((int)new HTuple(new HTuple(hv_PoseIn_COPY_INP_TMP.TupleLength()).TupleEqual(
+                        0)) != 0)
+                    {
+                        //If no pose was specified by the caller, automatically calculate
+                        //a pose that is appropriate for the visualization.
+                        //Set the initial model reference pose. The orientation is parallel
+                        //to the object coordinate system, the position is at the center
+                        //of gravity of all models.
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_PoseIn_COPY_INP_TMP.Dispose();
+                            HOperatorSet.CreatePose(-hv_Center.TupleSelect(0), -hv_Center.TupleSelect(
+                                1), -hv_Center.TupleSelect(2), 0, 0, 0, "Rp+T", "gba", "point",
+                                out hv_PoseIn_COPY_INP_TMP);
+                        }
+                        hv_PoseEstimated.Dispose();
+                        HDevelopExport.determine_optimum_pose_distance(hv_ObjectModel3D, hv_CamParam_COPY_INP_TMP,
+                            0.9, hv_PoseIn_COPY_INP_TMP, out hv_PoseEstimated);
+                        hv_Poses.Dispose();
+                        hv_Poses = new HTuple();
+                        hv_HomMat3Ds.Dispose();
+                        hv_HomMat3Ds = new HTuple();
+                        hv_Sequence.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Sequence = HTuple.TupleGenSequence(
+                                0, hv_NumModels * 7 - 1, 1);
+                        }
+                        hv_Poses.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Poses = hv_PoseEstimated.TupleSelect(
+                                hv_Sequence % 7);
+                        }
+                        ExpTmpLocalVar_gIsSinglePose = 1;
+                        HDevelopExport.ExpSetGlobalVar_gIsSinglePose(ExpTmpLocalVar_gIsSinglePose);
+                    }
+                    else if ((int)new HTuple(new HTuple(hv_PoseIn_COPY_INP_TMP.TupleLength()
+                        ).TupleEqual(7)) != 0)
+                    {
+                        hv_Poses.Dispose();
+                        hv_Poses = new HTuple();
+                        hv_HomMat3Ds.Dispose();
+                        hv_HomMat3Ds = new HTuple();
+                        hv_Sequence.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Sequence = HTuple.TupleGenSequence(
+                                0, hv_NumModels * 7 - 1, 1);
+                        }
+                        hv_Poses.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Poses = hv_PoseIn_COPY_INP_TMP.TupleSelect(
+                                hv_Sequence % 7);
+                        }
+                        ExpTmpLocalVar_gIsSinglePose = 1;
+                        HDevelopExport.ExpSetGlobalVar_gIsSinglePose(ExpTmpLocalVar_gIsSinglePose);
+                    }
+                    else
+                    {
+                        if ((int)new HTuple(new HTuple(hv_PoseIn_COPY_INP_TMP.TupleLength()).TupleNotEqual(
+                            new HTuple(hv_ObjectModel3D.TupleLength()) * 7)) != 0)
+                        {
+                            //Wrong number of values of input control parameter 'PoseIn'
+                            throw new HalconException("Wrong number of values of input control parameter 'PoseIn'.");
+                        }
+                        else
+                        {
+                            hv_Poses.Dispose();
+                            hv_Poses = new HTuple(hv_PoseIn_COPY_INP_TMP);
+                        }
+                        ExpTmpLocalVar_gIsSinglePose = 0;
+                        HDevelopExport.ExpSetGlobalVar_gIsSinglePose(ExpTmpLocalVar_gIsSinglePose);
+                    }
+                    //
+                    //Open (invisible) buffer window to avoid flickering
+                    hv_WindowHandleBuffer.Dispose();
+                    HOperatorSet.OpenWindow(0, 0, hv_Width, hv_Height, 0, "buffer", "", out hv_WindowHandleBuffer);
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.SetPart(hv_WindowHandleBuffer, 0, 0, hv_Height - 1, hv_Width - 1);
+                    }
+                    hv_Font.Dispose();
+                    HOperatorSet.GetFont(hv_WindowHandle, out hv_Font);
+                    try
+                    {
+                        HOperatorSet.SetFont(hv_WindowHandleBuffer, hv_Font);
+                    }
+                    // catch (Exception) 
+                    catch (HalconException HDevExpDefaultException2)
+                    {
+                        HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                    }
+                    //
+                    // Is OpenGL available and should it be used?
+                    ExpTmpLocalVar_gUsesOpenGL = "true";
+                    HDevelopExport.ExpSetGlobalVar_gUsesOpenGL(ExpTmpLocalVar_gUsesOpenGL);
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                            "opengl");
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            ExpTmpLocalVar_gUsesOpenGL = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                hv_Indices.TupleSelect(0));
+                        }
+                        HDevelopExport.ExpSetGlobalVar_gUsesOpenGL(ExpTmpLocalVar_gUsesOpenGL);
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                        if ((int)new HTuple(HDevelopExport.ExpGetGlobalVar_gUsesOpenGL().TupleNotEqual("true")).TupleAnd(
+                            new HTuple(HDevelopExport.ExpGetGlobalVar_gUsesOpenGL().TupleNotEqual("false"))) != 0)
+                        {
+                            //Wrong parameter value: Only 'true' and 'false' are allowed
+                            throw new HalconException("Wrong value for parameter 'opengl' (must be either 'true' or 'false')");
+                        }
+                    }
+                    if ((int)new HTuple(HDevelopExport.ExpGetGlobalVar_gUsesOpenGL().TupleEqual("true")) != 0)
+                    {
+                        hv_OpenGLInfo.Dispose();
+                        HOperatorSet.GetSystem("opengl_info", out hv_OpenGLInfo);
+                        if ((int)new HTuple(hv_OpenGLInfo.TupleEqual("No OpenGL support included.")) != 0)
+                        {
+                            ExpTmpLocalVar_gUsesOpenGL = "false";
+                            HDevelopExport.ExpSetGlobalVar_gUsesOpenGL(ExpTmpLocalVar_gUsesOpenGL);
+                        }
+                        else
+                        {
+                            hv_DummyObjectModel3D.Dispose();
+                            HOperatorSet.GenObjectModel3dFromPoints(0, 0, 0, out hv_DummyObjectModel3D);
+                            hv_Scene3DTest.Dispose();
+                            HOperatorSet.CreateScene3d(out hv_Scene3DTest);
+                            hv_CameraIndexTest.Dispose();
+                            HOperatorSet.AddScene3dCamera(hv_Scene3DTest, hv_CamParam_COPY_INP_TMP,
+                                out hv_CameraIndexTest);
+                            hv_PoseTest.Dispose();
+                            HDevelopExport.determine_optimum_pose_distance(hv_DummyObjectModel3D, hv_CamParam_COPY_INP_TMP,
+                                0.9, new HTuple(0).TupleConcat(0).TupleConcat(0).TupleConcat(
+                                0).TupleConcat(0).TupleConcat(0).TupleConcat(0), out hv_PoseTest);
+                            hv_InstanceIndexTest.Dispose();
+                            HOperatorSet.AddScene3dInstance(hv_Scene3DTest, hv_DummyObjectModel3D,
+                                hv_PoseTest, out hv_InstanceIndexTest);
+                            try
+                            {
+                                HOperatorSet.DisplayScene3d(hv_WindowHandleBuffer, hv_Scene3DTest,
+                                    hv_InstanceIndexTest);
+                            }
+                            // catch (Exception) 
+                            catch (HalconException HDevExpDefaultException2)
+                            {
+                                HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                                ExpTmpLocalVar_gUsesOpenGL = "false";
+                                HDevelopExport.ExpSetGlobalVar_gUsesOpenGL(ExpTmpLocalVar_gUsesOpenGL);
+                            }
+                            HOperatorSet.ClearScene3d(hv_Scene3DTest);
+                            hv_Scene3DTest.Dispose();
+                            hv_Scene3DTest = new HTuple();
+                            HOperatorSet.ClearObjectModel3d(hv_DummyObjectModel3D);
+                        }
+                    }
+                    //
+                    //Compute the trackball
+                    hv_MinImageSize.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_MinImageSize = hv_Width.TupleConcat(
+                            hv_Height).TupleMin();
+                    }
+                    hv_TrackballRadiusPixel.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TrackballRadiusPixel = hv_TrackballSize * hv_MinImageSize / 2.0;
+                    }
+                    //
+                    //Measure the text extents for the continue button in the
+                    //graphics window
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Ascent.Dispose(); hv_Descent.Dispose(); hv_TextWidth.Dispose(); hv_TextHeight.Dispose();
+                        HOperatorSet.GetStringExtents(hv_WindowHandleBuffer, HDevelopExport.ExpGetGlobalVar_gTerminationButtonLabel() + "  ",
+                            out hv_Ascent, out hv_Descent, out hv_TextWidth, out hv_TextHeight);
+                    }
+                    //
+                    //Store background image
+                    if ((int)new HTuple(hv_DispBackground.TupleEqual("false")) != 0)
+                    {
+                        HOperatorSet.ClearWindow(hv_WindowHandle);
+                    }
+                    ho_Image.Dispose();
+                    HOperatorSet.DumpWindowImage(out ho_Image, hv_WindowHandle);
+                    //Special treatment for color background images necessary
+                    hv_NumChannels.Dispose();
+                    HOperatorSet.CountChannels(ho_Image, out hv_NumChannels);
+                    hv_ColorImage.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_ColorImage = new HTuple(hv_NumChannels.TupleEqual(
+                            3));
+                    }
+                    //
+                    hv_Scene3D.Dispose();
+                    HOperatorSet.CreateScene3d(out hv_Scene3D);
+                    hv_CameraIndex.Dispose();
+                    HOperatorSet.AddScene3dCamera(hv_Scene3D, hv_CamParam_COPY_INP_TMP, out hv_CameraIndex);
+                    hv_AllInstances.Dispose();
+                    HOperatorSet.AddScene3dInstance(hv_Scene3D, hv_ObjectModel3D, hv_Poses, out hv_AllInstances);
+                    //Always set 'disp_background' to true,  because it is handled explicitly
+                    //in this procedure (see above)
+                    HOperatorSet.SetScene3dParam(hv_Scene3D, "disp_background", "true");
+                    //Check if we have to set light specific parameters
+                    hv_SetLight.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_SetLight = new HTuple(hv_GenParamName_COPY_INP_TMP.TupleRegexpTest(
+                            "light_"));
+                    }
+                    if ((int)hv_SetLight != 0)
+                    {
+                        //set position of light source
+                        hv_Indices.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                                "light_position");
+                        }
+                        if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                            new HTuple()))) != 0)
+                        {
+                            //If multiple light positions are given, use the last one
+                            hv_LightParam.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_LightParam = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                    hv_Indices.TupleSelect(new HTuple(hv_Indices.TupleLength()) - 1)).TupleSplit(
+                                    new HTuple(", ")).TupleNumber();
+                            }
+                            if ((int)new HTuple(new HTuple(hv_LightParam.TupleLength()).TupleNotEqual(
+                                4)) != 0)
+                            {
+                                throw new HalconException("light_position must be given as a string that contains four space separated floating point numbers");
+                            }
+                            hv_LightPosition.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_LightPosition = hv_LightParam.TupleSelectRange(
+                                    0, 2);
+                            }
+                            hv_LightKind.Dispose();
+                            hv_LightKind = "point_light";
+                            if ((int)new HTuple(hv_LightParam.TupleSelect(3).TupleEqual(0)) != 0)
+                            {
+                                hv_LightKind.Dispose();
+                                hv_LightKind = "directional_light";
+                            }
+                            //Currently, only one light source is supported
+                            HOperatorSet.RemoveScene3dLight(hv_Scene3D, 0);
+                            hv_LightIndex.Dispose();
+                            HOperatorSet.AddScene3dLight(hv_Scene3D, hv_LightPosition, hv_LightKind,
+                                out hv_LightIndex);
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamName_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamValue_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                        }
+                        //set ambient part of light source
+                        hv_Indices.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                                "light_ambient");
+                        }
+                        if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                            new HTuple()))) != 0)
+                        {
+                            //If the ambient part is set multiple times, use the last setting
+                            hv_LightParam.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_LightParam = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                    hv_Indices.TupleSelect(new HTuple(hv_Indices.TupleLength()) - 1)).TupleSplit(
+                                    new HTuple(", ")).TupleNumber();
+                            }
+                            if ((int)new HTuple(new HTuple(hv_LightParam.TupleLength()).TupleLess(
+                                3)) != 0)
+                            {
+                                throw new HalconException("light_ambient must be given as a string that contains three space separated floating point numbers");
+                            }
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                HOperatorSet.SetScene3dLightParam(hv_Scene3D, 0, "ambient", hv_LightParam.TupleSelectRange(
+                                    0, 2));
+                            }
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamName_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamValue_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                        }
+                        //Set diffuse part of light source
+                        hv_Indices.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                                "light_diffuse");
+                        }
+                        if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                            new HTuple()))) != 0)
+                        {
+                            //If the diffuse part is set multiple times, use the last setting
+                            hv_LightParam.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_LightParam = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                    hv_Indices.TupleSelect(new HTuple(hv_Indices.TupleLength()) - 1)).TupleSplit(
+                                    new HTuple(", ")).TupleNumber();
+                            }
+                            if ((int)new HTuple(new HTuple(hv_LightParam.TupleLength()).TupleLess(
+                                3)) != 0)
+                            {
+                                throw new HalconException("light_diffuse must be given as a string that contains three space separated floating point numbers");
+                            }
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                HOperatorSet.SetScene3dLightParam(hv_Scene3D, 0, "diffuse", hv_LightParam.TupleSelectRange(
+                                    0, 2));
+                            }
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamName_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamValue_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                        }
+                    }
+                    //
+                    //Handle persistence parameters separately because persistence will
+                    //only be activated immediately before leaving the visualization
+                    //procedure
+                    hv_PersistenceParamName.Dispose();
+                    hv_PersistenceParamName = new HTuple();
+                    hv_PersistenceParamValue.Dispose();
+                    hv_PersistenceParamValue = new HTuple();
+                    //Set position of light source
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                            "object_index_persistence");
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(hv_Indices.TupleSelect(
+                            new HTuple(hv_Indices.TupleLength()) - 1)).TupleEqual("true")) != 0)
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                {
+                                    HTuple
+                                      ExpTmpLocalVar_PersistenceParamName = hv_PersistenceParamName.TupleConcat(
+                                        "object_index_persistence");
+                                    hv_PersistenceParamName.Dispose();
+                                    hv_PersistenceParamName = ExpTmpLocalVar_PersistenceParamName;
+                                }
+                            }
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                {
+                                    HTuple
+                                      ExpTmpLocalVar_PersistenceParamValue = hv_PersistenceParamValue.TupleConcat(
+                                        "true");
+                                    hv_PersistenceParamValue.Dispose();
+                                    hv_PersistenceParamValue = ExpTmpLocalVar_PersistenceParamValue;
+                                }
+                            }
+                        }
+                        else if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                            hv_Indices.TupleSelect(new HTuple(hv_Indices.TupleLength()) - 1)).TupleEqual(
+                            "false")) != 0)
+                        {
+                        }
+                        else
+                        {
+                            throw new HalconException("Wrong value for parameter 'object_index_persistence' (must be either 'true' or 'false')");
+                        }
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            HOperatorSet.TupleRemove(hv_GenParamName_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                            hv_GenParamName_COPY_INP_TMP.Dispose();
+                            hv_GenParamName_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            HOperatorSet.TupleRemove(hv_GenParamValue_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                            hv_GenParamValue_COPY_INP_TMP.Dispose();
+                            hv_GenParamValue_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                    }
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                            "depth_persistence");
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(hv_Indices.TupleSelect(
+                            new HTuple(hv_Indices.TupleLength()) - 1)).TupleEqual("true")) != 0)
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                {
+                                    HTuple
+                                      ExpTmpLocalVar_PersistenceParamName = hv_PersistenceParamName.TupleConcat(
+                                        "depth_persistence");
+                                    hv_PersistenceParamName.Dispose();
+                                    hv_PersistenceParamName = ExpTmpLocalVar_PersistenceParamName;
+                                }
+                            }
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                {
+                                    HTuple
+                                      ExpTmpLocalVar_PersistenceParamValue = hv_PersistenceParamValue.TupleConcat(
+                                        "true");
+                                    hv_PersistenceParamValue.Dispose();
+                                    hv_PersistenceParamValue = ExpTmpLocalVar_PersistenceParamValue;
+                                }
+                            }
+                        }
+                        else if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                            hv_Indices.TupleSelect(new HTuple(hv_Indices.TupleLength()) - 1)).TupleEqual(
+                            "false")) != 0)
+                        {
+                        }
+                        else
+                        {
+                            throw new HalconException("Wrong value for parameter 'depth_persistence' (must be either 'true' or 'false')");
+                        }
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            HOperatorSet.TupleRemove(hv_GenParamName_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                            hv_GenParamName_COPY_INP_TMP.Dispose();
+                            hv_GenParamName_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            HOperatorSet.TupleRemove(hv_GenParamValue_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                            hv_GenParamValue_COPY_INP_TMP.Dispose();
+                            hv_GenParamValue_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                    }
+                    //
+                    //Parse the generic parameters
+                    //- First, all parameters that are understood by set_scene_3d_instance_param
+                    hv_AlphaOrig.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_AlphaOrig = HTuple.TupleGenConst(
+                            hv_NumModels, 1);
+                    }
+                    for (hv_I = 0; (int)hv_I <= (int)(new HTuple(hv_GenParamName_COPY_INP_TMP.TupleLength()
+                        ) - 1); hv_I = (int)hv_I + 1)
+                    {
+                        hv_ParamName.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamName = hv_GenParamName_COPY_INP_TMP.TupleSelect(
+                                hv_I);
+                        }
+                        hv_ParamValue.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamValue = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                hv_I);
+                        }
+                        //Check if this parameter is understood by set_scene_3d_param
+                        if ((int)new HTuple(hv_ParamName.TupleEqual("alpha")) != 0)
+                        {
+                            hv_AlphaOrig.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_AlphaOrig = HTuple.TupleGenConst(
+                                    hv_NumModels, hv_ParamValue);
+                            }
+                        }
+                        try
+                        {
+                            HOperatorSet.SetScene3dParam(hv_Scene3D, hv_ParamName, hv_ParamValue);
+                            continue;
+                        }
+                        // catch (Exception) 
+                        catch (HalconException HDevExpDefaultException2)
+                        {
+                            HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                            if ((int)new HTuple(hv_Exception.TupleSelect(0).TupleEqual(1203)).TupleOr(
+                                new HTuple(hv_Exception.TupleSelect(0).TupleEqual(1303))) != 0)
+                            {
+                                if ((int)new HTuple(new HTuple(new HTuple(hv_ParamName.TupleEqual(
+                                    "color_attrib")).TupleOr(new HTuple(hv_ParamName.TupleEqual("red_channel_attrib")))).TupleOr(
+                                    new HTuple(hv_ParamName.TupleEqual("green_channel_attrib")))).TupleOr(
+                                    new HTuple(hv_ParamName.TupleEqual("blue_channel_attrib"))) != 0)
+                                {
+                                    throw new HalconException("Wrong type or value for parameter " + hv_ParamName + ": " + hv_ParamValue + ". " + hv_ParamValue + " may not be attached to the points of the 3D object model. Compare the parameter AttachExtAttribTo of set_object_model_3d_attrib.");
+                                }
+                                else
+                                {
+                                    throw new HalconException("Wrong type or value for parameter " + hv_ParamName + ": " + hv_ParamValue);
+                                }
+                            }
+                        }
+                        //Check if it is a parameter that is valid for only one instance
+                        //and therefore can be set only with set_scene_3d_instance_param
+                        hv_ParamNameTrunk.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNameTrunk = hv_ParamName.TupleRegexpReplace(
+                                "_\\d+$", "");
+                        }
+                        if ((int)new HTuple(hv_ParamName.TupleEqual(hv_ParamNameTrunk)) != 0)
+                        {
+                            hv_Instance.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Instance = HTuple.TupleGenSequence(
+                                    0, hv_NumModels - 1, 1);
+                            }
+                        }
+                        else
+                        {
+                            hv_Instance.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Instance = hv_ParamName.TupleRegexpReplace(
+                                    "^" + hv_ParamNameTrunk + "_(\\d+)$", "$1").TupleNumber();
+                            }
+                            if ((int)new HTuple(hv_Instance.TupleLess(0)).TupleOr(new HTuple(hv_Instance.TupleGreater(
+                                hv_NumModels - 1))) != 0)
+                            {
+                                throw new HalconException("Parameter " + hv_ParamName + " refers to a non existing 3D object model");
+                            }
+                        }
+                        try
+                        {
+                            HOperatorSet.SetScene3dInstanceParam(hv_Scene3D, hv_Instance, hv_ParamNameTrunk,
+                                hv_ParamValue);
+                        }
+                        // catch (Exception) 
+                        catch (HalconException HDevExpDefaultException2)
+                        {
+                            HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                            if ((int)new HTuple(hv_Exception.TupleSelect(0).TupleEqual(1204)).TupleOr(
+                                new HTuple(hv_Exception.TupleSelect(0).TupleEqual(1304))) != 0)
+                            {
+                                if ((int)new HTuple(new HTuple(new HTuple(hv_ParamNameTrunk.TupleEqual(
+                                    "color_attrib")).TupleOr(new HTuple(hv_ParamNameTrunk.TupleEqual(
+                                    "red_channel_attrib")))).TupleOr(new HTuple(hv_ParamNameTrunk.TupleEqual(
+                                    "green_channel_attrib")))).TupleOr(new HTuple(hv_ParamNameTrunk.TupleEqual(
+                                    "blue_channel_attrib"))) != 0)
+                                {
+                                    throw new HalconException("Wrong type or value for parameter " + hv_ParamName + ": " + hv_ParamValue + ". " + hv_ParamValue + " may not be attached to the points of the 3D object model. Compare the parameter AttachExtAttribTo of set_object_model_3d_attrib.");
+                                }
+                                else
+                                {
+                                    throw new HalconException("Wrong type or value for parameter " + hv_ParamName + ": " + hv_ParamValue);
+                                }
+                            }
+                            else if ((int)new HTuple(hv_Exception.TupleSelect(0).TupleEqual(
+                                1203)).TupleOr(new HTuple(hv_Exception.TupleSelect(0).TupleEqual(
+                                1303))) != 0)
+                            {
+                                throw new HalconException("Wrong parameter name " + hv_ParamName);
+                            }
+                            else
+                            {
+                                throw new HalconException(hv_Exception);
+                            }
+                        }
+                        if ((int)new HTuple(hv_ParamNameTrunk.TupleEqual("alpha")) != 0)
+                        {
+                            if (hv_AlphaOrig == null)
+                                hv_AlphaOrig = new HTuple();
+                            hv_AlphaOrig[hv_Instance] = hv_ParamValue;
+                        }
+                    }
+                    //
+                    //Start the visualization loop
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_HomMat3D.Dispose();
+                        HOperatorSet.PoseToHomMat3d(hv_Poses.TupleSelectRange(0, 6), out hv_HomMat3D);
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Qx.Dispose(); hv_Qy.Dispose(); hv_Qz.Dispose();
+                        HOperatorSet.AffineTransPoint3d(hv_HomMat3D, hv_Center.TupleSelect(0), hv_Center.TupleSelect(
+                            1), hv_Center.TupleSelect(2), out hv_Qx, out hv_Qy, out hv_Qz);
+                    }
+                    hv_TBCenter.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TBCenter = new HTuple();
+                        hv_TBCenter = hv_TBCenter.TupleConcat(hv_Qx, hv_Qy, hv_Qz);
+                    }
+                    hv_TBSize.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TBSize = (0.5 + 0.5 * hv_SelectedObject.TupleSum()
+                             / hv_NumModels) * hv_TrackballRadiusPixel;
+                    }
+                    hv_ButtonHold.Dispose();
+                    hv_ButtonHold = 0;
+                    while (1 != 0)
+                    {
+                        // 璁剧疆鍦ㄦ寰幆涓嶅崱涓荤嚎绋�
+
+                        hv_VisualizeTB.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_VisualizeTB = new HTuple(hv_SelectedObject.TupleMax()
+                                .TupleNotEqual(0));
+                        }
+                        hv_MaxIndex.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_MaxIndex = new HTuple(hv_ObjectModel3D.TupleLength()
+                                ).TupleConcat(hv_MaxNumModels).TupleMin() - 1;
+                        }
+                        //Set trackball fixed in the center of the window
+                        hv_TrackballCenterRow.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_TrackballCenterRow = hv_Height / 2;
+                        }
+                        hv_TrackballCenterCol.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_TrackballCenterCol = hv_Width / 2;
+                        }
+                        if ((int)new HTuple(hv_WindowCenteredRotation.TupleEqual(1)) != 0)
+                        {
+                            try
+                            {
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_TBCenter.Dispose(); hv_TBSize.Dispose();
+                                    HDevelopExport.get_trackball_center_fixed(hv_SelectedObject.TupleSelectRange(0, hv_MaxIndex),
+                                        hv_TrackballCenterRow, hv_TrackballCenterCol, hv_TrackballRadiusPixel,
+                                        hv_Scene3D, hv_ObjectModel3D.TupleSelectRange(0, hv_MaxIndex), hv_Poses.TupleSelectRange(
+                                        0, (hv_MaxIndex + 1) * 7 - 1), hv_WindowHandleBuffer, hv_CamParam_COPY_INP_TMP,
+                                        hv_GenParamName_COPY_INP_TMP, hv_GenParamValue_COPY_INP_TMP, out hv_TBCenter,
+                                        out hv_TBSize);
+                                }
+                            }
+                            // catch (Exception) 
+                            catch (HalconException HDevExpDefaultException2)
+                            {
+                                HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                                disp_message(hv_WindowHandle, "Surface inspection mode is not available.",
+                                    "image", 5, 20, "red", "true");
+                                hv_WindowCenteredRotation.Dispose();
+                                hv_WindowCenteredRotation = 2;
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_TBCenter.Dispose(); hv_TBSize.Dispose();
+                                    HDevelopExport.get_trackball_center(hv_SelectedObject.TupleSelectRange(0, hv_MaxIndex),
+                                        hv_TrackballRadiusPixel, hv_ObjectModel3D.TupleSelectRange(0, hv_MaxIndex),
+                                        hv_Poses.TupleSelectRange(0, (hv_MaxIndex + 1) * 7 - 1), out hv_TBCenter,
+                                        out hv_TBSize);
+                                }
+                                HOperatorSet.WaitSeconds(1);
+                            }
+                        }
+                        else
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_TBCenter.Dispose(); hv_TBSize.Dispose();
+                                HDevelopExport.get_trackball_center(hv_SelectedObject.TupleSelectRange(0, hv_MaxIndex),
+                                    hv_TrackballRadiusPixel, hv_ObjectModel3D.TupleSelectRange(0, hv_MaxIndex),
+                                    hv_Poses.TupleSelectRange(0, (hv_MaxIndex + 1) * 7 - 1), out hv_TBCenter,
+                                    out hv_TBSize);
+                            }
+                        }
+                        HDevelopExport.dump_image_output(ho_Image, hv_WindowHandleBuffer, hv_Scene3D, hv_AlphaOrig,
+                            hv_ObjectModel3D, hv_GenParamName_COPY_INP_TMP, hv_GenParamValue_COPY_INP_TMP,
+                            hv_CamParam_COPY_INP_TMP, hv_Poses, hv_ColorImage, hv_Title, hv_Information,
+                            hv_Label_COPY_INP_TMP, hv_VisualizeTB, "true", hv_TrackballCenterRow,
+                            hv_TrackballCenterCol, hv_TBSize, hv_SelectedObject, hv_WindowCenteredRotation,
+                            hv_TBCenter);
+                        ho_ImageDump.Dispose();
+                        HOperatorSet.DumpWindowImage(out ho_ImageDump, hv_WindowHandleBuffer);
+                        HDevWindowStack.SetActive(hv_WindowHandle);
+                        if (HDevWindowStack.IsOpen())
+                        {
+                            HOperatorSet.DispObj(ho_ImageDump, HDevWindowStack.GetActive());
+                        }
+                        //
+                        //Check for mouse events
+                        hv_GraphEvent.Dispose();
+                        hv_GraphEvent = 0;
+                        hv_Exit.Dispose();
+                        hv_Exit = 0;
+                        while (1 != 0)
+                        {
+                            // 璁剧疆鍦ㄦ寰幆涓嶅崱涓荤嚎绋�
+                            //
+                            //Check graphic event
+                            try
+                            {
+                                hv_GraphButtonRow.Dispose(); hv_GraphButtonColumn.Dispose(); hv_GraphButton.Dispose();
+                                HOperatorSet.GetMpositionSubPix(hv_WindowHandle, out hv_GraphButtonRow,
+                                    out hv_GraphButtonColumn, out hv_GraphButton);
+                                if ((int)new HTuple(hv_GraphButton.TupleNotEqual(0)) != 0)
+                                {
+                                    if ((int)new HTuple(new HTuple(new HTuple(hv_GraphButtonRow.TupleGreater(
+                                        hv_Height - hv_TextHeight - 25)).TupleAnd(new HTuple(hv_GraphButtonRow.TupleLess(
+                                        hv_Height)))).TupleAnd(new HTuple(hv_GraphButtonColumn.TupleGreater(
+                                        hv_Width - hv_TextWidth - 15)))).TupleAnd(new HTuple(hv_GraphButtonColumn.TupleLess(
+                                        hv_Width))) != 0)
+                                    {
+                                        //Wait until the continue button has been released
+                                        if ((int)new HTuple(hv_WaitForButtonRelease.TupleEqual("true")) != 0)
+                                        {
+                                            while (1 != 0)
+                                            {
+                                                hv_GraphButtonRow.Dispose(); hv_GraphButtonColumn.Dispose(); hv_GraphButton.Dispose();
+                                                HOperatorSet.GetMpositionSubPix(hv_WindowHandle, out hv_GraphButtonRow,
+                                                    out hv_GraphButtonColumn, out hv_GraphButton);
+                                                if ((int)new HTuple(hv_GraphButton.TupleEqual(0)).TupleOr(
+                                                    new HTuple(hv_GraphButton.TupleEqual(new HTuple()))) != 0)
+                                                {
+                                                    if ((int)new HTuple(new HTuple(new HTuple(hv_GraphButtonRow.TupleGreater(
+                                                        hv_Height - hv_TextHeight - 25)).TupleAnd(new HTuple(hv_GraphButtonRow.TupleLess(
+                                                        hv_Height)))).TupleAnd(new HTuple(hv_GraphButtonColumn.TupleGreater(
+                                                        hv_Width - hv_TextWidth - 15)))).TupleAnd(new HTuple(hv_GraphButtonColumn.TupleLess(
+                                                        hv_Width))) != 0)
+                                                    {
+                                                        hv_ButtonReleased.Dispose();
+                                                        hv_ButtonReleased = 1;
+                                                    }
+                                                    else
+                                                    {
+                                                        hv_ButtonReleased.Dispose();
+                                                        hv_ButtonReleased = 0;
+                                                    }
+                                                    //
+                                                    break;
+                                                }
+                                                //Keep waiting until mouse button is released or moved out of the window
+                                            }
+                                        }
+                                        else
+                                        {
+                                            hv_ButtonReleased.Dispose();
+                                            hv_ButtonReleased = 1;
+                                        }
+                                        //Exit the visualization loop
+                                        if ((int)hv_ButtonReleased != 0)
+                                        {
+                                            hv_Exit.Dispose();
+                                            hv_Exit = 1;
+                                            break;
+                                        }
+                                    }
+                                    hv_GraphEvent.Dispose();
+                                    hv_GraphEvent = 1;
+                                    break;
+                                }
+                                else
+                                {
+                                    hv_ButtonHold.Dispose();
+                                    hv_ButtonHold = 0;
+                                }
+                            }
+                            // catch (Exception) 
+                            catch (HalconException HDevExpDefaultException2)
+                            {
+                                HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                                //Keep waiting
+                            }
+                        }
+                        if ((int)hv_GraphEvent != 0)
+                        {
+                            {
+                                HTuple ExpTmpOutVar_0; HTuple ExpTmpOutVar_1; HTuple ExpTmpOutVar_2; HTuple ExpTmpOutVar_3;
+                                HDevelopExport.analyze_graph_event(ho_Image, hv_MouseMapping, hv_GraphButton, hv_GraphButtonRow,
+                                    hv_GraphButtonColumn, hv_WindowHandle, hv_WindowHandleBuffer, hv_VirtualTrackball,
+                                    hv_TrackballSize, hv_SelectedObject, hv_Scene3D, hv_AlphaOrig, hv_ObjectModel3D,
+                                    hv_CamParam_COPY_INP_TMP, hv_Label_COPY_INP_TMP, hv_Title, hv_Information,
+                                    hv_GenParamName_COPY_INP_TMP, hv_GenParamValue_COPY_INP_TMP, hv_Poses,
+                                    hv_ButtonHold, hv_TBCenter, hv_TBSize, hv_WindowCenteredRotation,
+                                    hv_MaxNumModels, out ExpTmpOutVar_0, out ExpTmpOutVar_1, out ExpTmpOutVar_2,
+                                    out ExpTmpOutVar_3);
+                                hv_Poses.Dispose();
+                                hv_Poses = ExpTmpOutVar_0;
+                                hv_SelectedObject.Dispose();
+                                hv_SelectedObject = ExpTmpOutVar_1;
+                                hv_ButtonHold.Dispose();
+                                hv_ButtonHold = ExpTmpOutVar_2;
+                                hv_WindowCenteredRotation.Dispose();
+                                hv_WindowCenteredRotation = ExpTmpOutVar_3;
+                            }
+                        }
+                        if ((int)hv_Exit != 0)
+                        {
+                            break;
+                        }
+                    }
+                    //
+                    //Display final state with persistence, if requested
+                    //Note that disp_object_model_3d must be used instead of the 3D scene
+                    if ((int)new HTuple(new HTuple(hv_PersistenceParamName.TupleLength()).TupleGreater(
+                        0)) != 0)
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HOperatorSet.DispObjectModel3d(hv_WindowHandle, hv_ObjectModel3D, hv_CamParam_COPY_INP_TMP,
+                                hv_Poses, new HTuple("disp_background").TupleConcat("alpha").TupleConcat(
+                                hv_PersistenceParamName), new HTuple("true").TupleConcat(0.0).TupleConcat(
+                                hv_PersistenceParamValue));
+                        }
+                    }
+                    //
+                    //Compute the output pose
+                    if ((int)HDevelopExport.ExpGetGlobalVar_gIsSinglePose() != 0)
+                    {
+                        hv_PoseOut.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_PoseOut = hv_Poses.TupleSelectRange(
+                                0, 6);
+                        }
+                    }
+                    else
+                    {
+                        hv_PoseOut.Dispose();
+                        hv_PoseOut = new HTuple(hv_Poses);
+                    }
+                    //
+                    //Clean up.
+                    HOperatorSet.SetSystem("clip_region", hv_ClipRegion);
+                    // dev_set_preferences(...); only in hdevelop
+                    // dev_set_preferences(...); only in hdevelop
+                    HDevelopExport.dump_image_output(ho_Image, hv_WindowHandleBuffer, hv_Scene3D, hv_AlphaOrig,
+                        hv_ObjectModel3D, hv_GenParamName_COPY_INP_TMP, hv_GenParamValue_COPY_INP_TMP,
+                        hv_CamParam_COPY_INP_TMP, hv_Poses, hv_ColorImage, hv_Title, new HTuple(),
+                        hv_Label_COPY_INP_TMP, 0, "false", hv_TrackballCenterRow, hv_TrackballCenterCol,
+                        hv_TBSize, hv_SelectedObject, hv_WindowCenteredRotation, hv_TBCenter);
+                    ho_ImageDump.Dispose();
+                    HOperatorSet.DumpWindowImage(out ho_ImageDump, hv_WindowHandleBuffer);
+                    HDevWindowStack.SetActive(hv_WindowHandle);
+                    if (HDevWindowStack.IsOpen())
+                    {
+                        HOperatorSet.DispObj(ho_ImageDump, HDevWindowStack.GetActive());
+                    }
+                    HOperatorSet.CloseWindow(hv_WindowHandleBuffer);
+                    HOperatorSet.SetPart(hv_WindowHandle, hv_WPRow1, hv_WPColumn1, hv_WPRow2,
+                        hv_WPColumn2);
+                    HOperatorSet.ClearScene3d(hv_Scene3D);
+                    hv_Scene3D.Dispose();
+                    hv_Scene3D = new HTuple();
+                }
+                // catch (Exception) 
+                catch (HalconException HDevExpDefaultException1)
+                {
+                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                    try
+                    {
+                        //Try to clean up as much as possible.
+                        if ((int)new HTuple(new HTuple(0).TupleLess(new HTuple(hv_Scene3DTest.TupleLength()
+                            ))) != 0)
+                        {
+                            HOperatorSet.ClearScene3d(hv_Scene3DTest);
+                            hv_Scene3DTest.Dispose();
+                            hv_Scene3DTest = new HTuple();
+                        }
+                        if ((int)new HTuple(new HTuple(0).TupleLess(new HTuple(hv_Scene3D.TupleLength()
+                            ))) != 0)
+                        {
+                            HOperatorSet.ClearScene3d(hv_Scene3D);
+                            hv_Scene3D.Dispose();
+                            hv_Scene3D = new HTuple();
+                        }
+                        if ((int)new HTuple(new HTuple(0).TupleLess(new HTuple(hv_WindowHandleBuffer.TupleLength()
+                            ))) != 0)
+                        {
+                            HOperatorSet.CloseWindow(hv_WindowHandleBuffer);
+                            hv_WindowHandleBuffer.Dispose();
+                            hv_WindowHandleBuffer = new HTuple();
+                        }
+                    }
+                    // catch (e) 
+                    catch (HalconException HDevExpDefaultException2)
+                    {
+                        HDevExpDefaultException2.ToHTuple(out hv_e);
+                        //Suppress all further exceptions to return the original exception.
+                    }
+                    try
+                    {
+                        //Restore system settings.
+                        HOperatorSet.SetSystem("clip_region", hv_ClipRegion);
+                        // dev_set_preferences(...); only in hdevelop
+                        // dev_set_preferences(...); only in hdevelop
+                    }
+                    // catch (e) 
+                    catch (HalconException HDevExpDefaultException2)
+                    {
+                        HDevExpDefaultException2.ToHTuple(out hv_e);
+                        //Suppress all further exceptions to return the original exception.
+                    }
+                    //
+                    throw new HalconException(hv_Exception);
+                }
+                ho_Image.Dispose();
+                ho_ImageDump.Dispose();
+
+                hv_CamParam_COPY_INP_TMP.Dispose();
+                hv_GenParamName_COPY_INP_TMP.Dispose();
+                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                hv_Label_COPY_INP_TMP.Dispose();
+                hv_PoseIn_COPY_INP_TMP.Dispose();
+                hv_Scene3DTest.Dispose();
+                hv_Scene3D.Dispose();
+                hv_WindowHandleBuffer.Dispose();
+                hv_TrackballSize.Dispose();
+                hv_VirtualTrackball.Dispose();
+                hv_MouseMapping.Dispose();
+                hv_WaitForButtonRelease.Dispose();
+                hv_MaxNumModels.Dispose();
+                hv_WindowCenteredRotation.Dispose();
+                hv_NumModels.Dispose();
+                hv_SelectedObject.Dispose();
+                hv_ClipRegion.Dispose();
+                hv_CPLength.Dispose();
+                hv_RowNotUsed.Dispose();
+                hv_ColumnNotUsed.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_WPRow1.Dispose();
+                hv_WPColumn1.Dispose();
+                hv_WPRow2.Dispose();
+                hv_WPColumn2.Dispose();
+                hv_CamParamValue.Dispose();
+                hv_CamWidth.Dispose();
+                hv_CamHeight.Dispose();
+                hv_Scale.Dispose();
+                hv_Indices.Dispose();
+                hv_DispBackground.Dispose();
+                hv_Mask.Dispose();
+                hv_Center.Dispose();
+                hv_PoseEstimated.Dispose();
+                hv_Poses.Dispose();
+                hv_HomMat3Ds.Dispose();
+                hv_Sequence.Dispose();
+                hv_Font.Dispose();
+                hv_Exception.Dispose();
+                hv_OpenGLInfo.Dispose();
+                hv_DummyObjectModel3D.Dispose();
+                hv_CameraIndexTest.Dispose();
+                hv_PoseTest.Dispose();
+                hv_InstanceIndexTest.Dispose();
+                hv_MinImageSize.Dispose();
+                hv_TrackballRadiusPixel.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_TextWidth.Dispose();
+                hv_TextHeight.Dispose();
+                hv_NumChannels.Dispose();
+                hv_ColorImage.Dispose();
+                hv_CameraIndex.Dispose();
+                hv_AllInstances.Dispose();
+                hv_SetLight.Dispose();
+                hv_LightParam.Dispose();
+                hv_LightPosition.Dispose();
+                hv_LightKind.Dispose();
+                hv_LightIndex.Dispose();
+                hv_PersistenceParamName.Dispose();
+                hv_PersistenceParamValue.Dispose();
+                hv_AlphaOrig.Dispose();
+                hv_I.Dispose();
+                hv_ParamName.Dispose();
+                hv_ParamValue.Dispose();
+                hv_ParamNameTrunk.Dispose();
+                hv_Instance.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_Qx.Dispose();
+                hv_Qy.Dispose();
+                hv_Qz.Dispose();
+                hv_TBCenter.Dispose();
+                hv_TBSize.Dispose();
+                hv_ButtonHold.Dispose();
+                hv_VisualizeTB.Dispose();
+                hv_MaxIndex.Dispose();
+                hv_TrackballCenterRow.Dispose();
+                hv_TrackballCenterCol.Dispose();
+                hv_GraphEvent.Dispose();
+                hv_Exit.Dispose();
+                hv_GraphButtonRow.Dispose();
+                hv_GraphButtonColumn.Dispose();
+                hv_GraphButton.Dispose();
+                hv_ButtonReleased.Dispose();
+                hv_e.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_Image.Dispose();
+                ho_ImageDump.Dispose();
+
+                hv_CamParam_COPY_INP_TMP.Dispose();
+                hv_GenParamName_COPY_INP_TMP.Dispose();
+                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                hv_Label_COPY_INP_TMP.Dispose();
+                hv_PoseIn_COPY_INP_TMP.Dispose();
+                hv_Scene3DTest.Dispose();
+                hv_Scene3D.Dispose();
+                hv_WindowHandleBuffer.Dispose();
+                hv_TrackballSize.Dispose();
+                hv_VirtualTrackball.Dispose();
+                hv_MouseMapping.Dispose();
+                hv_WaitForButtonRelease.Dispose();
+                hv_MaxNumModels.Dispose();
+                hv_WindowCenteredRotation.Dispose();
+                hv_NumModels.Dispose();
+                hv_SelectedObject.Dispose();
+                hv_ClipRegion.Dispose();
+                hv_CPLength.Dispose();
+                hv_RowNotUsed.Dispose();
+                hv_ColumnNotUsed.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_WPRow1.Dispose();
+                hv_WPColumn1.Dispose();
+                hv_WPRow2.Dispose();
+                hv_WPColumn2.Dispose();
+                hv_CamParamValue.Dispose();
+                hv_CamWidth.Dispose();
+                hv_CamHeight.Dispose();
+                hv_Scale.Dispose();
+                hv_Indices.Dispose();
+                hv_DispBackground.Dispose();
+                hv_Mask.Dispose();
+                hv_Center.Dispose();
+                hv_PoseEstimated.Dispose();
+                hv_Poses.Dispose();
+                hv_HomMat3Ds.Dispose();
+                hv_Sequence.Dispose();
+                hv_Font.Dispose();
+                hv_Exception.Dispose();
+                hv_OpenGLInfo.Dispose();
+                hv_DummyObjectModel3D.Dispose();
+                hv_CameraIndexTest.Dispose();
+                hv_PoseTest.Dispose();
+                hv_InstanceIndexTest.Dispose();
+                hv_MinImageSize.Dispose();
+                hv_TrackballRadiusPixel.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_TextWidth.Dispose();
+                hv_TextHeight.Dispose();
+                hv_NumChannels.Dispose();
+                hv_ColorImage.Dispose();
+                hv_CameraIndex.Dispose();
+                hv_AllInstances.Dispose();
+                hv_SetLight.Dispose();
+                hv_LightParam.Dispose();
+                hv_LightPosition.Dispose();
+                hv_LightKind.Dispose();
+                hv_LightIndex.Dispose();
+                hv_PersistenceParamName.Dispose();
+                hv_PersistenceParamValue.Dispose();
+                hv_AlphaOrig.Dispose();
+                hv_I.Dispose();
+                hv_ParamName.Dispose();
+                hv_ParamValue.Dispose();
+                hv_ParamNameTrunk.Dispose();
+                hv_Instance.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_Qx.Dispose();
+                hv_Qy.Dispose();
+                hv_Qz.Dispose();
+                hv_TBCenter.Dispose();
+                hv_TBSize.Dispose();
+                hv_ButtonHold.Dispose();
+                hv_VisualizeTB.Dispose();
+                hv_MaxIndex.Dispose();
+                hv_TrackballCenterRow.Dispose();
+                hv_TrackballCenterCol.Dispose();
+                hv_GraphEvent.Dispose();
+                hv_Exit.Dispose();
+                hv_GraphButtonRow.Dispose();
+                hv_GraphButtonColumn.Dispose();
+                hv_GraphButton.Dispose();
+                hv_ButtonReleased.Dispose();
+                hv_e.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Calibration / Camera Parameters
+        // Short Description: Set the value of a specified camera parameter in the camera parameter tuple. 
+        public static void set_cam_par_data(HTuple hv_CameraParamIn, HTuple hv_ParamName, HTuple hv_ParamValue,
+            out HTuple hv_CameraParamOut)
+        {
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_CameraType = new HTuple(), hv_CameraParamNames = new HTuple();
+            HTuple hv_Index = new HTuple(), hv_ParamNameInd = new HTuple();
+            HTuple hv_I = new HTuple(), hv_IsTelecentric = new HTuple();
+            // Initialize local and output iconic variables 
+            hv_CameraParamOut = new HTuple();
+            try
+            {
+                //set_cam_par_data sets the value of the parameter that
+                //is given in ParamName in the tuple of camera parameters
+                //given in CameraParamIn. The modified camera parameters
+                //are returned in CameraParamOut.
+                //
+                //Check for consistent length of input parameters
+                if ((int)new HTuple(new HTuple(hv_ParamName.TupleLength()).TupleNotEqual(
+                    new HTuple(hv_ParamValue.TupleLength()))) != 0)
+                {
+                    throw new HalconException("Different number of values in ParamName and ParamValue");
+                }
+                //First, get the parameter names that correspond to the
+                //elements in the input camera parameter tuple.
+                hv_CameraType.Dispose(); hv_CameraParamNames.Dispose();
+                HDevelopExport.get_cam_par_names(hv_CameraParamIn, out hv_CameraType, out hv_CameraParamNames);
+                //
+                //Find the index of the requested camera data and return
+                //the corresponding value.
+                hv_CameraParamOut.Dispose();
+                hv_CameraParamOut = new HTuple(hv_CameraParamIn);
+                for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_ParamName.TupleLength()
+                    ) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    hv_ParamNameInd.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_ParamNameInd = hv_ParamName.TupleSelect(
+                            hv_Index);
+                    }
+                    hv_I.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_I = hv_CameraParamNames.TupleFind(
+                            hv_ParamNameInd);
+                    }
+                    if ((int)new HTuple(hv_I.TupleNotEqual(-1)) != 0)
+                    {
+                        if (hv_CameraParamOut == null)
+                            hv_CameraParamOut = new HTuple();
+                        hv_CameraParamOut[hv_I] = hv_ParamValue.TupleSelect(hv_Index);
+                    }
+                    else
+                    {
+                        throw new HalconException("Wrong ParamName " + hv_ParamNameInd);
+                    }
+                    //Check the consistency of focus and telecentricity
+                    if ((int)new HTuple(hv_ParamNameInd.TupleEqual("focus")) != 0)
+                    {
+                        hv_IsTelecentric.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_IsTelecentric = new HTuple(hv_CameraType.TupleStrstr(
+                                "telecentric").TupleNotEqual(-1)).TupleAnd(new HTuple(hv_CameraType.TupleStrstr(
+                                "image_side_telecentric").TupleEqual(-1)));
+                        }
+                        if ((int)hv_IsTelecentric != 0)
+                        {
+                            throw new HalconException(new HTuple("Focus for telecentric lenses is always 0, and hence, cannot be changed."));
+                        }
+                        if ((int)new HTuple(hv_IsTelecentric.TupleNot()).TupleAnd(new HTuple(hv_ParamValue.TupleSelect(
+                            hv_Index).TupleEqual(0.0))) != 0)
+                        {
+                            throw new HalconException("Focus for non-telecentric lenses must not be 0.");
+                        }
+                    }
+                }
+
+                hv_CameraType.Dispose();
+                hv_CameraParamNames.Dispose();
+                hv_Index.Dispose();
+                hv_ParamNameInd.Dispose();
+                hv_I.Dispose();
+                hv_IsTelecentric.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_CameraType.Dispose();
+                hv_CameraParamNames.Dispose();
+                hv_Index.Dispose();
+                hv_ParamNameInd.Dispose();
+                hv_I.Dispose();
+                hv_IsTelecentric.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        public static void gen_arrow_contour_xld(out HObject ho_Arrow, HTuple hv_Row1, HTuple hv_Column1,
+            HTuple hv_Row2, HTuple hv_Column2, HTuple hv_HeadLength, HTuple hv_HeadWidth)
+        {
+            // Stack for temporary objects 
+            HObject[] OTemp = new HObject[20];
+
+            // Local iconic variables 
+
+            HObject ho_TempArrow = null;
+
+            // Local control variables 
+
+            HTuple hv_Length = new HTuple(), hv_ZeroLengthIndices = new HTuple();
+            HTuple hv_DR = new HTuple(), hv_DC = new HTuple(), hv_HalfHeadWidth = new HTuple();
+            HTuple hv_RowP1 = new HTuple(), hv_ColP1 = new HTuple();
+            HTuple hv_RowP2 = new HTuple(), hv_ColP2 = new HTuple();
+            HTuple hv_Index = new HTuple();
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_Arrow);
+            HOperatorSet.GenEmptyObj(out ho_TempArrow);
+            try
+            {
+                //This procedure generates arrow shaped XLD contours,
+                //pointing from (Row1, Column1) to (Row2, Column2).
+                //If starting and end point are identical, a contour consisting
+                //of a single point is returned.
+                //
+                //input parameteres:
+                //Row1, Column1: Coordinates of the arrows' starting points
+                //Row2, Column2: Coordinates of the arrows' end points
+                //HeadLength, HeadWidth: Size of the arrow heads in pixels
+                //
+                //output parameter:
+                //Arrow: The resulting XLD contour
+                //
+                //The input tuples Row1, Column1, Row2, and Column2 have to be of
+                //the same length.
+                //HeadLength and HeadWidth either have to be of the same length as
+                //Row1, Column1, Row2, and Column2 or have to be a single element.
+                //If one of the above restrictions is violated, an error will occur.
+                //
+                //
+                //Init
+                ho_Arrow.Dispose();
+                HOperatorSet.GenEmptyObj(out ho_Arrow);
+                //
+                //Calculate the arrow length
+                hv_Length.Dispose();
+                HOperatorSet.DistancePp(hv_Row1, hv_Column1, hv_Row2, hv_Column2, out hv_Length);
+                //
+                //Mark arrows with identical start and end point
+                //(set Length to -1 to avoid division-by-zero exception)
+                hv_ZeroLengthIndices.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_ZeroLengthIndices = hv_Length.TupleFind(
+                        0);
+                }
+                if ((int)(new HTuple(hv_ZeroLengthIndices.TupleNotEqual(-1))) != 0)
+                {
+                    if (hv_Length == null)
+                        hv_Length = new HTuple();
+                    hv_Length[hv_ZeroLengthIndices] = -1;
+                }
+                //
+                //Calculate auxiliary variables.
+                hv_DR.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_DR = (1.0 * (hv_Row2 - hv_Row1)) / hv_Length;
+                }
+                hv_DC.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_DC = (1.0 * (hv_Column2 - hv_Column1)) / hv_Length;
+                }
+                hv_HalfHeadWidth.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_HalfHeadWidth = hv_HeadWidth / 2.0;
+                }
+                //
+                //Calculate end points of the arrow head.
+                hv_RowP1.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_RowP1 = (hv_Row1 + ((hv_Length - hv_HeadLength) * hv_DR)) + (hv_HalfHeadWidth * hv_DC);
+                }
+                hv_ColP1.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_ColP1 = (hv_Column1 + ((hv_Length - hv_HeadLength) * hv_DC)) - (hv_HalfHeadWidth * hv_DR);
+                }
+                hv_RowP2.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_RowP2 = (hv_Row1 + ((hv_Length - hv_HeadLength) * hv_DR)) - (hv_HalfHeadWidth * hv_DC);
+                }
+                hv_ColP2.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_ColP2 = (hv_Column1 + ((hv_Length - hv_HeadLength) * hv_DC)) + (hv_HalfHeadWidth * hv_DR);
+                }
+                //
+                //Finally create output XLD contour for each input point pair
+                for (hv_Index = 0; (int)hv_Index <= (int)((new HTuple(hv_Length.TupleLength())) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    if ((int)(new HTuple(((hv_Length.TupleSelect(hv_Index))).TupleEqual(-1))) != 0)
+                    {
+                        //Create_ single points for arrows with identical start and end point
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            ho_TempArrow.Dispose();
+                            HOperatorSet.GenContourPolygonXld(out ho_TempArrow, hv_Row1.TupleSelect(
+                                hv_Index), hv_Column1.TupleSelect(hv_Index));
+                        }
+                    }
+                    else
+                    {
+                        //Create arrow contour
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            ho_TempArrow.Dispose();
+                            HOperatorSet.GenContourPolygonXld(out ho_TempArrow, ((((((((((hv_Row1.TupleSelect(
+                                hv_Index))).TupleConcat(hv_Row2.TupleSelect(hv_Index)))).TupleConcat(
+                                hv_RowP1.TupleSelect(hv_Index)))).TupleConcat(hv_Row2.TupleSelect(hv_Index)))).TupleConcat(
+                                hv_RowP2.TupleSelect(hv_Index)))).TupleConcat(hv_Row2.TupleSelect(hv_Index)),
+                                ((((((((((hv_Column1.TupleSelect(hv_Index))).TupleConcat(hv_Column2.TupleSelect(
+                                hv_Index)))).TupleConcat(hv_ColP1.TupleSelect(hv_Index)))).TupleConcat(
+                                hv_Column2.TupleSelect(hv_Index)))).TupleConcat(hv_ColP2.TupleSelect(
+                                hv_Index)))).TupleConcat(hv_Column2.TupleSelect(hv_Index)));
+                        }
+                    }
+                    {
+                        HObject ExpTmpOutVar_0;
+                        HOperatorSet.ConcatObj(ho_Arrow, ho_TempArrow, out ExpTmpOutVar_0);
+                        ho_Arrow.Dispose();
+                        ho_Arrow = ExpTmpOutVar_0;
+                    }
+                }
+                ho_TempArrow.Dispose();
+
+                hv_Length.Dispose();
+                hv_ZeroLengthIndices.Dispose();
+                hv_DR.Dispose();
+                hv_DC.Dispose();
+                hv_HalfHeadWidth.Dispose();
+                hv_RowP1.Dispose();
+                hv_ColP1.Dispose();
+                hv_RowP2.Dispose();
+                hv_ColP2.Dispose();
+                hv_Index.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_TempArrow.Dispose();
+
+                hv_Length.Dispose();
+                hv_ZeroLengthIndices.Dispose();
+                hv_DR.Dispose();
+                hv_DC.Dispose();
+                hv_HalfHeadWidth.Dispose();
+                hv_RowP1.Dispose();
+                hv_ColP1.Dispose();
+                hv_RowP2.Dispose();
+                hv_ColP2.Dispose();
+                hv_Index.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        public static void get_rect2_vertex(HTuple hv_Row, HTuple hv_Column, HTuple hv_Phi, HTuple hv_Length1,
+            HTuple hv_Length2, out HTuple hv_TopLeft_Row, out HTuple hv_TopLeft_Col, out HTuple hv_TopRight_Row,
+            out HTuple hv_TopRight_Col, out HTuple hv_LowLeft_Row, out HTuple hv_LowLeft_Col,
+            out HTuple hv_LowRight_Row, out HTuple hv_LowRight_Col)
+        {
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_Tmp = new HTuple(), hv_Sin = new HTuple();
+            HTuple hv_Cos = new HTuple(), hv_TopLeft_X = new HTuple();
+            HTuple hv_TopLeft_Y = new HTuple(), hv_TopRight_X = new HTuple();
+            HTuple hv_TopRight_Y = new HTuple(), hv_LowerRight_X = new HTuple();
+            HTuple hv_LowerRight_Y = new HTuple(), hv_LowerLeft_X = new HTuple();
+            HTuple hv_LowerLeft_Y = new HTuple();
+            HTuple hv_Length1_COPY_INP_TMP = new HTuple(hv_Length1);
+            HTuple hv_Length2_COPY_INP_TMP = new HTuple(hv_Length2);
+            HTuple hv_Phi_COPY_INP_TMP = new HTuple(hv_Phi);
+
+            // Initialize local and output iconic variables 
+            hv_TopLeft_Row = new HTuple();
+            hv_TopLeft_Col = new HTuple();
+            hv_TopRight_Row = new HTuple();
+            hv_TopRight_Col = new HTuple();
+            hv_LowLeft_Row = new HTuple();
+            hv_LowLeft_Col = new HTuple();
+            hv_LowRight_Row = new HTuple();
+            hv_LowRight_Col = new HTuple();
+            try
+            {
+                if ((int)(new HTuple(((((hv_Phi_COPY_INP_TMP.TupleDeg())).TupleAbs())).TupleGreater(
+                    45))) != 0)
+                {
+
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Phi = (((hv_Phi_COPY_INP_TMP.TupleDeg()
+                                ) - (90 * (hv_Phi_COPY_INP_TMP / (hv_Phi_COPY_INP_TMP.TupleAbs()))))).TupleRad()
+                                ;
+                            hv_Phi_COPY_INP_TMP.Dispose();
+                            hv_Phi_COPY_INP_TMP = ExpTmpLocalVar_Phi;
+                        }
+                    }
+
+                    hv_Tmp.Dispose();
+                    hv_Tmp = new HTuple(hv_Length1_COPY_INP_TMP);
+
+                    hv_Length1_COPY_INP_TMP.Dispose();
+                    hv_Length1_COPY_INP_TMP = new HTuple(hv_Length2_COPY_INP_TMP);
+
+                    hv_Length2_COPY_INP_TMP.Dispose();
+                    hv_Length2_COPY_INP_TMP = new HTuple(hv_Tmp);
+
+                }
+
+                hv_Sin.Dispose();
+                HOperatorSet.TupleSin(hv_Phi_COPY_INP_TMP, out hv_Sin);
+
+                hv_Cos.Dispose();
+                HOperatorSet.TupleCos(hv_Phi_COPY_INP_TMP, out hv_Cos);
+
+                //宸︿笂瑙�
+
+                hv_TopLeft_X.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_TopLeft_X = ((-hv_Length1_COPY_INP_TMP) * hv_Cos) - (hv_Length2_COPY_INP_TMP * hv_Sin);
+                }
+
+                hv_TopLeft_Y.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_TopLeft_Y = ((-hv_Length1_COPY_INP_TMP) * hv_Sin) + (hv_Length2_COPY_INP_TMP * hv_Cos);
+                }
+
+                hv_TopLeft_Row.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_TopLeft_Row = hv_Row - hv_TopLeft_Y;
+                }
+
+                hv_TopLeft_Col.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_TopLeft_Col = hv_Column + hv_TopLeft_X;
+                }
+
+                //鍙充笂瑙�
+
+                hv_TopRight_X.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_TopRight_X = (hv_Length1_COPY_INP_TMP * hv_Cos) - (hv_Length2_COPY_INP_TMP * hv_Sin);
+                }
+
+                hv_TopRight_Y.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_TopRight_Y = (hv_Length1_COPY_INP_TMP * hv_Sin) + (hv_Length2_COPY_INP_TMP * hv_Cos);
+                }
+
+                hv_TopRight_Row.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_TopRight_Row = hv_Row - hv_TopRight_Y;
+                }
+
+                hv_TopRight_Col.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_TopRight_Col = hv_Column + hv_TopRight_X;
+                }
+
+                //鍙充笅瑙�
+
+                hv_LowerRight_X.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_LowerRight_X = (hv_Length1_COPY_INP_TMP * hv_Cos) + (hv_Length2_COPY_INP_TMP * hv_Sin);
+                }
+
+                hv_LowerRight_Y.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_LowerRight_Y = (hv_Length1_COPY_INP_TMP * hv_Sin) - (hv_Length2_COPY_INP_TMP * hv_Cos);
+                }
+
+                hv_LowRight_Row.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_LowRight_Row = hv_Row - hv_LowerRight_Y;
+                }
+
+                hv_LowRight_Col.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_LowRight_Col = hv_Column + hv_LowerRight_X;
+                }
+
+                //宸︿笅瑙�
+
+                hv_LowerLeft_X.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_LowerLeft_X = ((-hv_Length1_COPY_INP_TMP) * hv_Cos) + (hv_Length2_COPY_INP_TMP * hv_Sin);
+                }
+
+                hv_LowerLeft_Y.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_LowerLeft_Y = ((-hv_Length1_COPY_INP_TMP) * hv_Sin) - (hv_Length2_COPY_INP_TMP * hv_Cos);
+                }
+
+                hv_LowLeft_Row.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_LowLeft_Row = hv_Row - hv_LowerLeft_Y;
+                }
+
+                hv_LowLeft_Col.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_LowLeft_Col = hv_Column + hv_LowerLeft_X;
+                }
+
+
+                hv_Length1_COPY_INP_TMP.Dispose();
+                hv_Length2_COPY_INP_TMP.Dispose();
+                hv_Phi_COPY_INP_TMP.Dispose();
+                hv_Tmp.Dispose();
+                hv_Sin.Dispose();
+                hv_Cos.Dispose();
+                hv_TopLeft_X.Dispose();
+                hv_TopLeft_Y.Dispose();
+                hv_TopRight_X.Dispose();
+                hv_TopRight_Y.Dispose();
+                hv_LowerRight_X.Dispose();
+                hv_LowerRight_Y.Dispose();
+                hv_LowerLeft_X.Dispose();
+                hv_LowerLeft_Y.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Length1_COPY_INP_TMP.Dispose();
+                hv_Length2_COPY_INP_TMP.Dispose();
+                hv_Phi_COPY_INP_TMP.Dispose();
+                hv_Tmp.Dispose();
+                hv_Sin.Dispose();
+                hv_Cos.Dispose();
+                hv_TopLeft_X.Dispose();
+                hv_TopLeft_Y.Dispose();
+                hv_TopRight_X.Dispose();
+                hv_TopRight_Y.Dispose();
+                hv_LowerRight_X.Dispose();
+                hv_LowerRight_Y.Dispose();
+                hv_LowerLeft_X.Dispose();
+                hv_LowerLeft_Y.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        public static void pts_to_best_line(out HObject ho_LineXld, HTuple hv_Rows, HTuple hv_Columns,
+            HTuple hv_IgnoreNum, out HTuple hv_Row1, out HTuple hv_Column1, out HTuple hv_Row2,
+            out HTuple hv_Column2)
+        {
+            // Local iconic variables 
+
+            HObject ho_Contour = null;
+
+            // Local control variables 
+
+            HTuple hv_Length = new HTuple(), hv_Nr = new HTuple();
+            HTuple hv_Nc = new HTuple(), hv_Dist = new HTuple(), hv_Length1 = new HTuple();
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_LineXld);
+            HOperatorSet.GenEmptyObj(out ho_Contour);
+            hv_Row1 = new HTuple();
+            hv_Column1 = new HTuple();
+            hv_Row2 = new HTuple();
+            hv_Column2 = new HTuple();
+            try
+            {
+                //鍒濆鍖�
+                hv_Row1.Dispose();
+                hv_Row1 = 0;
+                hv_Column1.Dispose();
+                hv_Column1 = 0;
+                hv_Row2.Dispose();
+                hv_Row2 = 0;
+                hv_Column2.Dispose();
+                hv_Column2 = 0;
+                //浜х敓涓�涓┖鐨勭洿绾垮璞★紝鐢ㄤ簬淇濆瓨鎷熷悎鍚庣殑鐩寸嚎
+                ho_LineXld.Dispose();
+                HOperatorSet.GenEmptyObj(out ho_LineXld);
+                //璁$畻杈圭紭鏁伴噺
+                hv_Length.Dispose();
+                HOperatorSet.TupleLength(hv_Columns, out hv_Length);
+                //褰撹竟缂樻暟閲忎笉灏忎簬鏈夋晥鐐规暟鏃惰繘琛屾嫙鍚�
+                if ((int)((new HTuple(hv_Length.TupleGreaterEqual(2))).TupleAnd(new HTuple(hv_IgnoreNum.TupleLess(
+                    hv_Length - 2)))) != 0)
+                {
+                    //halcon鐨勬嫙鍚堟槸鍩轰簬xld鐨勶紝闇�瑕佹妸杈圭紭杩炴帴鎴恱ld
+                    ho_Contour.Dispose();
+                    HOperatorSet.GenContourPolygonXld(out ho_Contour, hv_Rows, hv_Columns);
+                    //鎷熷悎鐩寸嚎銆備娇鐢ㄧ殑绠楁硶鏄�'tukey'锛屽叾浠栫畻娉曞弬鑰僨it_line_contour_xld鐨勬弿杩�
+                    hv_Row1.Dispose(); hv_Column1.Dispose(); hv_Row2.Dispose(); hv_Column2.Dispose(); hv_Nr.Dispose(); hv_Nc.Dispose(); hv_Dist.Dispose();
+                    HOperatorSet.FitLineContourXld(ho_Contour, "tukey", -1, hv_IgnoreNum, 5,
+                        2, out hv_Row1, out hv_Column1, out hv_Row2, out hv_Column2, out hv_Nr,
+                        out hv_Nc, out hv_Dist);
+                    //鍒ゆ柇鎷熷悎缁撴灉鏄惁鏈夋晥锛氬鏋滄嫙鍚堟垚鍔燂紝鏁扮粍涓厓绱犵殑鏁伴噺澶т簬0
+                    hv_Length1.Dispose();
+                    HOperatorSet.TupleLength(hv_Dist, out hv_Length1);
+                    if ((int)(new HTuple(hv_Length1.TupleLess(1))) != 0)
+                    {
+                        ho_Contour.Dispose();
+
+                        hv_Length.Dispose();
+                        hv_Nr.Dispose();
+                        hv_Nc.Dispose();
+                        hv_Dist.Dispose();
+                        hv_Length1.Dispose();
+
+                        return;
+                    }
+                    //鏍规嵁鎷熷悎缁撴灉锛屼骇鐢熺洿绾縳ld
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        ho_LineXld.Dispose();
+                        HOperatorSet.GenContourPolygonXld(out ho_LineXld, hv_Row1.TupleConcat(hv_Row2),
+                            hv_Column1.TupleConcat(hv_Column2));
+                    }
+                }
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_Contour.Dispose();
+
+                hv_Length.Dispose();
+                hv_Nr.Dispose();
+                hv_Nc.Dispose();
+                hv_Dist.Dispose();
+                hv_Length1.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        public static (double, double) CalculateTailValues(HTuple minValue, HTuple maxValue, HTuple mean, HTuple deviation, double tailPercentage = 0.3)
+        {
+            // 璁$畻浣庡熬鐏板害鍊�
+            double lowTailValue = minValue.TupleReal() + (mean.TupleReal() - minValue.TupleReal()) * tailPercentage;
+            if (lowTailValue == 0)
+                lowTailValue = mean.TupleReal();
+
+            // 璁$畻楂樺熬鐏板害鍊�
+            double highTailValue = maxValue.TupleReal() - (maxValue.TupleReal() - mean.TupleReal()) * tailPercentage;
+            if (highTailValue == 0)
+                highTailValue = mean.TupleReal();
+
+            return (highTailValue, lowTailValue);
+        }
+
+        /// <summary>
+        /// 鍗″昂绠楁硶
+        /// </summary>
+        /// <param name="ho_Image">寰呮祴鍥剧墖</param>
+        /// <param name="ho_Regions">娴嬮噺鍗″昂鍖哄煙鏄剧ず</param>
+        /// <param name="hv_Elements">鍗″昂涓暟</param>
+        /// <param name="hv_DetectHeight">鍗″昂闀垮害</param>
+        /// <param name="hv_DetectWidth">鍗″昂瀹藉害</param>
+        /// <param name="hv_Sigma">杩囨护涓�鍗婂儚绱�(鎺ㄨ崘鍊�:2)</param>
+        /// <param name="hv_Threshold">瀵规瘮搴﹂槇鍊�(鎺ㄨ崘鍊�:5)</param>
+        /// <param name="hv_Transition">鏋佹��(negative/positive/ignore)</param>
+        /// <param name="hv_Select">杈圭紭浣嶇疆(first/last/best)</param>
+        /// <param name="hv_Row1">璧峰绾靛潗鏍�</param>
+        /// <param name="hv_Column1">璧峰妯潗鏍�</param>
+        /// <param name="hv_Row2">缁撴潫绾靛潗鏍�</param>
+        /// <param name="hv_Column2">缁撴潫妯潗鏍�</param>
+        /// <param name="hv_ResultRow">缁撴灉鐐归泦鍚堢旱鍧愭爣</param>
+        /// <param name="hv_ResultColumn">缁撴灉鐐归泦鍚堟í鍧愭爣</param>
+        public static void Rake(HObject ho_Image, out HObject ho_Regions, HTuple hv_Elements,
+            HTuple hv_DetectHeight, HTuple hv_DetectWidth, HTuple hv_Sigma, HTuple hv_Threshold,
+            HTuple hv_Transition, HTuple hv_Select, HTuple hv_Row1, HTuple hv_Column1, HTuple hv_Row2,
+            HTuple hv_Column2, out HTuple hv_ResultRow, out HTuple hv_ResultColumn)
+        {
+            // Stack for temporary objects 
+            HObject[] OTemp = new HObject[20];
+
+            // Local iconic variables 
+
+            HObject ho_RegionLines = null, ho_Rectangle = null;
+            HObject ho_Arrow1 = null;
+            HObject ExpTmpOutVar_0 = null;
+
+            // Local control variables 
+
+            HTuple hv_SelectOut = new HTuple(), hv_TransitionOut = new HTuple();
+            HTuple hv_Width = new HTuple(), hv_Height = new HTuple();
+            HTuple hv_ATan = new HTuple(), hv_i = new HTuple(), hv_RowC = new HTuple();
+            HTuple hv_ColC = new HTuple(), hv_Distance = new HTuple();
+            HTuple hv_RowL2 = new HTuple(), hv_RowL1 = new HTuple();
+            HTuple hv_ColL2 = new HTuple(), hv_ColL1 = new HTuple();
+            HTuple hv_MeasureHandle = new HTuple(), hv_RowEdge = new HTuple();
+            HTuple hv_ColEdge = new HTuple(), hv_Amplitude = new HTuple();
+            HTuple hv_tRow = new HTuple(), hv_tCol = new HTuple();
+            HTuple hv_t = new HTuple(), hv_Number = new HTuple(), hv_j = new HTuple();
+            HTuple hv_DetectWidth_COPY_INP_TMP = new HTuple(hv_DetectWidth);
+
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_Regions);
+            HOperatorSet.GenEmptyObj(out ho_RegionLines);
+            HOperatorSet.GenEmptyObj(out ho_Rectangle);
+            HOperatorSet.GenEmptyObj(out ho_Arrow1);
+            HOperatorSet.GenEmptyObj(out ExpTmpOutVar_0);
+            hv_ResultRow = new HTuple();
+            hv_ResultColumn = new HTuple();
+            try
+            {
+                hv_SelectOut.Dispose();
+                hv_SelectOut = new HTuple(hv_Select);
+
+                hv_TransitionOut.Dispose();
+                hv_TransitionOut = new HTuple(hv_Transition);
+
+                //鑾峰彇鍥惧儚灏哄
+                hv_Width.Dispose(); hv_Height.Dispose();
+                HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
+
+                //浜х敓涓�涓┖鏄剧ず瀵硅薄锛岀敤浜庢樉绀�
+                ho_Regions.Dispose();
+                HOperatorSet.GenEmptyObj(out ho_Regions);
+
+                //鍒濆鍖栬竟缂樺潗鏍囨暟缁�
+                hv_ResultRow.Dispose();
+                hv_ResultRow = new HTuple();
+
+                hv_ResultColumn.Dispose();
+                hv_ResultColumn = new HTuple();
+
+                //浜х敓鐩寸嚎xld
+                //using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                //{
+                //    ho_RegionLines.Dispose();
+                //    HOperatorSet.GenContourPolygonXld(out ho_RegionLines, hv_Row1.TupleConcat(hv_Row2),
+                //        hv_Column1.TupleConcat(hv_Column2));
+                //}
+
+                //瀛樺偍鍒版樉绀哄璞�
+                HOperatorSet.ConcatObj(ho_Regions, ho_RegionLines, out ExpTmpOutVar_0);
+                ho_Regions.Dispose();
+                ho_Regions = ExpTmpOutVar_0;
+
+                //璁$畻鐩寸嚎涓巟杞寸殑澶硅锛岄�嗘椂閽堟柟鍚戜负姝e悜
+                hv_ATan.Dispose();
+                HOperatorSet.AngleLx(hv_Row1, hv_Column1, hv_Row2, hv_Column2, out hv_ATan);
+
+                //杈圭紭妫�娴嬫柟鍚戝瀭鐩寸敱浜庢娴嬬洿绾匡細鐩寸嚎鏂瑰悜姝e悜鏃嬭浆90掳涓鸿竟缂樻娴嬫柟鍚�
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_ATan = hv_ATan + ((new HTuple(90)).TupleRad()
+                            );
+                        hv_ATan.Dispose();
+                        hv_ATan = ExpTmpLocalVar_ATan;
+                    }
+                }
+
+                //鏍规嵁妫�娴嬬洿绾挎寜椤哄簭浜х敓娴嬮噺鍖哄煙鐭╁舰锛屽苟瀛樺偍鍒版樉绀哄璞�
+                HTuple end_val36 = hv_Elements;
+                HTuple step_val36 = 1;
+                for (hv_i = 1; hv_i.Continue(end_val36, step_val36); hv_i = hv_i.TupleAdd(step_val36))
+                {
+                    //濡傛灉鍙湁涓�涓祴閲忕煩褰紝浣滀负鍗″昂宸ュ叿锛屽搴︿负妫�娴嬬洿绾跨殑闀垮害
+                    if ((int)(new HTuple(hv_Elements.TupleEqual(1))) != 0)
+                    {
+
+                        hv_RowC.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_RowC = (hv_Row1 + hv_Row2) * 0.5;
+                        }
+
+                        hv_ColC.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ColC = (hv_Column1 + hv_Column2) * 0.5;
+                        }
+
+                        //鍒ゆ柇鏄惁瓒呭嚭鍥惧儚锛岃秴鍑轰笉妫�娴嬭竟缂�
+                        if ((int)((new HTuple((new HTuple((new HTuple(hv_RowC.TupleGreater(hv_Height - 1))).TupleOr(
+                            new HTuple(hv_RowC.TupleLess(0))))).TupleOr(new HTuple(hv_ColC.TupleGreater(
+                            hv_Width - 1))))).TupleOr(new HTuple(hv_ColC.TupleLess(0)))) != 0)
+                            continue;
+
+                        hv_Distance.Dispose();
+                        HOperatorSet.DistancePp(hv_Row1, hv_Column1, hv_Row2, hv_Column2, out hv_Distance);
+
+                        hv_DetectWidth_COPY_INP_TMP.Dispose();
+                        hv_DetectWidth_COPY_INP_TMP = new HTuple(hv_Distance);
+
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            ho_Rectangle.Dispose();
+                            HOperatorSet.GenRectangle2ContourXld(out ho_Rectangle, hv_RowC, hv_ColC,
+                                hv_ATan, hv_DetectHeight / 2, hv_Distance / 2);
+                        }
+
+                    }
+                    else
+                    {
+                        //濡傛灉鏈夊涓祴閲忕煩褰紝浜х敓璇ユ祴閲忕煩褰ld
+                        hv_RowC.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_RowC = hv_Row1 + (((hv_Row2 - hv_Row1) * (hv_i - 1)) / (hv_Elements - 1));
+                        }
+
+                        hv_ColC.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ColC = hv_Column1 + (((hv_Column2 - hv_Column1) * (hv_i - 1)) / (hv_Elements - 1));
+                        }
+
+                        //鍒ゆ柇鏄惁瓒呭嚭鍥惧儚锛岃秴鍑轰笉妫�娴嬭竟缂�
+                        if ((int)((new HTuple((new HTuple((new HTuple(hv_RowC.TupleGreater(hv_Height - 1))).TupleOr(
+                            new HTuple(hv_RowC.TupleLess(0))))).TupleOr(new HTuple(hv_ColC.TupleGreater(
+                            hv_Width - 1))))).TupleOr(new HTuple(hv_ColC.TupleLess(0)))) != 0)
+                            continue;
+
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            ho_Rectangle.Dispose();
+                            HOperatorSet.GenRectangle2ContourXld(out ho_Rectangle, hv_RowC, hv_ColC,
+                                hv_ATan, hv_DetectHeight / 2, hv_DetectWidth_COPY_INP_TMP / 2);
+                        }
+
+                    }
+
+                    //鎶婃祴閲忕煩褰ld瀛樺偍鍒版樉绀哄璞�
+                    HOperatorSet.ConcatObj(ho_Regions, ho_Rectangle, out ExpTmpOutVar_0);
+                    ho_Regions.Dispose();
+                    ho_Regions = ExpTmpOutVar_0;
+
+                    if ((int)(new HTuple(hv_i.TupleEqual(1))) != 0)
+                    {
+
+                        //鍦ㄧ涓�涓祴閲忕煩褰㈢粯鍒朵竴涓澶磝ld锛岀敤浜庢寚绀鸿竟缂樻娴嬫柟鍚�
+                        hv_RowL2.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_RowL2 = hv_RowC + ((hv_DetectHeight / 2) * (((-hv_ATan)).TupleSin()
+                                ));
+                        }
+
+                        hv_RowL1.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_RowL1 = hv_RowC - ((hv_DetectHeight / 2) * (((-hv_ATan)).TupleSin()
+                                ));
+                        }
+
+                        hv_ColL2.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ColL2 = hv_ColC + ((hv_DetectHeight / 2) * (((-hv_ATan)).TupleCos()
+                                ));
+                        }
+
+                        hv_ColL1.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ColL1 = hv_ColC - ((hv_DetectHeight / 2) * (((-hv_ATan)).TupleCos()
+                                ));
+                        }
+
+                        //ho_Arrow1.Dispose();
+                        //gen_arrow_contour_xld(out ho_Arrow1, hv_RowL1, hv_ColL1, hv_RowL2, hv_ColL2,
+                        //    25, 25);
+
+                        ////鎶妜ld瀛樺偍鍒版樉绀哄璞�
+                        //HOperatorSet.ConcatObj(ho_Regions, ho_Arrow1, out ExpTmpOutVar_0);
+                        //ho_Regions.Dispose();
+                        //ho_Regions = ExpTmpOutVar_0;
+                    }
+
+                    //浜х敓娴嬮噺瀵硅薄鍙ユ焺
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_MeasureHandle.Dispose();
+                        HOperatorSet.GenMeasureRectangle2(hv_RowC, hv_ColC, hv_ATan, hv_DetectHeight / 2,
+                            hv_DetectWidth_COPY_INP_TMP / 2, hv_Width, hv_Height, "nearest_neighbor",
+                            out hv_MeasureHandle);
+                    }
+
+                    //璁剧疆鏋佹��
+                    if ((int)(new HTuple(hv_TransitionOut.TupleEqual("negative"))) != 0)
+                    {
+                        hv_TransitionOut.Dispose();
+                        hv_TransitionOut = "negative";
+                    }
+                    else if ((int)(new HTuple(hv_TransitionOut.TupleEqual("positive"))) != 0)
+                    {
+                        hv_TransitionOut.Dispose();
+                        hv_TransitionOut = "positive";
+                    }
+                    else
+                    {
+                        hv_TransitionOut.Dispose();
+                        hv_TransitionOut = "all";
+                    }
+
+                    //璁剧疆杈圭紭浣嶇疆,鏈�寮虹偣鏄粠鎵�鏈夎竟缂樹腑閫夋嫨骞呭害缁濆鍊煎澶х偣锛岄渶瑕佽缃负'all'
+                    if ((int)(new HTuple(hv_SelectOut.TupleEqual("first"))) != 0)
+                    {
+                        hv_SelectOut.Dispose();
+                        hv_SelectOut = "first";
+                    }
+                    else if ((int)(new HTuple(hv_SelectOut.TupleEqual("last"))) != 0)
+                    {
+                        hv_SelectOut.Dispose();
+                        hv_SelectOut = "last";
+                    }
+                    else
+                    {
+                        hv_SelectOut.Dispose();
+                        hv_SelectOut = "all";
+                    }
+
+                    //妫�娴嬭竟缂�
+                    hv_RowEdge.Dispose(); hv_ColEdge.Dispose(); hv_Amplitude.Dispose(); hv_Distance.Dispose();
+                    HOperatorSet.MeasurePos(ho_Image, hv_MeasureHandle, hv_Sigma, hv_Threshold,
+                        hv_TransitionOut, hv_SelectOut, out hv_RowEdge, out hv_ColEdge, out hv_Amplitude,
+                        out hv_Distance);
+
+                    //娓呴櫎娴嬮噺瀵硅薄鍙ユ焺
+                    HOperatorSet.CloseMeasure(hv_MeasureHandle);
+
+                    //涓存椂鍙橀噺鍒濆鍖�
+
+                    //淇濆瓨鎵惧埌鎸囧畾杈圭紭鐨勫潗鏍�
+                    hv_tRow.Dispose();
+                    hv_tRow = 0;
+
+                    hv_tCol.Dispose();
+                    hv_tCol = 0;
+
+                    //淇濆瓨杈圭紭鐨勫箙搴︾粷瀵瑰��
+                    hv_t.Dispose();
+                    hv_t = 0;
+
+                    //鎵惧埌鐨勮竟缂樺繀椤昏嚦灏戜负1涓�
+                    hv_Number.Dispose();
+                    HOperatorSet.TupleLength(hv_RowEdge, out hv_Number);
+
+                    if ((int)(new HTuple(hv_Number.TupleLess(1))) != 0)
+                        continue;
+
+
+                    //鏈夊涓竟缂樻椂锛岄�夋嫨骞呭害缁濆涔嬪悗鏈�澶х殑杈圭紭
+                    HTuple end_val178 = hv_Number - 1;
+                    HTuple step_val178 = 1;
+                    for (hv_j = 0; hv_j.Continue(end_val178, step_val178); hv_j = hv_j.TupleAdd(step_val178))
+                    {
+
+                        if ((int)(new HTuple(((((hv_Amplitude.TupleSelect(hv_j))).TupleAbs())).TupleGreater(
+                            hv_t))) != 0)
+                        {
+
+                            hv_tRow.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_tRow = hv_RowEdge.TupleSelect(
+                                    hv_j);
+                            }
+
+                            hv_tCol.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_tCol = hv_ColEdge.TupleSelect(
+                                    hv_j);
+                            }
+
+                            hv_t.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_t = hv_Amplitude.TupleAbs()
+                                    ;
+                            }
+
+                        }
+
+                    }
+
+                    //鎶婃壘鍒扮殑杈圭紭淇濆瓨鍦ㄨ緭鍑烘暟缁�
+
+                    if ((int)(new HTuple(hv_t.TupleGreater(0))) != 0)
+                    {
+
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_ResultRow = hv_ResultRow.TupleConcat(
+                                    hv_tRow);
+                                hv_ResultRow.Dispose();
+                                hv_ResultRow = ExpTmpLocalVar_ResultRow;
+                            }
+                        }
+
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_ResultColumn = hv_ResultColumn.TupleConcat(
+                                    hv_tCol);
+                                hv_ResultColumn.Dispose();
+                                hv_ResultColumn = ExpTmpLocalVar_ResultColumn;
+                            }
+                        }
+
+                    }
+
+                }
+
+                ho_RegionLines.Dispose();
+                ho_Rectangle.Dispose();
+                ho_Arrow1.Dispose();
+
+                hv_DetectWidth_COPY_INP_TMP.Dispose();
+                hv_SelectOut.Dispose();
+                hv_TransitionOut.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_ATan.Dispose();
+                hv_i.Dispose();
+                hv_RowC.Dispose();
+                hv_ColC.Dispose();
+                hv_Distance.Dispose();
+                hv_RowL2.Dispose();
+                hv_RowL1.Dispose();
+                hv_ColL2.Dispose();
+                hv_ColL1.Dispose();
+                hv_MeasureHandle.Dispose();
+                hv_RowEdge.Dispose();
+                hv_ColEdge.Dispose();
+                hv_Amplitude.Dispose();
+                hv_tRow.Dispose();
+                hv_tCol.Dispose();
+                hv_t.Dispose();
+                hv_Number.Dispose();
+                hv_j.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_RegionLines.Dispose();
+                ho_Rectangle.Dispose();
+                ho_Arrow1.Dispose();
+
+                hv_DetectWidth_COPY_INP_TMP.Dispose();
+                hv_SelectOut.Dispose();
+                hv_TransitionOut.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_ATan.Dispose();
+                hv_i.Dispose();
+                hv_RowC.Dispose();
+                hv_ColC.Dispose();
+                hv_Distance.Dispose();
+                hv_RowL2.Dispose();
+                hv_RowL1.Dispose();
+                hv_ColL2.Dispose();
+                hv_ColL1.Dispose();
+                hv_MeasureHandle.Dispose();
+                hv_RowEdge.Dispose();
+                hv_ColEdge.Dispose();
+                hv_Amplitude.Dispose();
+                hv_tRow.Dispose();
+                hv_tCol.Dispose();
+                hv_t.Dispose();
+                hv_Number.Dispose();
+                hv_j.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        public static void GetRakeRegions(HObject ho_Image, out HObject ho_Regions, HTuple hv_Elements,
+            HTuple hv_DetectHeight, HTuple hv_DetectWidth, HTuple hv_Sigma, HTuple hv_Threshold,
+            HTuple hv_Transition, HTuple hv_Select, HTuple hv_Row1, HTuple hv_Column1, HTuple hv_Row2,
+            HTuple hv_Column2, out HTuple hv_ResultRow, out HTuple hv_ResultColumn)
+        {
+            // Stack for temporary objects 
+            HObject[] OTemp = new HObject[20];
+
+            // Local iconic variables 
+
+            HObject ho_RegionLines = null, ho_Rectangle = null;
+            HObject ho_Arrow1 = null;
+            HObject ExpTmpOutVar_0 = null;
+
+            // Local control variables 
+
+            HTuple hv_SelectOut = new HTuple(), hv_TransitionOut = new HTuple();
+            HTuple hv_Width = new HTuple(), hv_Height = new HTuple();
+            HTuple hv_ATan = new HTuple(), hv_i = new HTuple(), hv_RowC = new HTuple();
+            HTuple hv_ColC = new HTuple(), hv_Distance = new HTuple();
+            HTuple hv_RowL2 = new HTuple(), hv_RowL1 = new HTuple();
+            HTuple hv_ColL2 = new HTuple(), hv_ColL1 = new HTuple();
+            HTuple hv_MeasureHandle = new HTuple(), hv_RowEdge = new HTuple();
+            HTuple hv_ColEdge = new HTuple(), hv_Amplitude = new HTuple();
+            HTuple hv_tRow = new HTuple(), hv_tCol = new HTuple();
+            HTuple hv_t = new HTuple(), hv_Number = new HTuple(), hv_j = new HTuple();
+            HTuple hv_DetectWidth_COPY_INP_TMP = new HTuple(hv_DetectWidth);
+
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_Regions);
+            HOperatorSet.GenEmptyObj(out ho_RegionLines);
+            HOperatorSet.GenEmptyObj(out ho_Rectangle);
+            HOperatorSet.GenEmptyObj(out ho_Arrow1);
+            HOperatorSet.GenEmptyObj(out ExpTmpOutVar_0);
+            hv_ResultRow = new HTuple();
+            hv_ResultColumn = new HTuple();
+            try
+            {
+                hv_SelectOut.Dispose();
+                hv_SelectOut = new HTuple(hv_Select);
+
+                hv_TransitionOut.Dispose();
+                hv_TransitionOut = new HTuple(hv_Transition);
+
+                //鑾峰彇鍥惧儚灏哄
+                hv_Width.Dispose(); hv_Height.Dispose();
+                //HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
+
+                //浜х敓涓�涓┖鏄剧ず瀵硅薄锛岀敤浜庢樉绀�
+                ho_Regions.Dispose();
+                HOperatorSet.GenEmptyObj(out ho_Regions);
+
+                //鍒濆鍖栬竟缂樺潗鏍囨暟缁�
+                hv_ResultRow.Dispose();
+                hv_ResultRow = new HTuple();
+
+                hv_ResultColumn.Dispose();
+                hv_ResultColumn = new HTuple();
+
+                //浜х敓鐩寸嚎xld
+                //using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                //{
+                //    ho_RegionLines.Dispose();
+                //    HOperatorSet.GenContourPolygonXld(out ho_RegionLines, hv_Row1.TupleConcat(hv_Row2),
+                //        hv_Column1.TupleConcat(hv_Column2));
+                //}
+
+                //瀛樺偍鍒版樉绀哄璞�
+                HOperatorSet.ConcatObj(ho_Regions, ho_RegionLines, out ExpTmpOutVar_0);
+                ho_Regions.Dispose();
+                ho_Regions = ExpTmpOutVar_0;
+
+                //璁$畻鐩寸嚎涓巟杞寸殑澶硅锛岄�嗘椂閽堟柟鍚戜负姝e悜
+                hv_ATan.Dispose();
+                HOperatorSet.AngleLx(hv_Row1, hv_Column1, hv_Row2, hv_Column2, out hv_ATan);
+
+                //杈圭紭妫�娴嬫柟鍚戝瀭鐩寸敱浜庢娴嬬洿绾匡細鐩寸嚎鏂瑰悜姝e悜鏃嬭浆90掳涓鸿竟缂樻娴嬫柟鍚�
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_ATan = hv_ATan + ((new HTuple(90)).TupleRad()
+                            );
+                        hv_ATan.Dispose();
+                        hv_ATan = ExpTmpLocalVar_ATan;
+                    }
+                }
+
+                //鏍规嵁妫�娴嬬洿绾挎寜椤哄簭浜х敓娴嬮噺鍖哄煙鐭╁舰锛屽苟瀛樺偍鍒版樉绀哄璞�
+                HTuple end_val36 = hv_Elements;
+                HTuple step_val36 = 1;
+                for (hv_i = 1; hv_i.Continue(end_val36, step_val36); hv_i = hv_i.TupleAdd(step_val36))
+                {
+                    //濡傛灉鍙湁涓�涓祴閲忕煩褰紝浣滀负鍗″昂宸ュ叿锛屽搴︿负妫�娴嬬洿绾跨殑闀垮害
+                    if ((int)(new HTuple(hv_Elements.TupleEqual(1))) != 0)
+                    {
+
+                        hv_RowC.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_RowC = (hv_Row1 + hv_Row2) * 0.5;
+                        }
+
+                        hv_ColC.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ColC = (hv_Column1 + hv_Column2) * 0.5;
+                        }
+
+                        ////鍒ゆ柇鏄惁瓒呭嚭鍥惧儚锛岃秴鍑轰笉妫�娴嬭竟缂�
+                        //if ((int)((new HTuple((new HTuple((new HTuple(hv_RowC.TupleGreater(hv_Height - 1))).TupleOr(
+                        //    new HTuple(hv_RowC.TupleLess(0))))).TupleOr(new HTuple(hv_ColC.TupleGreater(
+                        //    hv_Width - 1))))).TupleOr(new HTuple(hv_ColC.TupleLess(0)))) != 0)
+                        //    continue;
+
+                        hv_Distance.Dispose();
+                        HOperatorSet.DistancePp(hv_Row1, hv_Column1, hv_Row2, hv_Column2, out hv_Distance);
+
+                        hv_DetectWidth_COPY_INP_TMP.Dispose();
+                        hv_DetectWidth_COPY_INP_TMP = new HTuple(hv_Distance);
+
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            ho_Rectangle.Dispose();
+                            HOperatorSet.GenRectangle2ContourXld(out ho_Rectangle, hv_RowC, hv_ColC,
+                                hv_ATan, hv_DetectHeight / 2, hv_Distance / 2);
+                        }
+                    }
+                    else
+                    {
+                        //濡傛灉鏈夊涓祴閲忕煩褰紝浜х敓璇ユ祴閲忕煩褰ld
+                        hv_RowC.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_RowC = hv_Row1 + (((hv_Row2 - hv_Row1) * (hv_i - 1)) / (hv_Elements - 1));
+                        }
+
+                        hv_ColC.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ColC = hv_Column1 + (((hv_Column2 - hv_Column1) * (hv_i - 1)) / (hv_Elements - 1));
+                        }
+
+                        ////鍒ゆ柇鏄惁瓒呭嚭鍥惧儚锛岃秴鍑轰笉妫�娴嬭竟缂�
+                        //if ((int)((new HTuple((new HTuple((new HTuple(hv_RowC.TupleGreater(hv_Height - 1))).TupleOr(
+                        //    new HTuple(hv_RowC.TupleLess(0))))).TupleOr(new HTuple(hv_ColC.TupleGreater(
+                        //    hv_Width - 1))))).TupleOr(new HTuple(hv_ColC.TupleLess(0)))) != 0)
+                        //    continue;
+
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            ho_Rectangle.Dispose();
+                            HOperatorSet.GenRectangle2ContourXld(out ho_Rectangle, hv_RowC, hv_ColC,
+                                hv_ATan, hv_DetectHeight / 2, hv_DetectWidth_COPY_INP_TMP / 2);
+                        }
+
+                    }
+
+                    //鎶婃祴閲忕煩褰ld瀛樺偍鍒版樉绀哄璞�
+                    HOperatorSet.ConcatObj(ho_Regions, ho_Rectangle, out ExpTmpOutVar_0);
+                    ho_Regions.Dispose();
+                    ho_Regions = ExpTmpOutVar_0;
+
+                    //淇濆瓨鎵惧埌鎸囧畾杈圭紭鐨勫潗鏍�
+                    hv_tRow.Dispose();
+                    hv_tRow = 0;
+
+                    hv_tCol.Dispose();
+                    hv_tCol = 0;
+
+                    //淇濆瓨杈圭紭鐨勫箙搴︾粷瀵瑰��
+                    hv_t.Dispose();
+                    hv_t = 0;
+                }
+
+                ho_RegionLines.Dispose();
+                ho_Rectangle.Dispose();
+                ho_Arrow1.Dispose();
+
+                hv_DetectWidth_COPY_INP_TMP.Dispose();
+                hv_SelectOut.Dispose();
+                hv_TransitionOut.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_ATan.Dispose();
+                hv_i.Dispose();
+                hv_RowC.Dispose();
+                hv_ColC.Dispose();
+                hv_Distance.Dispose();
+                hv_RowL2.Dispose();
+                hv_RowL1.Dispose();
+                hv_ColL2.Dispose();
+                hv_ColL1.Dispose();
+                hv_MeasureHandle.Dispose();
+                hv_RowEdge.Dispose();
+                hv_ColEdge.Dispose();
+                hv_Amplitude.Dispose();
+                hv_tRow.Dispose();
+                hv_tCol.Dispose();
+                hv_t.Dispose();
+                hv_Number.Dispose();
+                hv_j.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_RegionLines.Dispose();
+                ho_Rectangle.Dispose();
+                ho_Arrow1.Dispose();
+
+                hv_DetectWidth_COPY_INP_TMP.Dispose();
+                hv_SelectOut.Dispose();
+                hv_TransitionOut.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_ATan.Dispose();
+                hv_i.Dispose();
+                hv_RowC.Dispose();
+                hv_ColC.Dispose();
+                hv_Distance.Dispose();
+                hv_RowL2.Dispose();
+                hv_RowL1.Dispose();
+                hv_ColL2.Dispose();
+                hv_ColL1.Dispose();
+                hv_MeasureHandle.Dispose();
+                hv_RowEdge.Dispose();
+                hv_ColEdge.Dispose();
+                hv_Amplitude.Dispose();
+                hv_tRow.Dispose();
+                hv_tCol.Dispose();
+                hv_t.Dispose();
+                hv_Number.Dispose();
+                hv_j.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        /// <summary>
+        /// 鏄剧ず绗﹀彿
+        /// </summary>
+        /// <param name="hv_WindowHandle"></param>
+        /// <param name="hv_String"></param>
+        /// <param name="hv_CoordSystem"></param>
+        /// <param name="hv_Row"></param>
+        /// <param name="hv_Column"></param>
+        /// <param name="hv_Color"></param>
+        /// <param name="hv_Box"></param>
+        static void disp_message(HTuple hv_WindowHandle, HTuple hv_String, HTuple hv_CoordSystem, HTuple hv_Row, HTuple hv_Column, HTuple hv_Color, HTuple hv_Box)
+        {
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_GenParamName = new HTuple(), hv_GenParamValue = new HTuple();
+            HTuple hv_Color_COPY_INP_TMP = new HTuple(hv_Color);
+            HTuple hv_Column_COPY_INP_TMP = new HTuple(hv_Column);
+            HTuple hv_CoordSystem_COPY_INP_TMP = new HTuple(hv_CoordSystem);
+            HTuple hv_Row_COPY_INP_TMP = new HTuple(hv_Row);
+
+            try
+            {
+                if ((int)new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(new HTuple())).TupleOr(
+                    new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(new HTuple()))) != 0)
+                {
+
+                    hv_Color_COPY_INP_TMP.Dispose();
+                    hv_Column_COPY_INP_TMP.Dispose();
+                    hv_CoordSystem_COPY_INP_TMP.Dispose();
+                    hv_Row_COPY_INP_TMP.Dispose();
+                    hv_GenParamName.Dispose();
+                    hv_GenParamValue.Dispose();
+
+                    return;
+                }
+                if ((int)new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(-1)) != 0)
+                {
+                    hv_Row_COPY_INP_TMP.Dispose();
+                    hv_Row_COPY_INP_TMP = 12;
+                }
+                if ((int)new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(-1)) != 0)
+                {
+                    hv_Column_COPY_INP_TMP.Dispose();
+                    hv_Column_COPY_INP_TMP = 12;
+                }
+                //
+                //Convert the parameter Box to generic parameters.
+                hv_GenParamName.Dispose();
+                hv_GenParamName = new HTuple();
+                hv_GenParamValue.Dispose();
+                hv_GenParamValue = new HTuple();
+                if ((int)new HTuple(new HTuple(hv_Box.TupleLength()).TupleGreater(0)) != 0)
+                {
+                    if ((int)new HTuple(hv_Box.TupleSelect(0).TupleEqual("false")) != 0)
+                    {
+                        //Display no box
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "box");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    "false");
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    else if ((int)new HTuple(hv_Box.TupleSelect(0).TupleNotEqual(
+                        "true")) != 0)
+                    {
+                        //Set a color other than the default.
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "box_color");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    hv_Box.TupleSelect(0));
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                }
+                if ((int)new HTuple(new HTuple(hv_Box.TupleLength()).TupleGreater(1)) != 0)
+                {
+                    if ((int)new HTuple(hv_Box.TupleSelect(1).TupleEqual("false")) != 0)
+                    {
+                        //Display no shadow.
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "shadow");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    "false");
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    else if ((int)new HTuple(hv_Box.TupleSelect(1).TupleNotEqual(
+                        "true")) != 0)
+                    {
+                        //Set a shadow color other than the default.
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "shadow_color");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    hv_Box.TupleSelect(1));
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                }
+                //Restore default CoordSystem behavior.
+                if ((int)new HTuple(hv_CoordSystem_COPY_INP_TMP.TupleNotEqual("window")) != 0)
+                {
+                    hv_CoordSystem_COPY_INP_TMP.Dispose();
+                    hv_CoordSystem_COPY_INP_TMP = "image";
+                }
+                //
+                if ((int)new HTuple(hv_Color_COPY_INP_TMP.TupleEqual("")) != 0)
+                {
+                    //disp_text does not accept an empty string for Color.
+                    hv_Color_COPY_INP_TMP.Dispose();
+                    hv_Color_COPY_INP_TMP = new HTuple();
+                }
+                //
+                //HOperatorSet.DispText(hv_WindowHandle, hv_String, hv_CoordSystem_COPY_INP_TMP,
+                //    hv_Row_COPY_INP_TMP, hv_Column_COPY_INP_TMP, hv_Color_COPY_INP_TMP, hv_GenParamName,hv_GenParamValue);
+                HOperatorSet.SetTposition(hv_WindowHandle, hv_Row_COPY_INP_TMP, hv_Column_COPY_INP_TMP);
+                HOperatorSet.WriteString(hv_WindowHandle, hv_String);
+                hv_Color_COPY_INP_TMP.Dispose();
+                hv_Column_COPY_INP_TMP.Dispose();
+                hv_CoordSystem_COPY_INP_TMP.Dispose();
+                hv_Row_COPY_INP_TMP.Dispose();
+                hv_GenParamName.Dispose();
+                hv_GenParamValue.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Color_COPY_INP_TMP.Dispose();
+                hv_Column_COPY_INP_TMP.Dispose();
+                hv_CoordSystem_COPY_INP_TMP.Dispose();
+                hv_Row_COPY_INP_TMP.Dispose();
+                hv_GenParamName.Dispose();
+                hv_GenParamValue.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        /// <summary>
+        /// 璁剧疆绗﹀彿澶у皬
+        /// </summary>
+        /// <param name="hv_WindowHandle"></param>
+        /// <param name="hv_Size"></param>
+        /// <param name="hv_Font"></param>
+        /// <param name="hv_Bold"></param>
+        /// <param name="hv_Slant"></param>
+        public static void set_display_font(HTuple hv_WindowHandle, HTuple hv_Size, string hv_Font = "mono", string hv_Bold = "true", string hv_Slant = "false")
+        {
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_OS = new HTuple(), hv_Fonts = new HTuple();
+            HTuple hv_Style = new HTuple(), hv_Exception = new HTuple();
+            HTuple hv_AvailableFonts = new HTuple(), hv_Fdx = new HTuple();
+            HTuple hv_Indices = new HTuple();
+            HTuple hv_Font_COPY_INP_TMP = new HTuple(hv_Font);
+            HTuple hv_Size_COPY_INP_TMP = new HTuple(hv_Size);
+
+            // Initialize local and output iconic variables 
+            try
+            {
+                //This procedure sets the text font of the current window with
+                //the specified attributes.
+                //
+                //Input parameters:
+                //WindowHandle: The graphics window for which the font will be set
+                //Size: The font size. If Size=-1, the default of 16 is used.
+                //Bold: If set to 'true', a bold font is used
+                //Slant: If set to 'true', a slanted font is used
+                //
+                hv_OS.Dispose();
+                HOperatorSet.GetSystem("operating_system", out hv_OS);
+                if ((int)((new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(new HTuple()))).TupleOr(
+                    new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(-1)))) != 0)
+                {
+                    hv_Size_COPY_INP_TMP.Dispose();
+                    hv_Size_COPY_INP_TMP = 16;
+                }
+                if ((int)(new HTuple(((hv_OS.TupleSubstr(0, 2))).TupleEqual("Win"))) != 0)
+                {
+                    //Restore previous behaviour
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Size = ((1.13677 * hv_Size_COPY_INP_TMP)).TupleInt()
+                                ;
+                            hv_Size_COPY_INP_TMP.Dispose();
+                            hv_Size_COPY_INP_TMP = ExpTmpLocalVar_Size;
+                        }
+                    }
+                }
+                else
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Size = hv_Size_COPY_INP_TMP.TupleInt()
+                                ;
+                            hv_Size_COPY_INP_TMP.Dispose();
+                            hv_Size_COPY_INP_TMP = ExpTmpLocalVar_Size;
+                        }
+                    }
+                }
+                if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("Courier"))) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Courier";
+                    hv_Fonts[1] = "Courier 10 Pitch";
+                    hv_Fonts[2] = "Courier New";
+                    hv_Fonts[3] = "CourierNew";
+                    hv_Fonts[4] = "Liberation Mono";
+                }
+                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("mono"))) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Consolas";
+                    hv_Fonts[1] = "Menlo";
+                    hv_Fonts[2] = "Courier";
+                    hv_Fonts[3] = "Courier 10 Pitch";
+                    hv_Fonts[4] = "FreeMono";
+                    hv_Fonts[5] = "Liberation Mono";
+                }
+                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("sans"))) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Luxi Sans";
+                    hv_Fonts[1] = "DejaVu Sans";
+                    hv_Fonts[2] = "FreeSans";
+                    hv_Fonts[3] = "Arial";
+                    hv_Fonts[4] = "Liberation Sans";
+                }
+                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("serif"))) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Times New Roman";
+                    hv_Fonts[1] = "Luxi Serif";
+                    hv_Fonts[2] = "DejaVu Serif";
+                    hv_Fonts[3] = "FreeSerif";
+                    hv_Fonts[4] = "Utopia";
+                    hv_Fonts[5] = "Liberation Serif";
+                }
+                else
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple(hv_Font_COPY_INP_TMP);
+                }
+                hv_Style.Dispose();
+                hv_Style = "";
+                if ((int)(new HTuple(((HTuple)hv_Bold).TupleEqual("true"))) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Style = hv_Style + "Bold";
+                            hv_Style.Dispose();
+                            hv_Style = ExpTmpLocalVar_Style;
+                        }
+                    }
+                }
+                else if ((int)(new HTuple(((HTuple)hv_Bold).TupleNotEqual("false"))) != 0)
+                {
+                    hv_Exception.Dispose();
+                    hv_Exception = "Wrong value of control parameter Bold";
+                    throw new HalconException(hv_Exception);
+                }
+                if ((int)(new HTuple(((HTuple)hv_Slant).TupleEqual("true"))) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Style = hv_Style + "Italic";
+                            hv_Style.Dispose();
+                            hv_Style = ExpTmpLocalVar_Style;
+                        }
+                    }
+                }
+                else if ((int)(new HTuple(((HTuple)hv_Slant).TupleNotEqual("false"))) != 0)
+                {
+                    hv_Exception.Dispose();
+                    hv_Exception = "Wrong value of control parameter Slant";
+                    throw new HalconException(hv_Exception);
+                }
+                if ((int)(new HTuple(hv_Style.TupleEqual(""))) != 0)
+                {
+                    hv_Style.Dispose();
+                    hv_Style = "Normal";
+                }
+                hv_AvailableFonts.Dispose();
+                HOperatorSet.QueryFont(hv_WindowHandle, out hv_AvailableFonts);
+                hv_Font_COPY_INP_TMP.Dispose();
+                hv_Font_COPY_INP_TMP = "";
+                for (hv_Fdx = 0; (int)hv_Fdx <= (int)((new HTuple(hv_Fonts.TupleLength())) - 1); hv_Fdx = (int)hv_Fdx + 1)
+                {
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_AvailableFonts.TupleFind(
+                            hv_Fonts.TupleSelect(hv_Fdx));
+                    }
+                    if ((int)(new HTuple((new HTuple(hv_Indices.TupleLength())).TupleGreater(
+                        0))) != 0)
+                    {
+                        if ((int)(new HTuple(((hv_Indices.TupleSelect(0))).TupleGreaterEqual(0))) != 0)
+                        {
+                            hv_Font_COPY_INP_TMP.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Font_COPY_INP_TMP = hv_Fonts.TupleSelect(
+                                    hv_Fdx);
+                            }
+                            break;
+                        }
+                    }
+                }
+                if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual(""))) != 0)
+                {
+                    throw new HalconException("Wrong value of control parameter Font");
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_Font = (((hv_Font_COPY_INP_TMP + "-") + hv_Style) + "-") + hv_Size_COPY_INP_TMP;
+                        hv_Font_COPY_INP_TMP.Dispose();
+                        hv_Font_COPY_INP_TMP = ExpTmpLocalVar_Font;
+                    }
+                }
+                HOperatorSet.SetFont(hv_WindowHandle, hv_Font_COPY_INP_TMP);
+
+                hv_Font_COPY_INP_TMP.Dispose();
+                hv_Size_COPY_INP_TMP.Dispose();
+                hv_OS.Dispose();
+                hv_Fonts.Dispose();
+                hv_Style.Dispose();
+                hv_Exception.Dispose();
+                hv_AvailableFonts.Dispose();
+                hv_Fdx.Dispose();
+                hv_Indices.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Font_COPY_INP_TMP.Dispose();
+                hv_Size_COPY_INP_TMP.Dispose();
+                hv_OS.Dispose();
+                hv_Fonts.Dispose();
+                hv_Style.Dispose();
+                hv_Exception.Dispose();
+                hv_AvailableFonts.Dispose();
+                hv_Fdx.Dispose();
+                hv_Indices.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        public static void DispImage(HObject image, HWindow window)
+        {
+            int imgWidth, imgHeight, winRow, winCol, winWidth, winHeight, partWidth, partHeight;
+            try
+            {
+                if (image != null && image.IsInitialized())
+                {
+                    HOperatorSet.GetImageSize(image, out HTuple hv_imgWidth, out HTuple hv_imgHeight);
+                    imgWidth = hv_imgWidth.I;
+                    imgHeight = hv_imgHeight.I;
+                    window.GetWindowExtents(out winRow, out winCol, out winWidth, out winHeight);
+                    if (winWidth < winHeight)
+                    {
+                        partWidth = imgWidth;
+                        partHeight = imgWidth * winHeight / winWidth;
+                    }
+                    else
+                    {
+                        partWidth = imgHeight * winWidth / winHeight;
+                        partHeight = imgHeight;
+                    }
+                    window.SetPart(0, 0, partHeight - 1, partWidth - 1);
+
+                    HOperatorSet.DispObj(image, window);
+                }
+                else
+                    HOperatorSet.ClearWindow(window);
+            }
+            catch { }
+        }
+
+        public static void DispObj(HObject hObject, HWindow window)
+        {
+            try
+            {
+                if (hObject != null && hObject.IsInitialized())
+                    HOperatorSet.DispObj(hObject, window);
+            }
+            catch { }
+        }
+
+        public static void DispMsg(string msg, HWindow window, string color, HTuple row, HTuple column)
+        {
+            try
+            {
+                SetColor(window, color);
+
+                disp_message(window, msg, "image", row, column, color, "true");
+            }
+            catch { }
+        }
+
+        public static void DispMsg(string msg, HWindow window, bool result = true, int x = 0, int y = 0)
+        {
+            try
+            {
+                if (result)
+                    SetColor(window, "green");
+                else
+                    SetColor(window, "red");
+
+                disp_message(window, msg, "image", y, x, result ? "green" : "red", "true");
+            }
+            catch { }
+        }
+
+        public static void ClearObj(HWindow window)
+        {
+            try
+            {
+                HOperatorSet.ClearWindow(window);
+            }
+            catch { }
+        }
+
+        static void ShowHoImage(HObject ho_image, HWindow hWindow, bool autoSize = true)
+        {
+            if (ho_image == null || !ho_image.IsInitialized())
+            {
+                HOperatorSet.ClearWindow(hWindow);
+                return;
+            }
+
+            try
+            {
+                HOperatorSet.ClearWindow(hWindow);
+
+                if (autoSize)
+                {
+                    HOperatorSet.GetImageSize(ho_image, out HTuple imgWidth, out HTuple imgHeight);
+                    if (imgWidth.Length > 0)
+                    {
+                        hWindow.GetWindowExtents(out int winRow, out int winCol, out int winWidth, out int winHeight);
+                        int partWidth = imgHeight * winWidth / winHeight;
+                        int partHeight = imgHeight;
+                        if (winWidth < winHeight)
+                        {
+                            partWidth = imgWidth;
+                            partHeight = imgWidth * winHeight / winWidth;
+                        }
+
+                        //璁$畻姣斾緥
+                        double scale = Math.Max(1.0 * imgWidth.I / winWidth, 1.0 * imgHeight.I / winHeight);
+                        double w = winWidth * scale;
+                        double h = winHeight * scale;
+
+                        double row1 = -(h - imgHeight.D) / 2;
+                        double col1 = -(w - imgWidth.D) / 2;
+                        double row2 = imgHeight + (h - imgHeight.D) / 2;
+                        double col2 = imgWidth + (w - imgWidth.D) / 2;
+
+                        //灞呬腑绛夋瘮渚�
+                        hWindow.SetPart(row1, col1, row2, col2);
+                    }
+                }
+
+                HOperatorSet.DispObj(ho_image, hWindow);
+            }
+            catch { }
+        }
+
+        public static void scale_gray_map(HObject ho_Image, out HObject ho_Image1, HTuple hv_Min, HTuple hv_Max)
+        {
+            HTuple hv_Mult = new HTuple(), hv_Add = new HTuple();
+            HOperatorSet.GenEmptyObj(out ho_Image1);
+            try
+            {
+                hv_Mult.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Mult = 255.0 / (hv_Max - hv_Min);
+                }
+                hv_Add.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Add = (-hv_Mult) * hv_Min;
+                }
+                ho_Image1.Dispose();
+                HOperatorSet.ScaleImage(ho_Image, out ho_Image1, hv_Mult, hv_Add);
+                hv_Mult.Dispose();
+                hv_Add.Dispose();
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Mult.Dispose();
+                hv_Add.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        public static void SetColor(HTuple hv_WindowHandle)
+        {
+            HOperatorSet.SetColor(hv_WindowHandle, GetRandomColor());
+        }
+
+        /// <summary>
+        /// 璁剧疆棰滆壊("dark olive green")
+        /// </summary>
+        /// <param name="hv_WindowHandle"></param>
+        /// <param name="color"></param>
+        public static void SetColor(HTuple hv_WindowHandle, string color)
+        {
+            //*鍦╯et_color鐨勭畻瀛愪腑锛屽垪鍑篐alcon鏀寔鐨勯鑹蹭唬鐮侊紝鍏�21绉嶃�� 
+            //*Suggested values: 'black', 'white', 'red', 'green', 
+            //*'blue', 'cyan', 'magenta', 'yellow', 'dim gray', 'gray', 
+            //*'light gray', 'medium slate blue', 'coral', 'slate blue', 
+            //*'spring green', 'orange red', 'orange', 'dark olive green', 
+            //*'pink', 'forest green','cadet blue'
+            //* 鍙互鐢ㄤ互涓嬬殑浠g爜鏉ユ祴璇曢鑹�
+            HOperatorSet.SetColor(hv_WindowHandle, color);
+        }
+
+        /// <summary>
+        /// 鐢熸垚Halcon闅忔満棰滆壊
+        /// </summary>
+        /// <returns></returns>
+        public static string GetRandomColor()
+        {
+            // 鑾峰彇褰撳墠鏃堕棿鐨勬绉掓暟浣滀负绉嶅瓙
+            int seed = DateTime.Now.Millisecond;
+
+            // 浣跨敤绉嶅瓙鍒涘缓 Random 瀹炰緥
+            Random random = new Random(seed);
+
+            // 鐢熸垚闅忔満鏁�
+            int randomNumber = random.Next(0, 18);
+
+            // 寤舵椂闅忔満鏃堕棿鍙樻洿闅忔満绉嶅瓙
+            Thread.Sleep(randomNumber);
+
+            string[] strsColors = new string[]
+            {
+                "red", "green","blue", "cyan", "magenta",
+                "yellow", "dim gray", "gray","light gray", "medium slate blue", "coral", "slate blue",
+                "spring green", "orange red", "orange", "dark olive green","pink", "forest green", "cadet blue"
+            };
+            if (randomNumber <= strsColors.Length)
+                return strsColors[randomNumber];
+            else
+                return strsColors[0];
+        }
+        #endregion
+
+        #region OpenCVSharp
+        // 鏍规嵁Mat绫诲瀷杩斿洖瀵瑰簲鐨勬棤鏁堝��
+        public static Scalar GetInvalidValueForMat(Mat mat)
+        {
+            MatType type = mat.Type();
+            if (type == MatType.CV_8UC1 || type == MatType.CV_8UC3)
+                return new Scalar(0); // 瀵逛簬8浣嶆棤绗﹀彿绫诲瀷锛�0鏄畨鍏ㄧ殑鏃犳晥鍊�
+            else if (type == MatType.CV_32FC1 || type == MatType.CV_32FC3)
+                return new Scalar(-1); // 瀵逛簬娴偣绫诲瀷锛�-1鎴朜aN鍙敤
+            else if (type == MatType.CV_64FC1 || type == MatType.CV_64FC3)
+                return new Scalar(double.NaN); // 鍙岀簿搴︽诞鐐圭敤NaN
+            else
+                return new Scalar(0); // 瀵逛簬8浣嶆棤绗﹀彿绫诲瀷锛�0鏄畨鍏ㄧ殑鏃犳晥鍊�
+        }
+
+        public static void RGB2XYZ(double sR, double sG, double sB, out double X, out double Y, out double Z)
+        {
+            // 杈撳叆鐨勯鑹插�� (sR, sG, sB) 搴斾负 0 鍒� 255 涔嬮棿鐨勫��
+
+            // 璁$畻褰掍竴鍖栧��
+            double var_R = sR / 255.0;
+            double var_G = sG / 255.0;
+            double var_B = sB / 255.0;
+
+            // 杞崲鍒扮嚎鎬х┖闂�
+            var_R = (var_R > 0.04045) ? Math.Pow((var_R + 0.055) / 1.055, 2.4) : var_R / 12.92;
+            var_G = (var_G > 0.04045) ? Math.Pow((var_G + 0.055) / 1.055, 2.4) : var_G / 12.92;
+            var_B = (var_B > 0.04045) ? Math.Pow((var_B + 0.055) / 1.055, 2.4) : var_B / 12.92;
+
+            // 杞崲涓虹櫨鍒嗘瘮
+            var_R *= 100;
+            var_G *= 100;
+            var_B *= 100;
+
+            // 璁$畻 XYZ 鍊�
+            double var_X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
+            double var_Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
+            double var_Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
+
+            // 璁$畻褰掍竴鍖栧��
+
+            X = Math.Round(var_X / (var_X + var_Y + var_Z), 3);
+            Y = Math.Round(var_Y / (var_X + var_Y + var_Z), 3);
+            Z = Math.Round(var_Z / (var_X + var_Y + var_Z), 3);
+        }
+
+        public static void ExtractFrames(string videoPath, string outputDir)
+        {
+            // 妫�鏌ヨ棰戞枃浠舵槸鍚﹀瓨鍦�
+            if (!File.Exists(videoPath))
+            {
+                throw new FileNotFoundException($"瑙嗛鏂囦欢涓嶅瓨鍦�: {videoPath}");
+            }
+
+            // 鍒涘缓杈撳嚭鐩綍
+            if (!Directory.Exists(outputDir))
+            {
+                Directory.CreateDirectory(outputDir);
+            }
+
+            using (var capture = new VideoCapture(videoPath))
+            {
+                if (!capture.IsOpened())
+                {
+                    throw new Exception("鏃犳硶鎵撳紑瑙嗛鏂囦欢");
+                }
+
+                // 鑾峰彇瑙嗛淇℃伅
+                int totalFrames = (int)capture.Get(VideoCaptureProperties.FrameCount);
+                double fps = capture.Get(VideoCaptureProperties.Fps);
+                int width = (int)capture.Get(VideoCaptureProperties.FrameWidth);
+                int height = (int)capture.Get(VideoCaptureProperties.FrameHeight);
+
+                Debug.WriteLine($"瑙嗛淇℃伅: {totalFrames}甯�, {fps:F2}fps, 鍒嗚鲸鐜�: {width}x{height}");
+
+                Mat frame = new Mat();
+                int frameCount = 0;
+
+                while (capture.Read(frame))
+                {
+                    if (frame.Empty())
+                        break;
+
+                    // 鐢熸垚杈撳嚭鏂囦欢鍚�
+                    string outputPath = Path.Combine(outputDir, $"frame_{frameCount:D6}.bmp");
+
+                    // 淇濆瓨甯т负鍥剧墖
+                    Cv2.ImWrite(outputPath, frame);
+
+                    frameCount++;
+
+                    // 鏄剧ず杩涘害
+                    if (frameCount % 100 == 0)
+                    {
+                        Debug.WriteLine($"宸插鐞� {frameCount}/{totalFrames} 甯�");
+                    }
+                }
+
+                Debug.WriteLine($"鎻愬彇瀹屾垚! 鍏辨彁鍙� {frameCount} 甯у浘鐗�");
+            }
+        }
+        #endregion
+    }
+
+    public class ObjectRecord : IDisposable
+    {
+        //鍒涘缓铏氭嫙HWindow鐢ㄤ簬鏄剧ず鍥剧墖[闇�瑕侀噴鏀綸
+        protected HWindowControl hWindowControl = null;
+
+        public bool bCompleted = false;
+
+        public HObject Image
+        {
+            set
+            {
+                try
+                {
+                    if (value == null)
+                        return;
+                    HOperatorSet.GetImageSize(value, out HTuple ho_ImageWidth, out HTuple ho_ImageHeight);
+                    hWindowControl = new HWindowControl();
+                    hWindowControl.Size = new System.Drawing.Size(ho_ImageWidth, ho_ImageHeight);
+                    TAlgorithm.DispImage(value, hWindowControl.HalconWindow);
+                }
+                catch { }
+            }
+        }
+
+        public HObject RecordObject_OK;
+        public HObject RecordObject_NG;
+
+        public ObjectRecord(HObject Image = null)
+        {
+            if (RecordObject_OK != null)
+                RecordObject_OK.Dispose();
+            HOperatorSet.GenEmptyObj(out RecordObject_OK);
+            RecordObject_OK = null;
+
+            if (RecordObject_NG != null)
+                RecordObject_NG.Dispose();
+            HOperatorSet.GenEmptyObj(out RecordObject_NG);
+            RecordObject_NG = null;
+
+            this.Image = Image;
+        }
+
+        public void AddRecord(HObject RecordObject, bool result = true)
+        {
+            if (RecordObject == null || !RecordObject.IsInitialized())
+                return;
+
+            try
+            {
+                HOperatorSet.GenContourRegionXld(RecordObject, out RecordObject, "border_holes");
+            }
+            catch { }
+
+            if (result)
+            {
+                if (this.RecordObject_OK == null || !this.RecordObject_OK.IsInitialized())
+                    this.RecordObject_OK = RecordObject;
+                else
+                    HOperatorSet.ConcatObj(this.RecordObject_OK, RecordObject, out this.RecordObject_OK);
+            }
+            else
+            {
+                if (this.RecordObject_NG == null || !this.RecordObject_NG.IsInitialized())
+                    this.RecordObject_NG = RecordObject;
+                else
+                    HOperatorSet.ConcatObj(this.RecordObject_NG, RecordObject, out this.RecordObject_NG);
+            }
+        }
+
+        public void AddXld(HObject RecordObjectXld, bool result = true)
+        {
+            if (RecordObjectXld == null || !RecordObjectXld.IsInitialized())
+                return;
+
+            if (result)
+            {
+                if (this.RecordObject_OK == null || !this.RecordObject_OK.IsInitialized())
+                    this.RecordObject_OK = RecordObjectXld;
+                else
+                    HOperatorSet.ConcatObj(this.RecordObject_OK, RecordObjectXld, out this.RecordObject_OK);
+            }
+            else
+            {
+                if (this.RecordObject_NG == null || !this.RecordObject_NG.IsInitialized())
+                    this.RecordObject_NG = RecordObjectXld;
+                else
+                    HOperatorSet.ConcatObj(this.RecordObject_NG, RecordObjectXld, out this.RecordObject_NG);
+            }
+        }
+
+        public void GetRecord(out HObject RecordObject)
+        {
+            try
+            {
+                if (this.RecordObject_OK == null || !this.RecordObject_OK.IsInitialized())
+                {
+                    RecordObject = this.RecordObject_NG;
+                    return;
+                }
+
+                if (this.RecordObject_NG == null || !this.RecordObject_NG.IsInitialized())
+                {
+                    RecordObject = this.RecordObject_NG;
+                    return;
+                }
+
+                HOperatorSet.ConcatObj(this.RecordObject_OK, this.RecordObject_NG, out RecordObject);
+                return;
+            }
+            catch { RecordObject = null; }
+        }
+
+        public virtual void ChangeAll2False()
+        {
+            if (this.RecordObject_OK == null || !this.RecordObject_OK.IsInitialized())
+                return;
+
+            if (this.RecordObject_NG == null || !this.RecordObject_NG.IsInitialized())
+                this.RecordObject_NG = RecordObject_OK.CopyObj(1, -1);
+            else
+                HOperatorSet.ConcatObj(RecordObject_OK, RecordObject_NG, out RecordObject_NG);
+
+            if (RecordObject_OK != null && RecordObject_OK.IsInitialized())
+                RecordObject_OK.Dispose();
+        }
+
+        public virtual void ChangeAll2True()
+        {
+            if (this.RecordObject_NG == null || !this.RecordObject_NG.IsInitialized())
+                return;
+
+            if (this.RecordObject_OK == null || !this.RecordObject_OK.IsInitialized())
+                this.RecordObject_OK = RecordObject_NG.CopyObj(1, -1);
+            else
+                HOperatorSet.ConcatObj(RecordObject_OK, RecordObject_NG, out RecordObject_OK);
+
+            if (RecordObject_OK != null && RecordObject_OK.IsInitialized())
+                RecordObject_OK.Dispose();
+        }
+
+        public virtual HObject GetRecordImage()
+        {
+            bCompleted = false;
+            try
+            {
+                if (hWindowControl == null)
+                    return null;
+
+
+                if (RecordObject_OK != null && RecordObject_OK.IsInitialized())
+                {
+                    HOperatorSet.SetColor(hWindowControl.HalconWindow, "true");
+                    HOperatorSet.DispObj(RecordObject_OK, hWindowControl.HalconWindow);
+                }
+
+                if (RecordObject_NG != null && RecordObject_NG.IsInitialized())
+                {
+                    HOperatorSet.SetColor(hWindowControl.HalconWindow, "red");
+                    HOperatorSet.DispObj(RecordObject_NG, hWindowControl.HalconWindow);
+                }
+
+                HOperatorSet.DumpWindowImage(out HObject hoRecordImage, hWindowControl.HalconWindow);
+                return hoRecordImage;
+            }
+            catch { return null; }
+            finally
+            {
+                if (RecordObject_OK != null && RecordObject_OK.IsInitialized())
+                    RecordObject_OK.Dispose();
+                HOperatorSet.GenEmptyObj(out RecordObject_OK);
+
+                if (RecordObject_NG != null && RecordObject_NG.IsInitialized())
+                    RecordObject_NG.Dispose();
+                HOperatorSet.GenEmptyObj(out RecordObject_NG);
+                bCompleted = true;
+            }
+        }
+
+        public virtual void Display(HWindow hWindow)
+        {
+            try
+            {
+                if (hWindow != null)
+                {
+                    if (RecordObject_NG != null && RecordObject_NG.IsInitialized())
+                    {
+                        HOperatorSet.SetColor(hWindow, "red");
+                        HOperatorSet.DispObj(RecordObject_NG, hWindow);
+                    }
+
+                    if (RecordObject_OK != null && RecordObject_OK.IsInitialized())
+                    {
+                        HOperatorSet.SetColor(hWindow, "green");
+                        HOperatorSet.DispObj(RecordObject_OK, hWindow);
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public virtual void Dispose()
+        {
+            try
+            {
+                if (hWindowControl != null)
+                    hWindowControl.Dispose();
+
+                if (RecordObject_OK != null && RecordObject_OK.IsInitialized())
+                {
+                    RecordObject_OK.Dispose();
+                    RecordObject_OK = null;
+                }
+                if (RecordObject_NG != null && RecordObject_NG.IsInitialized())
+                {
+                    RecordObject_NG.Dispose();
+                    RecordObject_NG = null;
+                }
+            }
+            catch { }
+        }
+    }
+
+    public class MsgRecord : ObjectRecord
+    {
+        public HTuple Msg = new HTuple();
+        public HTuple Row = new HTuple();
+        public HTuple Column = new HTuple();
+        public HTuple Result = new HTuple();
+
+        public MsgRecord(HObject RecordImage = null) : base(RecordImage)  // 杩欓噷璋冪敤鍩虹被鏋勯�犲嚱鏁�
+        {
+            Msg = new HTuple();
+            Row = new HTuple();
+            Column = new HTuple();
+            Result = new HTuple();
+        }
+
+        public void AddRecord(HTuple Msg, HTuple Row, HTuple Column, HObject RecordObject = null, bool Result = true)
+        {
+
+            if (Msg.Length <= 0 || Row.Length <= 0 || Column.Length <= 0)
+                return;
+
+            if (RecordObject != null && RecordObject.IsInitialized())
+            {
+                try
+                {
+                    HOperatorSet.GenContourRegionXld(RecordObject, out RecordObject, "border_holes");
+                }
+                catch { }
+
+                if (Result)
+                {
+                    if (this.RecordObject_OK == null || !this.RecordObject_OK.IsInitialized())
+                        this.RecordObject_OK = RecordObject;
+                    else
+                        HOperatorSet.ConcatObj(this.RecordObject_OK, RecordObject, out this.RecordObject_OK);
+                }
+                else
+                {
+                    if (this.RecordObject_NG == null || !this.RecordObject_NG.IsInitialized())
+                        this.RecordObject_NG = RecordObject;
+                    else
+                        HOperatorSet.ConcatObj(this.RecordObject_NG, RecordObject, out this.RecordObject_NG);
+                }
+            }
+
+            HOperatorSet.TupleConcat(this.Msg, Msg, out this.Msg);
+            HOperatorSet.TupleConcat(this.Row, Row, out this.Row);
+            HOperatorSet.TupleConcat(this.Column, Column, out this.Column);
+            HOperatorSet.TupleConcat(this.Result, Result ? 1 : 0, out this.Result);
+        }
+
+        public void GetRecord(out HObject RecordObject, out HTuple Msg, out HTuple Row, out HTuple Column)
+        {
+            Msg = this.Msg;
+            Row = this.Row;
+            Column = this.Column;
+            try
+            {
+                if (this.RecordObject_OK == null || !this.RecordObject_OK.IsInitialized())
+                {
+                    RecordObject = this.RecordObject_NG;
+                    return;
+                }
+
+                if (this.RecordObject_NG == null || !this.RecordObject_NG.IsInitialized())
+                {
+                    RecordObject = this.RecordObject_NG;
+                    return;
+                }
+
+                HOperatorSet.ConcatObj(this.RecordObject_OK, this.RecordObject_NG, out RecordObject);
+                return;
+            }
+            catch { RecordObject = null; }
+        }
+
+        public override void ChangeAll2False()
+        {
+            for (int i = 0; i < Result.Length; i++)
+                Result[i] = 0;
+
+            if (this.RecordObject_NG == null || !this.RecordObject_NG.IsInitialized())
+                this.RecordObject_NG = RecordObject_OK.CopyObj(1, -1);
+            else if (!(this.RecordObject_OK == null || !this.RecordObject_OK.IsInitialized()))
+                HOperatorSet.ConcatObj(RecordObject_OK, RecordObject_NG, out RecordObject_NG);
+
+            if (RecordObject_OK != null && RecordObject_OK.IsInitialized())
+                RecordObject_OK.Dispose();
+        }
+
+        public override void ChangeAll2True()
+        {
+            for (int i = 0; i < Result.Length; i++)
+                Result[i] = 1;
+
+            if (this.RecordObject_OK == null || !this.RecordObject_OK.IsInitialized())
+                this.RecordObject_OK = RecordObject_NG.CopyObj(1, -1);
+            else if (!(this.RecordObject_NG == null || !this.RecordObject_NG.IsInitialized()))
+                HOperatorSet.ConcatObj(RecordObject_OK, RecordObject_NG, out RecordObject_OK);
+
+            if (RecordObject_NG != null && RecordObject_NG.IsInitialized())
+                RecordObject_NG.Dispose();
+        }
+
+        public override HObject GetRecordImage()
+        {
+            bCompleted = false;
+            try
+            {
+                if (hWindowControl == null)
+                    return null;
+
+                if (RecordObject_OK != null && RecordObject_OK.IsInitialized())
+                {
+                    HOperatorSet.SetColor(hWindowControl.HalconWindow, "true");
+                    HOperatorSet.DispObj(RecordObject_OK, hWindowControl.HalconWindow);
+                }
+
+                if (RecordObject_NG != null && RecordObject_NG.IsInitialized())
+                {
+                    HOperatorSet.SetColor(hWindowControl.HalconWindow, "red");
+                    HOperatorSet.DispObj(RecordObject_NG, hWindowControl.HalconWindow);
+                }
+
+                for (int i = 0; i < Msg.Length; i++)
+                {
+                    if (1 == Result[i])
+                        HOperatorSet.SetColor(hWindowControl.HalconWindow, "green");
+                    else
+                        HOperatorSet.SetColor(hWindowControl.HalconWindow, "red");
+
+                    TAlgorithm.DispMsg(Msg[i], hWindowControl.HalconWindow, 1 == Result[i] ? "green" : "red", Row[i], Column[i]);
+                }
+
+                HOperatorSet.DumpWindowImage(out HObject hoRecordImage, hWindowControl.HalconWindow);
+                bCompleted = true;
+
+                return hoRecordImage;
+            }
+            catch { return null; }
+            finally
+            {
+                if (RecordObject_OK != null && RecordObject_OK.IsInitialized())
+                    RecordObject_OK.Dispose();
+                HOperatorSet.GenEmptyObj(out RecordObject_OK);
+
+                if (RecordObject_NG != null && RecordObject_NG.IsInitialized())
+                    RecordObject_NG.Dispose();
+                HOperatorSet.GenEmptyObj(out RecordObject_NG);
+
+                Msg = new HTuple();
+                Row = new HTuple();
+                Column = new HTuple();
+                Result = new HTuple();
+                bCompleted = true;
+            }
+        }
+
+        public override void Display(HWindow hWindow)
+        {
+            try
+            {
+                base.Display(hWindow);
+
+                for (int i = 0; i < Msg.Length; i++)
+                {
+                    if (hWindow != null)
+                    {
+                        if (1 == Result[i])
+                            HOperatorSet.SetColor(hWindow, "green");
+                        else
+                            HOperatorSet.SetColor(hWindow, "red");
+
+                        TAlgorithm.DispMsg(Msg[i], hWindow, 1 == Result[i] ? "green" : "red", Row[i], Column[i]);
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public override void Dispose()
+        {
+            try
+            {
+                if (hWindowControl != null)
+                    hWindowControl.Dispose();
+
+                if (RecordObject_OK != null && RecordObject_OK.IsInitialized())
+                {
+                    RecordObject_OK.Dispose();
+                    RecordObject_OK = null;
+                }
+                if (RecordObject_NG != null && RecordObject_NG.IsInitialized())
+                {
+                    RecordObject_NG.Dispose();
+                    RecordObject_NG = null;
+                }
+
+                Msg = new HTuple();
+                Row = new HTuple();
+                Column = new HTuple();
+                Result = new HTuple();
+            }
+            catch { }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.Designer.cs b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.Designer.cs
new file mode 100644
index 0000000..5e81bf2
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.Designer.cs
@@ -0,0 +1,48 @@
+锘縩amespace LB_VisionProcesses.Alogrithms
+{
+    partial class TAlgorithmEdit
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            SuspendLayout();
+            // 
+            // TAlgorithmEdit
+            // 
+            AutoScaleDimensions = new SizeF(10F, 21F);
+            AutoScaleMode = AutoScaleMode.Font;
+            BackColor = Color.FromArgb(32, 41, 50);
+            Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            ForeColor = SystemColors.Control;
+            Margin = new Padding(3, 4, 3, 4);
+            Name = "TAlgorithmEdit";
+            Size = new Size(1491, 740);
+            ResumeLayout(false);
+        }
+
+        #endregion
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.cs b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.cs
new file mode 100644
index 0000000..b3701a6
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.cs
@@ -0,0 +1,278 @@
+锘縰sing HalconDotNet;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using OpenCvSharp;
+using System.Diagnostics;
+using LB_VisionControl;
+
+namespace LB_VisionProcesses.Alogrithms
+{
+    public partial class TAlgorithmEdit : UserControl
+    {
+        public IProcess Subject;
+        public UserHSmartWindowControl inputImageHSmartWindowControl = new UserHSmartWindowControl();
+        public UserHSmartWindowControl recordImageHSmartWindowControl = new UserHSmartWindowControl();
+
+        public ToolTip lblMsgToolTip = new ToolTip();
+
+        public bool Result
+        {
+            get
+            {
+                if (Subject == null)
+                    return false;
+                return Subject.Result;
+            }
+            set
+            {
+                if (Subject != null)
+                    Subject.Result = value;
+            }
+        }
+
+        public string Msg
+        {
+            get
+            {
+                if (Subject == null)
+                    return "绠楁硶涓虹┖";
+                return Subject.Msg.Trim();
+            }
+        }
+
+        public Object InputImage
+        {
+            get
+            {
+                if (Subject == null)
+                    return null;
+                return Subject.InputImage;
+            }
+            set
+            {
+                Subject.InputImage = value;
+
+                if (InputImage == null)
+                    return;
+
+                if (InputImage is HObject)
+                    inputImageHSmartWindowControl.ShowHoImage((HObject)value);
+                else if (InputImage is Bitmap)
+                {
+                    TAlgorithm.Bitmap2HObject((Bitmap)value, out HObject image);
+                    inputImageHSmartWindowControl.ShowHoImage(image);
+                }
+                else if (InputImage is Mat)
+                {
+                    TAlgorithm.Mat2HObject((Mat)value, out HObject image);
+                    inputImageHSmartWindowControl.ShowHoImage(image);
+                }
+            }
+        }
+
+        public TAlgorithmEdit() { }
+
+        public TAlgorithmEdit(TAlgorithm subject = null)
+        {
+            if (subject != null)
+                Subject = subject;
+            else
+                Subject = new TAlgorithm();
+            this.Dock = DockStyle.Fill;
+
+            lblMsgToolTip.AutoPopDelay = 5000; // 鎻愮ず鏄剧ず5绉掑悗娑堝け
+            lblMsgToolTip.InitialDelay = 500;  // 榧犳爣鎮仠500姣鍚庢樉绀烘彁绀�
+
+            InitializeComponent();
+        }
+
+        /// <summary>
+        /// 杩愯绠楀瓙
+        /// </summary>
+        /// <param name="minThreshold"></param>
+        /// <param name="maxThreshold"></param>
+        /// <param name="minArea"></param>
+        /// <param name="maxArea"></param>
+        /// <param name="angle"></param>
+        /// <returns></returns>
+        public virtual bool Run()
+        {
+            //杩愯鍓嶉渶瑕佹洿鏂拌緭鍏ュ弬鏁癙aras
+            UpdataInputs();
+            Subject.Run();
+            return Subject.Result;
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯鍙傛暟
+        /// </summary>
+        public virtual void UpdataInputs()
+        {
+            Type type = inputImageHSmartWindowControl.oRoi?.GetType();
+            switch (type)
+            {
+                case Type t when t == typeof(HRectangle2):
+                    HRectangle2 hRectangle2 = (HRectangle2)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HRectangle2(hRectangle2.X - Subject.Params.Fixture.X, hRectangle2.Y - Subject.Params.Fixture.Y
+                        , hRectangle2.Phi - Subject.Params.Fixture.Phi, hRectangle2.Width, hRectangle2.Height);
+                    break;
+                case Type t when t == typeof(HCircle):
+                    HCircle hCircle = (HCircle)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HCircle(hCircle.X - Subject.Params.Fixture.X, hCircle.Y - Subject.Params.Fixture.Y, hCircle.Radius);
+                    break;
+                case Type t when t == typeof(HEllipse):
+                    HEllipse hEllipse = (HEllipse)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HEllipse(hEllipse.X - Subject.Params.Fixture.X, hEllipse.Y - Subject.Params.Fixture.Y
+                        , hEllipse.Phi, hEllipse.Radius1, hEllipse.Radius2, hEllipse.StartAngle, hEllipse.EndAngle);
+                    break;
+                case Type t when t == typeof(HSegment):
+                    HSegment hSegment = (HSegment)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HSegment(hSegment.StartX - Subject.Params.Fixture.X, hSegment.StartY - Subject.Params.Fixture.Y
+                        , hSegment.EndX - Subject.Params.Fixture.X, hSegment.EndY - Subject.Params.Fixture.Y);
+                    break;
+                default:
+                    Subject.Params.ROI = new ROI();
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// 鍔犺浇杩愯鍙傛暟
+        /// </summary>
+        public virtual void LoadParas()
+        {
+            Type type = Subject.Params.ROI?.GetType();
+            switch (type)
+            {
+                case Type t when t == typeof(HRectangle2):
+                    inputImageHSmartWindowControl.oRoi
+                         = new HRectangle2(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                         , Subject.Params.ROI.Phi + Subject.Params.Fixture.Phi, ((HRectangle2)Subject.Params.ROI).Width, ((HRectangle2)Subject.Params.ROI).Height);
+                    break;
+                case Type t when t == typeof(HCircle):
+                    inputImageHSmartWindowControl.oRoi
+                    = new HCircle(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                    , ((HCircle)Subject.Params.ROI).Radius);
+                    break;
+                case Type t when t == typeof(HEllipse):
+                    inputImageHSmartWindowControl.oRoi
+                    = new HEllipse(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                    , ((HEllipse)Subject.Params.ROI).Phi, ((HEllipse)Subject.Params.ROI).Radius1, ((HEllipse)Subject.Params.ROI).Radius2
+                    , ((HEllipse)Subject.Params.ROI).StartAngle, ((HEllipse)Subject.Params.ROI).EndAngle);
+                    break;
+                case Type t when t == typeof(HSegment):
+                    inputImageHSmartWindowControl.oRoi
+                    = new HSegment(((HSegment)Subject.Params.ROI).StartX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).StartY + Subject.Params.Fixture.Y
+                    , ((HSegment)Subject.Params.ROI).EndX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).EndY + Subject.Params.Fixture.Y);
+                    break;
+                default:
+                    inputImageHSmartWindowControl.oRoi = null;
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯缁撴灉
+        /// </summary>
+        public virtual void UpdataOutputs() { }
+
+        public virtual void btnRun_Click(object sender, EventArgs e) { }
+
+        public virtual void btnLoadImage_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    HOperatorSet.ReadImage(out HObject ho_Image, selectedFiles[0]);
+                    InputImage = ho_Image;
+                }
+            }
+        }
+
+        public virtual void btnSaveParas_Click(object sender, EventArgs e)
+        {
+            UpdataInputs();
+            // 鍒涘缓 SaveFileDialog 瀹炰緥
+            using (SaveFileDialog saveFileDialog = new SaveFileDialog())
+            {
+                // 璁剧疆瀵硅瘽妗嗘爣棰�
+                saveFileDialog.Title = "淇濆瓨鏂囦欢";
+
+                // 璁剧疆榛樿璺緞
+                saveFileDialog.InitialDirectory = Application.StartupPath;
+
+                // 璁剧疆鏂囦欢绫诲瀷杩囨护鍣�
+                saveFileDialog.Filter = "鏂囨湰鏂囦欢 (*.json)|*.json|鎵�鏈夋枃浠� (*.*)|*.*";
+
+                // 璁剧疆榛樿鏂囦欢鍚�
+                saveFileDialog.FileName = "Algorithm_1.json";
+
+                // 鏄剧ず瀵硅瘽妗嗗苟妫�鏌ョ敤鎴锋槸鍚︾偣鍑讳簡淇濆瓨鎸夐挳
+                if (saveFileDialog.ShowDialog() == DialogResult.OK)
+                {
+                    // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠惰矾寰�
+                    string fullPath = saveFileDialog.FileName;
+                    Debug.WriteLine("閫夋嫨鐨勬枃浠惰矾寰勬槸: " + fullPath);
+                    Subject.strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+                    //Subject.oRoi = inputImageHSmartWindowControl.oRoi;
+                    Subject.Save(System.IO.Path.GetDirectoryName(fullPath));
+                }
+            }
+        }
+
+        public virtual void btnLoadParas_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Ini Files (*.json)|*.json|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    Subject.Load(selectedFiles[0]);
+                    LoadParas();
+                }
+            }
+        }
+
+        public virtual void ckbDrawRoi_CheckedChanged(object sender, EventArgs e) { }
+
+        public virtual void cmbTypeRoi_SelectedIndexChanged(object sender, EventArgs e) { }
+
+        public virtual void cmbFixture_SelectedIndexChanged(object sender, EventArgs e) { }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.resx b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TAlgorithmEdit.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/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestTool.cs b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestTool.cs
new file mode 100644
index 0000000..2fb2f3e
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestTool.cs
@@ -0,0 +1,160 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Alogrithms
+{
+    [Process("娴嬭瘯宸ュ叿", Category = "鍏朵粬宸ュ叿", Description = "鍒涘缓娴嬭瘯宸ュ叿")]
+    public class TestTool : TAlgorithm
+    {
+        public TestTool()
+        {
+            strProcessClass = "LB_VisionProcesses.Alogrithms.TestTool";
+            strProcessName = "娴嬭瘯宸ュ叿";
+
+            Params.Inputs.Add("杈撳叆", "鎴戞槸杈撳叆");
+            Params.Outputs.Add("杈撳嚭", "");
+        }
+
+        #region 闃诲杩愯鏂瑰紡
+        /// <summary>
+        /// 闃诲杩愯鏂瑰紡
+        /// </summary>
+        /// <returns></returns>
+        //public override bool Run()
+        //{
+        //    try
+        //    {
+        //        InitRunParams();
+
+        //        #region 瑁佸壀鍖哄煙
+        //        object DomainImage = null;
+        //        if (!ReduceDomainImage(InputImage, ref DomainImage))
+        //        {
+        //            Msg = "瑁佸壀鍖哄煙澶辫触";
+        //            Result = false;
+        //            return false;
+        //        }
+        //        Record = new MsgRecord();
+        //        #endregion
+
+        //        #region 绠楀瓙閫昏緫
+        //        string input = Params.Inputs["杈撳叆"].ToString();
+        //        Params.Outputs.Add("杈撳嚭", "鎴戞槸杈撳嚭");
+        //        #endregion
+
+        //        #region 缁撴灉澶勭悊
+        //        ((MsgRecord)Record).AddRecord(input, 0, 0);
+        //        #endregion
+
+        //        #region 鐢熸垚OutputImage缁欏悗缁鐞�
+        //        try
+        //        {
+        //            OutputImage = DomainImage;
+        //        }
+        //        catch (Exception ex)
+        //        {
+        //            Msg = "鐢熸垚OutputImage澶辫触,鍘熷洜鏄�:" + ex.ToString();
+        //            Result = false;
+        //            return false;
+        //        }
+        //        #endregion
+
+        //        return Result;
+        //    }
+        //    catch
+        //    {
+        //        OutputImage = null;
+        //        Result = false;
+        //        Msg = string.Format("杩愯鍑虹幇寮傚父");
+        //        return false;
+        //    }
+        //    finally
+        //    {
+        //        if (!Result)
+        //            OutputImage = null;
+        //        bCompleted = true;
+        //    }
+        //}
+        #endregion
+
+        /// <summary>
+        /// 闈為樆濉炶繍琛屾柟寮�
+        /// </summary>
+        public override void TAlgorithmMain()
+        {
+            #region 鍒濆鍖栧彉閲�
+
+            #endregion
+
+            try
+            {
+                //if (InputImage == null)
+                //{
+                //    Msg = "杈撳叆鍥剧墖涓虹┖";
+                //    Result = false;
+                //    return;
+                //}
+
+                #region 瑁佸壀鍖哄煙
+                object DomainImage = null;
+                //if (!ReduceDomainImage(InputImage, ref DomainImage))
+                //{
+                //    Msg = "瑁佸壀鍖哄煙澶辫触";
+                //    Result = false;
+                //    return;
+                //}
+                #endregion
+
+                #region 绠楀瓙閫昏緫
+                string input = Params.Inputs["杈撳叆"].ToString();
+                Params.Outputs.Add("杈撳嚭", input);
+                #endregion
+
+                #region 鐢熸垚OutputImage缁欏悗缁鐞�
+                try
+                {
+                    OutputImage = DomainImage;
+                }
+                catch (Exception ex)
+                {
+                    Msg = "鐢熸垚OutputImage澶辫触,鍘熷洜鏄�:" + ex.ToString();
+                    Result = false;
+                    return;
+                }
+                #endregion
+
+                if (Msg == "杩愯瓒呮椂")
+                {
+                    Result = false;
+                    return;
+                }
+
+                Msg = "杩愯鎴愬姛";
+                Result = true;
+                return;
+            }
+            catch (Exception ex)
+            {
+                Msg = "杩愯澶辫触,鍘熷洜鏄�:" + ex.ToString().TrimEnd();
+                OutputImage = null;
+                Result = false;
+                return;
+            }
+            finally
+            {
+                if (!Result)
+                {
+                    Params.Outputs.Add("杈撳嚭", "");
+                }
+
+                bCompleted = true;
+                #region 鍐呭瓨閲婃斁
+
+                #endregion
+            }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.Designer.cs b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.Designer.cs
new file mode 100644
index 0000000..be3bb91
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.Designer.cs
@@ -0,0 +1,515 @@
+锘縰sing LB_VisionProcesses.Alogrithms;
+
+namespace LB_VisionProcesses.Alogrithms
+{
+    partial class TestToolEdit
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tablePanelParas = new TableLayoutPanel();
+            label1 = new Label();
+            stxtInput = new TextBox();
+            pnlInputImage = new Panel();
+            TopToolStrip = new ToolStrip();
+            btnRun = new ToolStripButton();
+            btnLoadImage = new ToolStripButton();
+            btnSaveParas = new ToolStripButton();
+            btnLoadParas = new ToolStripButton();
+            BtmStatusStrip = new StatusStrip();
+            lblResult = new ToolStripStatusLabel();
+            lblMsg = new ToolStripStatusLabel();
+            lblRunTime = new ToolStripStatusLabel();
+            MainTableLayoutPanel = new TableLayoutPanel();
+            parasTabControl = new TabControl();
+            tabPage1 = new TabPage();
+            tabPage5 = new TabPage();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            cmbTypeRoi = new ComboBox();
+            label21 = new Label();
+            label22 = new Label();
+            cmbFixture = new ComboBox();
+            ckbDrawRoi = new CheckBox();
+            tabPage2 = new TabPage();
+            tableLayoutResults = new TableLayoutPanel();
+            label5 = new Label();
+            stxtOutput = new TextBox();
+            imgTabControl = new TabControl();
+            tabPageInputImage = new TabPage();
+            tabPageRecordImage = new TabPage();
+            pnlRecordImage = new Panel();
+            tablePanelParas.SuspendLayout();
+            TopToolStrip.SuspendLayout();
+            BtmStatusStrip.SuspendLayout();
+            MainTableLayoutPanel.SuspendLayout();
+            parasTabControl.SuspendLayout();
+            tabPage1.SuspendLayout();
+            tabPage5.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tabPage2.SuspendLayout();
+            tableLayoutResults.SuspendLayout();
+            imgTabControl.SuspendLayout();
+            tabPageInputImage.SuspendLayout();
+            tabPageRecordImage.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tablePanelParas
+            // 
+            tablePanelParas.ColumnCount = 4;
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.Controls.Add(label1, 0, 0);
+            tablePanelParas.Controls.Add(stxtInput, 1, 0);
+            tablePanelParas.Dock = DockStyle.Fill;
+            tablePanelParas.Location = new Point(3, 3);
+            tablePanelParas.Margin = new Padding(2, 3, 2, 3);
+            tablePanelParas.Name = "tablePanelParas";
+            tablePanelParas.RowCount = 10;
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.Size = new Size(397, 510);
+            tablePanelParas.TabIndex = 0;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Location = new Point(2, 0);
+            label1.Margin = new Padding(2, 0, 2, 0);
+            label1.MaximumSize = new Size(0, 28);
+            label1.MinimumSize = new Size(0, 28);
+            label1.Name = "label1";
+            label1.Size = new Size(32, 28);
+            label1.TabIndex = 0;
+            label1.Text = "杈撳叆";
+            label1.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // stxtInput
+            // 
+            stxtInput.Location = new Point(92, 3);
+            stxtInput.Margin = new Padding(2, 3, 2, 3);
+            stxtInput.Name = "stxtInput";
+            stxtInput.Size = new Size(98, 23);
+            stxtInput.TabIndex = 5;
+            // 
+            // pnlInputImage
+            // 
+            pnlInputImage.Dock = DockStyle.Fill;
+            pnlInputImage.Location = new Point(3, 3);
+            pnlInputImage.Margin = new Padding(4);
+            pnlInputImage.Name = "pnlInputImage";
+            pnlInputImage.Size = new Size(607, 510);
+            pnlInputImage.TabIndex = 44;
+            // 
+            // TopToolStrip
+            // 
+            TopToolStrip.Items.AddRange(new ToolStripItem[] { btnRun, btnLoadImage, btnSaveParas, btnLoadParas });
+            TopToolStrip.Location = new Point(0, 0);
+            TopToolStrip.Name = "TopToolStrip";
+            TopToolStrip.Size = new Size(1044, 25);
+            TopToolStrip.TabIndex = 45;
+            TopToolStrip.Text = "toolStrip1";
+            // 
+            // btnRun
+            // 
+            btnRun.BackgroundImageLayout = ImageLayout.Zoom;
+            btnRun.ImageTransparentColor = Color.Magenta;
+            btnRun.Name = "btnRun";
+            btnRun.Size = new Size(36, 22);
+            btnRun.Text = "杩愯";
+            btnRun.Click += btnRun_Click;
+            // 
+            // btnLoadImage
+            // 
+            btnLoadImage.ImageTransparentColor = Color.Magenta;
+            btnLoadImage.Name = "btnLoadImage";
+            btnLoadImage.Size = new Size(36, 22);
+            btnLoadImage.Text = "瀵煎浘";
+            btnLoadImage.Click += btnLoadImage_Click;
+            // 
+            // btnSaveParas
+            // 
+            btnSaveParas.ImageTransparentColor = Color.Magenta;
+            btnSaveParas.Name = "btnSaveParas";
+            btnSaveParas.Size = new Size(36, 22);
+            btnSaveParas.Text = "淇濆瓨";
+            btnSaveParas.Click += btnSaveParas_Click;
+            // 
+            // btnLoadParas
+            // 
+            btnLoadParas.ImageTransparentColor = Color.Magenta;
+            btnLoadParas.Name = "btnLoadParas";
+            btnLoadParas.Size = new Size(36, 22);
+            btnLoadParas.Text = "鍔犺浇";
+            btnLoadParas.Click += btnLoadParas_Click;
+            // 
+            // BtmStatusStrip
+            // 
+            BtmStatusStrip.Items.AddRange(new ToolStripItem[] { lblResult, lblMsg, lblRunTime });
+            BtmStatusStrip.Location = new Point(0, 577);
+            BtmStatusStrip.Name = "BtmStatusStrip";
+            BtmStatusStrip.Size = new Size(1044, 22);
+            BtmStatusStrip.TabIndex = 46;
+            BtmStatusStrip.Text = "statusStrip1";
+            // 
+            // lblResult
+            // 
+            lblResult.Name = "lblResult";
+            lblResult.Size = new Size(34, 17);
+            lblResult.Text = "True";
+            // 
+            // lblMsg
+            // 
+            lblMsg.Name = "lblMsg";
+            lblMsg.Size = new Size(56, 17);
+            lblMsg.Text = "杩愯鎴愬姛";
+            // 
+            // lblRunTime
+            // 
+            lblRunTime.Name = "lblRunTime";
+            lblRunTime.Size = new Size(32, 17);
+            lblRunTime.Text = "0ms";
+            // 
+            // MainTableLayoutPanel
+            // 
+            MainTableLayoutPanel.ColumnCount = 2;
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F));
+            MainTableLayoutPanel.Controls.Add(parasTabControl, 0, 0);
+            MainTableLayoutPanel.Controls.Add(imgTabControl, 1, 0);
+            MainTableLayoutPanel.Dock = DockStyle.Fill;
+            MainTableLayoutPanel.Location = new Point(0, 25);
+            MainTableLayoutPanel.Name = "MainTableLayoutPanel";
+            MainTableLayoutPanel.RowCount = 1;
+            MainTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            MainTableLayoutPanel.Size = new Size(1044, 552);
+            MainTableLayoutPanel.TabIndex = 47;
+            // 
+            // parasTabControl
+            // 
+            parasTabControl.Controls.Add(tabPage1);
+            parasTabControl.Controls.Add(tabPage5);
+            parasTabControl.Controls.Add(tabPage2);
+            parasTabControl.Dock = DockStyle.Fill;
+            parasTabControl.Location = new Point(3, 3);
+            parasTabControl.Name = "parasTabControl";
+            parasTabControl.SelectedIndex = 0;
+            parasTabControl.Size = new Size(411, 546);
+            parasTabControl.TabIndex = 48;
+            // 
+            // tabPage1
+            // 
+            tabPage1.Controls.Add(tablePanelParas);
+            tabPage1.Location = new Point(4, 26);
+            tabPage1.Name = "tabPage1";
+            tabPage1.Padding = new Padding(3);
+            tabPage1.Size = new Size(403, 516);
+            tabPage1.TabIndex = 0;
+            tabPage1.Text = "杈撳叆鍙傛暟";
+            tabPage1.UseVisualStyleBackColor = true;
+            // 
+            // tabPage5
+            // 
+            tabPage5.Controls.Add(tableLayoutPanel2);
+            tabPage5.Location = new Point(4, 26);
+            tabPage5.Name = "tabPage5";
+            tabPage5.Size = new Size(403, 516);
+            tabPage5.TabIndex = 2;
+            tabPage5.Text = "杩愯鍙傛暟";
+            tabPage5.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 4;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 60F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 150F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(cmbTypeRoi, 1, 0);
+            tableLayoutPanel2.Controls.Add(label21, 0, 0);
+            tableLayoutPanel2.Controls.Add(label22, 0, 1);
+            tableLayoutPanel2.Controls.Add(cmbFixture, 1, 1);
+            tableLayoutPanel2.Controls.Add(ckbDrawRoi, 2, 0);
+            tableLayoutPanel2.Location = new Point(3, 3);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 8;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(323, 309);
+            tableLayoutPanel2.TabIndex = 4;
+            // 
+            // cmbTypeRoi
+            // 
+            cmbTypeRoi.Enabled = false;
+            cmbTypeRoi.FormattingEnabled = true;
+            cmbTypeRoi.Location = new Point(63, 3);
+            cmbTypeRoi.Name = "cmbTypeRoi";
+            cmbTypeRoi.Size = new Size(121, 25);
+            cmbTypeRoi.TabIndex = 1;
+            cmbTypeRoi.SelectedIndexChanged += cmbTypeRoi_SelectedIndexChanged;
+            // 
+            // label21
+            // 
+            label21.AutoSize = true;
+            label21.Dock = DockStyle.Fill;
+            label21.Location = new Point(3, 0);
+            label21.Name = "label21";
+            label21.Size = new Size(54, 30);
+            label21.TabIndex = 3;
+            label21.Text = "ROI";
+            label21.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label22
+            // 
+            label22.AutoSize = true;
+            label22.Dock = DockStyle.Fill;
+            label22.Location = new Point(3, 30);
+            label22.Name = "label22";
+            label22.Size = new Size(54, 30);
+            label22.TabIndex = 4;
+            label22.Text = "Fixture";
+            label22.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbFixture
+            // 
+            cmbFixture.FormattingEnabled = true;
+            cmbFixture.Location = new Point(63, 33);
+            cmbFixture.Name = "cmbFixture";
+            cmbFixture.Size = new Size(121, 25);
+            cmbFixture.TabIndex = 5;
+            cmbFixture.SelectedIndexChanged += cmbFixture_SelectedIndexChanged;
+            // 
+            // ckbDrawRoi
+            // 
+            ckbDrawRoi.AutoSize = true;
+            ckbDrawRoi.CheckAlign = ContentAlignment.MiddleCenter;
+            ckbDrawRoi.Location = new Point(213, 3);
+            ckbDrawRoi.Name = "ckbDrawRoi";
+            ckbDrawRoi.Size = new Size(14, 14);
+            ckbDrawRoi.TabIndex = 2;
+            ckbDrawRoi.UseVisualStyleBackColor = true;
+            ckbDrawRoi.CheckedChanged += ckbDrawRoi_CheckedChanged;
+            // 
+            // tabPage2
+            // 
+            tabPage2.Controls.Add(tableLayoutResults);
+            tabPage2.Location = new Point(4, 26);
+            tabPage2.Name = "tabPage2";
+            tabPage2.Padding = new Padding(3);
+            tabPage2.Size = new Size(403, 516);
+            tabPage2.TabIndex = 1;
+            tabPage2.Text = "杈撳嚭缁撴灉";
+            tabPage2.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutResults
+            // 
+            tableLayoutResults.ColumnCount = 2;
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutResults.Controls.Add(label5, 0, 0);
+            tableLayoutResults.Controls.Add(stxtOutput, 1, 0);
+            tableLayoutResults.Dock = DockStyle.Fill;
+            tableLayoutResults.Location = new Point(3, 3);
+            tableLayoutResults.Margin = new Padding(2, 3, 2, 3);
+            tableLayoutResults.Name = "tableLayoutResults";
+            tableLayoutResults.RowCount = 10;
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.Size = new Size(397, 510);
+            tableLayoutResults.TabIndex = 1;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Dock = DockStyle.Fill;
+            label5.Location = new Point(2, 0);
+            label5.Margin = new Padding(2, 0, 2, 0);
+            label5.MaximumSize = new Size(0, 28);
+            label5.MinimumSize = new Size(0, 28);
+            label5.Name = "label5";
+            label5.Size = new Size(96, 28);
+            label5.TabIndex = 0;
+            label5.Text = "杈撳嚭";
+            label5.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // stxtOutput
+            // 
+            stxtOutput.Dock = DockStyle.Fill;
+            stxtOutput.Location = new Point(102, 3);
+            stxtOutput.Margin = new Padding(2, 3, 2, 3);
+            stxtOutput.Name = "stxtOutput";
+            stxtOutput.ReadOnly = true;
+            stxtOutput.Size = new Size(293, 23);
+            stxtOutput.TabIndex = 5;
+            // 
+            // imgTabControl
+            // 
+            imgTabControl.Controls.Add(tabPageInputImage);
+            imgTabControl.Controls.Add(tabPageRecordImage);
+            imgTabControl.Dock = DockStyle.Fill;
+            imgTabControl.Location = new Point(420, 3);
+            imgTabControl.Name = "imgTabControl";
+            imgTabControl.SelectedIndex = 0;
+            imgTabControl.Size = new Size(621, 546);
+            imgTabControl.TabIndex = 49;
+            // 
+            // tabPageInputImage
+            // 
+            tabPageInputImage.Controls.Add(pnlInputImage);
+            tabPageInputImage.Location = new Point(4, 26);
+            tabPageInputImage.Name = "tabPageInputImage";
+            tabPageInputImage.Padding = new Padding(3);
+            tabPageInputImage.Size = new Size(613, 516);
+            tabPageInputImage.TabIndex = 0;
+            tabPageInputImage.Text = "杈撳叆鍥惧儚";
+            tabPageInputImage.UseVisualStyleBackColor = true;
+            // 
+            // tabPageRecordImage
+            // 
+            tabPageRecordImage.Controls.Add(pnlRecordImage);
+            tabPageRecordImage.Location = new Point(4, 26);
+            tabPageRecordImage.Name = "tabPageRecordImage";
+            tabPageRecordImage.Padding = new Padding(3);
+            tabPageRecordImage.Size = new Size(613, 516);
+            tabPageRecordImage.TabIndex = 1;
+            tabPageRecordImage.Text = "缁撴灉鍥惧儚";
+            tabPageRecordImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlRecordImage
+            // 
+            pnlRecordImage.Dock = DockStyle.Fill;
+            pnlRecordImage.Location = new Point(3, 3);
+            pnlRecordImage.Margin = new Padding(4);
+            pnlRecordImage.Name = "pnlRecordImage";
+            pnlRecordImage.Size = new Size(607, 510);
+            pnlRecordImage.TabIndex = 45;
+            // 
+            // TestToolEdit
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(MainTableLayoutPanel);
+            Controls.Add(BtmStatusStrip);
+            Controls.Add(TopToolStrip);
+            Margin = new Padding(2, 3, 2, 3);
+            Name = "TestToolEdit";
+            Size = new Size(1044, 599);
+            Load += TestToolEdit_Load;
+            tablePanelParas.ResumeLayout(false);
+            tablePanelParas.PerformLayout();
+            TopToolStrip.ResumeLayout(false);
+            TopToolStrip.PerformLayout();
+            BtmStatusStrip.ResumeLayout(false);
+            BtmStatusStrip.PerformLayout();
+            MainTableLayoutPanel.ResumeLayout(false);
+            parasTabControl.ResumeLayout(false);
+            tabPage1.ResumeLayout(false);
+            tabPage5.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel2.PerformLayout();
+            tabPage2.ResumeLayout(false);
+            tableLayoutResults.ResumeLayout(false);
+            tableLayoutResults.PerformLayout();
+            imgTabControl.ResumeLayout(false);
+            tabPageInputImage.ResumeLayout(false);
+            tabPageRecordImage.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TableLayoutPanel tablePanelParas;
+        private System.Windows.Forms.Panel pnlInputImage;
+        private ToolStrip TopToolStrip;
+        private ToolStripButton btnRun;
+        private StatusStrip BtmStatusStrip;
+        private ToolStripStatusLabel lblResult;
+        private ToolStripStatusLabel lblMsg;
+        private TableLayoutPanel MainTableLayoutPanel;
+        private ToolStripButton btnLoadImage;
+        private TabControl parasTabControl;
+        private TabPage tabPage1;
+        private TabPage tabPage2;
+        private TableLayoutPanel tableLayoutResults;
+        private Label label5;
+        private Label label6;
+        private Label label7;
+        private Label label8;
+        private TextBox stxtOutput;
+        private TextBox dtxtCenterY;
+        private TextBox dtxtAngle;
+        private TextBox dtxtWidth;
+        private TextBox dtxtHeight;
+        private Label label9;
+        private TabPage tabPage5;
+        private TabControl imgTabControl;
+        private TabPage tabPageInputImage;
+        private TabPage tabPageRecordImage;
+        private ToolStripButton btnSaveParas;
+        private ToolStripButton btnLoadParas;
+        private Panel pnlRecordImage;
+        private Label label1;
+        private TextBox stxtInput;
+        private Label label18;
+        private TextBox dtxtCount;
+        private ToolStripStatusLabel lblRunTime;
+        private TableLayoutPanel tableLayoutPanel2;
+        public ComboBox cmbTypeRoi;
+        private Label label21;
+        private Label label22;
+        private ComboBox cmbFixture;
+        private CheckBox ckbDrawRoi;
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.cs b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.cs
new file mode 100644
index 0000000..23027d1
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.cs
@@ -0,0 +1,317 @@
+锘縰sing HalconDotNet;
+using System.Data.Common;
+using LB_VisionProcesses.Alogrithms;
+using System.Windows.Forms;
+using OpenCvSharp;
+using LB_VisionControl;
+
+namespace LB_VisionProcesses.Alogrithms
+{
+    public partial class TestToolEdit : TAlgorithmEdit
+    {
+        public TestToolEdit(TestTool subject = null)
+        {
+            if (subject != null && subject is TestTool)
+                Subject = subject;
+            else
+                Subject = new TestTool();
+
+            this.Dock = DockStyle.Fill;
+            InitializeComponent();
+        }
+
+        /// <summary>
+        /// 鎺т欢鍔犺浇浜嬩欢
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void TestToolEdit_Load(object sender, EventArgs e)
+        {
+            pnlInputImage.Controls.Add(inputImageHSmartWindowControl);
+            inputImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            pnlRecordImage.Controls.Add(recordImageHSmartWindowControl);
+            recordImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            //閬嶅巻鍙互閫夋嫨鐨凴oi绫诲瀷鏋氫妇
+            foreach (var value in Enum.GetValues(typeof(RoiType)))
+                cmbTypeRoi.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨凢ixture鏋氫妇
+            cmbFixture.Items.Add("");
+            foreach (string value in IProcess.dicFixtures.Keys)
+                cmbFixture.Items.Add(value.ToString());
+
+            LoadParas();
+
+            if (Subject.Result)
+            {
+                lblResult.BackColor = Color.Green;
+                lblResult.Text = "True";
+            }
+            else
+            {
+                lblResult.BackColor = Color.Red;
+                lblResult.Text = "False";
+            }
+
+            lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+            lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+            lblRunTime.Text = $"{Subject.RunTime}ms";
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯鍙傛暟(闇�瑕佷慨鏀�)
+        /// </summary>
+        public override void UpdataInputs()
+        {
+            //璁剧疆杩愯鍙傛暟
+            double dResult = 0;
+            int iResult = 0;
+
+            Subject.Params.Inputs["杈撳叆"] = stxtInput.Text;
+
+            if (cmbFixture.Text == "")
+                Subject.Params.Fixture = new Fixture();
+            else if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+
+            base.UpdataInputs();
+        }
+
+        /// <summary>
+        /// 鍔犺浇杩愯鍙傛暟(闇�瑕佷慨鏀�)
+        /// </summary>
+        public override void LoadParas()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                stxtInput.Text = Subject.Params.Inputs["杈撳叆"].ToString();
+
+                if (Subject.InputImage != null && Subject.InputImage is HObject)
+                    inputImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+
+                Type type = Subject.Params.ROI?.GetType();
+                if (Subject.Params.ROI != null)
+                {
+                    switch (type)
+                    {
+                        case Type t when t == typeof(HRectangle2):
+                            cmbTypeRoi.Text = RoiType.Rectangle2.ToString();
+                            break;
+                        case Type t when t == typeof(HCircle):
+                            cmbTypeRoi.Text = RoiType.Circle.ToString();
+                            break;
+                        case Type t when t == typeof(HSegment):
+                            cmbTypeRoi.Text = RoiType.Segment.ToString();
+                            break;
+                        default:
+                            cmbTypeRoi.Text = RoiType.None.ToString();
+                            break;
+                    }
+                    if (cmbTypeRoi.Text.ToString() != "None")
+                        ckbDrawRoi.Checked = true;
+                    else
+                        ckbDrawRoi.Checked = false;
+
+                    inputImageHSmartWindowControl.oRoi = Subject.Params.ROI;
+                }
+
+                if (Subject.Params.Fixture != null)
+                    cmbFixture.Text = Subject.Params.Fixture.strName;
+                else
+                    cmbFixture.Text = "";
+
+                base.LoadParas();
+            }));
+        }
+
+        /// <summary>
+        /// 鏇存柊杈撳嚭缁撴灉(闇�瑕佷慨鏀�)
+        /// </summary>
+        public override void UpdataOutputs()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                //瀛樺湪鍙嶅簭鍒楀寲閿欎贡鐨勬儏鍐甸渶瑕佷娇鐢ㄨ嚜瀹氫箟鐨勮浆鎹㈠櫒
+                stxtOutput.Text = Subject.Params.Outputs["杈撳嚭"]?.ToString();
+
+            }));
+        }
+
+        /// <summary>
+        /// 鐐瑰嚮杩愯
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        public override void btnRun_Click(object sender, EventArgs e)
+        {
+            if (Subject.InputImage != null)
+                InputImage = Subject.InputImage;
+
+            DateTime StartTime = DateTime.Now;
+            Run();
+
+            //鏇存柊鏃ュ織涓庣粨鏋�
+            this.BeginInvoke(new Action(() =>
+            {
+                if (Subject.Result)
+                {
+                    lblResult.BackColor = Color.Green;
+                    lblResult.Text = "True";
+                    recordImageHSmartWindowControl.SetColor("green");
+                }
+                else
+                {
+                    lblResult.BackColor = Color.Red;
+                    lblResult.Text = "False";
+                    recordImageHSmartWindowControl.SetColor("red");
+                }
+
+                lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+                lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+                lblRunTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
+
+                UpdataOutputs();
+                imgTabControl.SelectedTab = tabPageRecordImage;
+
+                if (Subject.OutputImage != null)
+                {
+                    if (Subject.OutputImage is Mat)
+                    {
+                        TAlgorithm.Mat2HObject((Mat)Subject.OutputImage, out HObject image);
+                        recordImageHSmartWindowControl.ShowHoImage(image);
+                    }
+                    else if (Subject.OutputImage is Bitmap)
+                    {
+                        TAlgorithm.Bitmap2HObject((Bitmap)Subject.OutputImage, out HObject image);
+                        recordImageHSmartWindowControl.ShowHoImage(image);
+                    }
+                    else if (Subject.OutputImage is HObject)
+                        recordImageHSmartWindowControl.ShowHoImage((HObject)Subject.OutputImage);
+                }
+
+                //鍏堝垽鏂瓙绫诲啀鍒ゆ柇鐖剁被
+                if (Subject.Record != null && Subject.Record is MsgRecord msgRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_NG, false);
+
+                    for (int i = 0; i < msgRecord.Msg.Length; i++)
+                        recordImageHSmartWindowControl.ShowMsg(msgRecord.Msg[i]
+                            , 1 == msgRecord.Result[i] ? true : false, msgRecord.Column[i], msgRecord.Row[i]);
+                }
+                else if (Subject.Record != null && Subject.Record is ObjectRecord objRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_NG, false);
+                }
+
+                GC.Collect();
+            }));
+        }
+
+        public override void btnLoadImage_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    HOperatorSet.ReadImage(out HObject ho_Image, selectedFiles[0]);
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.CountChannels(ho_Image, out HTuple hv_Channels);
+                        if (hv_Channels.TupleInt() != 1)
+                        {
+                            HOperatorSet.Rgb1ToGray(ho_Image, out ho_Image);
+                            //鏇存柊鏃ュ織涓庣粨鏋�
+                            this.BeginInvoke(new Action(() =>
+                            {
+                                lblMsg.Text = "瀵煎叆鍥剧墖闈炵伆搴﹀浘,鑷姩杞崲涓虹伆搴﹀浘";
+                            }));
+                        }
+                        InputImage = ho_Image;
+                        imgTabControl.SelectedTab = tabPageInputImage;
+                        inputImageHSmartWindowControl.oRoi = inputImageHSmartWindowControl.oRoi;
+                    }
+                }
+            }
+        }
+
+        public override void btnSaveParas_Click(object sender, EventArgs e) { base.btnSaveParas_Click(sender, e); }
+
+        public override void ckbDrawRoi_CheckedChanged(object sender, EventArgs e)
+        {
+            if (ckbDrawRoi.Checked)
+            {
+                inputImageHSmartWindowControl.bAollowDraw = true;
+                imgTabControl.SelectedTab = tabPageInputImage;
+            }
+            else
+            {
+                inputImageHSmartWindowControl.bAollowDraw = false;
+                Subject.Params.ROI = new ROI();
+            }
+        }
+
+        public override void cmbTypeRoi_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (Enum.TryParse(cmbTypeRoi.Text.ToString(), out RoiType type))
+                {
+                    HTuple hv_imageWidth = 0;
+                    HTuple hv_imageHeight = 0;
+                    if (InputImage != null && InputImage is HObject)
+                        HOperatorSet.GetImageSize((HObject)InputImage, out hv_imageWidth, out hv_imageHeight);
+                    switch (type)
+                    {
+                        case RoiType.Rectangle2:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, 0
+                                , hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.Circle:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HCircle(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, hv_imageWidth.TupleReal() / 4);
+                            break;
+                        case RoiType.Segment:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HSegment(0, 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.None:
+                        default:
+                            inputImageHSmartWindowControl.oRoi = null;
+                            break;
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public override void cmbFixture_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+                else
+                    Subject.Params.Fixture = new Fixture();
+            }
+            catch { }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.resx b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.resx
new file mode 100644
index 0000000..1526ea6
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/BaseAlgorithm/TestTool/TestToolEdit.resx
@@ -0,0 +1,129 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema 
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="lblMsgToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="TopToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>156, 17</value>
+  </metadata>
+  <metadata name="BtmStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>287, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobTool.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobTool.cs
new file mode 100644
index 0000000..92cc55c
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobTool.cs
@@ -0,0 +1,361 @@
+锘縰sing HalconDotNet;
+using Newtonsoft.Json;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    [Process("Halcon2D鏂戠偣宸ュ叿", Category = "Halcon2D宸ュ叿", Description = "鍒涘缓鏂戠偣宸ュ叿")]
+    public class HBlobTool : TAlgorithm
+    {
+        public HBlobTool()
+        {
+            strProcessClass = "LB_VisionProcesses.Alogrithms.Halcon.HBlobTool";
+            strProcessName = "Halcon2D鏂戠偣宸ュ叿";
+
+            Params.Inputs.Add("MinThreshold", 0);
+            Params.Inputs.Add("MaxThreshold", 255);
+            Params.Inputs.Add("MinArea", 0);
+            Params.Inputs.Add("MaxArea", 0);
+
+            //鍖哄煙涓績鐨勮鍒楀潗鏍囷紙row銆乧ol锛�
+            Params.Inputs.Add("MinRow", 0.0);
+            Params.Inputs.Add("MaxRow", 0.0);
+            Params.Inputs.Add("MinColumn", 0.0);
+            Params.Inputs.Add("MaxColumn", 0.0);
+
+            //鍦嗗害锛坈ircularity锛�
+            Params.Inputs.Add("MinCircularity", 0.0);
+            Params.Inputs.Add("MaxCircularity", 1.0);
+            //鐭╁舰搴︼紙rectangularity锛�
+            Params.Inputs.Add("MinRectangularity", 0.0);
+            Params.Inputs.Add("MaxRectangularity", 1.0);
+
+            //鍛ㄩ暱锛坈ontlength锛�
+            Params.Inputs.Add("MinContlength", 0.0);
+            Params.Inputs.Add("MaxContlength", 0.0);
+
+            //妞渾闀垮崐杞翠笌鐭崐杞寸殑姣斿�硷紙anisometry锛�
+            Params.Inputs.Add("MinAnisometry", 0.0);
+            Params.Inputs.Add("MaxAnisometry", 0.0);
+
+            //鍖哄煙杈圭晫鍒颁腑蹇冪殑骞冲潎璺濈锛坉ist_mean锛�
+            Params.Inputs.Add("MinDistMean", 0.0);
+            Params.Inputs.Add("MaxDistMean", 0.0);
+
+            //鍖哄煙杈圭晫鍒颁腑蹇冪殑骞冲潎鏂瑰樊锛坉ist_deviation锛�
+            Params.Inputs.Add("MinDistDeviation", 0.0);
+            Params.Inputs.Add("MaxDistDeviation", 0.0);
+
+            Params.Inputs.Add("BlobAfterProcesses", JsonConvert.SerializeObject(new List<BlobAfterProcess>()));
+            Params.Inputs.Add("UnionResult", false);
+            Params.Inputs.Add("MinCount", 0);
+            Params.Inputs.Add("MaxCount", 9999);
+
+            Params.Outputs.Add("CenterX", new List<double>());
+            Params.Outputs.Add("CenterY", new List<double>());
+            Params.Outputs.Add("Phi", new List<double>());
+            Params.Outputs.Add("Width", new List<double>());
+            Params.Outputs.Add("Height", new List<double>());
+            Params.Outputs.Add("Area", new List<double>());
+            Params.Outputs.Add("Count", 0);
+        }
+
+        /// <summary>
+        /// 绠楀瓙閫昏緫
+        /// </summary>
+        public override void TAlgorithmMain()
+        {
+            #region 鍒濆鍖栧彉閲�
+            HObject ho_Regions, ho_ConnectedRegions, ho_SelectedRegions;
+            HOperatorSet.GenEmptyObj(out ho_Regions);
+            HOperatorSet.GenEmptyObj(out ho_ConnectedRegions);
+            #endregion
+
+            try
+            {
+                if (InputImage == null)
+                {
+                    Msg = "杈撳叆鍥剧墖涓虹┖";
+                    Result = false;
+                    return;
+                }
+                if (!(InputImage is HObject))
+                {
+                    Msg = "杈撳叆鍥剧墖鏍煎紡涓嶄负HObject";
+                    Result = false;
+                    return;
+                }
+
+                #region 瑁佸壀鍖哄煙
+                object DomainImage = null;
+                if (!ReduceDomainImage(InputImage, ref DomainImage))
+                {
+                    Msg = "瑁佸壀鍖哄煙澶辫触";
+                    Result = false;
+                    return;
+                }
+                #endregion
+
+                #region 绠楀瓙閫昏緫
+                Record = new ObjectRecord();
+                HObject hoDomainImage = DomainImage as HObject;
+                HTuple hv_Channels = new HTuple();
+                //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    try
+                    {
+                        HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                        if (hv_Channels.TupleInt() != 1)
+                            HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+
+                        //杞崲鍚庡啀娆℃鏌ユ槸鍚︿负鐏板害鍥�
+                        HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                        if (hv_Channels.TupleInt() != 1)
+                        {
+                            HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+                            Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥�";
+                            Result = false;
+                            return;
+                        }
+                    }
+                    catch
+                    {
+                        Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥句笖杞崲澶辫触";
+                        Result = false;
+                        return;
+                    }
+                }
+
+                //闃堝�煎垎鍓�
+                ho_Regions.Dispose();
+                HOperatorSet.Threshold(hoDomainImage, out ho_Regions
+                    , (HTuple)ProcessParams.ConvertToInt32(Params.Inputs["MinThreshold"]), (HTuple)ProcessParams.ConvertToInt32(Params.Inputs["MaxThreshold"]));
+
+                //褰㈡�佸澶勭悊
+                try
+                {
+                    List<BlobAfterProcess> BlobAfterProcesses
+                        = JsonConvert.DeserializeObject<List<BlobAfterProcess>>(Params.Inputs["BlobAfterProcesses"].ToString());
+                    for (int i = 0; i < BlobAfterProcesses.Count; i++)
+                    {
+                        if (!BlobAfterProcesses[i].Enable)
+                            continue;
+
+                        int width = BlobAfterProcesses[i].Width;
+                        int height = BlobAfterProcesses[i].Height;
+                        HOperatorSet.GenRectangle1(out HObject rec, 0, 0, height, width);
+                        HOperatorSet.GenCircle(out HObject cir, 0, 0, width);
+                        switch (BlobAfterProcesses[i].Type)
+                        {
+                            //闂繍绠�(鍏堣啫鑳�鍐嶈厫铓�)
+                            case BlobAfterProcess.ProcessType.Close:
+                                HOperatorSet.Closing(ho_Regions, rec, out ho_Regions);
+                                break;
+                            //寮�杩愮畻(鍏堣厫铓�鍐嶈啫鑳�)
+                            case BlobAfterProcess.ProcessType.Open:
+                                HOperatorSet.Opening(ho_Regions, rec, out ho_Regions);
+                                break;
+                            //鑶ㄨ儉
+                            case BlobAfterProcess.ProcessType.Dilation:
+                                if (BlobAfterProcesses[i].Shape == BlobAfterProcess.ShapeType.Rectangle)
+                                    HOperatorSet.DilationRectangle1(ho_Regions, out ho_Regions, height, width);
+                                else
+                                    HOperatorSet.DilationCircle(ho_Regions, out ho_Regions, width);
+                                break;
+                            //鑵愯殌
+                            case BlobAfterProcess.ProcessType.Erosion:
+                                if (BlobAfterProcesses[i].Shape == BlobAfterProcess.ShapeType.Rectangle)
+                                    HOperatorSet.ErosionRectangle1(ho_Regions, out ho_Regions, height, width);
+                                else
+                                    HOperatorSet.ErosionCircle(ho_Regions, out ho_Regions, width);
+                                break;
+                            //椤跺附
+                            case BlobAfterProcess.ProcessType.TopHat:
+                                break;
+                            //搴曞附
+                            case BlobAfterProcess.ProcessType.BottomHat:
+                                break;
+                        }
+                    }
+                }
+                catch { }
+
+                //鏂紑杩為�氬煙
+                ho_ConnectedRegions.Dispose();
+                HOperatorSet.Connection(ho_Regions, out ho_ConnectedRegions);
+                //缁撴灉绛涢��
+                ho_SelectedRegions = ho_ConnectedRegions.Clone();
+                if (ProcessParams.ConvertToInt32(Params.Inputs["MinArea"]) != ProcessParams.ConvertToInt32(Params.Inputs["MaxArea"]))
+                    HOperatorSet.SelectShape(ho_SelectedRegions, out ho_SelectedRegions, "area", "and"
+                        , (HTuple)ProcessParams.ConvertToInt32(Params.Inputs["MinArea"])
+                        , (HTuple)ProcessParams.ConvertToInt32(Params.Inputs["MaxArea"]));
+
+                if ((double)Params.Inputs["MinRow"] != (double)Params.Inputs["MaxRow"])
+                    HOperatorSet.SelectShape(ho_SelectedRegions, out ho_SelectedRegions, "row", "and"
+                        , (HTuple)(double)Params.Inputs["MinRow"]
+                        , (HTuple)(double)Params.Inputs["MaxRow"]);
+
+                if ((double)Params.Inputs["MinColumn"] != (double)Params.Inputs["MaxColumn"])
+                    HOperatorSet.SelectShape(ho_SelectedRegions, out ho_SelectedRegions, "column", "and"
+                        , (HTuple)(double)Params.Inputs["MinColumn"]
+                        , (HTuple)(double)Params.Inputs["MaxColumn"]);
+
+                //if ((double)Params.Inputs["MinCircularity"] != (double)Params.Inputs["MaxCircularity"])
+                HOperatorSet.SelectShape(ho_SelectedRegions, out ho_SelectedRegions, "circularity", "and"
+                    , (HTuple)(double)Params.Inputs["MinCircularity"]
+                    , (HTuple)(double)Params.Inputs["MaxCircularity"]);
+
+                //if ((double)Params.Inputs["MinRectangularity"] != (double)Params.Inputs["MaxRectangularity"])
+                HOperatorSet.SelectShape(ho_SelectedRegions, out ho_SelectedRegions, "rectangularity", "and"
+                    , (HTuple)(double)Params.Inputs["MinRectangularity"]
+                    , (HTuple)(double)Params.Inputs["MaxRectangularity"]);
+
+                //鍛ㄩ暱锛坈ontlength锛�
+                if ((double)Params.Inputs["MinContlength"] != (double)Params.Inputs["MaxContlength"])
+                    HOperatorSet.SelectShape(ho_SelectedRegions, out ho_SelectedRegions, "contlength", "and"
+                        , (HTuple)(double)Params.Inputs["MinContlength"]
+                        , (HTuple)(double)Params.Inputs["MaxContlength"]);
+
+                //妞渾闀垮崐杞翠笌鐭崐杞寸殑姣斿�硷紙anisometry锛�
+                if ((double)Params.Inputs["MinAnisometry"] != (double)Params.Inputs["MaxAnisometry"])
+                    HOperatorSet.SelectShape(ho_SelectedRegions, out ho_SelectedRegions, "anisometry", "and"
+                        , (HTuple)(double)Params.Inputs["MinAnisometry"]
+                        , (HTuple)(double)Params.Inputs["MaxAnisometry"]);
+
+                //鍖哄煙杈圭晫鍒颁腑蹇冪殑骞冲潎璺濈锛坉ist_mean锛�
+                if ((double)Params.Inputs["MinDistMean"] != (double)Params.Inputs["MaxDistMean"])
+                    HOperatorSet.SelectShape(ho_SelectedRegions, out ho_SelectedRegions, "dist_mean", "and"
+                        , (HTuple)(double)Params.Inputs["MinDistMean"]
+                        , (HTuple)(double)Params.Inputs["MaxDistMean"]);
+
+                //鍖哄煙杈圭晫鍒颁腑蹇冪殑骞冲潎鏂瑰樊锛坉ist_deviation锛�
+                if ((double)Params.Inputs["MinDistDeviation"] != (double)Params.Inputs["MaxDistDeviation"])
+                    HOperatorSet.SelectShape(ho_SelectedRegions, out ho_SelectedRegions, "dist_deviation", "and"
+                        , (HTuple)(double)Params.Inputs["MinDistDeviation"]
+                        , (HTuple)(double)Params.Inputs["MaxDistDeviation"]);
+                #endregion
+
+                #region 缁撴灉澶勭悊
+                //璁℃暟鐢ㄤ簬鍚庣画鍒ゆ柇
+
+                HOperatorSet.CountObj(ho_SelectedRegions, out HTuple ho_SelectedRegionsCount);
+                List<double> CenterX = new List<double>();
+                List<double> CenterY = new List<double>();
+                List<double> Phi = new List<double>();
+                List<double> Width = new List<double>();
+                List<double> Height = new List<double>();
+                List<double> Area = new List<double>();
+                for (int i = 1; i <= ho_SelectedRegionsCount.TupleInt(); i++)
+                {
+                    HOperatorSet.SelectObj(ho_SelectedRegions, out HObject ho_SelectedRegion, (HTuple)i);
+                    // 濉厖涓虹煩褰�
+                    HOperatorSet.SmallestRectangle2(ho_SelectedRegion, out HTuple hv_Row, out HTuple hv_Column, out HTuple hv_Phi, out HTuple hv_Length1, out HTuple hv_Length2);
+                    HOperatorSet.AreaCenter(ho_SelectedRegion, out HTuple hv_area, out _, out _);
+                    if ((double)hv_area.TupleReal() != 0)
+                    {
+                        CenterX.Add(Math.Round((double)hv_Column.TupleReal(), 3));
+                        CenterY.Add(Math.Round((double)hv_Row.TupleReal(), 3));
+                        Phi.Add(Math.Round((double)hv_Phi.TupleReal(), 3));
+                        Width.Add(Math.Round((double)hv_Length1.TupleReal() * 2, 3));
+                        Height.Add(Math.Round((double)hv_Length2.TupleReal() * 2, 3));
+                        Area.Add(Math.Round((double)hv_area.TupleReal(), 3));
+                    }
+                }
+
+                Params.Outputs["CenterX"] = CenterX;
+                Params.Outputs["CenterY"] = CenterY;
+                Params.Outputs["Phi"] = Phi;
+                Params.Outputs["Width"] = Width;
+                Params.Outputs["Height"] = Height;
+                Params.Outputs["Area"] = Area;
+                Params.Outputs["Count"] = CenterX.Count;
+                #endregion
+
+                #region 鐢熸垚OutputImage缁欏悗缁鐞�
+                try
+                {
+                    OutputImage = DomainImage;
+                }
+                catch (Exception ex)
+                {
+                    Msg = "鐢熸垚OutputImage澶辫触,鍘熷洜鏄�:" + ex.ToString();
+                    Result = false;
+                    return;
+                }
+                #endregion
+
+                if (Msg == "杩愯瓒呮椂")
+                {
+                    Result = false;
+                    return;
+                }
+
+                int MinCount = ProcessParams.ConvertToInt32(Params.Inputs["MinCount"]);
+                int MaxCount = ProcessParams.ConvertToInt32(Params.Inputs["MaxCount"]);
+
+                if (CenterX.Count < MinCount || CenterX.Count > MaxCount)
+                {
+                    Msg = string.Format("缁撴灉涓暟瓒呭嚭鑼冨洿({0},{1})", MinCount, MaxCount);
+                    ((ObjectRecord)Record).AddRecord(ho_SelectedRegions, false);
+                    Result = false;
+                    return;
+                }
+
+                Msg = "杩愯鎴愬姛";
+                ((ObjectRecord)Record).AddRecord(ho_SelectedRegions);
+                Result = true;
+                return;
+            }
+            catch (Exception ex)
+            {
+                Msg = "杩愯澶辫触,鍘熷洜鏄�:" + ex.ToString().TrimEnd();
+                OutputImage = null;
+                Result = false;
+                return;
+            }
+            finally
+            {
+                bCompleted = true;
+                #region 鍐呭瓨閲婃斁
+                ho_Regions.Dispose();
+                ho_ConnectedRegions.Dispose();
+                #endregion
+            }
+        }
+    }
+
+    [Serializable]
+    public class BlobAfterProcess
+    {
+        public enum ProcessType { Close, Open, Dilation, Erosion, TopHat, BottomHat }
+
+        public enum ShapeType { Rectangle, Circle }
+
+        [JsonProperty]
+        public int Width { get; set; } = 3;
+
+        [JsonProperty]
+        public int Height { get; set; } = 3;
+
+        [JsonProperty]
+        public bool Enable { get; set; } = true;
+
+        [JsonProperty]
+        public ProcessType Type { get; set; } = ProcessType.Close;
+
+        [JsonProperty]
+        public ShapeType Shape { get; set; } = ShapeType.Rectangle;
+
+        [JsonConstructor]
+        public BlobAfterProcess() { }
+
+        public BlobAfterProcess(ProcessType Type, ShapeType Shape = ShapeType.Rectangle, int Width = 3, int Height = 3, bool Enable = true)
+        {
+            this.Type = Type;
+            this.Shape = Shape;
+            this.Width = Width;
+            this.Height = Height;
+            this.Enable = Enable;
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.Designer.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.Designer.cs
new file mode 100644
index 0000000..80b4288
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.Designer.cs
@@ -0,0 +1,1419 @@
+锘縰sing LB_VisionProcesses.Alogrithms;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    partial class HBlobToolEdit
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tablePanelParas = new TableLayoutPanel();
+            dtxtMaxDistDeviation = new TextBox();
+            dtxtMinDistDeviation = new TextBox();
+            dtxtMaxDistMean = new TextBox();
+            dtxtMinDistMean = new TextBox();
+            dtxtMaxAnisometry = new TextBox();
+            dtxtMinAnisometry = new TextBox();
+            dtxtMaxContlength = new TextBox();
+            label1 = new Label();
+            dtxtMinThreshold = new TextBox();
+            label2 = new Label();
+            dtxtMaxThreshold = new TextBox();
+            label3 = new Label();
+            dtxtMinArea = new TextBox();
+            label4 = new Label();
+            dtxtMaxArea = new TextBox();
+            label10 = new Label();
+            dtxtMinRow = new TextBox();
+            label11 = new Label();
+            dtxtMaxRow = new TextBox();
+            label12 = new Label();
+            dtxtMinColumn = new TextBox();
+            label13 = new Label();
+            dtxtMaxColumn = new TextBox();
+            label19 = new Label();
+            dtxtMinCount = new TextBox();
+            label20 = new Label();
+            dtxtMaxCount = new TextBox();
+            label16 = new Label();
+            label14 = new Label();
+            dtxtMinRectangularity = new TextBox();
+            dtxtMinCircularity = new TextBox();
+            label17 = new Label();
+            dtxtMaxRectangularity = new TextBox();
+            label15 = new Label();
+            dtxtMaxCircularity = new TextBox();
+            label25 = new Label();
+            label26 = new Label();
+            label27 = new Label();
+            label28 = new Label();
+            label29 = new Label();
+            label30 = new Label();
+            label31 = new Label();
+            label32 = new Label();
+            dtxtMinContlength = new TextBox();
+            pnlInputImage = new Panel();
+            TopToolStrip = new ToolStrip();
+            btnRun = new ToolStripButton();
+            btnLoadImage = new ToolStripButton();
+            btnSaveParas = new ToolStripButton();
+            btnLoadParas = new ToolStripButton();
+            BtmStatusStrip = new StatusStrip();
+            lblResult = new ToolStripStatusLabel();
+            lblMsg = new ToolStripStatusLabel();
+            lblRunTime = new ToolStripStatusLabel();
+            parasTabControl = new TabControl();
+            tabPage1 = new TabPage();
+            tabPage5 = new TabPage();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            cmbTypeRoi = new ComboBox();
+            label21 = new Label();
+            label22 = new Label();
+            cmbFixture = new ComboBox();
+            ckbDrawRoi = new CheckBox();
+            ckbListAfter = new CheckedListBox();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            btnAdd = new Button();
+            btnDel = new Button();
+            btnUp = new Button();
+            btnDown = new Button();
+            label24 = new Label();
+            tableLayoutPanel3 = new TableLayoutPanel();
+            cmbProcessType = new ComboBox();
+            cmbShapeType = new ComboBox();
+            lblTips = new Label();
+            tableLayoutPanel4 = new TableLayoutPanel();
+            txtAfterProcessWidth = new NumericUpDown();
+            txtAfterProcessHeight = new NumericUpDown();
+            tabPage2 = new TabPage();
+            tableLayoutResults = new TableLayoutPanel();
+            dtxtHeight = new TextBox();
+            label9 = new Label();
+            label5 = new Label();
+            label6 = new Label();
+            label7 = new Label();
+            label8 = new Label();
+            dtxtCenterX = new TextBox();
+            dtxtCenterY = new TextBox();
+            dtxtPhi = new TextBox();
+            dtxtWidth = new TextBox();
+            label18 = new Label();
+            dtxtCount = new TextBox();
+            label23 = new Label();
+            dtxtArea = new TextBox();
+            imgTabControl = new TabControl();
+            tabPageInputImage = new TabPage();
+            tabPageRecordImage = new TabPage();
+            pnlRecordImage = new Panel();
+            splitContainer1 = new SplitContainer();
+            tablePanelParas.SuspendLayout();
+            TopToolStrip.SuspendLayout();
+            BtmStatusStrip.SuspendLayout();
+            parasTabControl.SuspendLayout();
+            tabPage1.SuspendLayout();
+            tabPage5.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel3.SuspendLayout();
+            tableLayoutPanel4.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)txtAfterProcessWidth).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)txtAfterProcessHeight).BeginInit();
+            tabPage2.SuspendLayout();
+            tableLayoutResults.SuspendLayout();
+            imgTabControl.SuspendLayout();
+            tabPageInputImage.SuspendLayout();
+            tabPageRecordImage.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
+            splitContainer1.Panel1.SuspendLayout();
+            splitContainer1.Panel2.SuspendLayout();
+            splitContainer1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tablePanelParas
+            // 
+            tablePanelParas.ColumnCount = 4;
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.Controls.Add(dtxtMaxDistDeviation, 3, 7);
+            tablePanelParas.Controls.Add(dtxtMinDistDeviation, 1, 7);
+            tablePanelParas.Controls.Add(dtxtMaxDistMean, 3, 6);
+            tablePanelParas.Controls.Add(dtxtMinDistMean, 1, 6);
+            tablePanelParas.Controls.Add(dtxtMaxAnisometry, 3, 5);
+            tablePanelParas.Controls.Add(dtxtMinAnisometry, 1, 5);
+            tablePanelParas.Controls.Add(dtxtMaxContlength, 3, 4);
+            tablePanelParas.Controls.Add(label1, 0, 0);
+            tablePanelParas.Controls.Add(dtxtMinThreshold, 1, 0);
+            tablePanelParas.Controls.Add(label2, 2, 0);
+            tablePanelParas.Controls.Add(dtxtMaxThreshold, 3, 0);
+            tablePanelParas.Controls.Add(label3, 0, 1);
+            tablePanelParas.Controls.Add(dtxtMinArea, 1, 1);
+            tablePanelParas.Controls.Add(label4, 2, 1);
+            tablePanelParas.Controls.Add(dtxtMaxArea, 3, 1);
+            tablePanelParas.Controls.Add(label10, 0, 2);
+            tablePanelParas.Controls.Add(dtxtMinRow, 1, 2);
+            tablePanelParas.Controls.Add(label11, 2, 2);
+            tablePanelParas.Controls.Add(dtxtMaxRow, 3, 2);
+            tablePanelParas.Controls.Add(label12, 0, 3);
+            tablePanelParas.Controls.Add(dtxtMinColumn, 1, 3);
+            tablePanelParas.Controls.Add(label13, 2, 3);
+            tablePanelParas.Controls.Add(dtxtMaxColumn, 3, 3);
+            tablePanelParas.Controls.Add(label19, 0, 11);
+            tablePanelParas.Controls.Add(dtxtMinCount, 1, 11);
+            tablePanelParas.Controls.Add(label20, 2, 11);
+            tablePanelParas.Controls.Add(dtxtMaxCount, 3, 11);
+            tablePanelParas.Controls.Add(label16, 0, 9);
+            tablePanelParas.Controls.Add(label14, 0, 8);
+            tablePanelParas.Controls.Add(dtxtMinRectangularity, 1, 9);
+            tablePanelParas.Controls.Add(dtxtMinCircularity, 1, 8);
+            tablePanelParas.Controls.Add(label17, 2, 9);
+            tablePanelParas.Controls.Add(dtxtMaxRectangularity, 3, 9);
+            tablePanelParas.Controls.Add(label15, 2, 8);
+            tablePanelParas.Controls.Add(dtxtMaxCircularity, 3, 8);
+            tablePanelParas.Controls.Add(label25, 0, 4);
+            tablePanelParas.Controls.Add(label26, 0, 5);
+            tablePanelParas.Controls.Add(label27, 0, 6);
+            tablePanelParas.Controls.Add(label28, 0, 7);
+            tablePanelParas.Controls.Add(label29, 2, 4);
+            tablePanelParas.Controls.Add(label30, 2, 5);
+            tablePanelParas.Controls.Add(label31, 2, 6);
+            tablePanelParas.Controls.Add(label32, 2, 7);
+            tablePanelParas.Controls.Add(dtxtMinContlength, 1, 4);
+            tablePanelParas.Dock = DockStyle.Fill;
+            tablePanelParas.Location = new Point(3, 3);
+            tablePanelParas.Margin = new Padding(2, 3, 2, 3);
+            tablePanelParas.Name = "tablePanelParas";
+            tablePanelParas.RowCount = 12;
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333334F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333334F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333334F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333334F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333334F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333334F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333334F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333334F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.Size = new Size(386, 516);
+            tablePanelParas.TabIndex = 0;
+            // 
+            // dtxtMaxDistDeviation
+            // 
+            dtxtMaxDistDeviation.Location = new Point(286, 297);
+            dtxtMaxDistDeviation.Name = "dtxtMaxDistDeviation";
+            dtxtMaxDistDeviation.Size = new Size(97, 23);
+            dtxtMaxDistDeviation.TabIndex = 36;
+            dtxtMaxDistDeviation.Text = "0";
+            // 
+            // dtxtMinDistDeviation
+            // 
+            dtxtMinDistDeviation.Location = new Point(93, 297);
+            dtxtMinDistDeviation.Name = "dtxtMinDistDeviation";
+            dtxtMinDistDeviation.Size = new Size(97, 23);
+            dtxtMinDistDeviation.TabIndex = 35;
+            dtxtMinDistDeviation.Text = "0";
+            // 
+            // dtxtMaxDistMean
+            // 
+            dtxtMaxDistMean.Location = new Point(286, 255);
+            dtxtMaxDistMean.Name = "dtxtMaxDistMean";
+            dtxtMaxDistMean.Size = new Size(97, 23);
+            dtxtMaxDistMean.TabIndex = 34;
+            dtxtMaxDistMean.Text = "0";
+            // 
+            // dtxtMinDistMean
+            // 
+            dtxtMinDistMean.Location = new Point(93, 255);
+            dtxtMinDistMean.Name = "dtxtMinDistMean";
+            dtxtMinDistMean.Size = new Size(97, 23);
+            dtxtMinDistMean.TabIndex = 33;
+            dtxtMinDistMean.Text = "0";
+            // 
+            // dtxtMaxAnisometry
+            // 
+            dtxtMaxAnisometry.Location = new Point(286, 213);
+            dtxtMaxAnisometry.Name = "dtxtMaxAnisometry";
+            dtxtMaxAnisometry.Size = new Size(97, 23);
+            dtxtMaxAnisometry.TabIndex = 32;
+            dtxtMaxAnisometry.Text = "0";
+            // 
+            // dtxtMinAnisometry
+            // 
+            dtxtMinAnisometry.Location = new Point(93, 213);
+            dtxtMinAnisometry.Name = "dtxtMinAnisometry";
+            dtxtMinAnisometry.Size = new Size(97, 23);
+            dtxtMinAnisometry.TabIndex = 31;
+            dtxtMinAnisometry.Text = "0";
+            // 
+            // dtxtMaxContlength
+            // 
+            dtxtMaxContlength.Location = new Point(286, 171);
+            dtxtMaxContlength.Name = "dtxtMaxContlength";
+            dtxtMaxContlength.Size = new Size(97, 23);
+            dtxtMaxContlength.TabIndex = 30;
+            dtxtMaxContlength.Text = "0";
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Location = new Point(2, 0);
+            label1.Margin = new Padding(2, 0, 2, 0);
+            label1.MaximumSize = new Size(0, 28);
+            label1.MinimumSize = new Size(0, 28);
+            label1.Name = "label1";
+            label1.Size = new Size(68, 28);
+            label1.TabIndex = 0;
+            label1.Text = "鏈�灏忕伆搴﹀��";
+            label1.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinThreshold
+            // 
+            dtxtMinThreshold.Location = new Point(92, 3);
+            dtxtMinThreshold.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinThreshold.Name = "dtxtMinThreshold";
+            dtxtMinThreshold.Size = new Size(99, 23);
+            dtxtMinThreshold.TabIndex = 5;
+            dtxtMinThreshold.Text = "0";
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.Location = new Point(195, 0);
+            label2.Margin = new Padding(2, 0, 2, 0);
+            label2.MaximumSize = new Size(0, 28);
+            label2.MinimumSize = new Size(0, 28);
+            label2.Name = "label2";
+            label2.Size = new Size(68, 28);
+            label2.TabIndex = 1;
+            label2.Text = "鏈�澶х伆搴﹀��";
+            label2.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxThreshold
+            // 
+            dtxtMaxThreshold.Location = new Point(285, 3);
+            dtxtMaxThreshold.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxThreshold.Name = "dtxtMaxThreshold";
+            dtxtMaxThreshold.Size = new Size(98, 23);
+            dtxtMaxThreshold.TabIndex = 6;
+            dtxtMaxThreshold.Text = "255";
+            // 
+            // label3
+            // 
+            label3.AutoSize = true;
+            label3.Location = new Point(2, 42);
+            label3.Margin = new Padding(2, 0, 2, 0);
+            label3.MaximumSize = new Size(0, 28);
+            label3.MinimumSize = new Size(0, 28);
+            label3.Name = "label3";
+            label3.Size = new Size(56, 28);
+            label3.TabIndex = 2;
+            label3.Text = "鏈�灏忛潰绉�";
+            label3.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinArea
+            // 
+            dtxtMinArea.Location = new Point(92, 45);
+            dtxtMinArea.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinArea.Name = "dtxtMinArea";
+            dtxtMinArea.Size = new Size(99, 23);
+            dtxtMinArea.TabIndex = 7;
+            dtxtMinArea.Text = "0";
+            // 
+            // label4
+            // 
+            label4.AutoSize = true;
+            label4.Location = new Point(195, 42);
+            label4.Margin = new Padding(2, 0, 2, 0);
+            label4.MaximumSize = new Size(0, 28);
+            label4.MinimumSize = new Size(0, 28);
+            label4.Name = "label4";
+            label4.Size = new Size(56, 28);
+            label4.TabIndex = 3;
+            label4.Text = "鏈�澶ч潰绉�";
+            label4.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxArea
+            // 
+            dtxtMaxArea.Location = new Point(285, 45);
+            dtxtMaxArea.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxArea.Name = "dtxtMaxArea";
+            dtxtMaxArea.Size = new Size(98, 23);
+            dtxtMaxArea.TabIndex = 8;
+            dtxtMaxArea.Text = "0";
+            // 
+            // label10
+            // 
+            label10.AutoSize = true;
+            label10.Location = new Point(2, 84);
+            label10.Margin = new Padding(2, 0, 2, 0);
+            label10.MaximumSize = new Size(0, 28);
+            label10.MinimumSize = new Size(0, 28);
+            label10.Name = "label10";
+            label10.Size = new Size(75, 28);
+            label10.TabIndex = 9;
+            label10.Text = "鏈�灏忕旱鍧愭爣Y";
+            label10.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinRow
+            // 
+            dtxtMinRow.Location = new Point(92, 87);
+            dtxtMinRow.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinRow.Name = "dtxtMinRow";
+            dtxtMinRow.Size = new Size(99, 23);
+            dtxtMinRow.TabIndex = 9;
+            dtxtMinRow.Text = "0";
+            // 
+            // label11
+            // 
+            label11.AutoSize = true;
+            label11.Location = new Point(195, 84);
+            label11.Margin = new Padding(2, 0, 2, 0);
+            label11.MaximumSize = new Size(0, 28);
+            label11.MinimumSize = new Size(0, 28);
+            label11.Name = "label11";
+            label11.Size = new Size(75, 28);
+            label11.TabIndex = 10;
+            label11.Text = "鏈�澶х旱鍧愭爣Y";
+            label11.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxRow
+            // 
+            dtxtMaxRow.Location = new Point(285, 87);
+            dtxtMaxRow.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxRow.Name = "dtxtMaxRow";
+            dtxtMaxRow.Size = new Size(98, 23);
+            dtxtMaxRow.TabIndex = 9;
+            dtxtMaxRow.Text = "0";
+            // 
+            // label12
+            // 
+            label12.AutoSize = true;
+            label12.Location = new Point(2, 126);
+            label12.Margin = new Padding(2, 0, 2, 0);
+            label12.MaximumSize = new Size(0, 28);
+            label12.MinimumSize = new Size(0, 28);
+            label12.Name = "label12";
+            label12.Size = new Size(76, 28);
+            label12.TabIndex = 11;
+            label12.Text = "鏈�灏忔í鍧愭爣X";
+            label12.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinColumn
+            // 
+            dtxtMinColumn.Location = new Point(92, 129);
+            dtxtMinColumn.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinColumn.Name = "dtxtMinColumn";
+            dtxtMinColumn.Size = new Size(99, 23);
+            dtxtMinColumn.TabIndex = 9;
+            dtxtMinColumn.Text = "0";
+            // 
+            // label13
+            // 
+            label13.AutoSize = true;
+            label13.Location = new Point(195, 126);
+            label13.Margin = new Padding(2, 0, 2, 0);
+            label13.MaximumSize = new Size(0, 28);
+            label13.MinimumSize = new Size(0, 28);
+            label13.Name = "label13";
+            label13.Size = new Size(76, 28);
+            label13.TabIndex = 12;
+            label13.Text = "鏈�澶фí鍧愭爣X";
+            label13.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxColumn
+            // 
+            dtxtMaxColumn.Location = new Point(285, 129);
+            dtxtMaxColumn.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxColumn.Name = "dtxtMaxColumn";
+            dtxtMaxColumn.Size = new Size(98, 23);
+            dtxtMaxColumn.TabIndex = 9;
+            dtxtMaxColumn.Text = "0";
+            // 
+            // label19
+            // 
+            label19.AutoSize = true;
+            label19.Location = new Point(3, 462);
+            label19.Name = "label19";
+            label19.Size = new Size(56, 17);
+            label19.TabIndex = 19;
+            label19.Text = "鏈�灏忔暟閲�";
+            // 
+            // dtxtMinCount
+            // 
+            dtxtMinCount.Location = new Point(93, 465);
+            dtxtMinCount.Name = "dtxtMinCount";
+            dtxtMinCount.Size = new Size(97, 23);
+            dtxtMinCount.TabIndex = 17;
+            dtxtMinCount.Text = "0";
+            // 
+            // label20
+            // 
+            label20.AutoSize = true;
+            label20.Location = new Point(196, 462);
+            label20.Name = "label20";
+            label20.Size = new Size(56, 17);
+            label20.TabIndex = 20;
+            label20.Text = "鏈�澶ф暟閲�";
+            // 
+            // dtxtMaxCount
+            // 
+            dtxtMaxCount.Location = new Point(286, 465);
+            dtxtMaxCount.Name = "dtxtMaxCount";
+            dtxtMaxCount.Size = new Size(97, 23);
+            dtxtMaxCount.TabIndex = 18;
+            dtxtMaxCount.Text = "9999";
+            // 
+            // label16
+            // 
+            label16.AutoSize = true;
+            label16.Location = new Point(2, 378);
+            label16.Margin = new Padding(2, 0, 2, 0);
+            label16.MaximumSize = new Size(0, 28);
+            label16.MinimumSize = new Size(0, 28);
+            label16.Name = "label16";
+            label16.Size = new Size(68, 28);
+            label16.TabIndex = 15;
+            label16.Text = "鏈�灏忕煩褰㈠害";
+            label16.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label14
+            // 
+            label14.AutoSize = true;
+            label14.Location = new Point(2, 336);
+            label14.Margin = new Padding(2, 0, 2, 0);
+            label14.MaximumSize = new Size(0, 28);
+            label14.MinimumSize = new Size(0, 28);
+            label14.Name = "label14";
+            label14.Size = new Size(56, 28);
+            label14.TabIndex = 13;
+            label14.Text = "鏈�灏忓渾搴�";
+            label14.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinRectangularity
+            // 
+            dtxtMinRectangularity.Location = new Point(92, 381);
+            dtxtMinRectangularity.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinRectangularity.Name = "dtxtMinRectangularity";
+            dtxtMinRectangularity.Size = new Size(98, 23);
+            dtxtMinRectangularity.TabIndex = 9;
+            dtxtMinRectangularity.Text = "0";
+            // 
+            // dtxtMinCircularity
+            // 
+            dtxtMinCircularity.Location = new Point(92, 339);
+            dtxtMinCircularity.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinCircularity.Name = "dtxtMinCircularity";
+            dtxtMinCircularity.Size = new Size(98, 23);
+            dtxtMinCircularity.TabIndex = 9;
+            dtxtMinCircularity.Text = "0";
+            // 
+            // label17
+            // 
+            label17.AutoSize = true;
+            label17.Location = new Point(195, 378);
+            label17.Margin = new Padding(2, 0, 2, 0);
+            label17.MaximumSize = new Size(0, 28);
+            label17.MinimumSize = new Size(0, 28);
+            label17.Name = "label17";
+            label17.Size = new Size(68, 28);
+            label17.TabIndex = 16;
+            label17.Text = "鏈�澶х煩褰㈠害";
+            label17.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxRectangularity
+            // 
+            dtxtMaxRectangularity.Location = new Point(285, 381);
+            dtxtMaxRectangularity.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxRectangularity.Name = "dtxtMaxRectangularity";
+            dtxtMaxRectangularity.Size = new Size(98, 23);
+            dtxtMaxRectangularity.TabIndex = 10;
+            dtxtMaxRectangularity.Text = "1";
+            // 
+            // label15
+            // 
+            label15.AutoSize = true;
+            label15.Location = new Point(195, 336);
+            label15.Margin = new Padding(2, 0, 2, 0);
+            label15.MaximumSize = new Size(0, 28);
+            label15.MinimumSize = new Size(0, 28);
+            label15.Name = "label15";
+            label15.Size = new Size(56, 28);
+            label15.TabIndex = 14;
+            label15.Text = "鏈�澶у渾搴�";
+            label15.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxCircularity
+            // 
+            dtxtMaxCircularity.Location = new Point(285, 339);
+            dtxtMaxCircularity.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxCircularity.Name = "dtxtMaxCircularity";
+            dtxtMaxCircularity.Size = new Size(98, 23);
+            dtxtMaxCircularity.TabIndex = 9;
+            dtxtMaxCircularity.Text = "1";
+            // 
+            // label25
+            // 
+            label25.AutoSize = true;
+            label25.Location = new Point(3, 168);
+            label25.Name = "label25";
+            label25.Size = new Size(56, 17);
+            label25.TabIndex = 21;
+            label25.Text = "鏈�灏忓懆闀�";
+            // 
+            // label26
+            // 
+            label26.AutoSize = true;
+            label26.Location = new Point(3, 210);
+            label26.Name = "label26";
+            label26.Size = new Size(68, 17);
+            label26.TabIndex = 22;
+            label26.Text = "鏈�灏忓楂樻瘮";
+            // 
+            // label27
+            // 
+            label27.AutoSize = true;
+            label27.Location = new Point(3, 252);
+            label27.Name = "label27";
+            label27.Size = new Size(80, 17);
+            label27.TabIndex = 23;
+            label27.Text = "杈硅窛鏈�灏忓钩鍧�";
+            // 
+            // label28
+            // 
+            label28.AutoSize = true;
+            label28.Location = new Point(3, 294);
+            label28.Name = "label28";
+            label28.Size = new Size(80, 17);
+            label28.TabIndex = 24;
+            label28.Text = "杈硅窛鏈�灏忔柟宸�";
+            // 
+            // label29
+            // 
+            label29.AutoSize = true;
+            label29.Location = new Point(196, 168);
+            label29.Name = "label29";
+            label29.Size = new Size(56, 17);
+            label29.TabIndex = 25;
+            label29.Text = "鏈�澶у懆闀�";
+            // 
+            // label30
+            // 
+            label30.AutoSize = true;
+            label30.Location = new Point(196, 210);
+            label30.Name = "label30";
+            label30.Size = new Size(68, 17);
+            label30.TabIndex = 26;
+            label30.Text = "鏈�澶у楂樻瘮";
+            // 
+            // label31
+            // 
+            label31.AutoSize = true;
+            label31.Location = new Point(196, 252);
+            label31.Name = "label31";
+            label31.Size = new Size(80, 17);
+            label31.TabIndex = 27;
+            label31.Text = "杈硅窛鏈�澶у钩鍧�";
+            // 
+            // label32
+            // 
+            label32.AutoSize = true;
+            label32.Location = new Point(196, 294);
+            label32.Name = "label32";
+            label32.Size = new Size(80, 17);
+            label32.TabIndex = 28;
+            label32.Text = "杈硅窛鏈�澶ф柟宸�";
+            // 
+            // dtxtMinContlength
+            // 
+            dtxtMinContlength.Location = new Point(93, 171);
+            dtxtMinContlength.Name = "dtxtMinContlength";
+            dtxtMinContlength.Size = new Size(97, 23);
+            dtxtMinContlength.TabIndex = 29;
+            dtxtMinContlength.Text = "0";
+            // 
+            // pnlInputImage
+            // 
+            pnlInputImage.Dock = DockStyle.Fill;
+            pnlInputImage.Location = new Point(3, 3);
+            pnlInputImage.Margin = new Padding(4);
+            pnlInputImage.Name = "pnlInputImage";
+            pnlInputImage.Size = new Size(626, 516);
+            pnlInputImage.TabIndex = 44;
+            // 
+            // TopToolStrip
+            // 
+            TopToolStrip.Items.AddRange(new ToolStripItem[] { btnRun, btnLoadImage, btnSaveParas, btnLoadParas });
+            TopToolStrip.Location = new Point(0, 0);
+            TopToolStrip.Name = "TopToolStrip";
+            TopToolStrip.Size = new Size(1044, 25);
+            TopToolStrip.TabIndex = 45;
+            TopToolStrip.Text = "toolStrip1";
+            // 
+            // btnRun
+            // 
+            btnRun.BackgroundImageLayout = ImageLayout.Zoom;
+            btnRun.ImageTransparentColor = Color.Magenta;
+            btnRun.Name = "btnRun";
+            btnRun.Size = new Size(36, 22);
+            btnRun.Text = "杩愯";
+            btnRun.Click += btnRun_Click;
+            // 
+            // btnLoadImage
+            // 
+            btnLoadImage.ImageTransparentColor = Color.Magenta;
+            btnLoadImage.Name = "btnLoadImage";
+            btnLoadImage.Size = new Size(36, 22);
+            btnLoadImage.Text = "瀵煎浘";
+            btnLoadImage.Click += btnLoadImage_Click;
+            // 
+            // btnSaveParas
+            // 
+            btnSaveParas.ImageTransparentColor = Color.Magenta;
+            btnSaveParas.Name = "btnSaveParas";
+            btnSaveParas.Size = new Size(36, 22);
+            btnSaveParas.Text = "淇濆瓨";
+            btnSaveParas.Click += btnSaveParas_Click;
+            // 
+            // btnLoadParas
+            // 
+            btnLoadParas.ImageTransparentColor = Color.Magenta;
+            btnLoadParas.Name = "btnLoadParas";
+            btnLoadParas.Size = new Size(36, 22);
+            btnLoadParas.Text = "鍔犺浇";
+            btnLoadParas.Click += btnLoadParas_Click;
+            // 
+            // BtmStatusStrip
+            // 
+            BtmStatusStrip.Items.AddRange(new ToolStripItem[] { lblResult, lblMsg, lblRunTime });
+            BtmStatusStrip.Location = new Point(0, 577);
+            BtmStatusStrip.Name = "BtmStatusStrip";
+            BtmStatusStrip.Size = new Size(1044, 22);
+            BtmStatusStrip.TabIndex = 46;
+            BtmStatusStrip.Text = "statusStrip1";
+            // 
+            // lblResult
+            // 
+            lblResult.Name = "lblResult";
+            lblResult.Size = new Size(34, 17);
+            lblResult.Text = "True";
+            // 
+            // lblMsg
+            // 
+            lblMsg.Name = "lblMsg";
+            lblMsg.Size = new Size(56, 17);
+            lblMsg.Text = "杩愯鎴愬姛";
+            // 
+            // lblRunTime
+            // 
+            lblRunTime.Name = "lblRunTime";
+            lblRunTime.Size = new Size(32, 17);
+            lblRunTime.Text = "0ms";
+            // 
+            // parasTabControl
+            // 
+            parasTabControl.Controls.Add(tabPage1);
+            parasTabControl.Controls.Add(tabPage5);
+            parasTabControl.Controls.Add(tabPage2);
+            parasTabControl.Dock = DockStyle.Fill;
+            parasTabControl.Location = new Point(0, 0);
+            parasTabControl.Name = "parasTabControl";
+            parasTabControl.SelectedIndex = 0;
+            parasTabControl.Size = new Size(400, 552);
+            parasTabControl.TabIndex = 48;
+            // 
+            // tabPage1
+            // 
+            tabPage1.Controls.Add(tablePanelParas);
+            tabPage1.Location = new Point(4, 26);
+            tabPage1.Name = "tabPage1";
+            tabPage1.Padding = new Padding(3);
+            tabPage1.Size = new Size(392, 522);
+            tabPage1.TabIndex = 0;
+            tabPage1.Text = "杈撳叆鍙傛暟";
+            tabPage1.UseVisualStyleBackColor = true;
+            // 
+            // tabPage5
+            // 
+            tabPage5.Controls.Add(tableLayoutPanel2);
+            tabPage5.Location = new Point(4, 26);
+            tabPage5.Name = "tabPage5";
+            tabPage5.Size = new Size(392, 522);
+            tabPage5.TabIndex = 2;
+            tabPage5.Text = "杩愯鍙傛暟";
+            tabPage5.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 4;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 60F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 150F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 40F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(cmbTypeRoi, 1, 0);
+            tableLayoutPanel2.Controls.Add(label21, 0, 0);
+            tableLayoutPanel2.Controls.Add(label22, 0, 1);
+            tableLayoutPanel2.Controls.Add(cmbFixture, 1, 1);
+            tableLayoutPanel2.Controls.Add(ckbDrawRoi, 2, 0);
+            tableLayoutPanel2.Controls.Add(ckbListAfter, 1, 2);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel1, 2, 2);
+            tableLayoutPanel2.Controls.Add(label24, 0, 2);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel3, 3, 2);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(0, 0);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 3;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(392, 522);
+            tableLayoutPanel2.TabIndex = 4;
+            // 
+            // cmbTypeRoi
+            // 
+            cmbTypeRoi.Dock = DockStyle.Fill;
+            cmbTypeRoi.FormattingEnabled = true;
+            cmbTypeRoi.Location = new Point(63, 3);
+            cmbTypeRoi.Name = "cmbTypeRoi";
+            cmbTypeRoi.Size = new Size(144, 25);
+            cmbTypeRoi.TabIndex = 1;
+            cmbTypeRoi.SelectedIndexChanged += cmbTypeRoi_SelectedIndexChanged;
+            // 
+            // label21
+            // 
+            label21.AutoSize = true;
+            label21.Dock = DockStyle.Fill;
+            label21.Location = new Point(3, 0);
+            label21.Name = "label21";
+            label21.Size = new Size(54, 30);
+            label21.TabIndex = 3;
+            label21.Text = "ROI";
+            label21.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label22
+            // 
+            label22.AutoSize = true;
+            label22.Dock = DockStyle.Fill;
+            label22.Location = new Point(3, 30);
+            label22.Name = "label22";
+            label22.Size = new Size(54, 30);
+            label22.TabIndex = 4;
+            label22.Text = "Fixture";
+            label22.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbFixture
+            // 
+            cmbFixture.Dock = DockStyle.Fill;
+            cmbFixture.FormattingEnabled = true;
+            cmbFixture.Location = new Point(63, 33);
+            cmbFixture.Name = "cmbFixture";
+            cmbFixture.Size = new Size(144, 25);
+            cmbFixture.TabIndex = 5;
+            cmbFixture.SelectedIndexChanged += cmbFixture_SelectedIndexChanged;
+            // 
+            // ckbDrawRoi
+            // 
+            ckbDrawRoi.AutoSize = true;
+            ckbDrawRoi.CheckAlign = ContentAlignment.MiddleCenter;
+            ckbDrawRoi.Location = new Point(213, 3);
+            ckbDrawRoi.Name = "ckbDrawRoi";
+            ckbDrawRoi.Size = new Size(15, 14);
+            ckbDrawRoi.TabIndex = 2;
+            ckbDrawRoi.UseVisualStyleBackColor = true;
+            ckbDrawRoi.CheckedChanged += ckbDrawRoi_CheckedChanged;
+            // 
+            // ckbListAfter
+            // 
+            ckbListAfter.Dock = DockStyle.Fill;
+            ckbListAfter.FormattingEnabled = true;
+            ckbListAfter.Location = new Point(63, 63);
+            ckbListAfter.Name = "ckbListAfter";
+            ckbListAfter.Size = new Size(144, 456);
+            ckbListAfter.TabIndex = 6;
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(btnAdd, 0, 0);
+            tableLayoutPanel1.Controls.Add(btnDel, 0, 1);
+            tableLayoutPanel1.Controls.Add(btnUp, 0, 2);
+            tableLayoutPanel1.Controls.Add(btnDown, 0, 3);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(213, 63);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 5;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Size = new Size(34, 456);
+            tableLayoutPanel1.TabIndex = 7;
+            // 
+            // btnAdd
+            // 
+            btnAdd.Dock = DockStyle.Fill;
+            btnAdd.Location = new Point(3, 3);
+            btnAdd.Name = "btnAdd";
+            btnAdd.Size = new Size(28, 24);
+            btnAdd.TabIndex = 0;
+            btnAdd.Text = "+";
+            btnAdd.UseVisualStyleBackColor = true;
+            // 
+            // btnDel
+            // 
+            btnDel.Dock = DockStyle.Fill;
+            btnDel.Location = new Point(3, 33);
+            btnDel.Name = "btnDel";
+            btnDel.Size = new Size(28, 24);
+            btnDel.TabIndex = 1;
+            btnDel.Text = "-";
+            btnDel.UseVisualStyleBackColor = true;
+            // 
+            // btnUp
+            // 
+            btnUp.Dock = DockStyle.Fill;
+            btnUp.Location = new Point(3, 63);
+            btnUp.Name = "btnUp";
+            btnUp.Size = new Size(28, 24);
+            btnUp.TabIndex = 2;
+            btnUp.Text = "鈫�";
+            btnUp.UseVisualStyleBackColor = true;
+            // 
+            // btnDown
+            // 
+            btnDown.Dock = DockStyle.Fill;
+            btnDown.Location = new Point(3, 93);
+            btnDown.Name = "btnDown";
+            btnDown.Size = new Size(28, 24);
+            btnDown.TabIndex = 3;
+            btnDown.Text = "鈫�";
+            btnDown.UseVisualStyleBackColor = true;
+            // 
+            // label24
+            // 
+            label24.AutoSize = true;
+            label24.Dock = DockStyle.Fill;
+            label24.Location = new Point(3, 60);
+            label24.Name = "label24";
+            label24.Size = new Size(54, 462);
+            label24.TabIndex = 8;
+            label24.Text = "褰㈡�佸";
+            label24.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // tableLayoutPanel3
+            // 
+            tableLayoutPanel3.ColumnCount = 1;
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 60F));
+            tableLayoutPanel3.Controls.Add(cmbProcessType, 0, 1);
+            tableLayoutPanel3.Controls.Add(cmbShapeType, 0, 2);
+            tableLayoutPanel3.Controls.Add(lblTips, 0, 3);
+            tableLayoutPanel3.Controls.Add(tableLayoutPanel4, 0, 0);
+            tableLayoutPanel3.Dock = DockStyle.Fill;
+            tableLayoutPanel3.Location = new Point(253, 63);
+            tableLayoutPanel3.Name = "tableLayoutPanel3";
+            tableLayoutPanel3.RowCount = 4;
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 35F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Size = new Size(136, 456);
+            tableLayoutPanel3.TabIndex = 9;
+            // 
+            // cmbProcessType
+            // 
+            cmbProcessType.Dock = DockStyle.Fill;
+            cmbProcessType.FormattingEnabled = true;
+            cmbProcessType.Location = new Point(3, 38);
+            cmbProcessType.Name = "cmbProcessType";
+            cmbProcessType.Size = new Size(130, 25);
+            cmbProcessType.TabIndex = 3;
+            // 
+            // cmbShapeType
+            // 
+            cmbShapeType.Dock = DockStyle.Fill;
+            cmbShapeType.FormattingEnabled = true;
+            cmbShapeType.Location = new Point(3, 68);
+            cmbShapeType.Name = "cmbShapeType";
+            cmbShapeType.Size = new Size(130, 25);
+            cmbShapeType.TabIndex = 5;
+            // 
+            // lblTips
+            // 
+            lblTips.AutoSize = true;
+            lblTips.Location = new Point(3, 95);
+            lblTips.Name = "lblTips";
+            lblTips.Size = new Size(32, 17);
+            lblTips.TabIndex = 6;
+            lblTips.Text = "鎻愮ず";
+            // 
+            // tableLayoutPanel4
+            // 
+            tableLayoutPanel4.ColumnCount = 2;
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tableLayoutPanel4.Controls.Add(txtAfterProcessWidth, 0, 0);
+            tableLayoutPanel4.Controls.Add(txtAfterProcessHeight, 1, 0);
+            tableLayoutPanel4.Location = new Point(3, 3);
+            tableLayoutPanel4.Name = "tableLayoutPanel4";
+            tableLayoutPanel4.RowCount = 1;
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+            tableLayoutPanel4.Size = new Size(130, 29);
+            tableLayoutPanel4.TabIndex = 7;
+            // 
+            // txtAfterProcessWidth
+            // 
+            txtAfterProcessWidth.Dock = DockStyle.Fill;
+            txtAfterProcessWidth.Location = new Point(3, 3);
+            txtAfterProcessWidth.Name = "txtAfterProcessWidth";
+            txtAfterProcessWidth.Size = new Size(59, 23);
+            txtAfterProcessWidth.TabIndex = 4;
+            txtAfterProcessWidth.Value = new decimal(new int[] { 3, 0, 0, 0 });
+            // 
+            // txtAfterProcessHeight
+            // 
+            txtAfterProcessHeight.Dock = DockStyle.Fill;
+            txtAfterProcessHeight.Location = new Point(68, 3);
+            txtAfterProcessHeight.Name = "txtAfterProcessHeight";
+            txtAfterProcessHeight.Size = new Size(59, 23);
+            txtAfterProcessHeight.TabIndex = 5;
+            txtAfterProcessHeight.Value = new decimal(new int[] { 3, 0, 0, 0 });
+            // 
+            // tabPage2
+            // 
+            tabPage2.Controls.Add(tableLayoutResults);
+            tabPage2.Location = new Point(4, 26);
+            tabPage2.Name = "tabPage2";
+            tabPage2.Padding = new Padding(3);
+            tabPage2.Size = new Size(392, 522);
+            tabPage2.TabIndex = 1;
+            tabPage2.Text = "杈撳嚭缁撴灉";
+            tabPage2.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutResults
+            // 
+            tableLayoutResults.ColumnCount = 2;
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutResults.Controls.Add(dtxtHeight, 1, 4);
+            tableLayoutResults.Controls.Add(label9, 0, 4);
+            tableLayoutResults.Controls.Add(label5, 0, 0);
+            tableLayoutResults.Controls.Add(label6, 0, 1);
+            tableLayoutResults.Controls.Add(label7, 0, 2);
+            tableLayoutResults.Controls.Add(label8, 0, 3);
+            tableLayoutResults.Controls.Add(dtxtCenterX, 1, 0);
+            tableLayoutResults.Controls.Add(dtxtCenterY, 1, 1);
+            tableLayoutResults.Controls.Add(dtxtPhi, 1, 2);
+            tableLayoutResults.Controls.Add(dtxtWidth, 1, 3);
+            tableLayoutResults.Controls.Add(label18, 0, 6);
+            tableLayoutResults.Controls.Add(dtxtCount, 1, 6);
+            tableLayoutResults.Controls.Add(label23, 0, 5);
+            tableLayoutResults.Controls.Add(dtxtArea, 1, 5);
+            tableLayoutResults.Dock = DockStyle.Fill;
+            tableLayoutResults.Location = new Point(3, 3);
+            tableLayoutResults.Margin = new Padding(2, 3, 2, 3);
+            tableLayoutResults.Name = "tableLayoutResults";
+            tableLayoutResults.RowCount = 10;
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.Size = new Size(386, 516);
+            tableLayoutResults.TabIndex = 1;
+            // 
+            // dtxtHeight
+            // 
+            dtxtHeight.Dock = DockStyle.Fill;
+            dtxtHeight.Location = new Point(102, 207);
+            dtxtHeight.Margin = new Padding(2, 3, 2, 3);
+            dtxtHeight.Name = "dtxtHeight";
+            dtxtHeight.ReadOnly = true;
+            dtxtHeight.Size = new Size(282, 23);
+            dtxtHeight.TabIndex = 9;
+            // 
+            // label9
+            // 
+            label9.AutoSize = true;
+            label9.Dock = DockStyle.Fill;
+            label9.Location = new Point(2, 204);
+            label9.Margin = new Padding(2, 0, 2, 0);
+            label9.MaximumSize = new Size(0, 28);
+            label9.MinimumSize = new Size(0, 28);
+            label9.Name = "label9";
+            label9.Size = new Size(96, 28);
+            label9.TabIndex = 3;
+            label9.Text = "楂樺害";
+            label9.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Dock = DockStyle.Fill;
+            label5.Location = new Point(2, 0);
+            label5.Margin = new Padding(2, 0, 2, 0);
+            label5.MaximumSize = new Size(0, 28);
+            label5.MinimumSize = new Size(0, 28);
+            label5.Name = "label5";
+            label5.Size = new Size(96, 28);
+            label5.TabIndex = 0;
+            label5.Text = "X";
+            label5.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label6
+            // 
+            label6.AutoSize = true;
+            label6.Dock = DockStyle.Fill;
+            label6.Location = new Point(2, 51);
+            label6.Margin = new Padding(2, 0, 2, 0);
+            label6.MaximumSize = new Size(0, 28);
+            label6.MinimumSize = new Size(0, 28);
+            label6.Name = "label6";
+            label6.Size = new Size(96, 28);
+            label6.TabIndex = 1;
+            label6.Text = "Y";
+            label6.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label7
+            // 
+            label7.AutoSize = true;
+            label7.Dock = DockStyle.Fill;
+            label7.Location = new Point(2, 102);
+            label7.Margin = new Padding(2, 0, 2, 0);
+            label7.MaximumSize = new Size(0, 28);
+            label7.MinimumSize = new Size(0, 28);
+            label7.Name = "label7";
+            label7.Size = new Size(96, 28);
+            label7.TabIndex = 2;
+            label7.Text = "寮у害(rad)";
+            label7.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label8
+            // 
+            label8.AutoSize = true;
+            label8.Dock = DockStyle.Fill;
+            label8.Location = new Point(2, 153);
+            label8.Margin = new Padding(2, 0, 2, 0);
+            label8.MaximumSize = new Size(0, 28);
+            label8.MinimumSize = new Size(0, 28);
+            label8.Name = "label8";
+            label8.Size = new Size(96, 28);
+            label8.TabIndex = 3;
+            label8.Text = "瀹藉害";
+            label8.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCenterX
+            // 
+            dtxtCenterX.Dock = DockStyle.Fill;
+            dtxtCenterX.Location = new Point(102, 3);
+            dtxtCenterX.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterX.Name = "dtxtCenterX";
+            dtxtCenterX.ReadOnly = true;
+            dtxtCenterX.Size = new Size(282, 23);
+            dtxtCenterX.TabIndex = 5;
+            // 
+            // dtxtCenterY
+            // 
+            dtxtCenterY.Dock = DockStyle.Fill;
+            dtxtCenterY.Location = new Point(102, 54);
+            dtxtCenterY.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterY.Name = "dtxtCenterY";
+            dtxtCenterY.ReadOnly = true;
+            dtxtCenterY.Size = new Size(282, 23);
+            dtxtCenterY.TabIndex = 6;
+            // 
+            // dtxtPhi
+            // 
+            dtxtPhi.Dock = DockStyle.Fill;
+            dtxtPhi.Location = new Point(102, 105);
+            dtxtPhi.Margin = new Padding(2, 3, 2, 3);
+            dtxtPhi.Name = "dtxtPhi";
+            dtxtPhi.ReadOnly = true;
+            dtxtPhi.Size = new Size(282, 23);
+            dtxtPhi.TabIndex = 7;
+            // 
+            // dtxtWidth
+            // 
+            dtxtWidth.Dock = DockStyle.Fill;
+            dtxtWidth.Location = new Point(102, 156);
+            dtxtWidth.Margin = new Padding(2, 3, 2, 3);
+            dtxtWidth.Name = "dtxtWidth";
+            dtxtWidth.ReadOnly = true;
+            dtxtWidth.Size = new Size(282, 23);
+            dtxtWidth.TabIndex = 8;
+            // 
+            // label18
+            // 
+            label18.AutoSize = true;
+            label18.Dock = DockStyle.Fill;
+            label18.Location = new Point(3, 306);
+            label18.Name = "label18";
+            label18.Size = new Size(94, 51);
+            label18.TabIndex = 10;
+            label18.Text = "鏁伴噺";
+            label18.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCount
+            // 
+            dtxtCount.Dock = DockStyle.Fill;
+            dtxtCount.Location = new Point(103, 309);
+            dtxtCount.Name = "dtxtCount";
+            dtxtCount.ReadOnly = true;
+            dtxtCount.Size = new Size(280, 23);
+            dtxtCount.TabIndex = 11;
+            // 
+            // label23
+            // 
+            label23.AutoSize = true;
+            label23.Dock = DockStyle.Fill;
+            label23.Location = new Point(3, 255);
+            label23.Name = "label23";
+            label23.Size = new Size(94, 51);
+            label23.TabIndex = 12;
+            label23.Text = "闈㈢Н";
+            label23.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtArea
+            // 
+            dtxtArea.Dock = DockStyle.Fill;
+            dtxtArea.Location = new Point(103, 258);
+            dtxtArea.Name = "dtxtArea";
+            dtxtArea.ReadOnly = true;
+            dtxtArea.Size = new Size(280, 23);
+            dtxtArea.TabIndex = 13;
+            // 
+            // imgTabControl
+            // 
+            imgTabControl.Controls.Add(tabPageInputImage);
+            imgTabControl.Controls.Add(tabPageRecordImage);
+            imgTabControl.Dock = DockStyle.Fill;
+            imgTabControl.Location = new Point(0, 0);
+            imgTabControl.Name = "imgTabControl";
+            imgTabControl.SelectedIndex = 0;
+            imgTabControl.Size = new Size(640, 552);
+            imgTabControl.TabIndex = 49;
+            // 
+            // tabPageInputImage
+            // 
+            tabPageInputImage.Controls.Add(pnlInputImage);
+            tabPageInputImage.Location = new Point(4, 26);
+            tabPageInputImage.Name = "tabPageInputImage";
+            tabPageInputImage.Padding = new Padding(3);
+            tabPageInputImage.Size = new Size(632, 522);
+            tabPageInputImage.TabIndex = 0;
+            tabPageInputImage.Text = "杈撳叆鍥惧儚";
+            tabPageInputImage.UseVisualStyleBackColor = true;
+            // 
+            // tabPageRecordImage
+            // 
+            tabPageRecordImage.Controls.Add(pnlRecordImage);
+            tabPageRecordImage.Location = new Point(4, 26);
+            tabPageRecordImage.Name = "tabPageRecordImage";
+            tabPageRecordImage.Padding = new Padding(3);
+            tabPageRecordImage.Size = new Size(632, 522);
+            tabPageRecordImage.TabIndex = 1;
+            tabPageRecordImage.Text = "缁撴灉鍥惧儚";
+            tabPageRecordImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlRecordImage
+            // 
+            pnlRecordImage.Dock = DockStyle.Fill;
+            pnlRecordImage.Location = new Point(3, 3);
+            pnlRecordImage.Margin = new Padding(4);
+            pnlRecordImage.Name = "pnlRecordImage";
+            pnlRecordImage.Size = new Size(626, 516);
+            pnlRecordImage.TabIndex = 45;
+            // 
+            // splitContainer1
+            // 
+            splitContainer1.Dock = DockStyle.Fill;
+            splitContainer1.Location = new Point(0, 25);
+            splitContainer1.Name = "splitContainer1";
+            // 
+            // splitContainer1.Panel1
+            // 
+            splitContainer1.Panel1.Controls.Add(parasTabControl);
+            // 
+            // splitContainer1.Panel2
+            // 
+            splitContainer1.Panel2.Controls.Add(imgTabControl);
+            splitContainer1.Size = new Size(1044, 552);
+            splitContainer1.SplitterDistance = 400;
+            splitContainer1.TabIndex = 48;
+            // 
+            // HBlobToolEdit
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(splitContainer1);
+            Controls.Add(BtmStatusStrip);
+            Controls.Add(TopToolStrip);
+            Margin = new Padding(2, 3, 2, 3);
+            Name = "HBlobToolEdit";
+            Size = new Size(1044, 599);
+            Load += HBlobToolEdit_Load;
+            tablePanelParas.ResumeLayout(false);
+            tablePanelParas.PerformLayout();
+            TopToolStrip.ResumeLayout(false);
+            TopToolStrip.PerformLayout();
+            BtmStatusStrip.ResumeLayout(false);
+            BtmStatusStrip.PerformLayout();
+            parasTabControl.ResumeLayout(false);
+            tabPage1.ResumeLayout(false);
+            tabPage5.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel2.PerformLayout();
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel3.ResumeLayout(false);
+            tableLayoutPanel3.PerformLayout();
+            tableLayoutPanel4.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)txtAfterProcessWidth).EndInit();
+            ((System.ComponentModel.ISupportInitialize)txtAfterProcessHeight).EndInit();
+            tabPage2.ResumeLayout(false);
+            tableLayoutResults.ResumeLayout(false);
+            tableLayoutResults.PerformLayout();
+            imgTabControl.ResumeLayout(false);
+            tabPageInputImage.ResumeLayout(false);
+            tabPageRecordImage.ResumeLayout(false);
+            splitContainer1.Panel1.ResumeLayout(false);
+            splitContainer1.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit();
+            splitContainer1.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TableLayoutPanel tablePanelParas;
+        private System.Windows.Forms.Panel pnlInputImage;
+        private ToolStrip TopToolStrip;
+        private ToolStripButton btnRun;
+        private StatusStrip BtmStatusStrip;
+        private ToolStripStatusLabel lblResult;
+        private ToolStripStatusLabel lblMsg;
+        private ToolStripButton btnLoadImage;
+        private TabControl parasTabControl;
+        private TabPage tabPage1;
+        private TabPage tabPage2;
+        private TableLayoutPanel tableLayoutResults;
+        private Label label5;
+        private Label label6;
+        private Label label7;
+        private Label label8;
+        private TextBox dtxtCenterX;
+        private TextBox dtxtCenterY;
+        private TextBox dtxtPhi;
+        private TextBox dtxtWidth;
+        private TextBox dtxtHeight;
+        private Label label9;
+        private TabPage tabPage5;
+        private TabControl imgTabControl;
+        private TabPage tabPageInputImage;
+        private TabPage tabPageRecordImage;
+        private ToolStripButton btnSaveParas;
+        private ToolStripButton btnLoadParas;
+        private Panel pnlRecordImage;
+        private Label label1;
+        private TextBox dtxtMinThreshold;
+        private Label label2;
+        private TextBox dtxtMaxThreshold;
+        private Label label3;
+        private TextBox dtxtMinArea;
+        private Label label4;
+        private TextBox dtxtMaxArea;
+        private Label label10;
+        private TextBox dtxtMinRow;
+        private Label label11;
+        private TextBox dtxtMaxRow;
+        private Label label12;
+        private TextBox dtxtMinColumn;
+        private Label label13;
+        private TextBox dtxtMaxColumn;
+        private Label label14;
+        private TextBox dtxtMinCircularity;
+        private Label label15;
+        private TextBox dtxtMaxCircularity;
+        private Label label16;
+        private TextBox dtxtMinRectangularity;
+        private Label label17;
+        private TextBox dtxtMaxRectangularity;
+        private Label label18;
+        private TextBox dtxtCount;
+        private TextBox dtxtMinCount;
+        private TextBox dtxtMaxCount;
+        private Label label19;
+        private Label label20;
+        private ToolStripStatusLabel lblRunTime;
+        private TableLayoutPanel tableLayoutPanel2;
+        public ComboBox cmbTypeRoi;
+        private Label label21;
+        private Label label22;
+        private ComboBox cmbFixture;
+        private CheckBox ckbDrawRoi;
+        private Label label23;
+        private TextBox dtxtArea;
+        private CheckedListBox ckbListAfter;
+        private TableLayoutPanel tableLayoutPanel1;
+        private Button btnAdd;
+        private Button btnDel;
+        private Button btnUp;
+        private Button btnDown;
+        private Label label24;
+        private TableLayoutPanel tableLayoutPanel3;
+        private ComboBox cmbProcessType;
+        private NumericUpDown txtAfterProcessWidth;
+        private ComboBox cmbShapeType;
+        private Label label25;
+        private Label label26;
+        private Label label27;
+        private Label label28;
+        private Label label29;
+        private Label label30;
+        private Label label31;
+        private Label label32;
+        private TextBox dtxtMaxDistDeviation;
+        private TextBox dtxtMinDistDeviation;
+        private TextBox dtxtMaxDistMean;
+        private TextBox dtxtMinDistMean;
+        private TextBox dtxtMaxAnisometry;
+        private TextBox dtxtMinAnisometry;
+        private TextBox dtxtMaxContlength;
+        private TextBox dtxtMinContlength;
+        private Label lblTips;
+        private SplitContainer splitContainer1;
+        private TableLayoutPanel tableLayoutPanel4;
+        private NumericUpDown txtAfterProcessHeight;
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.cs
new file mode 100644
index 0000000..066ab08
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.cs
@@ -0,0 +1,445 @@
+锘縰sing HalconDotNet;
+using System.Data.Common;
+using LB_VisionProcesses.Alogrithms;
+using System.Windows.Forms;
+using Newtonsoft.Json;
+using static LB_VisionProcesses.Alogrithms.Halcon.BlobAfterProcess;
+using LB_VisionControl;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    public partial class HBlobToolEdit : TAlgorithmEdit
+    {
+        public HBlobToolEdit(HBlobTool subject = null)
+        {
+            if (subject != null && subject is HBlobTool)
+                Subject = subject;
+            else
+                Subject = new HBlobTool();
+
+            this.Dock = DockStyle.Fill;
+            InitializeComponent();
+
+            // 閬嶅巻鍙互閫夋嫨鐨勭被鍨嬫灇涓�
+            foreach (var value in Enum.GetValues(typeof(ProcessType)))
+                cmbProcessType.Items.Add(value.ToString());
+            cmbProcessType.Text = ProcessType.Close.ToString();
+
+            // 閬嶅巻鍙互閫夋嫨鐨勭被鍨嬫灇涓�
+            foreach (var value in Enum.GetValues(typeof(ShapeType)))
+                cmbShapeType.Items.Add(value.ToString());
+            cmbShapeType.Text = ShapeType.Rectangle.ToString();
+
+            cmbShapeType.SelectedIndexChanged += (sender, e) =>
+            {
+                if (cmbShapeType.SelectedItem.ToString() == ShapeType.Circle.ToString())
+                    txtAfterProcessHeight.Enabled = false;
+                else
+                    txtAfterProcessHeight.Enabled = true;
+            };
+
+            btnAdd.Click += (sender, e) =>
+            {
+                if (txtAfterProcessWidth.Value > 0 && txtAfterProcessHeight.Value > 0
+                    && Enum.TryParse(cmbProcessType.Text, out ProcessType type)
+                    && Enum.TryParse(cmbShapeType.Text, out ShapeType shape))
+                {
+                    if (shape == ShapeType.Circle)
+                        ckbListAfter.Items.Add($"{type}_{shape}_{txtAfterProcessWidth.Value}*{txtAfterProcessWidth.Value}", true);
+                    else
+                        ckbListAfter.Items.Add($"{type}_{shape}_{txtAfterProcessWidth.Value}*{txtAfterProcessHeight.Value}", true);
+                }
+            };
+
+            btnDel.Click += (sender, e) =>
+            {
+                ckbListAfter.Items.RemoveAt(ckbListAfter.Items.Count - 1);
+            };
+
+            lblTips.Text = "闂繍绠�(鍏堣啫鑳�鍐嶈厫铓�) Close 濉厖瀛旀礊銆佸~琛ヤ笉瑙勫垯缂洪櫡" +
+                "\n寮�杩愮畻(鍏堣厫铓�鍐嶈啫鑳�) Open 鍘婚櫎鍣0銆佸幓闄ょ粏灏忔潅璐ㄣ�佷紭鍖栧舰鐘�" +
+                "\n鑶ㄨ儉 Dilation 鎵╁ぇ鍖哄煙銆佽缂濆~琛ャ�佺洰鏍囧尯鍩熸墿灞�" +
+                "\n鑵愯殌 Erosion 娑堥櫎鍣0銆佺洰鏍囧垎绂汇�佸舰鎬佽竟鐣岀缉灏�";
+        }
+
+        /// <summary>
+        /// 鎺т欢鍔犺浇浜嬩欢
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void HBlobToolEdit_Load(object sender, EventArgs e)
+        {
+            pnlInputImage.Controls.Add(inputImageHSmartWindowControl);
+            inputImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            pnlRecordImage.Controls.Add(recordImageHSmartWindowControl);
+            recordImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            //閬嶅巻鍙互閫夋嫨鐨凴oi绫诲瀷鏋氫妇
+            foreach (var value in Enum.GetValues(typeof(RoiType)))
+                cmbTypeRoi.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨凢ixture鏋氫妇
+            cmbFixture.Items.Add("");
+            foreach (string value in IProcess.dicFixtures.Keys)
+                cmbFixture.Items.Add(value.ToString());
+
+            cmbTypeRoi.Text = RoiType.None.ToString();
+            LoadParas();
+
+            if (Subject.Result)
+            {
+                lblResult.BackColor = Color.Green;
+                lblResult.Text = "True";
+            }
+            else
+            {
+                lblResult.BackColor = Color.Red;
+                lblResult.Text = "False";
+            }
+
+            lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+            lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+            lblRunTime.Text = $"{Subject.RunTime}ms";
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯鍙傛暟
+        /// </summary>
+        public override void UpdataInputs()
+        {
+            //璁剧疆杩愯鍙傛暟
+            double dResult = 0;
+            int iResult = 0;
+
+            Subject.Params.Inputs["MinThreshold"] = int.TryParse(dtxtMinThreshold.Text, out iResult) ? iResult : Subject.Params.Inputs["MinThreshold"];
+            Subject.Params.Inputs["MaxThreshold"] = int.TryParse(dtxtMaxThreshold.Text, out iResult) ? iResult : Subject.Params.Inputs["MaxThreshold"];
+
+            Subject.Params.Inputs["MinArea"] = double.TryParse(dtxtMinArea.Text, out dResult) ? dResult : Subject.Params.Inputs["MinArea"];
+            Subject.Params.Inputs["MaxArea"] = double.TryParse(dtxtMaxArea.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxArea"];
+
+            Subject.Params.Inputs["MinRow"] = double.TryParse(dtxtMinRow.Text, out dResult) ? dResult : Subject.Params.Inputs["MinRow"];
+            Subject.Params.Inputs["MaxRow"] = double.TryParse(dtxtMaxRow.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxRow"];
+
+            Subject.Params.Inputs["MinColumn"] = double.TryParse(dtxtMinColumn.Text, out dResult) ? dResult : Subject.Params.Inputs["MinColumn"];
+            Subject.Params.Inputs["MaxColumn"] = double.TryParse(dtxtMaxColumn.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxColumn"];
+
+            Subject.Params.Inputs["MinCircularity"] = double.TryParse(dtxtMinCircularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MinCircularity"];
+            Subject.Params.Inputs["MaxCircularity"] = double.TryParse(dtxtMaxCircularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxCircularity"];
+
+            Subject.Params.Inputs["MinRectangularity"] = double.TryParse(dtxtMinRectangularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MinRectangularity"];
+            Subject.Params.Inputs["MaxRectangularity"] = double.TryParse(dtxtMaxRectangularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxRectangularity"];
+
+            Subject.Params.Inputs["MinCount"] = int.TryParse(dtxtMinCount.Text, out iResult) ? iResult : Subject.Params.Inputs["MinCount"];
+            Subject.Params.Inputs["MaxCount"] = int.TryParse(dtxtMaxCount.Text, out iResult) ? iResult : Subject.Params.Inputs["MaxCount"];
+
+            Subject.Params.Inputs["MinContlength"] = double.TryParse(dtxtMinContlength.Text, out dResult) ? dResult : Subject.Params.Inputs["MinContlength"];
+            Subject.Params.Inputs["MaxContlength"] = double.TryParse(dtxtMaxContlength.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxContlength"];
+
+            Subject.Params.Inputs["MinAnisometry"] = double.TryParse(dtxtMinAnisometry.Text, out dResult) ? dResult : Subject.Params.Inputs["MinAnisometry"];
+            Subject.Params.Inputs["MaxAnisometry"] = double.TryParse(dtxtMaxAnisometry.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxAnisometry"];
+
+            Subject.Params.Inputs["MinDistMean"] = double.TryParse(dtxtMinDistMean.Text, out dResult) ? dResult : Subject.Params.Inputs["MinDistMean"];
+            Subject.Params.Inputs["MaxDistMean"] = double.TryParse(dtxtMaxDistMean.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxDistMean"];
+
+            Subject.Params.Inputs["MinDistDeviation"] = double.TryParse(dtxtMinDistDeviation.Text, out dResult) ? dResult : Subject.Params.Inputs["MinDistDeviation"];
+            Subject.Params.Inputs["MaxDistDeviation"] = double.TryParse(dtxtMaxDistDeviation.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxDistDeviation"];
+
+            try
+            {
+                List<BlobAfterProcess> BlobAfterProcesses = new List<BlobAfterProcess>();
+                for (int i = 0; i < ckbListAfter.Items.Count; i++)
+                {
+                    string[] arrStr = ckbListAfter.Items[i].ToString().Split('_');
+                    if (arrStr.Length >= 3
+                        && Enum.TryParse(arrStr[0], out ProcessType type)
+                        && Enum.TryParse(arrStr[1], out ShapeType shape))
+                    {
+                        string[] arrSize = arrStr[2].ToString().Split('*');
+                        BlobAfterProcesses.Add(new BlobAfterProcess(
+                            type, shape, Convert.ToInt32(arrSize[0]), Convert.ToInt32(arrSize[1]), ckbListAfter.GetItemChecked(i)));
+                    }
+
+                }
+                Subject.Params.Inputs["BlobAfterProcesses"] = JsonConvert.SerializeObject(BlobAfterProcesses);
+            }
+            catch { }
+
+            if (cmbFixture.Text == "")
+                Subject.Params.Fixture = new Fixture();
+            else if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+
+            base.UpdataInputs();
+        }
+
+        /// <summary>
+        /// 鍔犺浇杩愯鍙傛暟
+        /// </summary>
+        public override void LoadParas()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                dtxtMinThreshold.Text = Subject.Params.Inputs["MinThreshold"]?.ToString();
+                dtxtMaxThreshold.Text = Subject.Params.Inputs["MaxThreshold"]?.ToString();
+                dtxtMinArea.Text = Subject.Params.Inputs["MinArea"]?.ToString();
+                dtxtMaxArea.Text = Subject.Params.Inputs["MaxArea"]?.ToString();
+                dtxtMinRow.Text = Subject.Params.Inputs["MinRow"]?.ToString();
+                dtxtMaxRow.Text = Subject.Params.Inputs["MaxRow"]?.ToString();
+                dtxtMinColumn.Text = Subject.Params.Inputs["MinColumn"]?.ToString();
+                dtxtMaxColumn.Text = Subject.Params.Inputs["MaxColumn"]?.ToString();
+                dtxtMinCircularity.Text = Subject.Params.Inputs["MinCircularity"]?.ToString();
+                dtxtMaxCircularity.Text = Subject.Params.Inputs["MaxCircularity"]?.ToString();
+                dtxtMinRectangularity.Text = Subject.Params.Inputs["MinRectangularity"]?.ToString();
+                dtxtMaxRectangularity.Text = Subject.Params.Inputs["MaxRectangularity"]?.ToString();
+
+                dtxtMinContlength.Text = Subject.Params.Inputs["MinContlength"]?.ToString();
+                dtxtMaxContlength.Text = Subject.Params.Inputs["MaxContlength"]?.ToString();
+
+                dtxtMinAnisometry.Text = Subject.Params.Inputs["MinAnisometry"]?.ToString();
+                dtxtMaxAnisometry.Text = Subject.Params.Inputs["MaxAnisometry"]?.ToString();
+
+                dtxtMinDistMean.Text = Subject.Params.Inputs["MinDistMean"]?.ToString();
+                dtxtMaxDistMean.Text = Subject.Params.Inputs["MaxDistMean"]?.ToString();
+
+                dtxtMinDistDeviation.Text = Subject.Params.Inputs["MinDistDeviation"]?.ToString();
+                dtxtMaxDistDeviation.Text = Subject.Params.Inputs["MaxDistDeviation"]?.ToString();
+
+                dtxtMinCount.Text = Subject.Params.Inputs["MinCount"]?.ToString();
+                dtxtMaxCount.Text = Subject.Params.Inputs["MaxCount"]?.ToString();
+
+                try
+                {
+                    List<BlobAfterProcess> BlobAfterProcesses = JsonConvert.DeserializeObject<List<BlobAfterProcess>>(Subject.Params.Inputs["BlobAfterProcesses"].ToString());
+                    foreach (var BlobAfterProcess in BlobAfterProcesses)
+                        ckbListAfter.Items.Add($"{BlobAfterProcess.Type}_{BlobAfterProcess.Shape}_{BlobAfterProcess.Width}*{BlobAfterProcess.Height}", BlobAfterProcess.Enable);
+                }
+                catch { }
+
+                if (Subject.InputImage != null && Subject.InputImage is HObject)
+                    inputImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+
+                Type type = Subject.Params.ROI?.GetType();
+                if (Subject.Params.ROI != null)
+                {
+                    switch (type)
+                    {
+                        case Type t when t == typeof(HRectangle2):
+                            cmbTypeRoi.Text = RoiType.Rectangle2.ToString();
+                            break;
+                        case Type t when t == typeof(HCircle):
+                            cmbTypeRoi.Text = RoiType.Circle.ToString();
+                            break;
+                        case Type t when t == typeof(HSegment):
+                            cmbTypeRoi.Text = RoiType.Segment.ToString();
+                            break;
+                        default:
+                            cmbTypeRoi.Text = RoiType.None.ToString();
+                            break;
+                    }
+                    if (cmbTypeRoi.Text.ToString() != "None")
+                        ckbDrawRoi.Checked = true;
+                    else
+                        ckbDrawRoi.Checked = false;
+
+                    inputImageHSmartWindowControl.oRoi = Subject.Params.ROI;
+                }
+
+                if (Subject.Params.Fixture != null)
+                    cmbFixture.Text = Subject.Params.Fixture.strName;
+                else
+                    cmbFixture.Text = "";
+
+                base.LoadParas();
+            }));
+        }
+
+        /// <summary>
+        /// 鏇存柊杈撳嚭缁撴灉
+        /// </summary>
+        public override void UpdataOutputs()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                //瀛樺湪鍙嶅簭鍒楀寲閿欎贡鐨勬儏鍐甸渶瑕佷娇鐢ㄨ嚜瀹氫箟鐨勮浆鎹㈠櫒
+                dtxtCenterX.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterX"]);
+                dtxtCenterY.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterY"]);
+                dtxtPhi.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Phi"]);
+                dtxtWidth.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Width"]);
+                dtxtHeight.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Height"]);
+                dtxtArea.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Area"]);
+                dtxtCount.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Count"]);
+            }));
+        }
+
+        /// <summary>
+        /// 鐐瑰嚮杩愯
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        public override void btnRun_Click(object sender, EventArgs e)
+        {
+            if (Subject.InputImage != null)
+                InputImage = Subject.InputImage;
+
+            DateTime StartTime = DateTime.Now;
+            Run();
+
+            //鏇存柊鏃ュ織涓庣粨鏋�
+            this.BeginInvoke(new Action(() =>
+            {
+                if (Subject.Result)
+                {
+                    lblResult.BackColor = Color.Green;
+                    lblResult.Text = "True";
+                    recordImageHSmartWindowControl.SetColor("green");
+                }
+                else
+                {
+                    lblResult.BackColor = Color.Red;
+                    lblResult.Text = "False";
+                    recordImageHSmartWindowControl.SetColor("red");
+                }
+
+                lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+                lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+                lblRunTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
+
+                UpdataOutputs();
+                imgTabControl.SelectedTab = tabPageRecordImage;
+
+                if (Subject.InputImage != null && Subject.InputImage is HObject)
+                {
+                    HOperatorSet.GetImageSize((HObject)Subject.InputImage, out HTuple ho_ImageWidth, out HTuple ho_ImageHeight);
+                    recordImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+                }
+
+                //鍏堝垽鏂瓙绫诲啀鍒ゆ柇鐖剁被
+                if (Subject.Record != null && Subject.Record is MsgRecord msgRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_NG, false);
+
+                    for (int i = 0; i < msgRecord.Msg.Length; i++)
+                        recordImageHSmartWindowControl.ShowMsg(msgRecord.Msg[i]
+                            , 1 == msgRecord.Result[i] ? true : false, msgRecord.Column[i], msgRecord.Row[i]);
+                }
+                else if (Subject.Record != null && Subject.Record is ObjectRecord objRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_NG, false);
+                }
+
+                GC.Collect();
+            }));
+        }
+
+        public override void btnLoadImage_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    HOperatorSet.ReadImage(out HObject ho_Image, selectedFiles[0]);
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.CountChannels(ho_Image, out HTuple hv_Channels);
+                        if (hv_Channels.TupleInt() != 1)
+                        {
+                            HOperatorSet.Rgb1ToGray(ho_Image, out ho_Image);
+                            //鏇存柊鏃ュ織涓庣粨鏋�
+                            this.BeginInvoke(new Action(() =>
+                            {
+                                lblMsg.Text = "瀵煎叆鍥剧墖闈炵伆搴﹀浘,鑷姩杞崲涓虹伆搴﹀浘";
+                            }));
+                        }
+                        InputImage = ho_Image;
+                        imgTabControl.SelectedTab = tabPageInputImage;
+                        inputImageHSmartWindowControl.oRoi = inputImageHSmartWindowControl.oRoi;
+                    }
+                }
+            }
+        }
+
+        public override void btnSaveParas_Click(object sender, EventArgs e) { base.btnSaveParas_Click(sender, e); }
+
+        public override void ckbDrawRoi_CheckedChanged(object sender, EventArgs e)
+        {
+            if (ckbDrawRoi.Checked)
+            {
+                inputImageHSmartWindowControl.bAollowDraw = true;
+                imgTabControl.SelectedTab = tabPageInputImage;
+            }
+            else
+            {
+                inputImageHSmartWindowControl.bAollowDraw = false;
+                Subject.Params.ROI = new ROI();
+            }
+        }
+
+        public override void cmbTypeRoi_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (Enum.TryParse(cmbTypeRoi.Text.ToString(), out RoiType type))
+                {
+                    HTuple hv_imageWidth = 0;
+                    HTuple hv_imageHeight = 0;
+                    if (InputImage != null && InputImage is HObject)
+                        HOperatorSet.GetImageSize((HObject)InputImage, out hv_imageWidth, out hv_imageHeight);
+                    switch (type)
+                    {
+                        case RoiType.Rectangle2:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, 0
+                                , hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.Circle:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HCircle(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, hv_imageWidth.TupleReal() / 4);
+                            break;
+                        //case RoiType.Ellipse:
+                        //    inputImageHSmartWindowControl.oRoi
+                        //        = new HEllipse(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2,0, hv_imageHeight.TupleReal() / 4, hv_imageWidth.TupleReal() / 4);
+                        //    break;
+                        //case RoiType.Segment:
+                        //    inputImageHSmartWindowControl.oRoi
+                        //        = new HSegment(0, 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                        //    break;
+                        case RoiType.None:
+                        default:
+                            inputImageHSmartWindowControl.oRoi = null;
+                            break;
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public override void cmbFixture_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+                else
+                    Subject.Params.Fixture = new Fixture();
+            }
+            catch { }
+        }
+
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.resx b/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.resx
new file mode 100644
index 0000000..0960d33
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HBlobTool/HBlobToolEdit.resx
@@ -0,0 +1,129 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="lblMsgToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="TopToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>156, 17</value>
+  </metadata>
+  <metadata name="BtmStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>287, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HCalibTool/BaseCalib.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HCalibTool/BaseCalib.cs
new file mode 100644
index 0000000..a4b22ed
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HCalibTool/BaseCalib.cs
@@ -0,0 +1,272 @@
+锘縰sing HalconDotNet;
+using LB_VisionControl;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.Intrinsics.X86;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    public class BaseCalib
+    {
+        #region 鏍囧畾鏉�
+        // Procedures 
+        // Chapter: Calibration / Camera Parameters
+        // Short Description: Generate a camera parameter tuple for an area scan camera with distortions modeled by the division model. 
+        /// <summary>
+        /// 闈㈤樀鐩告満鍐呭弬鐢熸垚
+        /// </summary>
+        /// <param name="hv_Focus"></param>
+        /// <param name="hv_Kappa"></param>
+        /// <param name="hv_Sx"></param>
+        /// <param name="hv_Sy"></param>
+        /// <param name="hv_Cx"></param>
+        /// <param name="hv_Cy"></param>
+        /// <param name="hv_ImageWidth"></param>
+        /// <param name="hv_ImageHeight"></param>
+        /// <param name="hv_CameraParam"></param>
+        public static void gen_cam_par_area_scan_division(HTuple hv_Focus, HTuple hv_Kappa, HTuple hv_Sx,
+            HTuple hv_Sy, HTuple hv_Cx, HTuple hv_Cy, HTuple hv_ImageWidth, HTuple hv_ImageHeight,
+            out HTuple hv_CameraParam)
+        {
+            // Local iconic variables 
+            // Initialize local and output iconic variables 
+            hv_CameraParam = new HTuple();
+            //Generate a camera parameter tuple for an area scan camera
+            //with distortions modeled by the division model.
+            //
+            hv_CameraParam.Dispose();
+            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+            {
+                hv_CameraParam = new HTuple();
+                hv_CameraParam[0] = "area_scan_division";
+                hv_CameraParam = hv_CameraParam.TupleConcat(hv_Focus, hv_Kappa, hv_Sx, hv_Sy, hv_Cx, hv_Cy, hv_ImageWidth, hv_ImageHeight);
+            }
+            return;
+        }
+
+        /// <summary>
+        /// 鐢熸垚妫嬬洏鏍兼爣瀹氭澘鏂囦欢
+        /// </summary>
+        /// <param name="dirPath"></param>
+        /// <param name="size"></param>
+        /// <param name="count"></param>
+        public static void CreateCaltab(string dirPath = @"C://", int XNum = 7, int YNum = 7
+            , double MarkDist = 1.25, double DiameterRatio = 0.5)
+        {
+            try
+            {
+                //XNum锛氭瘡琛岄粦鑹叉爣蹇楀渾鐐圭殑鏁伴噺銆�
+                //YNum锛氭瘡琛岄粦鑹叉爣蹇楀渾鐐圭殑鏁伴噺銆�
+                //MarkDist锛氫袱涓氨杩戦粦鑹插渾鐐逛腑蹇冧箣闂寸殑璺濈銆�
+                //DiameterRstio锛氶粦鑹插渾鐐瑰崐寰勪笌鍦嗙偣涓績璺濈鐨勬瘮鍊笺��
+                //CalPlateDescr锛氭爣瀹氭澘鎻忚堪鏂囦欢鐨勬枃浠惰矾寰勶紙.descr鏂囦欢涓烘爣瀹氭澘鎻忚堪鏂囦欢锛夈��
+                //CalPlatePSFile锛氭爣瀹氭澘鍥惧儚鏂囦欢鐨勬枃浠惰矾寰勶紙.ps鏂囦欢涓烘爣瀹氭澘鍥惧舰鏂囦欢,鍙埄鐢≒S绫昏蒋浠舵墦寮�锛夈��
+
+                string CalPlateDescr = dirPath + $"Caltab_{XNum}*{YNum}_{DiameterRatio}.descr";
+                string CalPlatePSFile = dirPath + $"Caltab_{XNum}*{YNum}_{DiameterRatio}.ps";
+                HOperatorSet.GenCaltab(XNum, YNum, MarkDist / 1000.0, DiameterRatio, CalPlateDescr, CalPlatePSFile);
+            }
+            catch { }
+        }
+
+        public static void CaltabCalib(HTuple hv_CameraParam, List<HObject> lst_Images
+            , out HTuple CameraInner, out HTuple CameraPose, out HTuple CameraInner_Adaptive
+            , out HObject Map, out HObject CircleXld
+            , string CalPlateDescr = "C:/Caltab.descr"
+            , string CameraInnerPath = "C:/CameraInner_Adaptive.tup", string CameraPosePath = "C:/CameraPose.tup")
+        {
+            CameraInner = null; CameraPose = null; CameraInner_Adaptive = null; Map = null; CircleXld = null;
+            try
+            {
+                //1.鑾峰彇鐩告満鍙傛暟
+                //using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                //{
+                //    hv_CameraParam.Dispose();
+                //    gen_cam_par_area_scan_division(0.008, 0, 5.2e-06, 5.2e-06, 3072 / 2, 2048 / 2, 3072,
+                //        2048, out hv_CameraParam);
+                //}
+
+                //2.鍒涘缓鏍囧畾瀵硅薄
+                HOperatorSet.CreateCalibData("calibration_object", 1, 1, out HTuple hv_CalibDataID);
+
+                //3.鍦ㄦ爣瀹氬璞′腑璁剧疆鐩告満鍙傛暟
+                HOperatorSet.SetCalibDataCamParam(hv_CalibDataID, 0, new HTuple(), hv_CameraParam);
+
+                //4.鍦ㄦ爣瀹氬璞′腑璁剧疆鏍囧畾鏉挎弿杩版枃浠�
+                HOperatorSet.SetCalibDataCalibObject(hv_CalibDataID, 0, CalPlateDescr);
+
+                //5.鍔犺浇鏍囧畾鍥惧儚锛岃繘琛屾爣瀹�
+
+                //- 鏍囧畾鏉夸笉瑕佽繃鏇濓紝涓嶈鍑虹幇255鐨勭伆搴﹀��
+                //- 鍏夌収瑕佸潎鍖�
+                //- 鏍囧畾鏉跨壒寰佺偣鐨勫姣斿害瑕侀珮锛岄粦鐧藉尯鍩熺伆搴﹀�煎樊100浠ヤ笂
+                //- 鏍囧畾鏉垮湪鍥惧儚涓嚦灏戝崰1 / 4闈㈢Н
+                //- 鐗瑰緛鐐瑰簲璇ュ鐒︽竻鏅�
+                //- 鎵�鏈夌壒寰佺偣搴旇鍏ㄩ儴钀藉湪鍥惧儚鑼冨洿鍐�
+                //- 鏍囧畾鍥惧儚鑷冲皯10骞�
+                //- 鏍囧畾鏉垮簲璇ヨ鐩栨暣涓閲庣殑鍚勪釜瑙掕惤
+                //- 鏍囧畾鏉胯搴﹀彉鍖栬鏄庢樉
+                //- 鍥惧儚澶у皬瑕佷竴鑷�
+
+                int Index = 0;
+                if (lst_Images == null || lst_Images.Count == 0)
+                    throw new Exception();
+
+                // 鏍囧畾鍥剧墖蹇呴』涓洪粦鐧�
+                try
+                {
+                    for (int i = 0; i <= lst_Images.Count; i++)
+                    {
+                        var ho_Image = lst_Images[i];
+                        HOperatorSet.CountChannels(ho_Image, out HTuple hv_Channels);
+
+                        if (hv_Channels.TupleInt() != 1)
+                            HOperatorSet.Rgb1ToGray(ho_Image, out ho_Image);
+                        lst_Images[i] = ho_Image;
+                    }
+                }
+                catch { }
+
+                foreach (var ho_Image in lst_Images)
+                {
+                    //鏍囧畾鍥惧儚
+                    HOperatorSet.FindCalibObject(ho_Image, hv_CalibDataID, 0, 0, Index, new HTuple(),
+                        new HTuple());
+                    //鑾峰彇杞粨
+                    HOperatorSet.GetCalibDataObservContours(out HObject ho_Contours, hv_CalibDataID, "marks", 0, 0, Index);
+                    //鑾峰彇鍦嗗績鐐瑰拰浣嶅Э
+                    HOperatorSet.GetCalibDataObservPoints(hv_CalibDataID, 0, 0, Index
+                        , out HTuple hv_Row, out HTuple hv_Column, out HTuple _, out HTuple _);
+
+                    HOperatorSet.GenCrossContourXld(out CircleXld, hv_Row, hv_Column, 10, 0.785398);
+                }
+
+                //6.鏍囧畾
+                HOperatorSet.CalibrateCameras(hv_CalibDataID, out HTuple hv_Error);
+                //7.鑾峰彇鐩告満鍐呭弬
+                HOperatorSet.GetCalibData(hv_CalibDataID, "camera", 0, "params", out CameraInner);
+                //8.鑾峰彇鐩告満澶栧弬
+                HOperatorSet.GetCalibData(hv_CalibDataID, "calib_obj_pose", (new HTuple(0)).TupleConcat(
+                    0), "pose", out HTuple hv_Pose);
+                HOperatorSet.SetOriginPose(hv_Pose, 0, 0, 0.002, out CameraPose);
+
+                //9.鑾峰彇鐣稿彉鍙傛暟
+                //鎻忚堪锛氭牴鎹寚瀹氱殑寰勫悜鐣稿彉绯绘暟锛屾眰鍙栫悊鎯虫棤鐣稿彉鐨勭浉鏈哄唴鍙傘��
+                //鍙傛暟锛�
+                //Mode锛氱暩鍙樻ā寮�
+                //CamParamIn锛氱暩鍙樼殑鐩告満鍐呴儴鍙傛暟
+                //DistortionCoeffs 锛氱暩鍙樼郴鏁板��
+                //CamParamOut锛氬凡鏍℃鐨勭浉鏈哄唴鍙�
+                HOperatorSet.ChangeRadialDistortionCamPar("adaptive", CameraInner, 0, out CameraInner_Adaptive);
+
+                //10.淇濆瓨鐩告満鍙傛暟
+                //鐩告満鍐呭弬
+                HOperatorSet.WriteTuple(CameraInner_Adaptive, CameraInnerPath);
+                //鐩告満澶栧弬
+                HOperatorSet.WriteTuple(CameraPose, CameraPosePath);
+
+                //11.鐢熸垚鐣稿彉鐭Map
+                //鎻忚堪锛氭牴鎹寚瀹氬浘鍍忓拰鎸囧畾鐩稿姞鍙傛暟鏉ョ煫姝h緭鍏ュ浘鍍忕殑鐣稿彉銆俢hange_radial_distortion_image鏍规嵁鎽勫儚鏈哄唴閮ㄥ弬鏁癈amParamIn鍜孋amParamOut瀵硅緭鍏ュ浘鍍忓浘鍍忕殑寰勫悜鐣稿彉杩涜鏀瑰彉銆備娇鐢–amParamOut灏嗕綅浜庡尯鍩熷尯鍩熷唴鐨勮緭鍑哄浘鍍忕殑姣忎釜鍍忕礌杞崲涓哄浘鍍忓钩闈紝鐒跺悗浣跨敤CamParamIn灏嗗叾鎶曞奖涓哄浘鍍忕殑浜氬儚绱犮�傞�氳繃鍙岀嚎鎬ф彃鍊肩‘瀹氬緱鍒扮殑鐏板害鍊笺�傚鏋滆浜氬儚绱犲湪鍥惧儚涔嬪锛屽垯灏嗗浘鍍忛噸寤轰腑鐨勫搴斿儚绱犺缃负鈥滈粦鑹测�濆苟浠庡浘鍍忓煙涓秷闄ゃ��
+                //鍙傛暟锛�
+                //Image锛氳緭鍏ュ浘鍍�
+                //Region 锛氱煫姝e浘鍍忕殑鍖哄煙
+                //ImageRectified 锛氱煫姝e浘鍍�
+                //CamParamIn锛氳緭鍏ョ浉鏈哄弬鏁�
+                //CamParamOut 锛氳緭鍑虹浉鏈哄弬鏁�
+                HOperatorSet.GenRadialDistortionMap(out Map, CameraInner, CameraInner_Adaptive, "bilinear");
+            }
+            catch { CameraInner = null; CameraPose = null; CameraInner_Adaptive = null; Map = null; CircleXld = null; }
+        }
+
+        public static void ApplyCaltabCalib(HObject Image, HObject Map, out HObject MappedImage)
+        {
+            try
+            {
+                HOperatorSet.MapImage(Image, Map, out MappedImage);
+            }
+            catch { MappedImage = null; }
+        }
+
+        public static void ApplyCaltabCalibByPoint(HPoint imagePoint, out HPoint worldPoint, HTuple hv_CaltabCalibParams, HTuple hv_PoseCalibParams)
+        {
+            worldPoint = new HPoint(imagePoint);
+            try
+            {
+                HOperatorSet.ImagePointsToWorldPlane(hv_CaltabCalibParams, hv_PoseCalibParams
+                    , imagePoint.Row, imagePoint.Column, "mm", out HTuple Row, out HTuple Column);
+
+                worldPoint.Row = Row.D;
+                worldPoint.Column = Column.D;
+            }
+            catch { }
+        }
+        #endregion
+
+        #region 妫嬬洏鏍�
+        /// <summary>
+        /// 鐢熸垚妫嬬洏鏍兼爣瀹氭澘鏂囦欢
+        /// </summary>
+        /// <param name="dirPath"></param>
+        /// <param name="size"></param>
+        /// <param name="count"></param>
+        public static void CreateCheckerBoard(string dirPath = "C:\\", int size = 17, int count = 17)
+        {
+            try
+            {
+                string saveFullPath = dirPath + $"Grid_{size}*{size}_{count}.ps";
+                HOperatorSet.CreateRectificationGrid(size / 100.0, count, saveFullPath);
+            }
+            catch { }
+        }
+
+        public static void CheckerBoardCalib(HObject Image, out HObject Map
+            , int MinContrast = 25, int Radius = 10, int SigmaSaddlePoints = 2, int Threshold = 3
+            , double SigmaConnectGridPoints = 0.9, int MaxDist = 5, int GridSpacing = 45)
+        {
+            try
+            {
+                HOperatorSet.Rgb1ToGray(Image, out Image);
+                //****************************鏍囧畾鐭杩囩▼**************************************
+                //鏌ユ壘缁撴瀯鍖栫綉鏍�
+                //MinContrast 鏌ユ壘缃戞牸瀵规瘮搴�
+                //Radius 鏌ユ壘缃戞牸鍗婂緞
+                HOperatorSet.FindRectificationGrid(Image, out HObject ho_GridRegion, MinContrast, Radius);
+                HOperatorSet.ReduceDomain(Image, ho_GridRegion, out HObject Image_Reduced);
+
+                //鎻愬彇锛堥瀺锛夌偣锛岃緭鍑篟ow, Col
+                //'facet'锛氭护娉㈠櫒
+                //Sigma锛氬钩婊戠郴鏁�
+                //Threshold:鍒嗗壊闃堝��
+
+                HOperatorSet.SaddlePointsSubPix(Image_Reduced, "facet", SigmaSaddlePoints, Threshold, out HTuple hv_Row, out HTuple hv_Col);
+                HOperatorSet.GenCrossContourXld(out HObject ho_SaddlePoints, hv_Row, hv_Col, 20, 1);
+
+                HOperatorSet.ConnectGridPoints(Image_Reduced, out HObject ho_ConnectingLines, hv_Row,
+                    hv_Col, SigmaConnectGridPoints, MaxDist);
+                //鐢熸垚鍙樻崲鍥�
+
+                HOperatorSet.GenGridRectificationMap(Image_Reduced, ho_ConnectingLines, out Map,
+                    out HObject ho_Meshes, GridSpacing, 0, hv_Row, hv_Col, "bilinear");
+            }
+            catch { Map = null; }
+        }
+
+        public static void ApplyCheckerBoardCalibMap(HObject Image, HObject Map, out HObject MappedImage)
+        {
+            try
+            {
+                HOperatorSet.MapImage(Image, Map, out MappedImage);
+            }
+            catch { MappedImage = null; }
+        }
+        #endregion
+    }
+
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HCalibTool/HCaltab.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HCalibTool/HCaltab.cs
new file mode 100644
index 0000000..e486169
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HCalibTool/HCaltab.cs
@@ -0,0 +1,555 @@
+锘縰sing HalconDotNet;
+using LB_VisionControl;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+
+    public class HCaltab : IDisposable
+    {
+        public HCaltab() { }
+
+        public HCaltab(HCaltab HCaltab)
+        {
+            CameraInner = HCaltab.CameraInner.Clone();
+            CameraPose = HCaltab.CameraPose.Clone();
+            CameraInner_Adaptive = HCaltab.CameraInner_Adaptive.Clone();
+            Map = HCaltab.Map.Clone();
+            Xld = HCaltab.Xld.Clone();
+
+            CaltbImages = new List<HObject>(HCaltab.CaltbImages);
+            Params.XNum = HCaltab.Params.XNum;
+            Params.YNum = HCaltab.Params.YNum;
+            Params.MarkDist = HCaltab.Params.MarkDist;
+            Params.DiameterRatio = HCaltab.Params.DiameterRatio;
+            Params.Focus = HCaltab.Params.Focus;
+            Params.Kappa = HCaltab.Params.Kappa;
+            Params.Sx = HCaltab.Params.Sx;
+            Params.Sy = HCaltab.Params.Sy;
+            Params.Width = HCaltab.Params.Width;
+            Params.Height = HCaltab.Params.Height;
+        }
+
+        public void Dispose()
+        {
+            try
+            {
+                ClearCaltbImages();
+
+                if (Map != null && Map.IsInitialized())
+                    Map.Dispose();
+
+                if (Xld != null && Xld.IsInitialized())
+                    Xld.Dispose();
+            }
+            catch { }
+        }
+
+        /// <summary>
+        /// 鍚嶇О
+        /// </summary>
+        public string Name = "Calibration_0";
+
+        /// <summary>
+        /// 淇℃伅
+        /// </summary>
+        public string Msg = "";
+
+        /// <summary>
+        /// 缁撴灉
+        /// </summary>
+        public bool Result
+        {
+            get
+            {
+                if (Map == null || !Map.IsInitialized())
+                    return false;
+
+                if (CameraInner_Adaptive == null || CameraInner_Adaptive.Length == 0
+                    || CameraPose == null || CameraPose.Length == 0)
+                    return false;
+
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// 鏂囦欢璺緞
+        /// </summary>
+        public string FilePath = $"C://Name//";
+
+        /// <summary>
+        /// 鏍囧畾鍙傛暟鏂囦欢
+        /// </summary>
+        public HCalibrationParam Params = new HCalibrationParam();
+
+        List<HObject> CaltbImages = new List<HObject>();
+
+        public HObject Image
+        {
+            get
+            {
+                if (CaltbImages.Count > 0)
+                    return CaltbImages[0];
+                else
+                    return null;
+            }
+        }
+
+        public HObject Xld = new HObject();
+
+        /// <summary>
+        /// 鐩告満鍐呭弬
+        /// </summary>
+        HTuple CameraInner = new HTuple();
+
+        /// <summary>
+        /// 鐩告満澶栧弬
+        /// </summary>
+        HTuple CameraPose = new HTuple();
+
+        /// <summary>
+        /// 鏃犵暩鍙樼殑鐩告満鍐呭弬
+        /// </summary>
+        HTuple CameraInner_Adaptive = new HTuple();
+
+        /// <summary>
+        /// 鐣稿彉鍙樻崲鍥�
+        /// </summary>
+        HObject Map = new HObject();
+
+        #region 鐭缁撴灉
+        public bool GetCaltbImage(HObject OriImage, out HObject CaltbImage)
+        {
+            CaltbImage = OriImage;
+
+            try
+            {
+                if (OriImage == null || !OriImage.IsInitialized()
+                || Map == null || !Map.IsInitialized())
+                    return false;
+
+                HOperatorSet.MapImage(OriImage, Map, out CaltbImage);
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool GetCaltbPoint(HPoint OriPoint, out HPoint CaltbPoint)
+        {
+            CaltbPoint = new HPoint(OriPoint);
+
+            try
+            {
+                if (CameraInner_Adaptive == null || CameraInner_Adaptive.Length == 0
+                    || CameraPose == null || CameraPose.Length == 0)
+                    return false;
+
+                HOperatorSet.ImagePointsToWorldPlane(CameraInner_Adaptive, CameraPose
+                    , OriPoint.Row, OriPoint.Column, "mm", out HTuple row, out HTuple col);
+
+                if (row.Length == 0 || col.Length == 0)
+                    return false;
+
+                CaltbPoint.Row = row.D;
+                CaltbPoint.Column = col.D;
+                return true;
+            }
+            catch { return false; }
+        }
+        #endregion
+
+        public bool LoadCaltbImages()
+        {
+            try
+            {
+                ClearCaltbImages();
+
+                for (int i = 0; i < 999; i++)
+                {
+                    string ImagePath = FilePath + $"//CaltbImages_{i}.bmp";
+                    if (!File.Exists(ImagePath))
+                        break;
+
+                    HOperatorSet.ReadImage(out HObject ho_Image, ImagePath);
+                }
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool SaveCaltbImages()
+        {
+            //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+            if (!Directory.Exists(FilePath))
+            {
+                try
+                {
+                    Directory.CreateDirectory(FilePath);
+                }
+                catch { }
+            }
+
+            try
+            {
+                for (int i = 0; i <= CaltbImages.Count; i++)
+                {
+                    string ImagePath = FilePath + $"//CaltbImages_{i}.bmp";
+                    var Image = CaltbImages[i];
+                    if (Image != null && Image.IsInitialized())
+                    {
+                        HOperatorSet.CountChannels(Image, out HTuple hv_Channels);
+
+                        if (hv_Channels.TupleInt() != 1)
+                            HOperatorSet.Rgb1ToGray(Image, out Image);
+
+                        //Halcon瀛樺浘闇�瑕佺敤鏂滄潬
+                        ImagePath.Replace("\\", "/");
+                        HOperatorSet.WriteImage(Image, "bmp", 0, ImagePath);
+                    }
+                }
+            }
+            catch { return false; }
+
+            return true;
+        }
+
+        public void ClearCaltbImages()
+        {
+            foreach (var image in CaltbImages)
+            {
+                if (image != null && image.IsInitialized())
+                    image.Dispose();
+            }
+            CaltbImages.Clear();
+            CaltbImages = new List<HObject>();
+        }
+
+        public bool CheckCaltbImage(List<HObject> lst_Images = null, int Width = 0, int Height = 0)
+        {
+            if (lst_Images == null)
+                lst_Images = CaltbImages;
+
+            if (Width == 0 || Height == 0)
+            {
+                Width = Params.Width;
+                Height = Params.Height;
+            }
+
+            foreach (var imge in lst_Images)
+            {
+                if (imge == null || !imge.IsInitialized())
+                    return false;
+
+                HOperatorSet.GetImageSize(imge, out HTuple hv_Width, out HTuple hv_Height);
+                if (hv_Width.Length == 0 || hv_Height.Length == 0
+                    || hv_Width.I != Width || hv_Height.I != Height)
+                    return false;
+            }
+            return true;
+        }
+
+        public bool Caltb(List<HObject> lst_Images)
+        {
+            try
+            {
+                if (!CheckCaltbImage(lst_Images))
+                    return false;
+
+                BaseCalib.CreateCaltab(FilePath, Params.XNum, Params.YNum, Params.MarkDist, Params.DiameterRatio);
+
+                BaseCalib.gen_cam_par_area_scan_division(Params.Focus / 1000.0, Params.Kappa
+                    , Params.Sx / 1000000.0, Params.Sy / 1000000.0
+                    , Params.Width / 2.0, Params.Height / 2.0, Params.Width, Params.Height, out HTuple CameraParam);
+
+                string CalPlateDescr = Params.CalPlateDescr;
+                string CameraInnerPath = FilePath + "//CameraInner_Adaptive.tup";
+                string CameraPosePath = FilePath + "//CameraPose.tup";
+
+                CalPlateDescr.Replace("\\", "/");
+                CameraInnerPath.Replace("\\", "/");
+                CameraPosePath.Replace("\\", "/");
+
+                BaseCalib.CaltabCalib(CameraParam, lst_Images
+                    , out HTuple hv_CameraInner, out HTuple hv_CameraPose, out HTuple hv_CameraInner_Adaptive
+                    , out HObject ho_Map, out Xld
+                    , CalPlateDescr, CameraInnerPath, CameraPosePath);
+
+                if (hv_CameraInner == null || hv_CameraPose == null || hv_CameraInner_Adaptive == null
+                    || ho_Map == null || !ho_Map.IsInitialized())
+                    return false;
+
+                CameraInner = hv_CameraInner.Clone();
+                CameraPose = hv_CameraPose.Clone();
+                CameraInner_Adaptive = hv_CameraInner_Adaptive.Clone();
+                Map = ho_Map.Clone();
+
+                CaltbImages = lst_Images;
+                return SaveCaltbImages();
+            }
+            catch { return false; }
+        }
+
+        public bool Caltb(List<HObject> lst_Images, int XNum, int YNum, int MarkDist, double DiameterRatio
+            , int Focus, int Kappa, double Sx, double Sy, int Width, int Height)
+        {
+            if (!CheckCaltbImage(lst_Images, Width, Height))
+                return false;
+
+            BaseCalib.CreateCaltab(FilePath, XNum, YNum, MarkDist, DiameterRatio);
+
+            BaseCalib.gen_cam_par_area_scan_division(Focus / 1000.0, Kappa
+                , Sx / 1000000.0, Sy / 1000000.0
+                , Width / 2.0, Height / 2.0, Width, Height, out HTuple CameraParam);
+
+            string CalPlateDescr = Params.CalPlateDescr;
+            string CameraInnerPath = FilePath + "//CameraInner_Adaptive.tup";
+            string CameraPosePath = FilePath + "//CameraPose.tup";
+
+            CalPlateDescr.Replace("\\", "/");
+            CameraInnerPath.Replace("\\", "/");
+            CameraPosePath.Replace("\\", "/");
+
+            BaseCalib.CaltabCalib(CameraParam, CaltbImages
+                , out HTuple hv_CameraInner, out HTuple hv_CameraPose, out HTuple hv_CameraInner_Adaptive
+                , out HObject ho_Map, out Xld
+                , CalPlateDescr, CameraInnerPath, CameraPosePath);
+
+            if (hv_CameraInner == null || hv_CameraPose == null || hv_CameraInner_Adaptive == null
+                || ho_Map == null || !ho_Map.IsInitialized())
+                return false;
+
+            CameraInner = hv_CameraInner.Clone();
+            CameraPose = hv_CameraPose.Clone();
+            CameraInner_Adaptive = hv_CameraInner_Adaptive.Clone();
+            Map = ho_Map.Clone();
+
+            CaltbImages = lst_Images;
+            Params.XNum = XNum;
+            Params.YNum = YNum;
+            Params.MarkDist = MarkDist;
+            Params.DiameterRatio = DiameterRatio;
+            Params.Focus = Focus;
+            Params.Kappa = Kappa;
+            Params.Sx = Sx;
+            Params.Sy = Sy;
+            Params.Width = Width;
+            Params.Height = Height;
+
+            return SaveCaltbImages();
+        }
+
+        public bool Load(string fullPath)
+        {
+            try
+            {
+                // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                Name = Path.GetFileNameWithoutExtension(fullPath);
+                // 淇鐪熷疄璺緞,宸ュ叿鍏惰矾寰勪负涓�涓枃浠跺す,鑰屼笉鏄竴涓枃浠�
+                FilePath = Path.GetDirectoryName(fullPath) + Name;
+
+                if (!File.Exists(fullPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    Save(FilePath);
+                    return true;
+                }
+
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+                Params = JsonConvert.DeserializeObject<HCalibrationParam>(strJson);
+                if (Params == null)
+                    return false;
+
+                Params.Name = Name;
+                Params.FilePath = FilePath;
+
+                string CalPlateDescr = Params.CalPlateDescr;
+                string CameraInnerPath = FilePath + "//CameraInner_Adaptive.tup";
+                string CameraPosePath = FilePath + "//CameraPose.tup";
+
+                //鐩告満鍐呭弬
+                HOperatorSet.ReadTuple(CameraInnerPath, out CameraInner_Adaptive);
+                //鐩告満澶栧弬
+                HOperatorSet.ReadTuple(CameraPosePath, out CameraPose);
+
+                //BaseCalib.CreateCaltab(FilePath, Params.XNum, Params.YNum, Params.MarkDist, Params.DiameterRatio);
+
+                //BaseCalib.gen_cam_par_area_scan_division(Params.Focus / 1000.0, Params.Kappa
+                //    , Params.Sx / 1000000.0, Params.Sy / 1000000.0
+                //    , Params.Width / 2.0, Params.Height / 2.0, Params.Width, Params.Height, out HTuple CameraParam);
+
+                //CalPlateDescr.Replace("\\", "/");
+                //CameraInnerPath.Replace("\\", "/");
+                //CameraPosePath.Replace("\\", "/");
+
+                //BaseCalib.CaltabCalib(CameraParam, CaltbImages
+                //    , out CameraInner, out CameraPose, out CameraInner_Adaptive, out Map, out _
+                //    , CalPlateDescr, CameraInnerPath, CameraPosePath);
+
+                return LoadCaltbImages();
+            }
+            catch { return false; }
+        }
+
+        public bool Save(string filePath)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(filePath) || filePath.Trim() == "")
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                // 淇鐪熷疄璺緞,宸ュ叿鍏惰矾寰勪负涓�涓枃浠跺す,鑰屼笉鏄竴涓枃浠�
+                filePath += ("//" + Name);
+
+                string strJson = string.Empty;
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Newtonsoft.Json.Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+                strJson = JsonConvert.SerializeObject(Params, settings);
+
+                Params = JsonConvert.DeserializeObject<HCalibrationParam>(strJson);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                if (!Directory.Exists(filePath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(filePath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+                // filePath 宸茬粡鍚簡Name
+                File.WriteAllText(filePath + "//Params.json", strJson, Encoding.UTF8);
+
+                // filePath 宸茬粡鍚簡Name
+                FilePath = filePath;
+                try
+                {
+                    string CameraInnerPath = FilePath + "//CameraInner_Adaptive.tup";
+                    string CameraPosePath = FilePath + "//CameraPose.tup";
+                    //鐩告満鍐呭弬
+                    HOperatorSet.WriteTuple(CameraInner_Adaptive, CameraInnerPath);
+                    //鐩告満澶栧弬
+                    HOperatorSet.WriteTuple(CameraPose, CameraPosePath);
+                }
+                catch { }
+
+                return SaveCaltbImages();
+            }
+            catch { return false; }
+        }
+    }
+
+    /// <summary>
+    /// 鐣稿彉鏍囧畾鍙傛暟绫�
+    /// </summary>
+    [Serializable]
+    public class HCalibrationParam
+    {
+        public HCalibrationParam() { }
+
+        /// <summary>
+        /// 鍚嶇О
+        /// </summary>
+        public string Name = "Params";
+
+        /// <summary>
+        /// 鏂囦欢璺緞
+        /// </summary>
+        public string FilePath = @"C://";
+
+        /// <summary>
+        /// 鍦嗙偣琛屾暟
+        /// </summary>
+        public int XNum { get; set; } = 7;
+
+        /// <summary>
+        /// 鍦嗙偣琛屾暟
+        /// </summary>
+        public int YNum { get; set; } = 7;
+
+        /// <summary>
+        /// 涓や釜鍦嗕箣闂寸殑璺濈, 鍗曚綅mm
+        /// </summary>
+        public double MarkDist { get; set; } = 1.25;
+
+        /// <summary>
+        /// 姣斾緥鍊�, Mark鐩村緞姣斾笂Mark涓績璺濈
+        /// </summary>
+        public double DiameterRatio { get; set; } = 0.5;
+
+        /// <summary>
+        /// 鐢ㄤ簬鏍囧畾鐨勬弿杩版枃浠�
+        /// </summary>
+        public string CalPlateDescr { get { return FilePath + $"//Caltab_{XNum}*{YNum}_{DiameterRatio}.descr"; } }
+
+        /// <summary>
+        /// 鍒朵綔鏍囧畾鏉跨殑PS鏂囦欢
+        /// </summary>
+        public string CalPlatePSFile { get { return FilePath + $"//Caltab_{XNum}*{YNum}_{DiameterRatio}.ps"; } }
+
+        /// <summary>
+        /// 鍘氬害
+        /// </summary>
+        public int Thickness { get; set; } = 1;
+
+        /// <summary>
+        /// 鐩告満绫诲瀷(闈㈡壂鎻忥紙闄ゆ硶))
+        /// </summary>
+        public string CamType { get; set; } = "area_scan_division";
+
+        /// <summary>
+        /// 鍗曚釜鐩告満鍍忓厓鐨勫
+        /// </summary>
+        public double Sx { get; set; } = 8.3;
+
+        /// <summary>
+        /// 鍗曚釜鐩告満鍍忓厓鐨勯珮
+        /// </summary>
+        public double Sy { get; set; } = 8.3;
+
+        /// <summary>
+        /// 鍥惧儚瀹�
+        /// </summary>
+        public int Width { get; set; } = 1120;
+
+        /// <summary>
+        /// 鍥惧儚楂�
+        /// </summary>
+        public int Height { get; set; } = 1120;
+
+        /// <summary>
+        /// 闀滃ご鐨勭劍璺�
+        /// </summary>
+        public double Focus { get; set; } = 8;
+
+        public double Kappa { get; set; } = 0;
+
+        /// <summary>
+        /// 鏍囧畾鏁堟灉, 瓒婃帴杩�0瓒婅秺濂�
+        /// </summary>
+        public double RMS { get; set; } = 999.9;
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dTool.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dTool.cs
new file mode 100644
index 0000000..fcf47ec
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dTool.cs
@@ -0,0 +1,329 @@
+锘縰sing HalconDotNet;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    [Process("Halcon2D璇荤爜宸ュ叿", Category = "Halcon2D宸ュ叿", Description = "鍒涘缓璇荤爜宸ュ叿")]
+    public class HFindCode2dTool : TAlgorithm
+    {
+        public enum Code2dType { None, QRCode, BarCode };
+
+        HTuple hv_QRCodeHandle = new HTuple();//浜岀淮鐮佹ā鏉�
+        HTuple hv_BarCodeHandle = new HTuple();//鏉$爜妯℃澘
+        public HFindCode2dTool()
+        {
+            strProcessClass = "LB_VisionProcesses.Alogrithms.Halcon.HFindCode2dTool";
+            strProcessName = "Halcon2D璇荤爜宸ュ叿";
+
+            //鍒涘缓涓�涓潯鐮佹ā鍨�
+            hv_BarCodeHandle = CreateCodeMode();
+            hv_QRCodeHandle = CreateQRCodeMode();
+
+            Params.Inputs.Add("Code2dType", "BarCode");
+            Params.Inputs.Add("CodeHead", "");
+            Params.Inputs.Add("CodeLength", 0);
+            Params.Inputs.Add("MinThreshold", 80);
+            Params.Inputs.Add("MaxThreshold", 180);
+
+            Params.Inputs.Add("MinCount", 0);
+            Params.Inputs.Add("MaxCount", 9999);
+
+            Params.Outputs.Add("CodeStrings", new List<string>());
+        }
+
+        private static readonly object lockObj = new object();
+
+        /// <summary>
+        /// 绠楀瓙閫昏緫
+        /// </summary>
+        public override void TAlgorithmMain()
+        {
+            lock (lockObj)
+            {
+                #region 鍒濆鍖栧彉閲�
+                HOperatorSet.GenEmptyObj(out HObject ho_SymbolXLDs);
+                HOperatorSet.GenEmptyObj(out HObject ho_SymbolRegions);
+                HTuple hv_DecodedDataStrings = new HTuple();
+                HTuple hv_DecodedDataTypes = new HTuple();
+
+                //鍒涘缓涓�涓潯鐮佹ā鍨�
+                hv_BarCodeHandle = CreateCodeMode();
+                hv_QRCodeHandle = CreateQRCodeMode();
+                #endregion
+
+                try
+                {
+                    if (InputImage == null || !(InputImage is HObject))
+                    {
+                        Msg = "杈撳叆鍥剧墖涓虹┖";
+                        Result = false;
+                        return;
+                    }
+                    if (!(InputImage is HObject))
+                    {
+                        Msg = "杈撳叆鍥剧墖鏍煎紡涓嶄负Mat";
+                        Result = false;
+                        return;
+                    }
+
+                    object DomainImage = null;
+                    #region 瑁佸壀鍖哄煙
+                    if (!ReduceDomainImage(InputImage, ref DomainImage))
+                    {
+                        Msg = "瑁佸壀鍖哄煙澶辫触";
+                        Result = false;
+                        return;
+                    }
+                    this.Record = new MsgRecord();
+                    #endregion
+
+                    #region 绠楀瓙閫昏緫
+                    HObject hoDomainImage = DomainImage as HObject;
+                    HTuple hv_Channels = new HTuple();
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        try
+                        {
+                            HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                            if (hv_Channels.TupleInt() != 1)
+                                HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+
+                            //杞崲鍚庡啀娆℃鏌ユ槸鍚︿负鐏板害鍥�
+                            HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                            if (hv_Channels.TupleInt() != 1)
+                            {
+                                HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+                                Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥�";
+                                Result = false;
+                                return;
+                            }
+                        }
+                        catch
+                        {
+                            Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥句笖杞崲澶辫触";
+                            Result = false;
+                            return;
+                        }
+                    }
+
+                    Code2dType eCode2dType = Code2dType.None;
+                    string CodeHead = (ProcessParams.ConvertToString(Params.Inputs["CodeHead"])).TrimEnd();
+                    int CodeLength = ProcessParams.ConvertToInt32(Params.Inputs["CodeLength"]);
+                    int MinThreshold = ProcessParams.ConvertToInt32(Params.Inputs["MinThreshold"]);
+                    int MaxThreshold = ProcessParams.ConvertToInt32(Params.Inputs["MaxThreshold"]);
+
+                    // 灏濊瘯杞崲瀛楃涓蹭负鏋氫妇绫诲瀷
+                    if (!Enum.TryParse(ProcessParams.ConvertToString(Params.Inputs["Code2dType"]), out eCode2dType))
+                        eCode2dType = Code2dType.None;
+
+                    if (string.IsNullOrEmpty(CodeHead) || CodeHead.Trim() == "")
+                    {
+                        switch (eCode2dType)
+                        {
+                            case Code2dType.None:
+                                break;
+                            case Code2dType.QRCode:
+                                HOperatorSet.FindDataCode2d(hoDomainImage, out ho_SymbolXLDs, hv_QRCodeHandle, new HTuple(), new HTuple(), out hv_BarCodeHandle, out hv_DecodedDataStrings);
+                                break;
+                            case Code2dType.BarCode:
+                                HOperatorSet.FindBarCode(hoDomainImage, out ho_SymbolRegions, hv_BarCodeHandle, "auto", out hv_DecodedDataStrings);
+                                HOperatorSet.GetBarCodeResult(hv_BarCodeHandle, "all", "decoded_types", out hv_DecodedDataTypes);
+                                break;
+                        }
+                    }
+                    else
+                    {
+                        //浣跨敤鍥惧儚澧炲己绠楁硶鎵惧埌鎯宠鐨勬潯鐮�
+                        for (int i = 0; i <= ProcessParams.ConvertToInt32(Params.Inputs["MinThreshold"]); i = i + 20)
+                        {
+                            for (int j = 255; j >= ProcessParams.ConvertToInt32(Params.Inputs["MaxThreshold"]); j = j - 40)
+                            {
+                                //鑹查樁鏄犲皠锛屽寮哄浘鍍忓姣斿害
+                                scale_gray_map(hoDomainImage, out HObject ho_Image2, i, j);
+                                switch (eCode2dType)
+                                {
+                                    case Code2dType.None:
+                                        break;
+                                    case Code2dType.QRCode:
+                                        HOperatorSet.FindDataCode2d(ho_Image2, out ho_SymbolXLDs, hv_QRCodeHandle, new HTuple(), new HTuple(), out hv_BarCodeHandle, out hv_DecodedDataStrings);
+                                        hv_DecodedDataTypes = null;
+                                        break;
+                                    case Code2dType.BarCode:
+                                        HOperatorSet.FindBarCode(ho_Image2, out ho_SymbolRegions, hv_BarCodeHandle, "auto", out hv_DecodedDataStrings);
+                                        HOperatorSet.GetBarCodeResult(hv_BarCodeHandle, "all", "decoded_types", out hv_DecodedDataTypes);
+                                        break;
+                                }
+
+                                if ((int)(new HTuple(((hv_DecodedDataStrings.TupleStrlen())).TupleGreater(0))) != 0)
+                                {
+                                    HTuple row = new HTuple();
+                                    HTuple col = new HTuple();
+                                    HTuple phi = new HTuple();
+                                    HTuple length1 = new HTuple();
+                                    HTuple length2 = new HTuple();
+
+                                    List<string> listCodeStrings = new List<string>();
+
+                                    for (int k = 0; k < hv_DecodedDataStrings.Length; k++)
+                                    {
+                                        string strBarCode = (string)hv_DecodedDataStrings[k];
+                                        if (strBarCode.StartsWith(CodeHead))
+                                        {
+                                            //CodeLength澶т簬0鏃跺紑鍚暱搴︽牎楠�
+                                            if (CodeLength > 0 && strBarCode.Length != CodeLength)
+                                                continue;
+
+                                            switch (eCode2dType)
+                                            {
+                                                case Code2dType.None:
+                                                    break;
+                                                case Code2dType.QRCode:
+                                                    HOperatorSet.SelectObj(ho_SymbolXLDs, out HObject ho_SymbolXLD, k + 1);
+                                                    HOperatorSet.SmallestRectangle2Xld(ho_SymbolXLD, out row, out col, out phi, out length1, out length2);
+                                                    HOperatorSet.GenRectangle2(out HObject ho_SymbolXLDRegion, row, col, phi, length1, length2);
+                                                    ((MsgRecord)Record).AddRecord(strBarCode, row, col, ho_SymbolXLDRegion);
+                                                    break;
+                                                case Code2dType.BarCode:
+                                                    HOperatorSet.SelectObj(ho_SymbolRegions, out HObject ho_SymbolRegion, k + 1);
+                                                    HOperatorSet.SmallestRectangle2(ho_SymbolRegion, out row, out col, out phi, out length1, out length2);
+                                                    ((MsgRecord)Record).AddRecord(strBarCode, row, col, ho_SymbolRegion);
+                                                    break;
+                                            }
+                                            OutputImage = hoDomainImage;
+                                            listCodeStrings.Add(strBarCode);
+                                            Params.Outputs["CodeStrings"] = listCodeStrings;
+                                            Params.Outputs["Count"] = 1;
+                                            Msg = "杩愯鎴愬姛";
+                                            Result = true;
+                                            return;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+
+                        OutputImage = null;
+                        Params.Outputs["CodeStrings"] = null;
+                        Params.Outputs["Count"] = 0;
+                        if (CodeLength > 0)
+                            Msg = string.Format("娌℃湁鎵惧埌鎸囧畾澶翠负\"{0}\"涓旈暱搴︿负\"{1}\"鐨勭爜", CodeHead, CodeLength);
+                        else
+                            Msg = string.Format("娌℃湁鎵惧埌鎸囧畾澶翠负\"{0}\"鐮�", CodeHead);
+                        Result = false;
+                        return;
+                    }
+                    #endregion
+
+                    #region 缁撴灉澶勭悊
+                    this.Record = new ObjectRecord();
+                    List<string> CodeStrings = new List<string>();
+                    if ((int)(new HTuple(((hv_DecodedDataStrings.TupleStrlen())).TupleGreater(0))) != 0)
+                    {
+                        for (int k = 0; k < hv_DecodedDataStrings.Length; k++)
+                            CodeStrings.Add((string)hv_DecodedDataStrings[k]);
+
+                        switch (eCode2dType)
+                        {
+                            case Code2dType.None:
+                                break;
+                            case Code2dType.QRCode:
+                                ((ObjectRecord)Record).AddXld(ho_SymbolXLDs);
+                                break;
+                            case Code2dType.BarCode:
+                                HOperatorSet.DilationRectangle1(ho_SymbolRegions, out HObject Regiondilation, 9, 9);
+                                ((ObjectRecord)Record).AddRecord(Regiondilation);
+                                break;
+                        }
+                    }
+
+                    Params.Outputs["CodeStrings"] = CodeStrings;
+                    Params.Outputs["Count"] = CodeStrings.Count;
+                    #endregion
+
+                    #region 鐢熸垚OutputImage缁欏悗缁鐞�
+                    try
+                    {
+                        OutputImage = hoDomainImage;
+                    }
+                    catch (Exception ex)
+                    {
+                        Msg = "鐢熸垚OutputImage澶辫触,鍘熷洜鏄�:" + ex.ToString();
+                        Result = false;
+                        return;
+                    }
+                    #endregion
+
+                    if (Msg == "杩愯瓒呮椂")
+                    {
+                        Result = false;
+                        return;
+                    }
+
+                    int MinCount = ProcessParams.ConvertToInt32(Params.Inputs["MinCount"]);
+                    int MaxCount = ProcessParams.ConvertToInt32(Params.Inputs["MaxCount"]);
+
+                    if (CodeStrings.Count < MinCount || CodeStrings.Count > MaxCount)
+                    {
+                        Msg = string.Format("缁撴灉涓暟瓒呭嚭鑼冨洿({0},{1})", MinCount, MaxCount);
+                        Result = false;
+                        return;
+                    }
+
+                    Msg = "杩愯鎴愬姛";
+                    Result = true;
+                    return;
+                }
+                catch (Exception ex)
+                {
+                    Msg = "杩愯澶辫触,鍘熷洜鏄�:" + ex.ToString().TrimEnd();
+                    OutputImage = null;
+                    Result = false;
+                    return;
+                }
+                finally
+                {
+                    if (!Result)
+                    {
+                        Params.Outputs["CodeStrings"] = "";
+                        Params.Outputs["Count"] = 0;
+                    }
+                    bCompleted = true;
+
+                    #region 鍐呭瓨閲婃斁
+                    ho_SymbolXLDs.Dispose();
+                    ho_SymbolRegions.Dispose();
+                    #endregion
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鍒涘缓鏉$爜绫诲瀷
+        /// </summary>
+        public HTuple CreateCodeMode()
+        {
+            //鏉$爜妯″瀷鍙ユ焺
+            HTuple hv_BarCodeHandle = null;
+
+            //鍒涘缓鏉$爜妯″瀷
+            HOperatorSet.CreateBarCodeModel(new HTuple(), new HTuple(), out hv_BarCodeHandle);
+            HOperatorSet.SetBarCodeParam(hv_BarCodeHandle, "orientation", 0);
+            HOperatorSet.SetBarCodeParam(hv_BarCodeHandle, "orientation_tol", 90);
+            return hv_BarCodeHandle;
+        }
+
+        public HTuple CreateQRCodeMode()
+        {
+            //鏉$爜妯″瀷鍙ユ焺
+            HTuple hv_QRCodeHandle = null;
+            HOperatorSet.CreateDataCode2dModel("QR Code", new HTuple(), new HTuple(), out hv_QRCodeHandle);
+            return hv_QRCodeHandle;
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.Designer.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.Designer.cs
new file mode 100644
index 0000000..b39a675
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.Designer.cs
@@ -0,0 +1,674 @@
+锘縩amespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    partial class HFindCode2dToolEdit
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tablePanelParas = new TableLayoutPanel();
+            label1 = new Label();
+            dtxtMinThreshold = new TextBox();
+            dtxtMaxThreshold = new TextBox();
+            label19 = new Label();
+            dtxtMinCount = new TextBox();
+            label2 = new Label();
+            label20 = new Label();
+            dtxtMaxCount = new TextBox();
+            label3 = new Label();
+            stxtCodeHead = new TextBox();
+            label4 = new Label();
+            cmbCode2dType = new ComboBox();
+            label10 = new Label();
+            dtxtCodeLength = new TextBox();
+            pnlInputImage = new Panel();
+            TopToolStrip = new ToolStrip();
+            btnRun = new ToolStripButton();
+            btnLoadImage = new ToolStripButton();
+            btnSaveParas = new ToolStripButton();
+            btnLoadParas = new ToolStripButton();
+            BtmStatusStrip = new StatusStrip();
+            lblResult = new ToolStripStatusLabel();
+            lblMsg = new ToolStripStatusLabel();
+            lblRunTime = new ToolStripStatusLabel();
+            MainTableLayoutPanel = new TableLayoutPanel();
+            parasTabControl = new TabControl();
+            tabPage1 = new TabPage();
+            tabPage5 = new TabPage();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            cmbTypeRoi = new ComboBox();
+            label21 = new Label();
+            label22 = new Label();
+            cmbFixture = new ComboBox();
+            ckbDrawRoi = new CheckBox();
+            tabPage2 = new TabPage();
+            tableLayoutResults = new TableLayoutPanel();
+            label5 = new Label();
+            stxtCodeStrings = new TextBox();
+            label18 = new Label();
+            dtxtCount = new TextBox();
+            imgTabControl = new TabControl();
+            tabPageInputImage = new TabPage();
+            tabPageRecordImage = new TabPage();
+            pnlRecordImage = new Panel();
+            tablePanelParas.SuspendLayout();
+            TopToolStrip.SuspendLayout();
+            BtmStatusStrip.SuspendLayout();
+            MainTableLayoutPanel.SuspendLayout();
+            parasTabControl.SuspendLayout();
+            tabPage1.SuspendLayout();
+            tabPage5.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tabPage2.SuspendLayout();
+            tableLayoutResults.SuspendLayout();
+            imgTabControl.SuspendLayout();
+            tabPageInputImage.SuspendLayout();
+            tabPageRecordImage.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tablePanelParas
+            // 
+            tablePanelParas.ColumnCount = 4;
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.Controls.Add(label1, 0, 0);
+            tablePanelParas.Controls.Add(dtxtMinThreshold, 1, 0);
+            tablePanelParas.Controls.Add(dtxtMaxThreshold, 3, 0);
+            tablePanelParas.Controls.Add(label19, 0, 1);
+            tablePanelParas.Controls.Add(dtxtMinCount, 1, 1);
+            tablePanelParas.Controls.Add(label2, 2, 0);
+            tablePanelParas.Controls.Add(label20, 2, 1);
+            tablePanelParas.Controls.Add(dtxtMaxCount, 3, 1);
+            tablePanelParas.Controls.Add(label3, 0, 3);
+            tablePanelParas.Controls.Add(stxtCodeHead, 1, 3);
+            tablePanelParas.Controls.Add(label4, 0, 2);
+            tablePanelParas.Controls.Add(cmbCode2dType, 1, 2);
+            tablePanelParas.Controls.Add(label10, 2, 3);
+            tablePanelParas.Controls.Add(dtxtCodeLength, 3, 3);
+            tablePanelParas.Dock = DockStyle.Fill;
+            tablePanelParas.Location = new Point(3, 3);
+            tablePanelParas.Margin = new Padding(2, 3, 2, 3);
+            tablePanelParas.Name = "tablePanelParas";
+            tablePanelParas.RowCount = 10;
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.Size = new Size(397, 510);
+            tablePanelParas.TabIndex = 0;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Location = new Point(2, 0);
+            label1.Margin = new Padding(2, 0, 2, 0);
+            label1.MaximumSize = new Size(0, 28);
+            label1.MinimumSize = new Size(0, 28);
+            label1.Name = "label1";
+            label1.Size = new Size(68, 28);
+            label1.TabIndex = 0;
+            label1.Text = "鏈�灏忕伆搴﹀��";
+            label1.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinThreshold
+            // 
+            dtxtMinThreshold.Location = new Point(92, 3);
+            dtxtMinThreshold.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinThreshold.Name = "dtxtMinThreshold";
+            dtxtMinThreshold.Size = new Size(98, 23);
+            dtxtMinThreshold.TabIndex = 5;
+            dtxtMinThreshold.Text = "80";
+            // 
+            // dtxtMaxThreshold
+            // 
+            dtxtMaxThreshold.Location = new Point(290, 3);
+            dtxtMaxThreshold.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxThreshold.Name = "dtxtMaxThreshold";
+            dtxtMaxThreshold.Size = new Size(98, 23);
+            dtxtMaxThreshold.TabIndex = 6;
+            dtxtMaxThreshold.Text = "180";
+            // 
+            // label19
+            // 
+            label19.AutoSize = true;
+            label19.Location = new Point(3, 51);
+            label19.Name = "label19";
+            label19.Size = new Size(56, 17);
+            label19.TabIndex = 19;
+            label19.Text = "鏈�灏忔暟閲�";
+            // 
+            // dtxtMinCount
+            // 
+            dtxtMinCount.Location = new Point(93, 54);
+            dtxtMinCount.Name = "dtxtMinCount";
+            dtxtMinCount.Size = new Size(97, 23);
+            dtxtMinCount.TabIndex = 17;
+            dtxtMinCount.Text = "0";
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.Location = new Point(200, 0);
+            label2.Margin = new Padding(2, 0, 2, 0);
+            label2.MaximumSize = new Size(0, 28);
+            label2.MinimumSize = new Size(0, 28);
+            label2.Name = "label2";
+            label2.Size = new Size(68, 28);
+            label2.TabIndex = 1;
+            label2.Text = "鏈�澶х伆搴﹀��";
+            label2.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label20
+            // 
+            label20.AutoSize = true;
+            label20.Location = new Point(201, 51);
+            label20.Name = "label20";
+            label20.Size = new Size(56, 17);
+            label20.TabIndex = 20;
+            label20.Text = "鏈�澶ф暟閲�";
+            // 
+            // dtxtMaxCount
+            // 
+            dtxtMaxCount.Location = new Point(291, 54);
+            dtxtMaxCount.Name = "dtxtMaxCount";
+            dtxtMaxCount.Size = new Size(97, 23);
+            dtxtMaxCount.TabIndex = 18;
+            dtxtMaxCount.Text = "9999";
+            // 
+            // label3
+            // 
+            label3.AutoSize = true;
+            label3.Location = new Point(3, 153);
+            label3.Name = "label3";
+            label3.Size = new Size(44, 17);
+            label3.TabIndex = 21;
+            label3.Text = "鏉$爜澶�";
+            // 
+            // stxtCodeHead
+            // 
+            stxtCodeHead.Location = new Point(93, 156);
+            stxtCodeHead.Name = "stxtCodeHead";
+            stxtCodeHead.Size = new Size(97, 23);
+            stxtCodeHead.TabIndex = 22;
+            // 
+            // label4
+            // 
+            label4.AutoSize = true;
+            label4.Location = new Point(3, 102);
+            label4.Name = "label4";
+            label4.Size = new Size(56, 17);
+            label4.TabIndex = 23;
+            label4.Text = "鏉$爜绫诲瀷";
+            // 
+            // cmbCode2dType
+            // 
+            cmbCode2dType.FormattingEnabled = true;
+            cmbCode2dType.Location = new Point(93, 105);
+            cmbCode2dType.Name = "cmbCode2dType";
+            cmbCode2dType.Size = new Size(97, 25);
+            cmbCode2dType.TabIndex = 24;
+            // 
+            // label10
+            // 
+            label10.AutoSize = true;
+            label10.Location = new Point(201, 153);
+            label10.Name = "label10";
+            label10.Size = new Size(56, 17);
+            label10.TabIndex = 25;
+            label10.Text = "鏉$爜闀垮害";
+            // 
+            // dtxtCodeLength
+            // 
+            dtxtCodeLength.Location = new Point(291, 156);
+            dtxtCodeLength.Name = "dtxtCodeLength";
+            dtxtCodeLength.Size = new Size(97, 23);
+            dtxtCodeLength.TabIndex = 26;
+            // 
+            // pnlInputImage
+            // 
+            pnlInputImage.Dock = DockStyle.Fill;
+            pnlInputImage.Location = new Point(3, 3);
+            pnlInputImage.Margin = new Padding(4);
+            pnlInputImage.Name = "pnlInputImage";
+            pnlInputImage.Size = new Size(607, 510);
+            pnlInputImage.TabIndex = 44;
+            // 
+            // TopToolStrip
+            // 
+            TopToolStrip.Items.AddRange(new ToolStripItem[] { btnRun, btnLoadImage, btnSaveParas, btnLoadParas });
+            TopToolStrip.Location = new Point(0, 0);
+            TopToolStrip.Name = "TopToolStrip";
+            TopToolStrip.Size = new Size(1044, 25);
+            TopToolStrip.TabIndex = 45;
+            TopToolStrip.Text = "toolStrip1";
+            // 
+            // btnRun
+            // 
+            btnRun.BackgroundImageLayout = ImageLayout.Zoom;
+            btnRun.ImageTransparentColor = Color.Magenta;
+            btnRun.Name = "btnRun";
+            btnRun.Size = new Size(36, 22);
+            btnRun.Text = "杩愯";
+            btnRun.Click += btnRun_Click;
+            // 
+            // btnLoadImage
+            // 
+            btnLoadImage.ImageTransparentColor = Color.Magenta;
+            btnLoadImage.Name = "btnLoadImage";
+            btnLoadImage.Size = new Size(36, 22);
+            btnLoadImage.Text = "瀵煎浘";
+            btnLoadImage.Click += btnLoadImage_Click;
+            // 
+            // btnSaveParas
+            // 
+            btnSaveParas.ImageTransparentColor = Color.Magenta;
+            btnSaveParas.Name = "btnSaveParas";
+            btnSaveParas.Size = new Size(36, 22);
+            btnSaveParas.Text = "淇濆瓨";
+            btnSaveParas.Click += btnSaveParas_Click;
+            // 
+            // btnLoadParas
+            // 
+            btnLoadParas.ImageTransparentColor = Color.Magenta;
+            btnLoadParas.Name = "btnLoadParas";
+            btnLoadParas.Size = new Size(36, 22);
+            btnLoadParas.Text = "鍔犺浇";
+            btnLoadParas.Click += btnLoadParas_Click;
+            // 
+            // BtmStatusStrip
+            // 
+            BtmStatusStrip.Items.AddRange(new ToolStripItem[] { lblResult, lblMsg, lblRunTime });
+            BtmStatusStrip.Location = new Point(0, 577);
+            BtmStatusStrip.Name = "BtmStatusStrip";
+            BtmStatusStrip.Size = new Size(1044, 22);
+            BtmStatusStrip.TabIndex = 46;
+            BtmStatusStrip.Text = "statusStrip1";
+            // 
+            // lblResult
+            // 
+            lblResult.Name = "lblResult";
+            lblResult.Size = new Size(34, 17);
+            lblResult.Text = "True";
+            // 
+            // lblMsg
+            // 
+            lblMsg.Name = "lblMsg";
+            lblMsg.Size = new Size(56, 17);
+            lblMsg.Text = "杩愯鎴愬姛";
+            // 
+            // lblRunTime
+            // 
+            lblRunTime.Name = "lblRunTime";
+            lblRunTime.Size = new Size(32, 17);
+            lblRunTime.Text = "0ms";
+            // 
+            // MainTableLayoutPanel
+            // 
+            MainTableLayoutPanel.ColumnCount = 2;
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F));
+            MainTableLayoutPanel.Controls.Add(parasTabControl, 0, 0);
+            MainTableLayoutPanel.Controls.Add(imgTabControl, 1, 0);
+            MainTableLayoutPanel.Dock = DockStyle.Fill;
+            MainTableLayoutPanel.Location = new Point(0, 25);
+            MainTableLayoutPanel.Name = "MainTableLayoutPanel";
+            MainTableLayoutPanel.RowCount = 1;
+            MainTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            MainTableLayoutPanel.Size = new Size(1044, 552);
+            MainTableLayoutPanel.TabIndex = 47;
+            // 
+            // parasTabControl
+            // 
+            parasTabControl.Controls.Add(tabPage1);
+            parasTabControl.Controls.Add(tabPage5);
+            parasTabControl.Controls.Add(tabPage2);
+            parasTabControl.Dock = DockStyle.Fill;
+            parasTabControl.Location = new Point(3, 3);
+            parasTabControl.Name = "parasTabControl";
+            parasTabControl.SelectedIndex = 0;
+            parasTabControl.Size = new Size(411, 546);
+            parasTabControl.TabIndex = 48;
+            // 
+            // tabPage1
+            // 
+            tabPage1.Controls.Add(tablePanelParas);
+            tabPage1.Location = new Point(4, 26);
+            tabPage1.Name = "tabPage1";
+            tabPage1.Padding = new Padding(3);
+            tabPage1.Size = new Size(403, 516);
+            tabPage1.TabIndex = 0;
+            tabPage1.Text = "杈撳叆鍙傛暟";
+            tabPage1.UseVisualStyleBackColor = true;
+            // 
+            // tabPage5
+            // 
+            tabPage5.Controls.Add(tableLayoutPanel2);
+            tabPage5.Location = new Point(4, 26);
+            tabPage5.Name = "tabPage5";
+            tabPage5.Size = new Size(403, 516);
+            tabPage5.TabIndex = 2;
+            tabPage5.Text = "杩愯鍙傛暟";
+            tabPage5.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 4;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 60F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 150F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(cmbTypeRoi, 1, 0);
+            tableLayoutPanel2.Controls.Add(label21, 0, 0);
+            tableLayoutPanel2.Controls.Add(label22, 0, 1);
+            tableLayoutPanel2.Controls.Add(cmbFixture, 1, 1);
+            tableLayoutPanel2.Controls.Add(ckbDrawRoi, 2, 0);
+            tableLayoutPanel2.Location = new Point(3, 3);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 3;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(323, 196);
+            tableLayoutPanel2.TabIndex = 5;
+            // 
+            // cmbTypeRoi
+            // 
+            cmbTypeRoi.FormattingEnabled = true;
+            cmbTypeRoi.Location = new Point(63, 3);
+            cmbTypeRoi.Name = "cmbTypeRoi";
+            cmbTypeRoi.Size = new Size(121, 25);
+            cmbTypeRoi.TabIndex = 1;
+            cmbTypeRoi.SelectedIndexChanged += cmbTypeRoi_SelectedIndexChanged;
+            // 
+            // label21
+            // 
+            label21.AutoSize = true;
+            label21.Dock = DockStyle.Fill;
+            label21.Location = new Point(3, 0);
+            label21.Name = "label21";
+            label21.Size = new Size(54, 30);
+            label21.TabIndex = 3;
+            label21.Text = "ROI";
+            label21.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label22
+            // 
+            label22.AutoSize = true;
+            label22.Dock = DockStyle.Fill;
+            label22.Location = new Point(3, 30);
+            label22.Name = "label22";
+            label22.Size = new Size(54, 30);
+            label22.TabIndex = 4;
+            label22.Text = "Fixture";
+            label22.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbFixture
+            // 
+            cmbFixture.FormattingEnabled = true;
+            cmbFixture.Location = new Point(63, 33);
+            cmbFixture.Name = "cmbFixture";
+            cmbFixture.Size = new Size(121, 25);
+            cmbFixture.TabIndex = 5;
+            cmbFixture.SelectedIndexChanged += cmbFixture_SelectedIndexChanged;
+            // 
+            // ckbDrawRoi
+            // 
+            ckbDrawRoi.AutoSize = true;
+            ckbDrawRoi.CheckAlign = ContentAlignment.MiddleCenter;
+            ckbDrawRoi.Location = new Point(213, 3);
+            ckbDrawRoi.Name = "ckbDrawRoi";
+            ckbDrawRoi.Size = new Size(14, 14);
+            ckbDrawRoi.TabIndex = 2;
+            ckbDrawRoi.UseVisualStyleBackColor = true;
+            ckbDrawRoi.CheckedChanged += ckbDrawRoi_CheckedChanged;
+            // 
+            // tabPage2
+            // 
+            tabPage2.Controls.Add(tableLayoutResults);
+            tabPage2.Location = new Point(4, 26);
+            tabPage2.Name = "tabPage2";
+            tabPage2.Padding = new Padding(3);
+            tabPage2.Size = new Size(403, 516);
+            tabPage2.TabIndex = 1;
+            tabPage2.Text = "杈撳嚭缁撴灉";
+            tabPage2.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutResults
+            // 
+            tableLayoutResults.ColumnCount = 2;
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutResults.Controls.Add(label5, 0, 0);
+            tableLayoutResults.Controls.Add(stxtCodeStrings, 1, 0);
+            tableLayoutResults.Controls.Add(label18, 0, 1);
+            tableLayoutResults.Controls.Add(dtxtCount, 1, 1);
+            tableLayoutResults.Dock = DockStyle.Fill;
+            tableLayoutResults.Location = new Point(3, 3);
+            tableLayoutResults.Margin = new Padding(2, 3, 2, 3);
+            tableLayoutResults.Name = "tableLayoutResults";
+            tableLayoutResults.RowCount = 10;
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.Size = new Size(397, 510);
+            tableLayoutResults.TabIndex = 1;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Dock = DockStyle.Fill;
+            label5.Location = new Point(2, 0);
+            label5.Margin = new Padding(2, 0, 2, 0);
+            label5.MaximumSize = new Size(0, 28);
+            label5.MinimumSize = new Size(0, 28);
+            label5.Name = "label5";
+            label5.Size = new Size(96, 28);
+            label5.TabIndex = 0;
+            label5.Text = "缁撴灉";
+            label5.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // stxtCodeStrings
+            // 
+            stxtCodeStrings.Dock = DockStyle.Fill;
+            stxtCodeStrings.Location = new Point(102, 3);
+            stxtCodeStrings.Margin = new Padding(2, 3, 2, 3);
+            stxtCodeStrings.Multiline = true;
+            stxtCodeStrings.Name = "stxtCodeStrings";
+            stxtCodeStrings.ReadOnly = true;
+            stxtCodeStrings.Size = new Size(293, 45);
+            stxtCodeStrings.TabIndex = 5;
+            // 
+            // label18
+            // 
+            label18.AutoSize = true;
+            label18.Dock = DockStyle.Fill;
+            label18.Location = new Point(3, 51);
+            label18.Name = "label18";
+            label18.Size = new Size(94, 51);
+            label18.TabIndex = 10;
+            label18.Text = "鏁伴噺";
+            label18.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCount
+            // 
+            dtxtCount.Dock = DockStyle.Fill;
+            dtxtCount.Location = new Point(103, 54);
+            dtxtCount.Name = "dtxtCount";
+            dtxtCount.ReadOnly = true;
+            dtxtCount.Size = new Size(291, 23);
+            dtxtCount.TabIndex = 11;
+            // 
+            // imgTabControl
+            // 
+            imgTabControl.Controls.Add(tabPageInputImage);
+            imgTabControl.Controls.Add(tabPageRecordImage);
+            imgTabControl.Dock = DockStyle.Fill;
+            imgTabControl.Location = new Point(420, 3);
+            imgTabControl.Name = "imgTabControl";
+            imgTabControl.SelectedIndex = 0;
+            imgTabControl.Size = new Size(621, 546);
+            imgTabControl.TabIndex = 49;
+            // 
+            // tabPageInputImage
+            // 
+            tabPageInputImage.Controls.Add(pnlInputImage);
+            tabPageInputImage.Location = new Point(4, 26);
+            tabPageInputImage.Name = "tabPageInputImage";
+            tabPageInputImage.Padding = new Padding(3);
+            tabPageInputImage.Size = new Size(613, 516);
+            tabPageInputImage.TabIndex = 0;
+            tabPageInputImage.Text = "杈撳叆鍥惧儚";
+            tabPageInputImage.UseVisualStyleBackColor = true;
+            // 
+            // tabPageRecordImage
+            // 
+            tabPageRecordImage.Controls.Add(pnlRecordImage);
+            tabPageRecordImage.Location = new Point(4, 26);
+            tabPageRecordImage.Name = "tabPageRecordImage";
+            tabPageRecordImage.Padding = new Padding(3);
+            tabPageRecordImage.Size = new Size(613, 516);
+            tabPageRecordImage.TabIndex = 1;
+            tabPageRecordImage.Text = "缁撴灉鍥惧儚";
+            tabPageRecordImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlRecordImage
+            // 
+            pnlRecordImage.Dock = DockStyle.Fill;
+            pnlRecordImage.Location = new Point(3, 3);
+            pnlRecordImage.Margin = new Padding(4);
+            pnlRecordImage.Name = "pnlRecordImage";
+            pnlRecordImage.Size = new Size(607, 510);
+            pnlRecordImage.TabIndex = 45;
+            // 
+            // HFindCode2dToolEdit
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(MainTableLayoutPanel);
+            Controls.Add(BtmStatusStrip);
+            Controls.Add(TopToolStrip);
+            Margin = new Padding(2, 3, 2, 3);
+            Name = "HFindCode2dToolEdit";
+            Size = new Size(1044, 599);
+            Load += HFindCode2dToolEdit_Load;
+            tablePanelParas.ResumeLayout(false);
+            tablePanelParas.PerformLayout();
+            TopToolStrip.ResumeLayout(false);
+            TopToolStrip.PerformLayout();
+            BtmStatusStrip.ResumeLayout(false);
+            BtmStatusStrip.PerformLayout();
+            MainTableLayoutPanel.ResumeLayout(false);
+            parasTabControl.ResumeLayout(false);
+            tabPage1.ResumeLayout(false);
+            tabPage5.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel2.PerformLayout();
+            tabPage2.ResumeLayout(false);
+            tableLayoutResults.ResumeLayout(false);
+            tableLayoutResults.PerformLayout();
+            imgTabControl.ResumeLayout(false);
+            tabPageInputImage.ResumeLayout(false);
+            tabPageRecordImage.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TableLayoutPanel tablePanelParas;
+        private System.Windows.Forms.Panel pnlInputImage;
+        private ToolStrip TopToolStrip;
+        private ToolStripButton btnRun;
+        private StatusStrip BtmStatusStrip;
+        private ToolStripStatusLabel lblResult;
+        private ToolStripStatusLabel lblMsg;
+        private TableLayoutPanel MainTableLayoutPanel;
+        private ToolStripButton btnLoadImage;
+        private TabControl parasTabControl;
+        private TabPage tabPage1;
+        private TabPage tabPage2;
+        private TableLayoutPanel tableLayoutResults;
+        private Label label5;
+        private Label label6;
+        private Label label7;
+        private Label label8;
+        private TextBox stxtCodeStrings;
+        private TextBox dtxtCenterY;
+        private TextBox dtxtAngle;
+        private TextBox dtxtWidth;
+        private TextBox dtxtHeight;
+        private Label label9;
+        private TabPage tabPage5;
+        private TabControl imgTabControl;
+        private TabPage tabPageInputImage;
+        private TabPage tabPageRecordImage;
+        private ToolStripButton btnSaveParas;
+        private ToolStripButton btnLoadParas;
+        private Panel pnlRecordImage;
+        private Label label1;
+        private TextBox dtxtMinThreshold;
+        private Label label2;
+        private TextBox dtxtMaxThreshold;
+        private Label label18;
+        private TextBox dtxtCount;
+        private TextBox dtxtMinCount;
+        private TextBox dtxtMaxCount;
+        private Label label19;
+        private Label label20;
+        private Label label3;
+        private TextBox stxtCodeHead;
+        private Label label4;
+        private ComboBox cmbCode2dType;
+        private ToolStripStatusLabel lblRunTime;
+        private Label label10;
+        private TextBox dtxtCodeLength;
+        private TableLayoutPanel tableLayoutPanel2;
+        public ComboBox cmbTypeRoi;
+        private Label label21;
+        private Label label22;
+        private ComboBox cmbFixture;
+        private CheckBox ckbDrawRoi;
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.cs
new file mode 100644
index 0000000..e0bdaec
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.cs
@@ -0,0 +1,325 @@
+锘縰sing HalconDotNet;
+using LB_VisionProcesses.Alogrithms.Halcon;
+using static LB_VisionProcesses.Alogrithms.Halcon.HFindCode2dTool;
+using LB_VisionControl;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    public partial class HFindCode2dToolEdit : TAlgorithmEdit
+    {
+        public HFindCode2dToolEdit(HFindCode2dTool subject = null)
+        {
+            if (subject != null && subject is HFindCode2dTool)
+                Subject = subject;
+            else
+                Subject = new HFindCode2dTool();
+
+            this.Dock = DockStyle.Fill;
+            InitializeComponent();
+        }
+
+        /// <summary>
+        /// 鎺т欢鍔犺浇浜嬩欢
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void HFindCode2dToolEdit_Load(object sender, EventArgs e)
+        {
+            pnlInputImage.Controls.Add(inputImageHSmartWindowControl);
+            inputImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            pnlRecordImage.Controls.Add(recordImageHSmartWindowControl);
+            recordImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            //閬嶅巻鍙互閫夋嫨鐨凴oi绫诲瀷鏋氫妇
+            foreach (var value in Enum.GetValues(typeof(RoiType)))
+                cmbTypeRoi.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨勬潯鐮佺被鍨嬫灇涓�
+            foreach (var value in Enum.GetValues(typeof(Code2dType)))
+                cmbCode2dType.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨凢ixture鏋氫妇
+            cmbFixture.Items.Add("");
+            foreach (string value in IProcess.dicFixtures.Keys)
+                cmbFixture.Items.Add(value.ToString());
+
+            cmbTypeRoi.Text = RoiType.None.ToString();
+            cmbCode2dType.Text = Code2dType.None.ToString();
+            LoadParas();
+
+            if (Subject.Result)
+            {
+                lblResult.BackColor = Color.Green;
+                lblResult.Text = "True";
+            }
+            else
+            {
+                lblResult.BackColor = Color.Red;
+                lblResult.Text = "False";
+            }
+
+            lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+            lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+            lblRunTime.Text = $"{Subject.RunTime}ms";
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯鍙傛暟
+        /// </summary>
+        public override void UpdataInputs()
+        {
+            //璁剧疆杩愯鍙傛暟
+            int iResult = 0;
+
+            Subject.Params.Inputs["Code2dType"] = cmbCode2dType.SelectedItem.ToString();
+            Subject.Params.Inputs["CodeHead"] = stxtCodeHead.Text;
+            Subject.Params.Inputs["CodeLength"] = int.TryParse(dtxtCodeLength.Text, out iResult) ? iResult : Subject.Params.Inputs["CodeLength"];
+
+            Subject.Params.Inputs["MinThreshold"] = int.TryParse(dtxtMinThreshold.Text, out iResult) ? iResult : Subject.Params.Inputs["MinThreshold"];
+            Subject.Params.Inputs["MaxThreshold"] = int.TryParse(dtxtMaxThreshold.Text, out iResult) ? iResult : Subject.Params.Inputs["MaxThreshold"];
+            Subject.Params.Inputs["MinCount"] = int.TryParse(dtxtMinCount.Text, out iResult) ? iResult : Subject.Params.Inputs["MinCount"];
+            Subject.Params.Inputs["MaxCount"] = int.TryParse(dtxtMaxCount.Text, out iResult) ? iResult : Subject.Params.Inputs["MaxCount"];
+
+            if (cmbFixture.Text == "")
+                Subject.Params.Fixture = new Fixture();
+            else if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+
+            base.UpdataInputs();
+        }
+
+        /// <summary>
+        /// 鍔犺浇杩愯鍙傛暟
+        /// </summary>
+        public override void LoadParas()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                cmbCode2dType.Text = ProcessParams.ConvertToString(Subject.Params.Inputs["Code2dType"]);
+                stxtCodeHead.Text = ProcessParams.ConvertToString(Subject.Params.Inputs["CodeHead"]);
+                dtxtCodeLength.Text = Subject.Params.Inputs["CodeLength"].ToString();
+
+                dtxtMinThreshold.Text = Subject.Params.Inputs["MinThreshold"].ToString();
+                dtxtMaxThreshold.Text = Subject.Params.Inputs["MaxThreshold"].ToString();
+
+                dtxtMinCount.Text = Subject.Params.Inputs["MinCount"].ToString();
+                dtxtMaxCount.Text = Subject.Params.Inputs["MaxCount"].ToString();
+
+                if (Subject.InputImage != null && Subject.InputImage is HObject)
+                    inputImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+
+                Type type = Subject.Params.ROI?.GetType();
+                if (Subject.Params.ROI != null)
+                {
+                    switch (type)
+                    {
+                        case Type t when t == typeof(HRectangle2):
+                            cmbTypeRoi.Text = RoiType.Rectangle2.ToString();
+                            break;
+                        case Type t when t == typeof(HCircle):
+                            cmbTypeRoi.Text = RoiType.Circle.ToString();
+                            break;
+                        case Type t when t == typeof(HSegment):
+                            cmbTypeRoi.Text = RoiType.Segment.ToString();
+                            break;
+                        default:
+                            cmbTypeRoi.Text = RoiType.None.ToString();
+                            break;
+                    }
+                    if (cmbTypeRoi.Text.ToString() != "None")
+                        ckbDrawRoi.Checked = true;
+                    else
+                        ckbDrawRoi.Checked = false;
+
+                    inputImageHSmartWindowControl.oRoi = Subject.Params.ROI;
+                }
+
+                if (Subject.Params.Fixture != null)
+                    cmbFixture.Text = Subject.Params.Fixture.strName;
+                else
+                    cmbFixture.Text = "";
+
+                base.LoadParas();
+            }));
+        }
+
+        /// <summary>
+        /// 鏇存柊杈撳嚭缁撴灉
+        /// </summary>
+        public override void UpdataOutputs()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                //瀛樺湪鍙嶅簭鍒楀寲閿欎贡鐨勬儏鍐甸渶瑕佷娇鐢ㄨ嚜瀹氫箟鐨勮浆鎹㈠櫒
+                stxtCodeStrings.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CodeStrings"]);
+                dtxtCount.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Count"]);
+            }));
+        }
+
+        /// <summary>
+        /// 鐐瑰嚮杩愯
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        public override void btnRun_Click(object sender, EventArgs e)
+        {
+            if (Subject.InputImage != null)
+                InputImage = Subject.InputImage;
+
+            DateTime StartTime = DateTime.Now;
+            Run();
+
+            //鏇存柊鏃ュ織涓庣粨鏋�
+            this.BeginInvoke(new Action(() =>
+            {
+                if (Subject.Result)
+                {
+                    lblResult.BackColor = Color.Green;
+                    lblResult.Text = "True";
+                    recordImageHSmartWindowControl.SetColor("green");
+                }
+                else
+                {
+                    lblResult.BackColor = Color.Red;
+                    lblResult.Text = "False";
+                    recordImageHSmartWindowControl.SetColor("red");
+                }
+
+                lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+                lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+                lblRunTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
+
+                UpdataOutputs();
+                imgTabControl.SelectedTab = tabPageRecordImage;
+
+                if (Subject.InputImage != null && Subject.InputImage is HObject)
+                {
+                    HOperatorSet.GetImageSize((HObject)Subject.InputImage, out HTuple ho_ImageWidth, out HTuple ho_ImageHeight);
+                    recordImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+                }
+
+                //鍏堝垽鏂瓙绫诲啀鍒ゆ柇鐖剁被
+                if (Subject.Record != null && Subject.Record is MsgRecord msgRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_NG, false);
+
+                    for (int i = 0; i < msgRecord.Msg.Length; i++)
+                        recordImageHSmartWindowControl.ShowMsg(msgRecord.Msg[i]
+                            , 1 == msgRecord.Result[i] ? true : false, msgRecord.Column[i], msgRecord.Row[i]);
+                }
+                else if (Subject.Record != null && Subject.Record is ObjectRecord objRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_NG, false);
+                }
+
+                GC.Collect();
+            }));
+        }
+
+        private new void btnLoadImage_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    HOperatorSet.ReadImage(out HObject ho_Image, selectedFiles[0]);
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.CountChannels(ho_Image, out HTuple hv_Channels);
+                        if (hv_Channels.TupleInt() != 1)
+                        {
+                            HOperatorSet.Rgb1ToGray(ho_Image, out ho_Image);
+                            //鏇存柊鏃ュ織涓庣粨鏋�
+                            this.BeginInvoke(new Action(() =>
+                            {
+                                lblMsg.Text = "瀵煎叆鍥剧墖闈炵伆搴﹀浘,鑷姩杞崲涓虹伆搴﹀浘";
+                            }));
+                        }
+                        InputImage = ho_Image;
+                        imgTabControl.SelectedTab = tabPageInputImage;
+                        inputImageHSmartWindowControl.oRoi = inputImageHSmartWindowControl.oRoi;
+                    }
+                }
+            }
+        }
+
+        public override void btnSaveParas_Click(object sender, EventArgs e) { base.btnSaveParas_Click(sender, e); }
+
+        public override void ckbDrawRoi_CheckedChanged(object sender, EventArgs e)
+        {
+            if (ckbDrawRoi.Checked)
+            {
+                inputImageHSmartWindowControl.bAollowDraw = true;
+                imgTabControl.SelectedTab = tabPageInputImage;
+            }
+            else
+            {
+                inputImageHSmartWindowControl.bAollowDraw = false;
+                Subject.Params.ROI = new ROI();
+            }
+        }
+
+        public override void cmbTypeRoi_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (Enum.TryParse(cmbTypeRoi.Text.ToString(), out RoiType type))
+                {
+                    HTuple hv_imageWidth = 0;
+                    HTuple hv_imageHeight = 0;
+                    if (InputImage != null && InputImage is HObject)
+                        HOperatorSet.GetImageSize((HObject)InputImage, out hv_imageWidth, out hv_imageHeight);
+                    switch (type)
+                    {
+                        case RoiType.Rectangle2:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, 0
+                                , hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.Circle:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HCircle(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, hv_imageWidth.TupleReal() / 4);
+                            break;
+                        case RoiType.Segment:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HSegment(0, 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.None:
+                        default:
+                            inputImageHSmartWindowControl.oRoi = null;
+                            break;
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public override void cmbFixture_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+                else
+                    Subject.Params.Fixture = new Fixture();
+            }
+            catch { }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.resx b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.resx
new file mode 100644
index 0000000..7600563
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindCode2dTool/HFindCode2dToolEdit.resx
@@ -0,0 +1,126 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema 
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="TopToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="BtmStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>148, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineTool.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineTool.cs
new file mode 100644
index 0000000..533a89c
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineTool.cs
@@ -0,0 +1,267 @@
+锘縰sing HalconDotNet;
+using LB_VisionControl;
+using LB_VisionProcesses.Alogrithms.Halcon;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static LB_VisionProcesses.Alogrithms.Halcon.HFindCode2dTool;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    public enum Transition { Positive, Negative, Ignore }
+
+    public enum Selector { First, Last, Best }
+    [Process("Halcon2D鎵剧嚎宸ュ叿", Category = "Halcon2D宸ュ叿", Description = "鍒涘缓鎵剧嚎宸ュ叿")]
+    public class HFindLineTool : TAlgorithm
+    {
+        public HFindLineTool()
+        {
+            strProcessClass = "LB_VisionProcesses.Alogrithms.Halcon.HFindLineTool";
+            strProcessName = "Halcon2D鎵剧嚎宸ュ叿";
+
+            Params.Inputs.Add("鍗″昂鏁伴噺", 6);
+            Params.Inputs.Add("鍗″昂闀垮害", 30);
+            Params.Inputs.Add("鍗″昂瀹藉害", 10);
+            Params.Inputs.Add("杩囨护涓�鍗婂儚绱�", 2);
+            Params.Inputs.Add("瀵规瘮搴﹂槇鍊�", 5);
+            Params.Inputs.Add("鏋佹��", "Ignore");
+            Params.Inputs.Add("杈圭紭浣嶇疆", "Best");
+            Params.Inputs.Add("蹇界暐鐐规暟", 0);
+
+            Params.Outputs.Add("X", new List<double>());
+            Params.Outputs.Add("Y", new List<double>());
+            Params.Outputs.Add("CenterX", 0.0);
+            Params.Outputs.Add("CenterY", 0.0);
+            Params.Outputs.Add("Phi", 0.0);
+            Params.Outputs.Add("Angle", 0.0);
+            Params.Outputs.Add("Count", 0);
+            Params.Outputs.Add("Segment", new HSegment());
+
+            Params.ROI = new HSegment(0, 0, 250, 250);
+        }
+
+        /// <summary>
+        /// 绠楀瓙閫昏緫
+        /// </summary>
+        public override void TAlgorithmMain()
+        {
+            #region 鍒濆鍖栧彉閲�
+            HObject ho_Regions, ho_LineXld;
+            HOperatorSet.GenEmptyObj(out ho_Regions);
+            HOperatorSet.GenEmptyObj(out ho_LineXld);
+            #endregion
+
+            try
+            {
+                if (InputImage == null)
+                {
+                    Msg = "杈撳叆鍥剧墖涓虹┖";
+                    Result = false;
+                    return;
+                }
+
+                #region 瑁佸壀鍖哄煙
+                if (!(Params.ROI is HSegment))
+                {
+                    Msg = "ROI绫诲瀷閿欒,蹇呴』涓篐Segment绫诲瀷";
+                    Result = false;
+                    return;
+                }
+
+                if (!(InputImage is HObject))
+                {
+                    Msg = "杈撳叆鍥剧墖绫诲瀷閿欒,蹇呴』涓篐Object绫诲瀷";
+                    Result = false;
+                    return;
+                }
+
+                HObject DomainImage = ((HObject)InputImage)?.CopyObj(1, -1);
+                #endregion
+
+                #region 绠楀瓙閫昏緫
+                Record = new ObjectRecord();
+                HObject hoDomainImage = DomainImage as HObject;
+                HTuple hv_Channels = new HTuple();
+                //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    try
+                    {
+                        HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                        if (hv_Channels.TupleInt() != 1)
+                            HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+
+                        //杞崲鍚庡啀娆℃鏌ユ槸鍚︿负鐏板害鍥�
+                        HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                        if (hv_Channels.TupleInt() != 1)
+                        {
+                            HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+                            Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥�";
+                            Result = false;
+                            return;
+                        }
+                    }
+                    catch
+                    {
+                        Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥句笖杞崲澶辫触";
+                        Result = false;
+                        return;
+                    }
+                }
+
+                int hv_Elements = Convert.ToInt16(Params.Inputs["鍗″昂鏁伴噺"]);
+                double hv_DetectHeight = Convert.ToDouble(Params.Inputs["鍗″昂闀垮害"]);
+                double hv_DetectWidth = Convert.ToDouble(Params.Inputs["鍗″昂瀹藉害"]);
+                int hv_Sigma = Convert.ToInt16(Params.Inputs["杩囨护涓�鍗婂儚绱�"]);
+                int hv_Threshold = Convert.ToInt16(Params.Inputs["瀵规瘮搴﹂槇鍊�"]);
+                int hv_IgnoreNum = Convert.ToInt16(Params.Inputs["蹇界暐鐐规暟"]);
+
+                Enum.TryParse(Params.Inputs["鏋佹��"]?.ToString(), out Transition transition);
+                string hv_Transition = "ignore";
+                switch (transition)
+                {
+                    case Transition.Positive:
+                        hv_Transition = "positive";
+                        break;
+                    case Transition.Negative:
+                        hv_Transition = "negative";
+                        break;
+                    case Transition.Ignore:
+                    default:
+                        hv_Transition = "ignore";
+                        break;
+                }
+
+                Enum.TryParse(Params.Inputs["杈圭紭浣嶇疆"]?.ToString(), out Selector selector);
+                string hv_Select = "best";
+                switch (selector)
+                {
+                    case Selector.First:
+                        hv_Select = "first";
+                        break;
+                    case Selector.Last:
+                        hv_Select = "last";
+                        break;
+                    case Selector.Best:
+                    default:
+                        hv_Select = "best";
+                        break;
+                }
+
+                double hv_Row1 = Convert.ToDouble(((HSegment)Params.ROI).BeginRow + Params.Fixture.Row);
+                double hv_Column1 = Convert.ToDouble(((HSegment)Params.ROI).BeginColumn + Params.Fixture.Column);
+                double hv_Row2 = Convert.ToDouble(((HSegment)Params.ROI).EndRow + Params.Fixture.Row);
+                double hv_Column2 = Convert.ToDouble(((HSegment)Params.ROI).EndColumn + Params.Fixture.Column);
+
+                Rake(hoDomainImage, out ho_Regions, hv_Elements, hv_DetectHeight, hv_DetectWidth
+                    , hv_Sigma, hv_Threshold, hv_Transition, hv_Select
+                    , hv_Row1, hv_Column1, hv_Row2, hv_Column2
+                    , out HTuple hv_ResultRow, out HTuple hv_ResultColumn);
+                #endregion
+
+                #region 缁撴灉澶勭悊
+                List<double> X = new List<double>();
+                List<double> Y = new List<double>();
+                double CenterX = 0;
+                double CenterY = 0;
+                double Phi = 0;
+                HSegment HSegment = new HSegment();
+                if (hv_ResultRow.Type != HTupleType.EMPTY && hv_ResultRow.Length > 0)
+                {
+                    for (int k = 0; k < hv_ResultRow.Length; k++)
+                    {
+                        Y.Add(hv_ResultRow[k].D);
+                        X.Add(hv_ResultColumn[k].D);
+                    }
+
+                    if (X.Count >= 3)
+                    {
+                        pts_to_best_line(out ho_LineXld, hv_ResultRow, hv_ResultColumn, hv_IgnoreNum
+                            , out HTuple hv_Row11, out HTuple hv_Column11, out HTuple hv_Row21, out HTuple hv_Column21);
+                        ((ObjectRecord)Record).AddXld(ho_LineXld);
+                        CenterX = (hv_Column11.D + hv_Column21.D) / 2;
+                        CenterY = (hv_Row11.D + hv_Row21.D) / 2;
+
+                        //璁$畻鐩寸嚎涓巟杞寸殑澶硅锛岄�嗘椂閽堟柟鍚戜负姝e悜
+                        HOperatorSet.AngleLx(hv_Row11, hv_Column11, hv_Row21, hv_Column21, out HTuple hv_ATan);
+                        Phi = hv_ATan;
+
+                        HSegment = new HSegment(hv_Column11.D, hv_Row11.D, hv_Column21.D, hv_Row21.D);
+                    }
+                    else
+                    {
+                        Msg = "鎵剧嚎澶辫触";
+                        Result = false;
+                        return;
+                    }
+                }
+                else
+                {
+                    Msg = "鎵剧嚎澶辫触";
+                    Result = false;
+                    return;
+                }
+                Params.Outputs["X"] = X;
+                Params.Outputs["Y"] = Y;
+                Params.Outputs["CenterX"] = CenterX;
+                Params.Outputs["CenterY"] = CenterY;
+                Params.Outputs["Phi"] = Phi;
+                Params.Outputs["Angle"] = Phi * 180.0 / Math.PI;
+                Params.Outputs["Count"] = X.Count;
+                Params.Outputs["Segment"] = HSegment;
+                #endregion
+
+                #region 鐢熸垚OutputImage缁欏悗缁鐞�
+                try
+                {
+                    OutputImage = hoDomainImage;
+                }
+                catch (Exception ex)
+                {
+                    Msg = "鐢熸垚OutputImage澶辫触,鍘熷洜鏄�:" + ex.ToString();
+                    Result = false;
+                    return;
+                }
+                #endregion
+
+                if (Msg == "杩愯瓒呮椂")
+                {
+                    Result = false;
+                    return;
+                }
+
+                Msg = "杩愯鎴愬姛";
+                Result = true;
+                return;
+            }
+            catch (Exception ex)
+            {
+                Msg = "杩愯澶辫触,鍘熷洜鏄�:" + ex.ToString().TrimEnd();
+                OutputImage = null;
+                Result = false;
+                return;
+            }
+            finally
+            {
+                if (!Result)
+                {
+                    Params.Outputs.Add("X", new List<double>());
+                    Params.Outputs.Add("Y", new List<double>());
+                    Params.Outputs.Add("CenterX", 0.0);
+                    Params.Outputs.Add("CenterY", 0.0);
+                    Params.Outputs.Add("Phi", 0.0);
+                    Params.Outputs.Add("Angle", 0.0);
+                    Params.Outputs.Add("Count", 0);
+                    Params.Outputs.Add("Segment", new HSegment());
+                }
+
+                bCompleted = true;
+                #region 鍐呭瓨閲婃斁
+                ho_Regions.Dispose();
+                #endregion
+            }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.Designer.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.Designer.cs
new file mode 100644
index 0000000..7190e9e
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.Designer.cs
@@ -0,0 +1,860 @@
+锘縰sing LB_VisionProcesses.Alogrithms;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    partial class HFindLineToolEdit
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tablePanelParas = new TableLayoutPanel();
+            label1 = new Label();
+            itxtCaliperCount = new TextBox();
+            label2 = new Label();
+            dtxtCaliperHeight = new TextBox();
+            label3 = new Label();
+            dtxtCaliperWidth = new TextBox();
+            label4 = new Label();
+            itxtSigma = new TextBox();
+            label10 = new Label();
+            itxtThreshold = new TextBox();
+            label11 = new Label();
+            itxtIgnoreCount = new TextBox();
+            label12 = new Label();
+            label13 = new Label();
+            cmbTransition = new ComboBox();
+            cmbSelect = new ComboBox();
+            pnlInputImage = new Panel();
+            TopToolStrip = new ToolStrip();
+            btnRun = new ToolStripButton();
+            btnLoadImage = new ToolStripButton();
+            btnSaveParas = new ToolStripButton();
+            btnLoadParas = new ToolStripButton();
+            BtmStatusStrip = new StatusStrip();
+            lblResult = new ToolStripStatusLabel();
+            lblMsg = new ToolStripStatusLabel();
+            lblRunTime = new ToolStripStatusLabel();
+            MainTableLayoutPanel = new TableLayoutPanel();
+            parasTabControl = new TabControl();
+            tabPage1 = new TabPage();
+            tabPage5 = new TabPage();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            cmbTypeRoi = new ComboBox();
+            label21 = new Label();
+            label22 = new Label();
+            cmbFixture = new ComboBox();
+            ckbDrawRoi = new CheckBox();
+            tabPage2 = new TabPage();
+            tableLayoutResults = new TableLayoutPanel();
+            dtxtHeight = new TextBox();
+            label9 = new Label();
+            label5 = new Label();
+            label6 = new Label();
+            label7 = new Label();
+            label8 = new Label();
+            dtxtCenterX = new TextBox();
+            dtxtCenterY = new TextBox();
+            dtxtAngle = new TextBox();
+            dtxtWidth = new TextBox();
+            label18 = new Label();
+            dtxtCount = new TextBox();
+            imgTabControl = new TabControl();
+            tabPageInputImage = new TabPage();
+            tabPageRecordImage = new TabPage();
+            pnlRecordImage = new Panel();
+            btnShowROI = new Button();
+            tablePanelParas.SuspendLayout();
+            TopToolStrip.SuspendLayout();
+            BtmStatusStrip.SuspendLayout();
+            MainTableLayoutPanel.SuspendLayout();
+            parasTabControl.SuspendLayout();
+            tabPage1.SuspendLayout();
+            tabPage5.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tabPage2.SuspendLayout();
+            tableLayoutResults.SuspendLayout();
+            imgTabControl.SuspendLayout();
+            tabPageInputImage.SuspendLayout();
+            tabPageRecordImage.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tablePanelParas
+            // 
+            tablePanelParas.ColumnCount = 4;
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.Controls.Add(label1, 0, 0);
+            tablePanelParas.Controls.Add(itxtCaliperCount, 1, 0);
+            tablePanelParas.Controls.Add(label2, 2, 0);
+            tablePanelParas.Controls.Add(dtxtCaliperHeight, 3, 0);
+            tablePanelParas.Controls.Add(label3, 0, 1);
+            tablePanelParas.Controls.Add(dtxtCaliperWidth, 1, 1);
+            tablePanelParas.Controls.Add(label4, 2, 1);
+            tablePanelParas.Controls.Add(itxtSigma, 3, 1);
+            tablePanelParas.Controls.Add(label10, 0, 2);
+            tablePanelParas.Controls.Add(itxtThreshold, 1, 2);
+            tablePanelParas.Controls.Add(label11, 2, 2);
+            tablePanelParas.Controls.Add(itxtIgnoreCount, 3, 2);
+            tablePanelParas.Controls.Add(label12, 0, 3);
+            tablePanelParas.Controls.Add(label13, 2, 3);
+            tablePanelParas.Controls.Add(cmbTransition, 1, 3);
+            tablePanelParas.Controls.Add(cmbSelect, 3, 3);
+            tablePanelParas.Controls.Add(btnShowROI, 0, 4);
+            tablePanelParas.Dock = DockStyle.Fill;
+            tablePanelParas.Location = new Point(3, 3);
+            tablePanelParas.Margin = new Padding(2, 3, 2, 3);
+            tablePanelParas.Name = "tablePanelParas";
+            tablePanelParas.RowCount = 10;
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.Size = new Size(397, 510);
+            tablePanelParas.TabIndex = 0;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Location = new Point(2, 0);
+            label1.Margin = new Padding(2, 0, 2, 0);
+            label1.MaximumSize = new Size(0, 28);
+            label1.MinimumSize = new Size(0, 28);
+            label1.Name = "label1";
+            label1.Size = new Size(56, 28);
+            label1.TabIndex = 0;
+            label1.Text = "鍗″昂鏁伴噺";
+            label1.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // itxtCaliperCount
+            // 
+            itxtCaliperCount.Location = new Point(92, 3);
+            itxtCaliperCount.Margin = new Padding(2, 3, 2, 3);
+            itxtCaliperCount.Name = "itxtCaliperCount";
+            itxtCaliperCount.Size = new Size(98, 23);
+            itxtCaliperCount.TabIndex = 5;
+            itxtCaliperCount.Text = "6";
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.Location = new Point(200, 0);
+            label2.Margin = new Padding(2, 0, 2, 0);
+            label2.MaximumSize = new Size(0, 28);
+            label2.MinimumSize = new Size(0, 28);
+            label2.Name = "label2";
+            label2.Size = new Size(56, 28);
+            label2.TabIndex = 1;
+            label2.Text = "鍗″昂闀垮害";
+            label2.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtCaliperHeight
+            // 
+            dtxtCaliperHeight.Location = new Point(290, 3);
+            dtxtCaliperHeight.Margin = new Padding(2, 3, 2, 3);
+            dtxtCaliperHeight.Name = "dtxtCaliperHeight";
+            dtxtCaliperHeight.Size = new Size(98, 23);
+            dtxtCaliperHeight.TabIndex = 6;
+            dtxtCaliperHeight.Text = "30";
+            // 
+            // label3
+            // 
+            label3.AutoSize = true;
+            label3.Location = new Point(2, 51);
+            label3.Margin = new Padding(2, 0, 2, 0);
+            label3.MaximumSize = new Size(0, 28);
+            label3.MinimumSize = new Size(0, 28);
+            label3.Name = "label3";
+            label3.Size = new Size(56, 28);
+            label3.TabIndex = 2;
+            label3.Text = "鍗″昂瀹藉害";
+            label3.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtCaliperWidth
+            // 
+            dtxtCaliperWidth.Location = new Point(92, 54);
+            dtxtCaliperWidth.Margin = new Padding(2, 3, 2, 3);
+            dtxtCaliperWidth.Name = "dtxtCaliperWidth";
+            dtxtCaliperWidth.Size = new Size(98, 23);
+            dtxtCaliperWidth.TabIndex = 7;
+            dtxtCaliperWidth.Text = "10";
+            // 
+            // label4
+            // 
+            label4.AutoSize = true;
+            label4.Location = new Point(200, 51);
+            label4.Margin = new Padding(2, 0, 2, 0);
+            label4.MaximumSize = new Size(0, 28);
+            label4.MinimumSize = new Size(0, 28);
+            label4.Name = "label4";
+            label4.Size = new Size(80, 28);
+            label4.TabIndex = 3;
+            label4.Text = "杩囨护涓�鍗婂儚绱�";
+            label4.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // itxtSigma
+            // 
+            itxtSigma.Location = new Point(290, 54);
+            itxtSigma.Margin = new Padding(2, 3, 2, 3);
+            itxtSigma.Name = "itxtSigma";
+            itxtSigma.Size = new Size(98, 23);
+            itxtSigma.TabIndex = 8;
+            itxtSigma.Text = "0";
+            // 
+            // label10
+            // 
+            label10.AutoSize = true;
+            label10.Location = new Point(2, 102);
+            label10.Margin = new Padding(2, 0, 2, 0);
+            label10.MaximumSize = new Size(0, 28);
+            label10.MinimumSize = new Size(0, 28);
+            label10.Name = "label10";
+            label10.Size = new Size(68, 28);
+            label10.TabIndex = 9;
+            label10.Text = "瀵规瘮搴﹂槇鍊�";
+            label10.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // itxtThreshold
+            // 
+            itxtThreshold.Location = new Point(92, 105);
+            itxtThreshold.Margin = new Padding(2, 3, 2, 3);
+            itxtThreshold.Name = "itxtThreshold";
+            itxtThreshold.Size = new Size(98, 23);
+            itxtThreshold.TabIndex = 9;
+            itxtThreshold.Text = "0";
+            // 
+            // label11
+            // 
+            label11.AutoSize = true;
+            label11.Location = new Point(200, 102);
+            label11.Margin = new Padding(2, 0, 2, 0);
+            label11.MaximumSize = new Size(0, 28);
+            label11.MinimumSize = new Size(0, 28);
+            label11.Name = "label11";
+            label11.Size = new Size(56, 28);
+            label11.TabIndex = 10;
+            label11.Text = "蹇界暐鐐规暟";
+            label11.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // itxtIgnoreCount
+            // 
+            itxtIgnoreCount.Location = new Point(290, 105);
+            itxtIgnoreCount.Margin = new Padding(2, 3, 2, 3);
+            itxtIgnoreCount.Name = "itxtIgnoreCount";
+            itxtIgnoreCount.Size = new Size(98, 23);
+            itxtIgnoreCount.TabIndex = 9;
+            itxtIgnoreCount.Text = "0";
+            // 
+            // label12
+            // 
+            label12.AutoSize = true;
+            label12.Location = new Point(2, 153);
+            label12.Margin = new Padding(2, 0, 2, 0);
+            label12.MaximumSize = new Size(0, 28);
+            label12.MinimumSize = new Size(0, 28);
+            label12.Name = "label12";
+            label12.Size = new Size(32, 28);
+            label12.TabIndex = 11;
+            label12.Text = "鏋佹��";
+            label12.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label13
+            // 
+            label13.AutoSize = true;
+            label13.Location = new Point(200, 153);
+            label13.Margin = new Padding(2, 0, 2, 0);
+            label13.MaximumSize = new Size(0, 28);
+            label13.MinimumSize = new Size(0, 28);
+            label13.Name = "label13";
+            label13.Size = new Size(56, 28);
+            label13.TabIndex = 12;
+            label13.Text = "杈圭紭浣嶇疆";
+            label13.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbTransition
+            // 
+            cmbTransition.FormattingEnabled = true;
+            cmbTransition.Location = new Point(93, 156);
+            cmbTransition.Name = "cmbTransition";
+            cmbTransition.Size = new Size(102, 25);
+            cmbTransition.TabIndex = 13;
+            // 
+            // cmbSelect
+            // 
+            cmbSelect.FormattingEnabled = true;
+            cmbSelect.Location = new Point(291, 156);
+            cmbSelect.Name = "cmbSelect";
+            cmbSelect.Size = new Size(103, 25);
+            cmbSelect.TabIndex = 14;
+            // 
+            // pnlInputImage
+            // 
+            pnlInputImage.Dock = DockStyle.Fill;
+            pnlInputImage.Location = new Point(3, 3);
+            pnlInputImage.Margin = new Padding(4);
+            pnlInputImage.Name = "pnlInputImage";
+            pnlInputImage.Size = new Size(607, 510);
+            pnlInputImage.TabIndex = 44;
+            // 
+            // TopToolStrip
+            // 
+            TopToolStrip.Items.AddRange(new ToolStripItem[] { btnRun, btnLoadImage, btnSaveParas, btnLoadParas });
+            TopToolStrip.Location = new Point(0, 0);
+            TopToolStrip.Name = "TopToolStrip";
+            TopToolStrip.Size = new Size(1044, 25);
+            TopToolStrip.TabIndex = 45;
+            TopToolStrip.Text = "toolStrip1";
+            // 
+            // btnRun
+            // 
+            btnRun.BackgroundImageLayout = ImageLayout.Zoom;
+            btnRun.ImageTransparentColor = Color.Magenta;
+            btnRun.Name = "btnRun";
+            btnRun.Size = new Size(36, 22);
+            btnRun.Text = "杩愯";
+            btnRun.Click += btnRun_Click;
+            // 
+            // btnLoadImage
+            // 
+            btnLoadImage.ImageTransparentColor = Color.Magenta;
+            btnLoadImage.Name = "btnLoadImage";
+            btnLoadImage.Size = new Size(36, 22);
+            btnLoadImage.Text = "瀵煎浘";
+            btnLoadImage.Click += btnLoadImage_Click;
+            // 
+            // btnSaveParas
+            // 
+            btnSaveParas.ImageTransparentColor = Color.Magenta;
+            btnSaveParas.Name = "btnSaveParas";
+            btnSaveParas.Size = new Size(36, 22);
+            btnSaveParas.Text = "淇濆瓨";
+            btnSaveParas.Click += btnSaveParas_Click;
+            // 
+            // btnLoadParas
+            // 
+            btnLoadParas.ImageTransparentColor = Color.Magenta;
+            btnLoadParas.Name = "btnLoadParas";
+            btnLoadParas.Size = new Size(36, 22);
+            btnLoadParas.Text = "鍔犺浇";
+            btnLoadParas.Click += btnLoadParas_Click;
+            // 
+            // BtmStatusStrip
+            // 
+            BtmStatusStrip.Items.AddRange(new ToolStripItem[] { lblResult, lblMsg, lblRunTime });
+            BtmStatusStrip.Location = new Point(0, 577);
+            BtmStatusStrip.Name = "BtmStatusStrip";
+            BtmStatusStrip.Size = new Size(1044, 22);
+            BtmStatusStrip.TabIndex = 46;
+            BtmStatusStrip.Text = "statusStrip1";
+            // 
+            // lblResult
+            // 
+            lblResult.Name = "lblResult";
+            lblResult.Size = new Size(34, 17);
+            lblResult.Text = "True";
+            // 
+            // lblMsg
+            // 
+            lblMsg.Name = "lblMsg";
+            lblMsg.Size = new Size(56, 17);
+            lblMsg.Text = "杩愯鎴愬姛";
+            // 
+            // lblRunTime
+            // 
+            lblRunTime.Name = "lblRunTime";
+            lblRunTime.Size = new Size(32, 17);
+            lblRunTime.Text = "0ms";
+            // 
+            // MainTableLayoutPanel
+            // 
+            MainTableLayoutPanel.ColumnCount = 2;
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F));
+            MainTableLayoutPanel.Controls.Add(parasTabControl, 0, 0);
+            MainTableLayoutPanel.Controls.Add(imgTabControl, 1, 0);
+            MainTableLayoutPanel.Dock = DockStyle.Fill;
+            MainTableLayoutPanel.Location = new Point(0, 25);
+            MainTableLayoutPanel.Name = "MainTableLayoutPanel";
+            MainTableLayoutPanel.RowCount = 1;
+            MainTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            MainTableLayoutPanel.Size = new Size(1044, 552);
+            MainTableLayoutPanel.TabIndex = 47;
+            // 
+            // parasTabControl
+            // 
+            parasTabControl.Controls.Add(tabPage1);
+            parasTabControl.Controls.Add(tabPage5);
+            parasTabControl.Controls.Add(tabPage2);
+            parasTabControl.Dock = DockStyle.Fill;
+            parasTabControl.Location = new Point(3, 3);
+            parasTabControl.Name = "parasTabControl";
+            parasTabControl.SelectedIndex = 0;
+            parasTabControl.Size = new Size(411, 546);
+            parasTabControl.TabIndex = 48;
+            // 
+            // tabPage1
+            // 
+            tabPage1.Controls.Add(tablePanelParas);
+            tabPage1.Location = new Point(4, 26);
+            tabPage1.Name = "tabPage1";
+            tabPage1.Padding = new Padding(3);
+            tabPage1.Size = new Size(403, 516);
+            tabPage1.TabIndex = 0;
+            tabPage1.Text = "杈撳叆鍙傛暟";
+            tabPage1.UseVisualStyleBackColor = true;
+            // 
+            // tabPage5
+            // 
+            tabPage5.Controls.Add(tableLayoutPanel2);
+            tabPage5.Location = new Point(4, 26);
+            tabPage5.Name = "tabPage5";
+            tabPage5.Size = new Size(403, 516);
+            tabPage5.TabIndex = 2;
+            tabPage5.Text = "杩愯鍙傛暟";
+            tabPage5.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 4;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 60F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 150F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(cmbTypeRoi, 1, 0);
+            tableLayoutPanel2.Controls.Add(label21, 0, 0);
+            tableLayoutPanel2.Controls.Add(label22, 0, 1);
+            tableLayoutPanel2.Controls.Add(cmbFixture, 1, 1);
+            tableLayoutPanel2.Controls.Add(ckbDrawRoi, 2, 0);
+            tableLayoutPanel2.Location = new Point(3, 3);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 8;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(323, 309);
+            tableLayoutPanel2.TabIndex = 4;
+            // 
+            // cmbTypeRoi
+            // 
+            cmbTypeRoi.Enabled = false;
+            cmbTypeRoi.FormattingEnabled = true;
+            cmbTypeRoi.Location = new Point(63, 3);
+            cmbTypeRoi.Name = "cmbTypeRoi";
+            cmbTypeRoi.Size = new Size(121, 25);
+            cmbTypeRoi.TabIndex = 1;
+            cmbTypeRoi.SelectedIndexChanged += cmbTypeRoi_SelectedIndexChanged;
+            // 
+            // label21
+            // 
+            label21.AutoSize = true;
+            label21.Dock = DockStyle.Fill;
+            label21.Location = new Point(3, 0);
+            label21.Name = "label21";
+            label21.Size = new Size(54, 30);
+            label21.TabIndex = 3;
+            label21.Text = "ROI";
+            label21.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label22
+            // 
+            label22.AutoSize = true;
+            label22.Dock = DockStyle.Fill;
+            label22.Location = new Point(3, 30);
+            label22.Name = "label22";
+            label22.Size = new Size(54, 30);
+            label22.TabIndex = 4;
+            label22.Text = "Fixture";
+            label22.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbFixture
+            // 
+            cmbFixture.FormattingEnabled = true;
+            cmbFixture.Location = new Point(63, 33);
+            cmbFixture.Name = "cmbFixture";
+            cmbFixture.Size = new Size(121, 25);
+            cmbFixture.TabIndex = 5;
+            cmbFixture.SelectedIndexChanged += cmbFixture_SelectedIndexChanged;
+            // 
+            // ckbDrawRoi
+            // 
+            ckbDrawRoi.AutoSize = true;
+            ckbDrawRoi.CheckAlign = ContentAlignment.MiddleCenter;
+            ckbDrawRoi.Location = new Point(213, 3);
+            ckbDrawRoi.Name = "ckbDrawRoi";
+            ckbDrawRoi.Size = new Size(14, 14);
+            ckbDrawRoi.TabIndex = 2;
+            ckbDrawRoi.UseVisualStyleBackColor = true;
+            ckbDrawRoi.CheckedChanged += ckbDrawRoi_CheckedChanged;
+            // 
+            // tabPage2
+            // 
+            tabPage2.Controls.Add(tableLayoutResults);
+            tabPage2.Location = new Point(4, 26);
+            tabPage2.Name = "tabPage2";
+            tabPage2.Padding = new Padding(3);
+            tabPage2.Size = new Size(403, 516);
+            tabPage2.TabIndex = 1;
+            tabPage2.Text = "杈撳嚭缁撴灉";
+            tabPage2.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutResults
+            // 
+            tableLayoutResults.ColumnCount = 2;
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutResults.Controls.Add(dtxtHeight, 1, 4);
+            tableLayoutResults.Controls.Add(label9, 0, 4);
+            tableLayoutResults.Controls.Add(label5, 0, 0);
+            tableLayoutResults.Controls.Add(label6, 0, 1);
+            tableLayoutResults.Controls.Add(label7, 0, 2);
+            tableLayoutResults.Controls.Add(label8, 0, 3);
+            tableLayoutResults.Controls.Add(dtxtCenterX, 1, 0);
+            tableLayoutResults.Controls.Add(dtxtCenterY, 1, 1);
+            tableLayoutResults.Controls.Add(dtxtAngle, 1, 2);
+            tableLayoutResults.Controls.Add(dtxtWidth, 1, 3);
+            tableLayoutResults.Controls.Add(label18, 0, 5);
+            tableLayoutResults.Controls.Add(dtxtCount, 1, 5);
+            tableLayoutResults.Dock = DockStyle.Fill;
+            tableLayoutResults.Location = new Point(3, 3);
+            tableLayoutResults.Margin = new Padding(2, 3, 2, 3);
+            tableLayoutResults.Name = "tableLayoutResults";
+            tableLayoutResults.RowCount = 10;
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.Size = new Size(397, 510);
+            tableLayoutResults.TabIndex = 1;
+            // 
+            // dtxtHeight
+            // 
+            dtxtHeight.Dock = DockStyle.Fill;
+            dtxtHeight.Location = new Point(102, 207);
+            dtxtHeight.Margin = new Padding(2, 3, 2, 3);
+            dtxtHeight.Name = "dtxtHeight";
+            dtxtHeight.ReadOnly = true;
+            dtxtHeight.Size = new Size(293, 23);
+            dtxtHeight.TabIndex = 9;
+            // 
+            // label9
+            // 
+            label9.AutoSize = true;
+            label9.Dock = DockStyle.Fill;
+            label9.Location = new Point(2, 204);
+            label9.Margin = new Padding(2, 0, 2, 0);
+            label9.MaximumSize = new Size(0, 28);
+            label9.MinimumSize = new Size(0, 28);
+            label9.Name = "label9";
+            label9.Size = new Size(96, 28);
+            label9.TabIndex = 3;
+            label9.Text = "楂樺害";
+            label9.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Dock = DockStyle.Fill;
+            label5.Location = new Point(2, 0);
+            label5.Margin = new Padding(2, 0, 2, 0);
+            label5.MaximumSize = new Size(0, 28);
+            label5.MinimumSize = new Size(0, 28);
+            label5.Name = "label5";
+            label5.Size = new Size(96, 28);
+            label5.TabIndex = 0;
+            label5.Text = "X";
+            label5.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label6
+            // 
+            label6.AutoSize = true;
+            label6.Dock = DockStyle.Fill;
+            label6.Location = new Point(2, 51);
+            label6.Margin = new Padding(2, 0, 2, 0);
+            label6.MaximumSize = new Size(0, 28);
+            label6.MinimumSize = new Size(0, 28);
+            label6.Name = "label6";
+            label6.Size = new Size(96, 28);
+            label6.TabIndex = 1;
+            label6.Text = "Y";
+            label6.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label7
+            // 
+            label7.AutoSize = true;
+            label7.Dock = DockStyle.Fill;
+            label7.Location = new Point(2, 102);
+            label7.Margin = new Padding(2, 0, 2, 0);
+            label7.MaximumSize = new Size(0, 28);
+            label7.MinimumSize = new Size(0, 28);
+            label7.Name = "label7";
+            label7.Size = new Size(96, 28);
+            label7.TabIndex = 2;
+            label7.Text = "瑙掑害(掳)";
+            label7.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label8
+            // 
+            label8.AutoSize = true;
+            label8.Dock = DockStyle.Fill;
+            label8.Location = new Point(2, 153);
+            label8.Margin = new Padding(2, 0, 2, 0);
+            label8.MaximumSize = new Size(0, 28);
+            label8.MinimumSize = new Size(0, 28);
+            label8.Name = "label8";
+            label8.Size = new Size(96, 28);
+            label8.TabIndex = 3;
+            label8.Text = "瀹藉害";
+            label8.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCenterX
+            // 
+            dtxtCenterX.Dock = DockStyle.Fill;
+            dtxtCenterX.Location = new Point(102, 3);
+            dtxtCenterX.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterX.Name = "dtxtCenterX";
+            dtxtCenterX.ReadOnly = true;
+            dtxtCenterX.Size = new Size(293, 23);
+            dtxtCenterX.TabIndex = 5;
+            // 
+            // dtxtCenterY
+            // 
+            dtxtCenterY.Dock = DockStyle.Fill;
+            dtxtCenterY.Location = new Point(102, 54);
+            dtxtCenterY.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterY.Name = "dtxtCenterY";
+            dtxtCenterY.ReadOnly = true;
+            dtxtCenterY.Size = new Size(293, 23);
+            dtxtCenterY.TabIndex = 6;
+            // 
+            // dtxtAngle
+            // 
+            dtxtAngle.Dock = DockStyle.Fill;
+            dtxtAngle.Location = new Point(102, 105);
+            dtxtAngle.Margin = new Padding(2, 3, 2, 3);
+            dtxtAngle.Name = "dtxtAngle";
+            dtxtAngle.ReadOnly = true;
+            dtxtAngle.Size = new Size(293, 23);
+            dtxtAngle.TabIndex = 7;
+            // 
+            // dtxtWidth
+            // 
+            dtxtWidth.Dock = DockStyle.Fill;
+            dtxtWidth.Location = new Point(102, 156);
+            dtxtWidth.Margin = new Padding(2, 3, 2, 3);
+            dtxtWidth.Name = "dtxtWidth";
+            dtxtWidth.ReadOnly = true;
+            dtxtWidth.Size = new Size(293, 23);
+            dtxtWidth.TabIndex = 8;
+            // 
+            // label18
+            // 
+            label18.AutoSize = true;
+            label18.Dock = DockStyle.Fill;
+            label18.Location = new Point(3, 255);
+            label18.Name = "label18";
+            label18.Size = new Size(94, 51);
+            label18.TabIndex = 10;
+            label18.Text = "鏁伴噺";
+            label18.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCount
+            // 
+            dtxtCount.Dock = DockStyle.Fill;
+            dtxtCount.Location = new Point(103, 258);
+            dtxtCount.Name = "dtxtCount";
+            dtxtCount.ReadOnly = true;
+            dtxtCount.Size = new Size(291, 23);
+            dtxtCount.TabIndex = 11;
+            // 
+            // imgTabControl
+            // 
+            imgTabControl.Controls.Add(tabPageInputImage);
+            imgTabControl.Controls.Add(tabPageRecordImage);
+            imgTabControl.Dock = DockStyle.Fill;
+            imgTabControl.Location = new Point(420, 3);
+            imgTabControl.Name = "imgTabControl";
+            imgTabControl.SelectedIndex = 0;
+            imgTabControl.Size = new Size(621, 546);
+            imgTabControl.TabIndex = 49;
+            // 
+            // tabPageInputImage
+            // 
+            tabPageInputImage.Controls.Add(pnlInputImage);
+            tabPageInputImage.Location = new Point(4, 26);
+            tabPageInputImage.Name = "tabPageInputImage";
+            tabPageInputImage.Padding = new Padding(3);
+            tabPageInputImage.Size = new Size(613, 516);
+            tabPageInputImage.TabIndex = 0;
+            tabPageInputImage.Text = "杈撳叆鍥惧儚";
+            tabPageInputImage.UseVisualStyleBackColor = true;
+            // 
+            // tabPageRecordImage
+            // 
+            tabPageRecordImage.Controls.Add(pnlRecordImage);
+            tabPageRecordImage.Location = new Point(4, 26);
+            tabPageRecordImage.Name = "tabPageRecordImage";
+            tabPageRecordImage.Padding = new Padding(3);
+            tabPageRecordImage.Size = new Size(613, 516);
+            tabPageRecordImage.TabIndex = 1;
+            tabPageRecordImage.Text = "缁撴灉鍥惧儚";
+            tabPageRecordImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlRecordImage
+            // 
+            pnlRecordImage.Dock = DockStyle.Fill;
+            pnlRecordImage.Location = new Point(3, 3);
+            pnlRecordImage.Margin = new Padding(4);
+            pnlRecordImage.Name = "pnlRecordImage";
+            pnlRecordImage.Size = new Size(607, 510);
+            pnlRecordImage.TabIndex = 45;
+            // 
+            // btnShowROI
+            // 
+            btnShowROI.Dock = DockStyle.Fill;
+            btnShowROI.Location = new Point(3, 207);
+            btnShowROI.Name = "btnShowROI";
+            btnShowROI.Size = new Size(84, 45);
+            btnShowROI.TabIndex = 15;
+            btnShowROI.Text = "鏄剧ず鎵剧嚎鍖哄煙";
+            btnShowROI.UseVisualStyleBackColor = true;
+            btnShowROI.Click += btnShowROI_Click;
+            // 
+            // HFindLineToolEdit
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(MainTableLayoutPanel);
+            Controls.Add(BtmStatusStrip);
+            Controls.Add(TopToolStrip);
+            Margin = new Padding(2, 3, 2, 3);
+            Name = "HFindLineToolEdit";
+            Size = new Size(1044, 599);
+            Load += HFindLineToolEdit_Load;
+            tablePanelParas.ResumeLayout(false);
+            tablePanelParas.PerformLayout();
+            TopToolStrip.ResumeLayout(false);
+            TopToolStrip.PerformLayout();
+            BtmStatusStrip.ResumeLayout(false);
+            BtmStatusStrip.PerformLayout();
+            MainTableLayoutPanel.ResumeLayout(false);
+            parasTabControl.ResumeLayout(false);
+            tabPage1.ResumeLayout(false);
+            tabPage5.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel2.PerformLayout();
+            tabPage2.ResumeLayout(false);
+            tableLayoutResults.ResumeLayout(false);
+            tableLayoutResults.PerformLayout();
+            imgTabControl.ResumeLayout(false);
+            tabPageInputImage.ResumeLayout(false);
+            tabPageRecordImage.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TableLayoutPanel tablePanelParas;
+        private System.Windows.Forms.Panel pnlInputImage;
+        private ToolStrip TopToolStrip;
+        private ToolStripButton btnRun;
+        private StatusStrip BtmStatusStrip;
+        private ToolStripStatusLabel lblResult;
+        private ToolStripStatusLabel lblMsg;
+        private TableLayoutPanel MainTableLayoutPanel;
+        private ToolStripButton btnLoadImage;
+        private TabControl parasTabControl;
+        private TabPage tabPage1;
+        private TabPage tabPage2;
+        private TableLayoutPanel tableLayoutResults;
+        private Label label5;
+        private Label label6;
+        private Label label7;
+        private Label label8;
+        private TextBox dtxtCenterX;
+        private TextBox dtxtCenterY;
+        private TextBox dtxtAngle;
+        private TextBox dtxtWidth;
+        private TextBox dtxtHeight;
+        private Label label9;
+        private TabPage tabPage5;
+        private TabControl imgTabControl;
+        private TabPage tabPageInputImage;
+        private TabPage tabPageRecordImage;
+        private ToolStripButton btnSaveParas;
+        private ToolStripButton btnLoadParas;
+        private Panel pnlRecordImage;
+        private Label label1;
+        private TextBox itxtCaliperCount;
+        private Label label2;
+        private TextBox dtxtCaliperHeight;
+        private Label label3;
+        private TextBox dtxtCaliperWidth;
+        private Label label4;
+        private TextBox itxtSigma;
+        private Label label10;
+        private TextBox itxtThreshold;
+        private Label label11;
+        private TextBox itxtIgnoreCount;
+        private Label label12;
+        private Label label13;
+        private Label label18;
+        private TextBox dtxtCount;
+        private ToolStripStatusLabel lblRunTime;
+        private TableLayoutPanel tableLayoutPanel2;
+        public ComboBox cmbTypeRoi;
+        private Label label21;
+        private Label label22;
+        private ComboBox cmbFixture;
+        private CheckBox ckbDrawRoi;
+        private ComboBox cmbTransition;
+        private ComboBox cmbSelect;
+        private Button btnShowROI;
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.cs
new file mode 100644
index 0000000..026965d
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.cs
@@ -0,0 +1,424 @@
+锘縰sing HalconDotNet;
+using System.Data.Common;
+using LB_VisionProcesses.Alogrithms;
+using System.Windows.Forms;
+using static LB_VisionProcesses.Alogrithms.Halcon.HFindCode2dTool;
+using LB_VisionControl;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    public partial class HFindLineToolEdit : TAlgorithmEdit
+    {
+        public HFindLineToolEdit(HFindLineTool subject = null)
+        {
+            if (subject != null && subject is HFindLineTool)
+                Subject = subject;
+            else
+                Subject = new HFindLineTool();
+
+            if (!(Subject.Params.ROI is HSegment))
+                Subject.Params.ROI = new HSegment(0, 0, 250, 250);
+
+            this.Dock = DockStyle.Fill;
+            InitializeComponent();
+        }
+
+        /// <summary>
+        /// 鎺т欢鍔犺浇浜嬩欢
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void HFindLineToolEdit_Load(object sender, EventArgs e)
+        {
+            pnlInputImage.Controls.Add(inputImageHSmartWindowControl);
+            inputImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            pnlRecordImage.Controls.Add(recordImageHSmartWindowControl);
+            recordImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            //閬嶅巻鍙互閫夋嫨鐨凴oi绫诲瀷鏋氫妇
+            foreach (var value in Enum.GetValues(typeof(RoiType)))
+                cmbTypeRoi.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨勬瀬鎬х被鍨嬫灇涓�
+            foreach (var value in Enum.GetValues(typeof(Transition)))
+                cmbTransition.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨勮竟缂樼被鍨嬫灇涓�
+            foreach (var value in Enum.GetValues(typeof(Selector)))
+                cmbSelect.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨凢ixture鏋氫妇
+            cmbFixture.Items.Add("");
+            foreach (string value in IProcess.dicFixtures.Keys)
+                cmbFixture.Items.Add(value.ToString());
+
+            ckbDrawRoi.Checked = true;
+            cmbTypeRoi.Text = RoiType.Segment.ToString();
+            cmbTransition.Text = Transition.Ignore.ToString();
+            cmbSelect.Text = Selector.Best.ToString();
+            LoadParas();
+
+            if (Subject.Result)
+            {
+                lblResult.BackColor = Color.Green;
+                lblResult.Text = "True";
+            }
+            else
+            {
+                lblResult.BackColor = Color.Red;
+                lblResult.Text = "False";
+            }
+
+            lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+            lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+            lblRunTime.Text = $"{Subject.RunTime}ms";
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯鍙傛暟
+        /// </summary>
+        public override void UpdataInputs()
+        {
+            //璁剧疆杩愯鍙傛暟
+            double dResult = 0;
+            int iResult = 0;
+
+            Subject.Params.Inputs["鍗″昂鏁伴噺"] = int.TryParse(itxtCaliperCount.Text, out iResult) ? iResult : Subject.Params.Inputs["鍗″昂鏁伴噺"];
+            Subject.Params.Inputs["鍗″昂闀垮害"] = double.TryParse(dtxtCaliperHeight.Text, out dResult) ? dResult : Subject.Params.Inputs["鍗″昂闀垮害"];
+            Subject.Params.Inputs["鍗″昂瀹藉害"] = double.TryParse(dtxtCaliperWidth.Text, out dResult) ? dResult : Subject.Params.Inputs["鍗″昂瀹藉害"];
+
+            Subject.Params.Inputs["杩囨护涓�鍗婂儚绱�"] = int.TryParse(itxtSigma.Text, out iResult) ? iResult : Subject.Params.Inputs["杩囨护涓�鍗婂儚绱�"];
+            Subject.Params.Inputs["瀵规瘮搴﹂槇鍊�"] = int.TryParse(itxtThreshold.Text, out iResult) ? iResult : Subject.Params.Inputs["瀵规瘮搴﹂槇鍊�"];
+            Subject.Params.Inputs["蹇界暐鐐规暟"] = int.TryParse(itxtIgnoreCount.Text, out iResult) ? iResult : Subject.Params.Inputs["蹇界暐鐐规暟"];
+
+            Subject.Params.Inputs["鏋佹��"] = cmbTransition.SelectedItem?.ToString();
+            Subject.Params.Inputs["杈圭紭浣嶇疆"] = cmbSelect.SelectedItem?.ToString();
+
+            if (cmbFixture.Text == "")
+                Subject.Params.Fixture = new Fixture();
+            else if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+
+            Type type = inputImageHSmartWindowControl.oRoi?.GetType();
+            switch (type)
+            {
+                case Type t when t == typeof(HRectangle2):
+                    HRectangle2 hRectangle2 = (HRectangle2)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HRectangle2(hRectangle2.X - Subject.Params.Fixture.X, hRectangle2.Y - Subject.Params.Fixture.Y
+                        , hRectangle2.Phi - Subject.Params.Fixture.Phi, hRectangle2.Width, hRectangle2.Height);
+                    break;
+                case Type t when t == typeof(HCircle):
+                    HCircle hCircle = (HCircle)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HCircle(hCircle.X - Subject.Params.Fixture.X, hCircle.Y - Subject.Params.Fixture.Y, hCircle.Radius);
+                    break;
+                case Type t when t == typeof(HSegment):
+                    HSegment hSegment = (HSegment)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HSegment(hSegment.StartX - Subject.Params.Fixture.X, hSegment.StartY - Subject.Params.Fixture.Y
+                        , hSegment.EndX - Subject.Params.Fixture.X, hSegment.EndY - Subject.Params.Fixture.Y);
+                    break;
+                default:
+                    Subject.Params.ROI = new ROI();
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// 鍔犺浇杩愯鍙傛暟
+        /// </summary>
+        public override void LoadParas()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                itxtCaliperCount.Text = Subject.Params.Inputs["鍗″昂鏁伴噺"].ToString();
+                dtxtCaliperHeight.Text = Subject.Params.Inputs["鍗″昂闀垮害"].ToString();
+                dtxtCaliperWidth.Text = Subject.Params.Inputs["鍗″昂瀹藉害"].ToString();
+                itxtSigma.Text = Subject.Params.Inputs["杩囨护涓�鍗婂儚绱�"].ToString();
+                itxtThreshold.Text = Subject.Params.Inputs["瀵规瘮搴﹂槇鍊�"].ToString();
+                itxtIgnoreCount.Text = Subject.Params.Inputs["蹇界暐鐐规暟"].ToString();
+
+                cmbTransition.Text = Subject.Params.Inputs["鏋佹��"].ToString();
+                cmbSelect.Text = Subject.Params.Inputs["杈圭紭浣嶇疆"].ToString();
+
+                if (Subject.InputImage != null && Subject.InputImage is HObject)
+                    inputImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+
+                Type type = Subject.Params.ROI?.GetType();
+                if (Subject.Params.ROI != null)
+                {
+                    switch (type)
+                    {
+                        case Type t when t == typeof(HRectangle2):
+                            cmbTypeRoi.Text = RoiType.Rectangle2.ToString();
+                            break;
+                        case Type t when t == typeof(HCircle):
+                            cmbTypeRoi.Text = RoiType.Circle.ToString();
+                            break;
+                        case Type t when t == typeof(HSegment):
+                            cmbTypeRoi.Text = RoiType.Segment.ToString();
+                            break;
+                        default:
+                            cmbTypeRoi.Text = RoiType.None.ToString();
+                            break;
+                    }
+                    if (cmbTypeRoi.Text.ToString() != "None")
+                        ckbDrawRoi.Checked = true;
+                    else
+                        ckbDrawRoi.Checked = false;
+
+                    inputImageHSmartWindowControl.oRoi = Subject.Params.ROI;
+                }
+
+                if (Subject.Params.Fixture != null)
+                    cmbFixture.Text = Subject.Params.Fixture.strName;
+                else
+                    cmbFixture.Text = "";
+
+                switch (type)
+                {
+                    case Type t when t == typeof(HRectangle2):
+                        inputImageHSmartWindowControl.oRoi
+                             = new HRectangle2(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                             , Subject.Params.ROI.Phi + Subject.Params.Fixture.Phi, ((HRectangle2)Subject.Params.ROI).Width, ((HRectangle2)Subject.Params.ROI).Height);
+                        break;
+                    case Type t when t == typeof(HCircle):
+                        inputImageHSmartWindowControl.oRoi
+                        = new HCircle(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                        , ((HCircle)Subject.Params.ROI).Radius);
+                        break;
+                    case Type t when t == typeof(HSegment):
+                        inputImageHSmartWindowControl.oRoi
+                        = new HSegment(((HSegment)Subject.Params.ROI).StartX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).StartY + Subject.Params.Fixture.Y
+                        , ((HSegment)Subject.Params.ROI).EndX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).EndY + Subject.Params.Fixture.Y);
+                        break;
+                    default:
+                        inputImageHSmartWindowControl.oRoi = null;
+                        break;
+                }
+            }));
+        }
+
+        /// <summary>
+        /// 鏇存柊杈撳嚭缁撴灉
+        /// </summary>
+        public override void UpdataOutputs()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                //瀛樺湪鍙嶅簭鍒楀寲閿欎贡鐨勬儏鍐甸渶瑕佷娇鐢ㄨ嚜瀹氫箟鐨勮浆鎹㈠櫒
+                dtxtCenterX.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterX"]);
+                dtxtCenterY.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterY"]);
+                dtxtAngle.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Angle"]);
+                dtxtWidth.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Width"]);
+                dtxtHeight.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Height"]);
+                dtxtCount.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Count"]);
+            }));
+        }
+
+        /// <summary>
+        /// 鐐瑰嚮杩愯
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        public override void btnRun_Click(object sender, EventArgs e)
+        {
+            if (Subject.InputImage != null)
+                InputImage = Subject.InputImage;
+
+            DateTime StartTime = DateTime.Now;
+            Run();
+
+            //鏇存柊鏃ュ織涓庣粨鏋�
+            this.BeginInvoke(new Action(() =>
+            {
+                if (Subject.Result)
+                {
+                    lblResult.BackColor = Color.Green;
+                    lblResult.Text = "True";
+                    recordImageHSmartWindowControl.SetColor("green");
+                }
+                else
+                {
+                    lblResult.BackColor = Color.Red;
+                    lblResult.Text = "False";
+                    recordImageHSmartWindowControl.SetColor("red");
+                }
+
+                lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+                lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+                lblRunTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
+
+                UpdataOutputs();
+                imgTabControl.SelectedTab = tabPageRecordImage;
+
+                if (Subject.InputImage != null && Subject.InputImage is HObject)
+                {
+                    HOperatorSet.GetImageSize((HObject)Subject.InputImage, out HTuple ho_ImageWidth, out HTuple ho_ImageHeight);
+                    recordImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+                }
+
+                //鍏堝垽鏂瓙绫诲啀鍒ゆ柇鐖剁被
+                if (Subject.Record != null && Subject.Record is MsgRecord msgRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_NG, false);
+
+                    for (int i = 0; i < msgRecord.Msg.Length; i++)
+                        recordImageHSmartWindowControl.ShowMsg(msgRecord.Msg[i]
+                            , 1 == msgRecord.Result[i] ? true : false, msgRecord.Column[i], msgRecord.Row[i]);
+                }
+                else if (Subject.Record != null && Subject.Record is ObjectRecord objRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_NG, false);
+                }
+
+                GC.Collect();
+            }));
+        }
+
+        public override void btnLoadImage_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    HOperatorSet.ReadImage(out HObject ho_Image, selectedFiles[0]);
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.CountChannels(ho_Image, out HTuple hv_Channels);
+                        if (hv_Channels.TupleInt() != 1)
+                        {
+                            HOperatorSet.Rgb1ToGray(ho_Image, out ho_Image);
+                            //鏇存柊鏃ュ織涓庣粨鏋�
+                            this.BeginInvoke(new Action(() =>
+                            {
+                                lblMsg.Text = "瀵煎叆鍥剧墖闈炵伆搴﹀浘,鑷姩杞崲涓虹伆搴﹀浘";
+                            }));
+                        }
+                        InputImage = ho_Image;
+                        imgTabControl.SelectedTab = tabPageInputImage;
+                        inputImageHSmartWindowControl.oRoi = inputImageHSmartWindowControl.oRoi;
+                    }
+                }
+            }
+        }
+
+        public override void btnSaveParas_Click(object sender, EventArgs e) { base.btnSaveParas_Click(sender, e); }
+
+        public override void ckbDrawRoi_CheckedChanged(object sender, EventArgs e)
+        {
+            if (ckbDrawRoi.Checked)
+            {
+                inputImageHSmartWindowControl.bAollowDraw = true;
+                imgTabControl.SelectedTab = tabPageInputImage;
+            }
+            else
+            {
+                inputImageHSmartWindowControl.bAollowDraw = false;
+                Subject.Params.ROI = new ROI();
+            }
+        }
+
+        public override void cmbTypeRoi_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (Enum.TryParse(cmbTypeRoi.Text.ToString(), out RoiType type))
+                {
+                    HTuple hv_imageWidth = 0;
+                    HTuple hv_imageHeight = 0;
+                    if (InputImage != null && InputImage is HObject)
+                        HOperatorSet.GetImageSize((HObject)InputImage, out hv_imageWidth, out hv_imageHeight);
+                    switch (type)
+                    {
+                        case RoiType.Rectangle2:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, 0
+                                , hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.Circle:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HCircle(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, hv_imageWidth.TupleReal() / 4);
+                            break;
+                        case RoiType.Segment:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HSegment(0, 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.None:
+                        default:
+                            inputImageHSmartWindowControl.oRoi = null;
+                            break;
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public override void cmbFixture_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+                else
+                    Subject.Params.Fixture = new Fixture();
+            }
+            catch { }
+        }
+
+        private void btnShowROI_Click(object sender, EventArgs e)
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                try
+                {
+                    imgTabControl.SelectedTab = tabPageInputImage;
+
+                    inputImageHSmartWindowControl.ClearObj();
+
+                    if (Subject.InputImage != null && Subject.InputImage is HObject)
+                        inputImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+
+                    int hv_Elements = Convert.ToInt16(itxtCaliperCount.Text);
+                    double hv_DetectHeight = Convert.ToDouble(dtxtCaliperHeight.Text);
+                    double hv_DetectWidth = Convert.ToDouble(dtxtCaliperWidth.Text);
+
+                    //double hv_Row1 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).BeginRow + Subject.Params.Fixture.Row);
+                    //double hv_Column1 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).BeginColumn + Subject.Params.Fixture.Column);
+                    //double hv_Row2 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).EndRow + Subject.Params.Fixture.Row);
+                    //double hv_Column2 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).EndColumn + Subject.Params.Fixture.Column);
+
+                    double hv_Row1 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).BeginRow);
+                    double hv_Column1 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).BeginColumn);
+                    double hv_Row2 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).EndRow);
+                    double hv_Column2 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).EndColumn);
+
+                    TAlgorithm.GetRakeRegions(null, out HObject ho_Regions, hv_Elements, hv_DetectHeight, hv_DetectWidth
+                        , new HTuple(), new HTuple(), new HTuple(), new HTuple()
+                        , hv_Row1, hv_Column1, hv_Row2, hv_Column2
+                        , out HTuple hv_ResultRow, out HTuple hv_ResultColumn);
+
+                    inputImageHSmartWindowControl.DispObj(ho_Regions);
+                }
+                catch { }
+            }));
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.resx b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.resx
new file mode 100644
index 0000000..551e0b0
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindLineTool/HFindLineToolEdit.resx
@@ -0,0 +1,126 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema 
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="TopToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="BtmStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>129, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelTool.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelTool.cs
new file mode 100644
index 0000000..4ca9695
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelTool.cs
@@ -0,0 +1,705 @@
+锘縰sing HalconDotNet;
+using LB_VisionProcesses.Alogrithms.Halcon;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static LB_VisionProcesses.Alogrithms.Halcon.HFindModelTool;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    [Process("Halcon2D鍗曟ā鏉垮尮閰嶅伐鍏�", Category = "Halcon2D宸ュ叿", Description = "鍒涘缓鍗曟ā鏉垮尮閰嶅伐鍏�")]
+    public class HFindModelTool : TAlgorithm
+    {
+        public enum ModelType { 鍚勫悜寮傚舰妯℃澘, 灞�閮ㄥ彉褰㈡ā鏉� };
+
+        public enum SubPixel { none, interpolation };
+
+        public enum Metric { use_polarity, ignore_local_polarity };
+
+
+        public HModel ModelID = new HModel();
+
+        public HFindModelTool()
+        {
+            strProcessClass = "LB_VisionProcesses.Alogrithms.Halcon.HFindModelTool";
+            strProcessName = "Halcon2D鍗曟ā鏉垮尮閰嶅伐鍏�";
+
+            Params.Inputs.Add("ModelType", ModelType.鍚勫悜寮傚舰妯℃澘);
+
+            //AngleStart锛氭悳绱㈡椂鐨勮捣濮嬭搴闇�瑕佽浆鎹负寮у害]
+            Params.Inputs.Add("AngleStart", -5.0);
+            //AngleExtent锛氭悳绱㈡椂鐨勮搴﹁寖鍥�,0琛ㄧず鏃犺搴︽悳绱闇�瑕佽浆鎹负寮у害]
+            Params.Inputs.Add("AngleExtent", 10.0);
+            //AngleStep锛氳搴︽闀�--寮у害[瑙掑害姝ラ暱 >= 0鍜岃搴︽闀� <= pi / 16]
+            Params.Inputs.Add("AngleStep", "auto");
+            Params.Inputs.Add("ScaleRMin", 0.9);
+            Params.Inputs.Add("ScaleRMax", 1.1);
+            Params.Inputs.Add("ScaleCMin", 0.9);
+            Params.Inputs.Add("ScaleCMax", 1.1);
+            //MinScore锛氳鎵惧埌鐨勬ā鏉挎渶灏忓垎鏁�
+            Params.Inputs.Add("MinScore", 0.5);
+            //NumMatches锛氳鎵惧埌鐨勬ā鏉挎渶澶氱殑瀹炰緥鏁�,0鍒欐壘鍒版墍鏈夊彲鑳界殑鍖归厤
+            Params.Inputs.Add("NumMatches", 0);
+            //MaxOverlap锛氬厑璁告壘鍒扮殑妯″瀷瀹炰緥鐨勬渶澶ч噸鍙犳瘮渚�, 寤鸿鍊硷細0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
+            Params.Inputs.Add("MaxOverlap", 0.2);
+            //SubPixel锛氳绠楃簿搴︾殑璁剧疆
+            //'none'    涓嶉�傜敤浜氬儚绱�,鏈�澶ц宸负鍗婁釜鍍忕礌
+            //'interpolation'   宸�煎緱鍒颁簹鍍忕礌绮惧害
+            //'least_squares', 'least_squares_high', 'least_squares_very_high'
+            //'max_deformation 1', 'max_deformation 2', 'max_deformation 3', 'max_deformation 4'
+            Params.Inputs.Add("SubPixel", "none");
+            //NumLevels锛氭悳绱㈡椂閲戝瓧濉旂殑灞傜骇,0琛ㄧず涓嶄娇鐢ㄩ噾瀛楀
+            Params.Inputs.Add("NumLevels", 0);
+            //Greediness锛氳椽濠害,鎼滅储鍚彂寮�,涓�鑸兘璁句负0.8,瓒婇珮閫熷害瓒婂揩,瀹规槗鍑虹幇鎵句笉鍒扮殑鎯呭喌
+            Params.Inputs.Add("Greediness", 0.8);
+            Params.Inputs.Add("ResultType", "");
+
+            Params.Inputs.Add("MinCount", 0);
+            Params.Inputs.Add("MaxCount", 9999);
+
+            Params.Outputs.Add("CenterX", new List<double>());
+            Params.Outputs.Add("CenterY", new List<double>());
+            Params.Outputs.Add("Phi", new List<double>());
+            Params.Outputs.Add("Score", new List<double>());
+            Params.Outputs.Add("Count", 0);
+        }
+
+        private static readonly object lockObj = new object();
+        /// <summary>
+        /// 杩愯绠楀瓙
+        /// </summary>
+        public override void TAlgorithmMain()
+        {
+            lock (lockObj)
+            {
+                #region 鍒濆鍖栧彉閲�
+                HTuple hv_CenterRow = new HTuple();
+                HTuple hv_CenterColumn = new HTuple();
+                HTuple hv_CenterPhi = new HTuple();
+                HTuple hv_Score = new HTuple();
+                #endregion
+
+                try
+                {
+                    if (InputImage == null)
+                    {
+                        Msg = "杈撳叆鍥剧墖涓虹┖";
+                        Result = false;
+                        return;
+                    }
+                    if (!(InputImage is HObject))
+                    {
+                        Msg = "杈撳叆鍥剧墖鏍煎紡涓嶄负HObject";
+                        Result = false;
+                        return;
+                    }
+
+                    object DomainImage = null;
+
+                    #region 瑁佸壀鍖哄煙
+                    if (!ReduceDomainImage(InputImage, ref DomainImage))
+                    {
+                        Msg = "瑁佸壀鍖哄煙澶辫触";
+                        Result = false;
+                        return;
+                    }
+
+                    HObject hoDomainImage = DomainImage as HObject;
+                    HTuple hv_Channels = new HTuple();
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        try
+                        {
+                            HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                            if (hv_Channels.TupleInt() != 1)
+                                HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+
+                            //杞崲鍚庡啀娆℃鏌ユ槸鍚︿负鐏板害鍥�
+                            HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                            if (hv_Channels.TupleInt() != 1)
+                            {
+                                HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+                                Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥�";
+                                Result = false;
+                                return;
+                            }
+                        }
+                        catch
+                        {
+                            Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥句笖杞崲澶辫触";
+                            Result = false;
+                            return;
+                        }
+                    }
+                    #endregion
+
+                    //鍒ゆ柇鏄惁鏈夋ā鏉�
+                    if (ModelID.hvModel == null || ModelID.hvModel.Length == 0)
+                    {
+                        Msg = "鏈垱寤烘ā鏉�";
+                        Result = false;
+                        return;
+                    }
+
+                    #region 绠楀瓙閫昏緫
+                    Record = new ObjectRecord();
+                    HOperatorSet.GetImageSize(ModelID.hoImage, out HTuple ho_ModelWidth, out HTuple ho_ModelHeight);
+                    ModelType type = ModelID.Type;
+                    double AngleStart = Convert.ToDouble(Params.Inputs["AngleStart"]);
+                    double AngleExtent = Convert.ToDouble(Params.Inputs["AngleExtent"]);
+                    double MinScore = Convert.ToDouble(Params.Inputs["MinScore"]);
+                    int NumMatches = ProcessParams.ConvertToInt32(Params.Inputs["NumMatches"]);
+                    double MaxOverlap = Convert.ToDouble(Params.Inputs["MaxOverlap"]);
+                    string SubPixel = ProcessParams.ConvertToString(Params.Inputs["SubPixel"]);
+                    string NumLevels = ProcessParams.ConvertToString(Params.Inputs["NumLevels"]);
+                    double Greediness = Convert.ToDouble(Params.Inputs["Greediness"]);
+
+                    double ScaleRMin = Convert.ToDouble(Params.Inputs["ScaleRMin"]);
+                    double ScaleRMax = Convert.ToDouble(Params.Inputs["ScaleRMax"]);
+                    double ScaleCMin = Convert.ToDouble(Params.Inputs["ScaleCMin"]);
+                    double ScaleCMax = Convert.ToDouble(Params.Inputs["ScaleCMax"]);
+
+                    switch (type)
+                    {
+                        case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                            //灞�閮ㄥ彉褰㈡ā鏉垮尮閰�
+                            MaxTimeOut = 8000;
+                            #region 鍙傛暟浠嬬粛
+                            //* 鍙傛暟1锛氳緭鍏ュ浘鍍�
+                            //* 鍙傛暟2锛氭ā鏉垮彞鏌�
+                            //* 鍙傛暟3锛氭悳绱㈡椂鐨勮捣濮嬭搴�
+                            //* 鍙傛暟4锛氭悳绱㈡椂鐨勭粓姝㈣搴�,蹇呴』涓庡垱寤烘ā鏉挎椂鐨勬湁浜ら泦
+                            //* 鍙傛暟5:琚壘鍒扮殑妯℃澘鏈�灏忓垎鏁�--澶т簬绛変簬杩欎釜鍊兼墠鑳借鍖归厤
+                            //* 榛樿鍊硷細0.5      寤鸿鍊硷細0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
+                            //* 鍏稿瀷鍊艰寖鍥达細0鈮inScore 鈮� 1
+                            //* 鏈�灏忓閲忥細0.01       寤鸿澧為噺锛�0.05
+                            //* 鍙傛暟6锛氳鎵惧埌鐨勬ā鏉挎渶澶у疄渚嬫暟
+                            //* 0   涓嶉檺鍒�
+                            //* 鍙傛暟7锛氳鎵惧埌鐨勬ā鍨嬪疄渚嬬殑鏈�澶ч噸鍙犳瘮渚�
+                            //* 榛樿鍊硷細0.5       寤鸿鍊硷細0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
+                            //* 鍏稿瀷鍊艰寖鍥达細0鈮� MaxOverlap鈮� 1      鏈�灏忓閲忥細0.01     寤鸿澧為噺锛�0.05
+                            //* 0 琛ㄧず涓嶅厑璁搁噸鍙�
+                            //* 鍙傛暟8锛氳绠楃簿搴︾殑璁剧疆
+                            //* 'none'   涓嶉�傜敤浜氬儚绱�,鏈�澶ц宸负鍗婁釜鍍忕礌
+                            //* 'interpolation'   宸�煎緱鍒颁簹鍍忕礌绮惧害
+                            //* 'least_squares', 'least_squares_high', 'least_squares_very_high'
+                            //* 'max_deformation 1', 'max_deformation 2', 'max_deformation 3', 'max_deformation 4'
+                            //* 'max_deformation 5', 'max_deformation 6'
+                            //* 鍙傛暟9锛氭悳绱㈡椂閲戝瓧濉旂殑灞傜骇
+                            //* 鍙傛暟10锛氳椽濠害,鎼滅储鍚彂寮�,涓�鑸兘璁句负0.8,瓒婇珮閫熷害蹇�,瀹规槗鍑虹幇鎵句笉鍒扮殑鎯呭喌
+                            //* 0鈮� Greediness 鈮� 1
+                            //* 鏈�鍚�4涓細杈撳嚭鍖归厤浣嶇疆鐨勮鍜屽垪鍧愭爣銆佽搴︺�佸緱鍒� 銆愪腑蹇冨潗鏍囥��
+                            #endregion
+
+                            //0.5涓烘渶浣庡垎鏁伴槇鍊硷紝鍚庣画閫氳繃MinScore杩囨护
+                            HOperatorSet.FindLocalDeformableModel(hoDomainImage, out _, out _, out _, ModelID.hvModel
+                                , AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                                , ScaleRMin, ScaleRMax
+                                , ScaleCMin, ScaleCMax
+                                , 0.5, NumMatches, MaxOverlap
+                                , NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                                , Greediness, new HTuple(), new HTuple(), new HTuple()
+                                , out hv_Score, out hv_CenterRow, out hv_CenterColumn);
+                            break;
+                        case ModelType.鍚勫悜寮傚舰妯℃澘:
+                            //褰㈢姸妯℃澘鍖归厤
+                            #region 鍙傛暟浠嬬粛
+                            //* 鍙傛暟1锛氳緭鍏ュ浘鍍�
+                            //* 鍙傛暟2锛氭ā鏉垮彞鏌�
+                            //* 鍙傛暟3锛氭悳绱㈡椂鐨勮捣濮嬭搴�
+                            //* 鍙傛暟4锛氭悳绱㈡椂鐨勭粓姝㈣搴�,蹇呴』涓庡垱寤烘ā鏉挎椂鐨勬湁浜ら泦
+                            //* 鍙傛暟5:琚壘鍒扮殑妯℃澘鏈�灏忓垎鏁�--澶т簬绛変簬杩欎釜鍊兼墠鑳借鍖归厤
+                            //* 榛樿鍊硷細0.5      寤鸿鍊硷細0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
+                            //* 鍏稿瀷鍊艰寖鍥达細0鈮inScore 鈮� 1
+                            //* 鏈�灏忓閲忥細0.01       寤鸿澧為噺锛�0.05
+                            //* 鍙傛暟6锛氳鎵惧埌鐨勬ā鏉挎渶澶у疄渚嬫暟
+                            //* 0   涓嶉檺鍒�
+                            //* 鍙傛暟7锛氳鎵惧埌鐨勬ā鍨嬪疄渚嬬殑鏈�澶ч噸鍙犳瘮渚�
+                            //* 榛樿鍊硷細0.5       寤鸿鍊硷細0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
+                            //* 鍏稿瀷鍊艰寖鍥达細0鈮� MaxOverlap鈮� 1      鏈�灏忓閲忥細0.01     寤鸿澧為噺锛�0.05
+                            //* 0 琛ㄧず涓嶅厑璁搁噸鍙�
+                            //* 鍙傛暟8锛氳绠楃簿搴︾殑璁剧疆
+                            //* 'none'   涓嶉�傜敤浜氬儚绱�,鏈�澶ц宸负鍗婁釜鍍忕礌
+                            //* 'interpolation'   宸�煎緱鍒颁簹鍍忕礌绮惧害
+                            //* 'least_squares', 'least_squares_high', 'least_squares_very_high'
+                            //* 'max_deformation 1', 'max_deformation 2', 'max_deformation 3', 'max_deformation 4'
+                            //* 'max_deformation 5', 'max_deformation 6'
+                            //* 鍙傛暟9锛氭悳绱㈡椂閲戝瓧濉旂殑灞傜骇
+                            //* 鍙傛暟10锛氳椽濠害,鎼滅储鍚彂寮�,涓�鑸兘璁句负0.8,瓒婇珮閫熷害蹇�,瀹规槗鍑虹幇鎵句笉鍒扮殑鎯呭喌
+                            //* 0鈮� Greediness 鈮� 1
+                            //* 鏈�鍚�4涓細杈撳嚭鍖归厤浣嶇疆鐨勮鍜屽垪鍧愭爣銆佽搴︺�佸緱鍒� [涓績鍧愭爣]
+                            #endregion
+
+                            //0.5涓烘渶浣庡垎鏁伴槇鍊硷紝鍚庣画閫氳繃MinScore杩囨护
+                            HOperatorSet.FindAnisoShapeModel(hoDomainImage, ModelID.hvModel
+                                , AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                                , ScaleRMin, ScaleRMax
+                                , ScaleCMin, ScaleCMax
+                                , 0.5, NumMatches, MaxOverlap, SubPixel
+                                , NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                                , Greediness
+                                , out hv_CenterRow, out hv_CenterColumn
+                                , out hv_CenterPhi
+                                , out _, out _, out hv_Score);
+                            break;
+                        default:
+                            Msg = "涓嶆敮鎸佺殑妯℃澘";
+                            Result = false;
+                            return;
+                    }
+                    #endregion
+
+                    #region 缁撴灉澶勭悊
+                    List<double> CenterX = new List<double>();
+                    List<double> CenterY = new List<double>();
+                    List<double> Phi = new List<double>();
+                    List<double> Score = new List<double>();
+                    for (int i = 0; i < hv_CenterRow.Length; i++)
+                    {
+                        if (hv_Score[i].D < MinScore)
+                            continue;
+
+                        CenterX.Add(Math.Round(hv_CenterColumn[i].D, 3));
+                        CenterY.Add(Math.Round(hv_CenterRow[i].D, 3));
+
+                        if (i >= hv_CenterPhi.Length)
+                            Phi.Add(0);
+                        else
+                            Phi.Add(Math.Round(hv_CenterPhi[i].D, 3));
+
+                        Score.Add(Math.Round(hv_Score[i].D, 3));
+                        //HOperatorSet.GenRectangle2ContourXld(out HObject hRectangle, hv_CenterRow[i].D, hv_CenterColumn[i].D, hv_CenterPhi[i].D, ho_ModelWidth / 2, ho_ModelHeight / 2);
+                        HOperatorSet.GenRectangle2(out HObject hRectangle, CenterY[i], CenterX[i], Phi[i], ho_ModelWidth / 2, ho_ModelHeight / 2);
+                        ((ObjectRecord)Record).AddRecord(hRectangle);
+                    }
+
+                    Params.Outputs["CenterX"] = CenterX;
+                    Params.Outputs["CenterY"] = CenterY;
+                    Params.Outputs["Phi"] = Phi;
+                    Params.Outputs["Score"] = Score;
+                    Params.Outputs["Count"] = Score.Count;
+                    #endregion
+
+                    #region 鐢熸垚OutputImage缁欏悗缁鐞�
+                    try
+                    {
+                        OutputImage = hoDomainImage;
+                    }
+                    catch (Exception ex)
+                    {
+                        Msg = "鐢熸垚OutputImage澶辫触,鍘熷洜鏄�:" + ex.ToString();
+                        Result = false;
+                        return;
+                    }
+                    #endregion
+
+                    if (Msg == "杩愯瓒呮椂")
+                    {
+                        Result = false;
+                        Record.ChangeAll2False();
+                        return;
+                    }
+
+                    int MinCount = ProcessParams.ConvertToInt32(Params.Inputs["MinCount"]);
+                    int MaxCount = ProcessParams.ConvertToInt32(Params.Inputs["MaxCount"]);
+
+                    if (CenterX.Count < MinCount || CenterX.Count > MaxCount)
+                    {
+                        Msg = string.Format("缁撴灉涓暟瓒呭嚭鑼冨洿({0},{1})", MinCount, MaxCount);
+                        Record.ChangeAll2False();
+                        Result = false;
+                        return;
+                    }
+
+                    Msg = "杩愯鎴愬姛";
+                    Result = true;
+                    return;
+                }
+                catch (Exception ex)
+                {
+                    Msg = "杩愯澶辫触,鍘熷洜鏄�:" + ex.ToString().TrimEnd();
+                    OutputImage = null;
+                    Result = false;
+                    return;
+                }
+                finally
+                {
+                    if (!Result)
+                    {
+                        Params.Outputs["CenterX"] = 0;
+                        Params.Outputs["CenterY"] = 0;
+                        Params.Outputs["Phi"] = 0;
+                        Params.Outputs["Score"] = 0;
+                        Params.Outputs["Count"] = 0;
+                    }
+                    bCompleted = true;
+                    #region 鍐呭瓨閲婃斁
+
+                    #endregion
+                }
+            }
+        }
+
+        public bool CreateModel(HObject Template, ModelType modelType = ModelType.鍚勫悜寮傚舰妯℃澘, string NumLevels = "auto"
+            , double AngleStart = -5, double AngleExtent = 10, string AngleStep = "auto"
+            , double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto"
+            , double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto"
+            , string Optimization = "none", string Metric = "ignore_local_polarity"
+            , string Contrast = "auto", int MinContrast = 10)
+        {
+            try
+            {
+                #region 鍙傛暟浠嬬粛
+                //Template: : //reduce_domain鍚庣殑妯℃澘鍥惧儚
+                //NumLevels ,//閲戝瓧濉旂殑灞傛暟锛屽彲璁句负鈥渁uto鈥濇垨0鈥�10鐨勬暣鏁�
+                //AngleStart ,//妯℃澘鏃嬭浆鐨勮捣濮嬭搴�
+                //AngleExtent ,//妯℃澘鏃嬭浆瑙掑害鑼冨洿, >=0
+                //AngleStep ,//鏃嬭浆瑙掑害鐨勬闀匡紝 >=0 and <=pi/16
+                //Optimization ,//璁剧疆妯℃澘浼樺寲鍜屾ā鏉垮垱寤烘柟娉�
+                //Metric , //鍖归厤鏂规硶璁剧疆
+                //Contrast ,//璁剧疆瀵规瘮搴�
+                //MinContrast // 璁剧疆鏈�灏忓姣斿害
+                #endregion
+                switch (modelType)
+                {
+                    case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                        HOperatorSet.CreateLocalDeformableModel(Template, NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
+                            , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
+                            , ScaleRMin, ScaleRMax, ScaleRStep == "auto" ? ScaleRStep : Convert.ToDouble(ScaleRStep)
+                            , ScaleCMin, ScaleCMax, ScaleCStep == "auto" ? ScaleCStep : Convert.ToDouble(ScaleCStep)
+                            , Optimization, Metric
+                            , Contrast, MinContrast
+                            , new HTuple(), new HTuple()
+                            , out ModelID.hvModel);
+                        ModelID.hoImage = Template.CopyObj(1, -1);
+                        ModelID.Type = ModelType.灞�閮ㄥ彉褰㈡ā鏉�;
+                        return true;
+                    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                    default:
+                        HOperatorSet.CreateAnisoShapeModel(Template, NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
+                            , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
+                            , ScaleRMin, ScaleRMax, ScaleRStep == "auto" ? ScaleRStep : Convert.ToDouble(ScaleRStep)
+                            , ScaleCMin, ScaleCMax, ScaleCStep == "auto" ? ScaleCStep : Convert.ToDouble(ScaleCStep)
+                            , Optimization, Metric
+                            , Contrast, MinContrast, out ModelID.hvModel);
+                        ModelID.hoImage = Template.CopyObj(1, -1);
+                        ModelID.Type = ModelType.鍚勫悜寮傚舰妯℃澘;
+                        return true;
+                }
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 鍔犺浇绠楁硶
+        /// </summary>
+        /// <param name="fullPath">瀹屾暣璺緞甯�.json</param>
+        /// <returns></returns>
+        public override bool Load(string fullPath)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                if (!fullPath.Contains(".json"))
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                if (fullPath.StartsWith(".\\"))
+                {
+                    // 鍒ゆ柇鍘熷瓧绗︿覆闀垮害鏄惁澶т簬绛変簬2锛岄伩鍏嶈秺鐣�
+                    if (fullPath.Length >= 2)
+                    {
+                        // 鏇挎崲寮�澶翠袱涓瓧绗�
+                        fullPath = Application.StartupPath + fullPath.Substring(2);
+                        Debug.WriteLine($"淇敼鍚庣殑瀛楃涓�: {fullPath}");
+                    }
+                }
+
+                // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                string directoryPath = Path.GetDirectoryName(fullPath);
+                strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+                // 淇鐪熷疄璺緞,妯℃澘鍖归厤宸ュ叿鍏惰矾寰勪负涓�涓枃浠跺す,鑰屼笉鏄竴涓枃浠�
+                fullPath = directoryPath + "\\" + strProcessName + "\\" + strProcessName + ".json";
+
+                if (!File.Exists(fullPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    ModelID = new HModel(fullPath, ModelType.鍚勫悜寮傚舰妯℃澘, strProcessName);
+                    Save(directoryPath);
+                    ModelID.Save(fullPath, ModelID.Type);
+                    return true;
+                }
+
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+                Params = JsonConvert.DeserializeObject<ProcessParams>(strJson);
+                if (Params == null)
+                    return false;
+
+                // 鍙嶅簭鍒楀寲鍚庝慨澶嶆暟鎹�
+                Params.FixDeserializedData();
+                strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+
+                if (!Enum.TryParse(Params.Inputs["ModelType"].ToString(), out ModelType modelType))
+                    return false;
+
+                if (!ModelID.Load(fullPath, modelType))
+                    return false;
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨绠楁硶
+        /// </summary>
+        /// <param name="filePath">涓嶅甫.json</param>
+        /// <returns></returns>
+        public override bool Save(string filePath)
+        {
+            try
+            {
+                // 淇鐪熷疄璺緞,妯℃澘鍖归厤宸ュ叿鍏惰矾寰勪负涓�涓枃浠跺す,鑰屼笉鏄竴涓枃浠�
+                filePath += ("\\" + strProcessName);
+                Params.Inputs.Add("ModelType", ModelID.Type.ToString());
+                if (!base.Save(filePath)
+                    || !ModelID.Save(filePath + "\\" + strProcessName + ".json", ModelID.Type))
+                    return false;
+
+                return true;
+            }
+            catch { return false; }
+        }
+    }
+
+    public class HModel
+    {
+        public HModel(string modelName = "") { ModelName = modelName; }
+
+        public HModel(string modelFullPath, ModelType modelType, string modelName)
+        {
+            ModelFullPath = modelFullPath;
+            ModelName = modelName;
+            Type = modelType;
+            switch (modelType)
+            {
+                case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                    Load(ModelFullPath, modelType);
+                    break;
+                case ModelType.鍚勫悜寮傚舰妯℃澘:
+                default:
+                    Load(ModelFullPath, modelType);
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// 妯℃澘璺緞
+        /// </summary>
+        public string ModelFullPath = "C:\\MyVisionModel\\ModelName.temp";
+
+        /// <summary>
+        /// 妯℃澘鍚嶇О
+        /// </summary>
+        public string ModelName
+        {
+            get { return Path.GetFileNameWithoutExtension(ModelFullPath); }
+            set
+            {
+                // 鑾峰彇鏂囦欢鐨勬墿灞曞悕锛堝寘鎷偣锛�
+                string fileExtension = Path.GetExtension(ModelFullPath);
+
+                // 鑾峰彇鏂囦欢鎵�鍦ㄧ殑鏂囦欢澶硅矾寰�
+                string directoryPath = Path.GetDirectoryName(ModelFullPath);
+
+                ModelFullPath = directoryPath + "\\" + value + fileExtension;
+            }
+        }
+
+        /// <summary>
+        /// Halcon妯℃澘鍙ユ焺
+        /// </summary>
+        public HTuple hvModel;
+
+        /// <summary>
+        /// 妯℃澘鍥剧墖
+        /// </summary>
+        public HObject hoImage;
+
+        public HTuple Width
+        {
+            get
+            {
+                if (hoImage == null)
+                    return (HTuple)0;
+
+                HOperatorSet.GetImageSize(hoImage, out HTuple ho_ModelWidth, out HTuple ho_ModelHeight);
+                return ho_ModelWidth;
+            }
+        }
+
+        public HTuple Height
+        {
+            get
+            {
+                if (hoImage == null)
+                    return (HTuple)0;
+
+                HOperatorSet.GetImageSize(hoImage, out HTuple ho_ModelWidth, out HTuple ho_ModelHeight);
+                return ho_ModelHeight;
+            }
+        }
+
+        /// <summary>
+        /// Halcon妯℃澘绫诲瀷
+        /// </summary>
+        public ModelType Type = ModelType.鍚勫悜寮傚舰妯℃澘;
+
+        /// <summary>
+        /// 鍔犺浇妯℃澘(甯�.json)
+        /// </summary>
+        /// <param name="fullPath">瀹屾暣璺緞甯�.json</param>
+        /// <returns></returns>
+        public bool Load(string fullPath, ModelType modelType)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                string filePath = Path.GetDirectoryName(fullPath);
+                ModelName = Path.GetFileNameWithoutExtension(fullPath);
+                ModelFullPath = filePath + "\\" + ModelName;
+                ModelFullPath += ".model";
+                Type = modelType;
+                switch (modelType)
+                {
+                    case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                        ModelFullPath += ".dfm";
+                        if (File.Exists(ModelFullPath))
+                            HOperatorSet.ReadDeformableModel(ModelFullPath, out hvModel);
+                        break;
+                    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                    default:
+                        if (File.Exists(ModelFullPath))
+                            HOperatorSet.ReadShapeModel(ModelFullPath, out hvModel);
+                        break;
+                }
+
+                string ImageFileName = Path.GetFileNameWithoutExtension(fullPath);
+                string ImageFullPath = filePath + "\\" + ImageFileName + ".bmp";
+                if (File.Exists(ImageFullPath))
+                    HOperatorSet.ReadImage(out hoImage, ImageFullPath);
+                return true;
+            }
+            catch { Type = ModelType.鍚勫悜寮傚舰妯℃澘; return false; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨妯℃澘(璺緞甯�.model)
+        /// </summary>
+        /// <param name="fullPath">甯�.model</param>
+        /// <returns></returns>
+        public bool Save(string fullPath)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                string filePath = Path.GetDirectoryName(fullPath);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦�
+                if (!Directory.Exists(filePath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(filePath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+
+                ModelName = Path.GetFileNameWithoutExtension(fullPath);
+                // 浣跨敤 Path.GetExtension 鎻愬彇鎵╁睍鍚�
+                switch (Type)
+                {
+                    case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                        HOperatorSet.WriteDeformableModel(hvModel, fullPath);
+                        break;
+                    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                    default:
+                        HOperatorSet.WriteShapeModel(hvModel, fullPath);
+                        break;
+                }
+
+                string ImageFileName = Path.GetFileNameWithoutExtension(fullPath);
+                string ImageFullPath = filePath + "\\" + ImageFileName + ".bmp";
+                HOperatorSet.WriteImage(hoImage, "bmp", 0, ImageFullPath);
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨妯℃澘(璺緞甯�.json)
+        /// </summary>
+        /// <param name="fullPath">甯�.json</param>
+        /// <returns></returns>
+        public bool Save(string fullPath, ModelType modelType)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                string filePath = Path.GetDirectoryName(fullPath);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦�
+                if (!Directory.Exists(filePath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(filePath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+
+                ModelName = Path.GetFileNameWithoutExtension(fullPath);
+                ModelFullPath = filePath + "\\" + ModelName + ".model";
+                Type = modelType;
+                switch (modelType)
+                {
+                    case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                        HOperatorSet.WriteDeformableModel(hvModel, ModelFullPath);
+                        break;
+                    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                    default:
+                        HOperatorSet.WriteShapeModel(hvModel, ModelFullPath);
+                        break;
+                }
+
+                string ImageFileName = Path.GetFileNameWithoutExtension(fullPath);
+                string ImageFullPath = filePath + "\\" + ImageFileName + ".bmp";
+                HOperatorSet.WriteImage(hoImage, "bmp", 0, ImageFullPath);
+                return true;
+            }
+            catch { return false; }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.Designer.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.Designer.cs
new file mode 100644
index 0000000..317d5e8
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.Designer.cs
@@ -0,0 +1,1849 @@
+锘縩amespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    partial class HFindModelToolEdit
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tablePanelParas = new TableLayoutPanel();
+            lblInputParam1 = new Label();
+            dtxtInputParam1 = new TextBox();
+            lblInputParam2 = new Label();
+            dtxtInputParam2 = new TextBox();
+            lblInputParam3 = new Label();
+            dtxtInputParam3 = new TextBox();
+            lblInputParam4 = new Label();
+            dtxtInputParam4 = new TextBox();
+            lblInputParam5 = new Label();
+            dtxtInputParam5 = new TextBox();
+            lblInputParam6 = new Label();
+            dtxtInputParam6 = new TextBox();
+            lblInputParam7 = new Label();
+            lblInputParam9 = new Label();
+            lblInputParam11 = new Label();
+            lblInputParam13 = new Label();
+            lblInputParam15 = new Label();
+            lblInputParam17 = new Label();
+            dtxtInputParam7 = new TextBox();
+            dtxtInputParam9 = new TextBox();
+            dtxtInputParam11 = new TextBox();
+            dtxtInputParam13 = new TextBox();
+            dtxtInputParam15 = new TextBox();
+            dtxtInputParam17 = new TextBox();
+            lblInputParam8 = new Label();
+            dtxtInputParam8 = new TextBox();
+            lblInputParam10 = new Label();
+            dtxtInputParam10 = new TextBox();
+            lblInputParam12 = new Label();
+            dtxtInputParam12 = new TextBox();
+            lblInputParam14 = new Label();
+            dtxtInputParam14 = new TextBox();
+            lblInputParam16 = new Label();
+            dtxtInputParam16 = new TextBox();
+            lblInputParam18 = new Label();
+            dtxtInputParam18 = new TextBox();
+            TopToolStrip = new ToolStrip();
+            btnRun = new ToolStripButton();
+            btnLoadImage = new ToolStripButton();
+            btnSaveParas = new ToolStripButton();
+            btnLoadParas = new ToolStripButton();
+            BtmStatusStrip = new StatusStrip();
+            lblResult = new ToolStripStatusLabel();
+            lblMsg = new ToolStripStatusLabel();
+            lblRunTime = new ToolStripStatusLabel();
+            MainTableLayoutPanel = new TableLayoutPanel();
+            parasTabControl = new TabControl();
+            tabPageInputParas = new TabPage();
+            tabPageRunParas = new TabPage();
+            tableLayoutPanel3 = new TableLayoutPanel();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            cmbTypeRoi = new ComboBox();
+            label21 = new Label();
+            label22 = new Label();
+            cmbFixture = new ComboBox();
+            ckbDrawRoi = new CheckBox();
+            ckbStartMask = new CheckBox();
+            txtMaskSize = new TextBox();
+            grpModel = new GroupBox();
+            tabPageModelParas = new TabPage();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            dtxtModelParam13 = new TextBox();
+            lblModelParam13 = new Label();
+            lblModelParam11 = new Label();
+            dtxtModelParam11 = new TextBox();
+            lblModelParam9 = new Label();
+            dtxtModelParam9 = new TextBox();
+            lblModelParam7 = new Label();
+            dtxtModelParam7 = new TextBox();
+            lblModelParam5 = new Label();
+            dtxtModelParam5 = new TextBox();
+            lblModelParam3 = new Label();
+            dtxtModelParam3 = new TextBox();
+            lblModelParam1 = new Label();
+            dtxtModelParam1 = new TextBox();
+            dtxtModelParam2 = new TextBox();
+            btnSaveModel = new Button();
+            lblModelParam2 = new Label();
+            lblModelParam4 = new Label();
+            dtxtModelParam4 = new TextBox();
+            lblModelParam6 = new Label();
+            dtxtModelParam6 = new TextBox();
+            lblModelParam8 = new Label();
+            dtxtModelParam8 = new TextBox();
+            lblModelParam10 = new Label();
+            lblModelParam12 = new Label();
+            dtxtModelParam12 = new TextBox();
+            lblModelParam14 = new Label();
+            dtxtModelParam14 = new TextBox();
+            lblModelParam15 = new Label();
+            lblModelParam17 = new Label();
+            dtxtModelParam15 = new TextBox();
+            dtxtModelParam17 = new TextBox();
+            lblModelParam16 = new Label();
+            lblModelParam18 = new Label();
+            dtxtModelParam16 = new TextBox();
+            dtxtModelParam18 = new TextBox();
+            btnCreateModel = new Button();
+            lblModelType = new Label();
+            cmbModelType = new ComboBox();
+            dtxtModelParam10 = new TextBox();
+            tabPageOutputParas = new TabPage();
+            tableLayoutResults = new TableLayoutPanel();
+            dtxtCount = new TextBox();
+            label5 = new Label();
+            label6 = new Label();
+            label7 = new Label();
+            dtxtCenterX = new TextBox();
+            dtxtCenterY = new TextBox();
+            dtxtPhi = new TextBox();
+            label8 = new Label();
+            dtxtScore = new TextBox();
+            label9 = new Label();
+            imgTabControl = new TabControl();
+            tabPageInputImage = new TabPage();
+            pnlInputImage = new Panel();
+            tabPageModelImage = new TabPage();
+            pnlCreateModelImage = new Panel();
+            tabPageRecordImage = new TabPage();
+            pnlRecordImage = new Panel();
+            tablePanelParas.SuspendLayout();
+            TopToolStrip.SuspendLayout();
+            BtmStatusStrip.SuspendLayout();
+            MainTableLayoutPanel.SuspendLayout();
+            parasTabControl.SuspendLayout();
+            tabPageInputParas.SuspendLayout();
+            tabPageRunParas.SuspendLayout();
+            tableLayoutPanel3.SuspendLayout();
+            tableLayoutPanel1.SuspendLayout();
+            tabPageModelParas.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tabPageOutputParas.SuspendLayout();
+            tableLayoutResults.SuspendLayout();
+            imgTabControl.SuspendLayout();
+            tabPageInputImage.SuspendLayout();
+            tabPageModelImage.SuspendLayout();
+            tabPageRecordImage.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tablePanelParas
+            // 
+            tablePanelParas.ColumnCount = 4;
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.Controls.Add(lblInputParam1, 0, 0);
+            tablePanelParas.Controls.Add(dtxtInputParam1, 1, 0);
+            tablePanelParas.Controls.Add(lblInputParam2, 2, 0);
+            tablePanelParas.Controls.Add(dtxtInputParam2, 3, 0);
+            tablePanelParas.Controls.Add(lblInputParam3, 0, 1);
+            tablePanelParas.Controls.Add(dtxtInputParam3, 1, 1);
+            tablePanelParas.Controls.Add(lblInputParam4, 2, 1);
+            tablePanelParas.Controls.Add(dtxtInputParam4, 3, 1);
+            tablePanelParas.Controls.Add(lblInputParam5, 0, 2);
+            tablePanelParas.Controls.Add(dtxtInputParam5, 1, 2);
+            tablePanelParas.Controls.Add(lblInputParam6, 2, 2);
+            tablePanelParas.Controls.Add(dtxtInputParam6, 3, 2);
+            tablePanelParas.Controls.Add(lblInputParam7, 0, 3);
+            tablePanelParas.Controls.Add(lblInputParam9, 0, 4);
+            tablePanelParas.Controls.Add(lblInputParam11, 0, 5);
+            tablePanelParas.Controls.Add(lblInputParam13, 0, 6);
+            tablePanelParas.Controls.Add(lblInputParam15, 0, 7);
+            tablePanelParas.Controls.Add(lblInputParam17, 0, 8);
+            tablePanelParas.Controls.Add(dtxtInputParam7, 1, 3);
+            tablePanelParas.Controls.Add(dtxtInputParam9, 1, 4);
+            tablePanelParas.Controls.Add(dtxtInputParam11, 1, 5);
+            tablePanelParas.Controls.Add(dtxtInputParam13, 1, 6);
+            tablePanelParas.Controls.Add(dtxtInputParam15, 1, 7);
+            tablePanelParas.Controls.Add(dtxtInputParam17, 1, 8);
+            tablePanelParas.Controls.Add(lblInputParam8, 2, 3);
+            tablePanelParas.Controls.Add(dtxtInputParam8, 3, 3);
+            tablePanelParas.Controls.Add(lblInputParam10, 2, 4);
+            tablePanelParas.Controls.Add(dtxtInputParam10, 3, 4);
+            tablePanelParas.Controls.Add(lblInputParam12, 2, 5);
+            tablePanelParas.Controls.Add(dtxtInputParam12, 3, 5);
+            tablePanelParas.Controls.Add(lblInputParam14, 2, 6);
+            tablePanelParas.Controls.Add(dtxtInputParam14, 3, 6);
+            tablePanelParas.Controls.Add(lblInputParam16, 2, 7);
+            tablePanelParas.Controls.Add(dtxtInputParam16, 3, 7);
+            tablePanelParas.Controls.Add(lblInputParam18, 2, 8);
+            tablePanelParas.Controls.Add(dtxtInputParam18, 3, 8);
+            tablePanelParas.Dock = DockStyle.Fill;
+            tablePanelParas.Location = new Point(3, 3);
+            tablePanelParas.Margin = new Padding(2, 3, 2, 3);
+            tablePanelParas.Name = "tablePanelParas";
+            tablePanelParas.RowCount = 12;
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.Size = new Size(397, 510);
+            tablePanelParas.TabIndex = 0;
+            // 
+            // lblInputParam1
+            // 
+            lblInputParam1.AutoSize = true;
+            lblInputParam1.Location = new Point(2, 0);
+            lblInputParam1.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam1.MaximumSize = new Size(0, 28);
+            lblInputParam1.MinimumSize = new Size(0, 28);
+            lblInputParam1.Name = "lblInputParam1";
+            lblInputParam1.Size = new Size(39, 28);
+            lblInputParam1.TabIndex = 0;
+            lblInputParam1.Text = "鍙傛暟1";
+            lblInputParam1.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam1.Visible = false;
+            // 
+            // dtxtInputParam1
+            // 
+            dtxtInputParam1.Location = new Point(92, 3);
+            dtxtInputParam1.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam1.Name = "dtxtInputParam1";
+            dtxtInputParam1.Size = new Size(98, 23);
+            dtxtInputParam1.TabIndex = 5;
+            dtxtInputParam1.Text = "0";
+            dtxtInputParam1.Visible = false;
+            // 
+            // lblInputParam2
+            // 
+            lblInputParam2.AutoSize = true;
+            lblInputParam2.Location = new Point(200, 0);
+            lblInputParam2.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam2.MaximumSize = new Size(0, 28);
+            lblInputParam2.MinimumSize = new Size(0, 28);
+            lblInputParam2.Name = "lblInputParam2";
+            lblInputParam2.Size = new Size(39, 28);
+            lblInputParam2.TabIndex = 1;
+            lblInputParam2.Text = "鍙傛暟2";
+            lblInputParam2.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam2.Visible = false;
+            // 
+            // dtxtInputParam2
+            // 
+            dtxtInputParam2.Location = new Point(290, 3);
+            dtxtInputParam2.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam2.Name = "dtxtInputParam2";
+            dtxtInputParam2.Size = new Size(98, 23);
+            dtxtInputParam2.TabIndex = 6;
+            dtxtInputParam2.Text = "0";
+            dtxtInputParam2.Visible = false;
+            // 
+            // lblInputParam3
+            // 
+            lblInputParam3.AutoSize = true;
+            lblInputParam3.Location = new Point(2, 42);
+            lblInputParam3.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam3.MaximumSize = new Size(0, 28);
+            lblInputParam3.MinimumSize = new Size(0, 28);
+            lblInputParam3.Name = "lblInputParam3";
+            lblInputParam3.Size = new Size(39, 28);
+            lblInputParam3.TabIndex = 2;
+            lblInputParam3.Text = "鍙傛暟3";
+            lblInputParam3.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam3.Visible = false;
+            // 
+            // dtxtInputParam3
+            // 
+            dtxtInputParam3.Location = new Point(92, 45);
+            dtxtInputParam3.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam3.Name = "dtxtInputParam3";
+            dtxtInputParam3.Size = new Size(98, 23);
+            dtxtInputParam3.TabIndex = 7;
+            dtxtInputParam3.Text = "0";
+            dtxtInputParam3.Visible = false;
+            // 
+            // lblInputParam4
+            // 
+            lblInputParam4.AutoSize = true;
+            lblInputParam4.Location = new Point(200, 42);
+            lblInputParam4.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam4.MaximumSize = new Size(0, 28);
+            lblInputParam4.MinimumSize = new Size(0, 28);
+            lblInputParam4.Name = "lblInputParam4";
+            lblInputParam4.Size = new Size(39, 28);
+            lblInputParam4.TabIndex = 3;
+            lblInputParam4.Text = "鍙傛暟4";
+            lblInputParam4.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam4.Visible = false;
+            // 
+            // dtxtInputParam4
+            // 
+            dtxtInputParam4.Location = new Point(290, 45);
+            dtxtInputParam4.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam4.Name = "dtxtInputParam4";
+            dtxtInputParam4.Size = new Size(98, 23);
+            dtxtInputParam4.TabIndex = 8;
+            dtxtInputParam4.Text = "0";
+            dtxtInputParam4.Visible = false;
+            // 
+            // lblInputParam5
+            // 
+            lblInputParam5.AutoSize = true;
+            lblInputParam5.Location = new Point(2, 84);
+            lblInputParam5.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam5.MaximumSize = new Size(0, 28);
+            lblInputParam5.MinimumSize = new Size(0, 28);
+            lblInputParam5.Name = "lblInputParam5";
+            lblInputParam5.Size = new Size(39, 28);
+            lblInputParam5.TabIndex = 9;
+            lblInputParam5.Text = "鍙傛暟5";
+            lblInputParam5.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam5.Visible = false;
+            // 
+            // dtxtInputParam5
+            // 
+            dtxtInputParam5.Location = new Point(92, 87);
+            dtxtInputParam5.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam5.Name = "dtxtInputParam5";
+            dtxtInputParam5.Size = new Size(98, 23);
+            dtxtInputParam5.TabIndex = 9;
+            dtxtInputParam5.Text = "0";
+            dtxtInputParam5.Visible = false;
+            // 
+            // lblInputParam6
+            // 
+            lblInputParam6.AutoSize = true;
+            lblInputParam6.Location = new Point(200, 84);
+            lblInputParam6.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam6.MaximumSize = new Size(0, 28);
+            lblInputParam6.MinimumSize = new Size(0, 28);
+            lblInputParam6.Name = "lblInputParam6";
+            lblInputParam6.Size = new Size(39, 28);
+            lblInputParam6.TabIndex = 10;
+            lblInputParam6.Text = "鍙傛暟6";
+            lblInputParam6.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam6.Visible = false;
+            // 
+            // dtxtInputParam6
+            // 
+            dtxtInputParam6.Location = new Point(290, 87);
+            dtxtInputParam6.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam6.Name = "dtxtInputParam6";
+            dtxtInputParam6.Size = new Size(98, 23);
+            dtxtInputParam6.TabIndex = 9;
+            dtxtInputParam6.Text = "0";
+            dtxtInputParam6.Visible = false;
+            // 
+            // lblInputParam7
+            // 
+            lblInputParam7.AutoSize = true;
+            lblInputParam7.Location = new Point(2, 126);
+            lblInputParam7.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam7.MaximumSize = new Size(0, 28);
+            lblInputParam7.MinimumSize = new Size(0, 28);
+            lblInputParam7.Name = "lblInputParam7";
+            lblInputParam7.Size = new Size(39, 28);
+            lblInputParam7.TabIndex = 11;
+            lblInputParam7.Text = "鍙傛暟7";
+            lblInputParam7.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam7.Visible = false;
+            // 
+            // lblInputParam9
+            // 
+            lblInputParam9.AutoSize = true;
+            lblInputParam9.Location = new Point(2, 168);
+            lblInputParam9.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam9.MaximumSize = new Size(0, 28);
+            lblInputParam9.MinimumSize = new Size(0, 28);
+            lblInputParam9.Name = "lblInputParam9";
+            lblInputParam9.Size = new Size(39, 28);
+            lblInputParam9.TabIndex = 13;
+            lblInputParam9.Text = "鍙傛暟9";
+            lblInputParam9.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam9.Visible = false;
+            // 
+            // lblInputParam11
+            // 
+            lblInputParam11.AutoSize = true;
+            lblInputParam11.Location = new Point(2, 210);
+            lblInputParam11.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam11.MaximumSize = new Size(0, 28);
+            lblInputParam11.MinimumSize = new Size(0, 28);
+            lblInputParam11.Name = "lblInputParam11";
+            lblInputParam11.Size = new Size(46, 28);
+            lblInputParam11.TabIndex = 15;
+            lblInputParam11.Text = "鍙傛暟11";
+            lblInputParam11.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam11.Visible = false;
+            // 
+            // lblInputParam13
+            // 
+            lblInputParam13.AutoSize = true;
+            lblInputParam13.Location = new Point(2, 252);
+            lblInputParam13.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam13.MaximumSize = new Size(0, 28);
+            lblInputParam13.MinimumSize = new Size(0, 28);
+            lblInputParam13.Name = "lblInputParam13";
+            lblInputParam13.Size = new Size(46, 28);
+            lblInputParam13.TabIndex = 17;
+            lblInputParam13.Text = "鍙傛暟13";
+            lblInputParam13.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam13.Visible = false;
+            // 
+            // lblInputParam15
+            // 
+            lblInputParam15.AutoSize = true;
+            lblInputParam15.Location = new Point(2, 294);
+            lblInputParam15.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam15.MaximumSize = new Size(0, 28);
+            lblInputParam15.MinimumSize = new Size(0, 28);
+            lblInputParam15.Name = "lblInputParam15";
+            lblInputParam15.Size = new Size(46, 28);
+            lblInputParam15.TabIndex = 19;
+            lblInputParam15.Text = "鍙傛暟15";
+            lblInputParam15.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam15.Visible = false;
+            // 
+            // lblInputParam17
+            // 
+            lblInputParam17.AutoSize = true;
+            lblInputParam17.Location = new Point(2, 336);
+            lblInputParam17.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam17.MaximumSize = new Size(0, 28);
+            lblInputParam17.MinimumSize = new Size(0, 28);
+            lblInputParam17.Name = "lblInputParam17";
+            lblInputParam17.Size = new Size(46, 28);
+            lblInputParam17.TabIndex = 21;
+            lblInputParam17.Text = "鍙傛暟17";
+            lblInputParam17.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam17.Visible = false;
+            // 
+            // dtxtInputParam7
+            // 
+            dtxtInputParam7.Location = new Point(92, 129);
+            dtxtInputParam7.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam7.Name = "dtxtInputParam7";
+            dtxtInputParam7.Size = new Size(98, 23);
+            dtxtInputParam7.TabIndex = 9;
+            dtxtInputParam7.Text = "0";
+            dtxtInputParam7.Visible = false;
+            // 
+            // dtxtInputParam9
+            // 
+            dtxtInputParam9.Location = new Point(92, 171);
+            dtxtInputParam9.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam9.Name = "dtxtInputParam9";
+            dtxtInputParam9.Size = new Size(98, 23);
+            dtxtInputParam9.TabIndex = 9;
+            dtxtInputParam9.Text = "0";
+            dtxtInputParam9.Visible = false;
+            // 
+            // dtxtInputParam11
+            // 
+            dtxtInputParam11.Location = new Point(92, 213);
+            dtxtInputParam11.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam11.Name = "dtxtInputParam11";
+            dtxtInputParam11.Size = new Size(98, 23);
+            dtxtInputParam11.TabIndex = 9;
+            dtxtInputParam11.Text = "0";
+            dtxtInputParam11.Visible = false;
+            // 
+            // dtxtInputParam13
+            // 
+            dtxtInputParam13.Location = new Point(92, 255);
+            dtxtInputParam13.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam13.Name = "dtxtInputParam13";
+            dtxtInputParam13.Size = new Size(98, 23);
+            dtxtInputParam13.TabIndex = 23;
+            dtxtInputParam13.Text = "0";
+            dtxtInputParam13.Visible = false;
+            // 
+            // dtxtInputParam15
+            // 
+            dtxtInputParam15.Location = new Point(92, 297);
+            dtxtInputParam15.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam15.Name = "dtxtInputParam15";
+            dtxtInputParam15.Size = new Size(98, 23);
+            dtxtInputParam15.TabIndex = 25;
+            dtxtInputParam15.Text = "0";
+            dtxtInputParam15.Visible = false;
+            // 
+            // dtxtInputParam17
+            // 
+            dtxtInputParam17.Location = new Point(92, 339);
+            dtxtInputParam17.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam17.Name = "dtxtInputParam17";
+            dtxtInputParam17.Size = new Size(98, 23);
+            dtxtInputParam17.TabIndex = 27;
+            dtxtInputParam17.Text = "0";
+            dtxtInputParam17.Visible = false;
+            // 
+            // lblInputParam8
+            // 
+            lblInputParam8.AutoSize = true;
+            lblInputParam8.Location = new Point(200, 126);
+            lblInputParam8.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam8.MaximumSize = new Size(0, 28);
+            lblInputParam8.MinimumSize = new Size(0, 28);
+            lblInputParam8.Name = "lblInputParam8";
+            lblInputParam8.Size = new Size(39, 28);
+            lblInputParam8.TabIndex = 12;
+            lblInputParam8.Text = "鍙傛暟8";
+            lblInputParam8.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam8.Visible = false;
+            // 
+            // dtxtInputParam8
+            // 
+            dtxtInputParam8.Location = new Point(290, 129);
+            dtxtInputParam8.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam8.Name = "dtxtInputParam8";
+            dtxtInputParam8.Size = new Size(98, 23);
+            dtxtInputParam8.TabIndex = 9;
+            dtxtInputParam8.Text = "0";
+            dtxtInputParam8.Visible = false;
+            // 
+            // lblInputParam10
+            // 
+            lblInputParam10.AutoSize = true;
+            lblInputParam10.Location = new Point(200, 168);
+            lblInputParam10.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam10.MaximumSize = new Size(0, 28);
+            lblInputParam10.MinimumSize = new Size(0, 28);
+            lblInputParam10.Name = "lblInputParam10";
+            lblInputParam10.Size = new Size(46, 28);
+            lblInputParam10.TabIndex = 14;
+            lblInputParam10.Text = "鍙傛暟10";
+            lblInputParam10.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam10.Visible = false;
+            // 
+            // dtxtInputParam10
+            // 
+            dtxtInputParam10.Location = new Point(290, 171);
+            dtxtInputParam10.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam10.Name = "dtxtInputParam10";
+            dtxtInputParam10.Size = new Size(98, 23);
+            dtxtInputParam10.TabIndex = 9;
+            dtxtInputParam10.Text = "0";
+            dtxtInputParam10.Visible = false;
+            // 
+            // lblInputParam12
+            // 
+            lblInputParam12.AutoSize = true;
+            lblInputParam12.Location = new Point(200, 210);
+            lblInputParam12.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam12.MaximumSize = new Size(0, 28);
+            lblInputParam12.MinimumSize = new Size(0, 28);
+            lblInputParam12.Name = "lblInputParam12";
+            lblInputParam12.Size = new Size(46, 28);
+            lblInputParam12.TabIndex = 16;
+            lblInputParam12.Text = "鍙傛暟12";
+            lblInputParam12.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam12.Visible = false;
+            // 
+            // dtxtInputParam12
+            // 
+            dtxtInputParam12.Location = new Point(290, 213);
+            dtxtInputParam12.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam12.Name = "dtxtInputParam12";
+            dtxtInputParam12.Size = new Size(98, 23);
+            dtxtInputParam12.TabIndex = 10;
+            dtxtInputParam12.Text = "0";
+            dtxtInputParam12.Visible = false;
+            // 
+            // lblInputParam14
+            // 
+            lblInputParam14.AutoSize = true;
+            lblInputParam14.Location = new Point(200, 252);
+            lblInputParam14.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam14.MaximumSize = new Size(0, 28);
+            lblInputParam14.MinimumSize = new Size(0, 28);
+            lblInputParam14.Name = "lblInputParam14";
+            lblInputParam14.Size = new Size(46, 28);
+            lblInputParam14.TabIndex = 18;
+            lblInputParam14.Text = "鍙傛暟14";
+            lblInputParam14.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam14.Visible = false;
+            // 
+            // dtxtInputParam14
+            // 
+            dtxtInputParam14.Location = new Point(290, 255);
+            dtxtInputParam14.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam14.Name = "dtxtInputParam14";
+            dtxtInputParam14.Size = new Size(98, 23);
+            dtxtInputParam14.TabIndex = 24;
+            dtxtInputParam14.Text = "0";
+            dtxtInputParam14.Visible = false;
+            // 
+            // lblInputParam16
+            // 
+            lblInputParam16.AutoSize = true;
+            lblInputParam16.Location = new Point(200, 294);
+            lblInputParam16.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam16.MaximumSize = new Size(0, 28);
+            lblInputParam16.MinimumSize = new Size(0, 28);
+            lblInputParam16.Name = "lblInputParam16";
+            lblInputParam16.Size = new Size(46, 28);
+            lblInputParam16.TabIndex = 20;
+            lblInputParam16.Text = "鍙傛暟16";
+            lblInputParam16.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam16.Visible = false;
+            // 
+            // dtxtInputParam16
+            // 
+            dtxtInputParam16.Location = new Point(290, 297);
+            dtxtInputParam16.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam16.Name = "dtxtInputParam16";
+            dtxtInputParam16.Size = new Size(98, 23);
+            dtxtInputParam16.TabIndex = 26;
+            dtxtInputParam16.Text = "0";
+            dtxtInputParam16.Visible = false;
+            // 
+            // lblInputParam18
+            // 
+            lblInputParam18.AutoSize = true;
+            lblInputParam18.Location = new Point(200, 336);
+            lblInputParam18.Margin = new Padding(2, 0, 2, 0);
+            lblInputParam18.MaximumSize = new Size(0, 28);
+            lblInputParam18.MinimumSize = new Size(0, 28);
+            lblInputParam18.Name = "lblInputParam18";
+            lblInputParam18.Size = new Size(46, 28);
+            lblInputParam18.TabIndex = 22;
+            lblInputParam18.Text = "鍙傛暟18";
+            lblInputParam18.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam18.Visible = false;
+            // 
+            // dtxtInputParam18
+            // 
+            dtxtInputParam18.Location = new Point(290, 339);
+            dtxtInputParam18.Margin = new Padding(2, 3, 2, 3);
+            dtxtInputParam18.Name = "dtxtInputParam18";
+            dtxtInputParam18.Size = new Size(98, 23);
+            dtxtInputParam18.TabIndex = 28;
+            dtxtInputParam18.Text = "0";
+            dtxtInputParam18.Visible = false;
+            // 
+            // TopToolStrip
+            // 
+            TopToolStrip.Items.AddRange(new ToolStripItem[] { btnRun, btnLoadImage, btnSaveParas, btnLoadParas });
+            TopToolStrip.Location = new Point(0, 0);
+            TopToolStrip.Name = "TopToolStrip";
+            TopToolStrip.Size = new Size(1044, 25);
+            TopToolStrip.TabIndex = 45;
+            TopToolStrip.Text = "toolStrip1";
+            // 
+            // btnRun
+            // 
+            btnRun.BackgroundImageLayout = ImageLayout.Zoom;
+            btnRun.ImageTransparentColor = Color.Magenta;
+            btnRun.Name = "btnRun";
+            btnRun.Size = new Size(36, 22);
+            btnRun.Text = "杩愯";
+            btnRun.Click += btnRun_Click;
+            // 
+            // btnLoadImage
+            // 
+            btnLoadImage.ImageTransparentColor = Color.Magenta;
+            btnLoadImage.Name = "btnLoadImage";
+            btnLoadImage.Size = new Size(36, 22);
+            btnLoadImage.Text = "瀵煎浘";
+            btnLoadImage.Click += btnLoadImage_Click;
+            // 
+            // btnSaveParas
+            // 
+            btnSaveParas.ImageTransparentColor = Color.Magenta;
+            btnSaveParas.Name = "btnSaveParas";
+            btnSaveParas.Size = new Size(36, 22);
+            btnSaveParas.Text = "淇濆瓨";
+            btnSaveParas.Click += btnSaveParas_Click;
+            // 
+            // btnLoadParas
+            // 
+            btnLoadParas.ImageTransparentColor = Color.Magenta;
+            btnLoadParas.Name = "btnLoadParas";
+            btnLoadParas.Size = new Size(36, 22);
+            btnLoadParas.Text = "鍔犺浇";
+            btnLoadParas.Click += btnLoadParas_Click;
+            // 
+            // BtmStatusStrip
+            // 
+            BtmStatusStrip.Items.AddRange(new ToolStripItem[] { lblResult, lblMsg, lblRunTime });
+            BtmStatusStrip.Location = new Point(0, 577);
+            BtmStatusStrip.Name = "BtmStatusStrip";
+            BtmStatusStrip.Size = new Size(1044, 22);
+            BtmStatusStrip.TabIndex = 46;
+            BtmStatusStrip.Text = "statusStrip1";
+            // 
+            // lblResult
+            // 
+            lblResult.Name = "lblResult";
+            lblResult.Size = new Size(34, 17);
+            lblResult.Text = "True";
+            // 
+            // lblMsg
+            // 
+            lblMsg.Name = "lblMsg";
+            lblMsg.Size = new Size(56, 17);
+            lblMsg.Text = "杩愯鎴愬姛";
+            lblMsg.TextAlign = ContentAlignment.MiddleLeft;
+            // 
+            // lblRunTime
+            // 
+            lblRunTime.Name = "lblRunTime";
+            lblRunTime.Size = new Size(32, 17);
+            lblRunTime.Text = "0ms";
+            // 
+            // MainTableLayoutPanel
+            // 
+            MainTableLayoutPanel.ColumnCount = 2;
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F));
+            MainTableLayoutPanel.Controls.Add(parasTabControl, 0, 0);
+            MainTableLayoutPanel.Controls.Add(imgTabControl, 1, 0);
+            MainTableLayoutPanel.Dock = DockStyle.Fill;
+            MainTableLayoutPanel.Location = new Point(0, 25);
+            MainTableLayoutPanel.Name = "MainTableLayoutPanel";
+            MainTableLayoutPanel.RowCount = 1;
+            MainTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            MainTableLayoutPanel.Size = new Size(1044, 552);
+            MainTableLayoutPanel.TabIndex = 47;
+            // 
+            // parasTabControl
+            // 
+            parasTabControl.Controls.Add(tabPageInputParas);
+            parasTabControl.Controls.Add(tabPageRunParas);
+            parasTabControl.Controls.Add(tabPageModelParas);
+            parasTabControl.Controls.Add(tabPageOutputParas);
+            parasTabControl.Dock = DockStyle.Fill;
+            parasTabControl.Location = new Point(3, 3);
+            parasTabControl.Name = "parasTabControl";
+            parasTabControl.SelectedIndex = 0;
+            parasTabControl.Size = new Size(411, 546);
+            parasTabControl.TabIndex = 48;
+            parasTabControl.SelectedIndexChanged += parasTabControl_SelectedIndexChanged;
+            // 
+            // tabPageInputParas
+            // 
+            tabPageInputParas.Controls.Add(tablePanelParas);
+            tabPageInputParas.Location = new Point(4, 26);
+            tabPageInputParas.Name = "tabPageInputParas";
+            tabPageInputParas.Padding = new Padding(3);
+            tabPageInputParas.Size = new Size(403, 516);
+            tabPageInputParas.TabIndex = 0;
+            tabPageInputParas.Text = "杈撳叆鍙傛暟";
+            tabPageInputParas.UseVisualStyleBackColor = true;
+            // 
+            // tabPageRunParas
+            // 
+            tabPageRunParas.Controls.Add(tableLayoutPanel3);
+            tabPageRunParas.Location = new Point(4, 26);
+            tabPageRunParas.Name = "tabPageRunParas";
+            tabPageRunParas.Size = new Size(403, 516);
+            tabPageRunParas.TabIndex = 2;
+            tabPageRunParas.Text = "杩愯鍙傛暟";
+            tabPageRunParas.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel3
+            // 
+            tableLayoutPanel3.ColumnCount = 1;
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Controls.Add(tableLayoutPanel1, 0, 0);
+            tableLayoutPanel3.Controls.Add(grpModel, 0, 1);
+            tableLayoutPanel3.Dock = DockStyle.Fill;
+            tableLayoutPanel3.Location = new Point(0, 0);
+            tableLayoutPanel3.Name = "tableLayoutPanel3";
+            tableLayoutPanel3.RowCount = 2;
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 100F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel3.Size = new Size(403, 516);
+            tableLayoutPanel3.TabIndex = 2;
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 4;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 117F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(cmbTypeRoi, 1, 0);
+            tableLayoutPanel1.Controls.Add(label21, 0, 0);
+            tableLayoutPanel1.Controls.Add(label22, 0, 1);
+            tableLayoutPanel1.Controls.Add(cmbFixture, 1, 1);
+            tableLayoutPanel1.Controls.Add(ckbDrawRoi, 2, 0);
+            tableLayoutPanel1.Controls.Add(ckbStartMask, 0, 2);
+            tableLayoutPanel1.Controls.Add(txtMaskSize, 1, 2);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(3, 3);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 3;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Size = new Size(397, 94);
+            tableLayoutPanel1.TabIndex = 6;
+            // 
+            // cmbTypeRoi
+            // 
+            cmbTypeRoi.Dock = DockStyle.Fill;
+            cmbTypeRoi.FormattingEnabled = true;
+            cmbTypeRoi.Location = new Point(103, 3);
+            cmbTypeRoi.Name = "cmbTypeRoi";
+            cmbTypeRoi.Size = new Size(111, 25);
+            cmbTypeRoi.TabIndex = 1;
+            cmbTypeRoi.SelectedIndexChanged += cmbTypeRoi_SelectedIndexChanged;
+            // 
+            // label21
+            // 
+            label21.AutoSize = true;
+            label21.Dock = DockStyle.Fill;
+            label21.Location = new Point(3, 0);
+            label21.Name = "label21";
+            label21.Size = new Size(94, 30);
+            label21.TabIndex = 3;
+            label21.Text = "ROI";
+            label21.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label22
+            // 
+            label22.AutoSize = true;
+            label22.Dock = DockStyle.Fill;
+            label22.Location = new Point(3, 30);
+            label22.Name = "label22";
+            label22.Size = new Size(94, 30);
+            label22.TabIndex = 4;
+            label22.Text = "Fixture";
+            label22.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbFixture
+            // 
+            cmbFixture.Dock = DockStyle.Fill;
+            cmbFixture.FormattingEnabled = true;
+            cmbFixture.Location = new Point(103, 33);
+            cmbFixture.Name = "cmbFixture";
+            cmbFixture.Size = new Size(111, 25);
+            cmbFixture.TabIndex = 5;
+            cmbFixture.SelectedIndexChanged += cmbFixture_SelectedIndexChanged;
+            // 
+            // ckbDrawRoi
+            // 
+            ckbDrawRoi.AutoSize = true;
+            ckbDrawRoi.CheckAlign = ContentAlignment.MiddleCenter;
+            ckbDrawRoi.Location = new Point(220, 3);
+            ckbDrawRoi.Name = "ckbDrawRoi";
+            ckbDrawRoi.Size = new Size(14, 14);
+            ckbDrawRoi.TabIndex = 2;
+            ckbDrawRoi.UseVisualStyleBackColor = true;
+            ckbDrawRoi.CheckedChanged += ckbDrawRoi_CheckedChanged;
+            // 
+            // ckbStartMask
+            // 
+            ckbStartMask.AutoSize = true;
+            ckbStartMask.Dock = DockStyle.Fill;
+            ckbStartMask.Location = new Point(3, 63);
+            ckbStartMask.Name = "ckbStartMask";
+            ckbStartMask.Size = new Size(94, 28);
+            ckbStartMask.TabIndex = 6;
+            ckbStartMask.Text = "鎺╄啘妯℃澘";
+            ckbStartMask.UseVisualStyleBackColor = true;
+            // 
+            // txtMaskSize
+            // 
+            txtMaskSize.Dock = DockStyle.Fill;
+            txtMaskSize.Location = new Point(103, 63);
+            txtMaskSize.Name = "txtMaskSize";
+            txtMaskSize.Size = new Size(111, 23);
+            txtMaskSize.TabIndex = 7;
+            txtMaskSize.Text = "10";
+            // 
+            // grpModel
+            // 
+            grpModel.Dock = DockStyle.Fill;
+            grpModel.Location = new Point(3, 103);
+            grpModel.Name = "grpModel";
+            grpModel.Size = new Size(397, 410);
+            grpModel.TabIndex = 3;
+            grpModel.TabStop = false;
+            grpModel.Text = "杩愯妯℃澘";
+            // 
+            // tabPageModelParas
+            // 
+            tabPageModelParas.Controls.Add(tableLayoutPanel2);
+            tabPageModelParas.Location = new Point(4, 26);
+            tabPageModelParas.Name = "tabPageModelParas";
+            tabPageModelParas.Padding = new Padding(3);
+            tabPageModelParas.Size = new Size(403, 516);
+            tabPageModelParas.TabIndex = 3;
+            tabPageModelParas.Text = "妯℃澘鍙傛暟";
+            tabPageModelParas.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 4;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tableLayoutPanel2.Controls.Add(dtxtModelParam13, 1, 7);
+            tableLayoutPanel2.Controls.Add(lblModelParam13, 0, 7);
+            tableLayoutPanel2.Controls.Add(lblModelParam11, 0, 6);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam11, 1, 6);
+            tableLayoutPanel2.Controls.Add(lblModelParam9, 0, 5);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam9, 1, 5);
+            tableLayoutPanel2.Controls.Add(lblModelParam7, 0, 4);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam7, 1, 4);
+            tableLayoutPanel2.Controls.Add(lblModelParam5, 0, 3);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam5, 1, 3);
+            tableLayoutPanel2.Controls.Add(lblModelParam3, 0, 2);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam3, 1, 2);
+            tableLayoutPanel2.Controls.Add(lblModelParam1, 0, 1);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam1, 1, 1);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam2, 3, 1);
+            tableLayoutPanel2.Controls.Add(btnSaveModel, 3, 0);
+            tableLayoutPanel2.Controls.Add(lblModelParam2, 2, 1);
+            tableLayoutPanel2.Controls.Add(lblModelParam4, 2, 2);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam4, 3, 2);
+            tableLayoutPanel2.Controls.Add(lblModelParam6, 2, 3);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam6, 3, 3);
+            tableLayoutPanel2.Controls.Add(lblModelParam8, 2, 4);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam8, 3, 4);
+            tableLayoutPanel2.Controls.Add(lblModelParam10, 2, 5);
+            tableLayoutPanel2.Controls.Add(lblModelParam12, 2, 6);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam12, 3, 6);
+            tableLayoutPanel2.Controls.Add(lblModelParam14, 2, 7);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam14, 3, 7);
+            tableLayoutPanel2.Controls.Add(lblModelParam15, 0, 8);
+            tableLayoutPanel2.Controls.Add(lblModelParam17, 0, 9);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam15, 1, 8);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam17, 1, 9);
+            tableLayoutPanel2.Controls.Add(lblModelParam16, 2, 8);
+            tableLayoutPanel2.Controls.Add(lblModelParam18, 2, 9);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam16, 3, 8);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam18, 3, 9);
+            tableLayoutPanel2.Controls.Add(btnCreateModel, 2, 0);
+            tableLayoutPanel2.Controls.Add(lblModelType, 0, 0);
+            tableLayoutPanel2.Controls.Add(cmbModelType, 1, 0);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam10, 3, 5);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 3);
+            tableLayoutPanel2.Margin = new Padding(2, 3, 2, 3);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 12;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.Size = new Size(397, 510);
+            tableLayoutPanel2.TabIndex = 1;
+            // 
+            // dtxtModelParam13
+            // 
+            dtxtModelParam13.Location = new Point(92, 297);
+            dtxtModelParam13.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam13.Name = "dtxtModelParam13";
+            dtxtModelParam13.Size = new Size(98, 23);
+            dtxtModelParam13.TabIndex = 23;
+            dtxtModelParam13.Text = "0";
+            dtxtModelParam13.Visible = false;
+            // 
+            // lblModelParam13
+            // 
+            lblModelParam13.AutoSize = true;
+            lblModelParam13.Location = new Point(2, 294);
+            lblModelParam13.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam13.MaximumSize = new Size(0, 28);
+            lblModelParam13.MinimumSize = new Size(0, 28);
+            lblModelParam13.Name = "lblModelParam13";
+            lblModelParam13.Size = new Size(46, 28);
+            lblModelParam13.TabIndex = 17;
+            lblModelParam13.Text = "鍙傛暟13";
+            lblModelParam13.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam13.Visible = false;
+            // 
+            // lblModelParam11
+            // 
+            lblModelParam11.AutoSize = true;
+            lblModelParam11.Location = new Point(2, 252);
+            lblModelParam11.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam11.MaximumSize = new Size(0, 28);
+            lblModelParam11.MinimumSize = new Size(0, 28);
+            lblModelParam11.Name = "lblModelParam11";
+            lblModelParam11.Size = new Size(46, 28);
+            lblModelParam11.TabIndex = 15;
+            lblModelParam11.Text = "鍙傛暟11";
+            lblModelParam11.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam11.Visible = false;
+            // 
+            // dtxtModelParam11
+            // 
+            dtxtModelParam11.Location = new Point(92, 255);
+            dtxtModelParam11.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam11.Name = "dtxtModelParam11";
+            dtxtModelParam11.Size = new Size(98, 23);
+            dtxtModelParam11.TabIndex = 9;
+            dtxtModelParam11.Text = "0";
+            dtxtModelParam11.Visible = false;
+            // 
+            // lblModelParam9
+            // 
+            lblModelParam9.AutoSize = true;
+            lblModelParam9.Location = new Point(2, 210);
+            lblModelParam9.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam9.MaximumSize = new Size(0, 28);
+            lblModelParam9.MinimumSize = new Size(0, 28);
+            lblModelParam9.Name = "lblModelParam9";
+            lblModelParam9.Size = new Size(39, 28);
+            lblModelParam9.TabIndex = 13;
+            lblModelParam9.Text = "鍙傛暟9";
+            lblModelParam9.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam9.Visible = false;
+            // 
+            // dtxtModelParam9
+            // 
+            dtxtModelParam9.Location = new Point(92, 213);
+            dtxtModelParam9.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam9.Name = "dtxtModelParam9";
+            dtxtModelParam9.Size = new Size(98, 23);
+            dtxtModelParam9.TabIndex = 9;
+            dtxtModelParam9.Text = "0";
+            dtxtModelParam9.Visible = false;
+            // 
+            // lblModelParam7
+            // 
+            lblModelParam7.AutoSize = true;
+            lblModelParam7.Location = new Point(2, 168);
+            lblModelParam7.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam7.MaximumSize = new Size(0, 28);
+            lblModelParam7.MinimumSize = new Size(0, 28);
+            lblModelParam7.Name = "lblModelParam7";
+            lblModelParam7.Size = new Size(39, 28);
+            lblModelParam7.TabIndex = 11;
+            lblModelParam7.Text = "鍙傛暟7";
+            lblModelParam7.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam7.Visible = false;
+            // 
+            // dtxtModelParam7
+            // 
+            dtxtModelParam7.Location = new Point(92, 171);
+            dtxtModelParam7.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam7.Name = "dtxtModelParam7";
+            dtxtModelParam7.Size = new Size(98, 23);
+            dtxtModelParam7.TabIndex = 9;
+            dtxtModelParam7.Text = "0";
+            dtxtModelParam7.Visible = false;
+            // 
+            // lblModelParam5
+            // 
+            lblModelParam5.AutoSize = true;
+            lblModelParam5.Location = new Point(2, 126);
+            lblModelParam5.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam5.MaximumSize = new Size(0, 28);
+            lblModelParam5.MinimumSize = new Size(0, 28);
+            lblModelParam5.Name = "lblModelParam5";
+            lblModelParam5.Size = new Size(39, 28);
+            lblModelParam5.TabIndex = 9;
+            lblModelParam5.Text = "鍙傛暟5";
+            lblModelParam5.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam5.Visible = false;
+            // 
+            // dtxtModelParam5
+            // 
+            dtxtModelParam5.Location = new Point(92, 129);
+            dtxtModelParam5.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam5.Name = "dtxtModelParam5";
+            dtxtModelParam5.Size = new Size(98, 23);
+            dtxtModelParam5.TabIndex = 9;
+            dtxtModelParam5.Text = "0";
+            dtxtModelParam5.Visible = false;
+            // 
+            // lblModelParam3
+            // 
+            lblModelParam3.AutoSize = true;
+            lblModelParam3.Location = new Point(2, 84);
+            lblModelParam3.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam3.MaximumSize = new Size(0, 28);
+            lblModelParam3.MinimumSize = new Size(0, 28);
+            lblModelParam3.Name = "lblModelParam3";
+            lblModelParam3.Size = new Size(39, 28);
+            lblModelParam3.TabIndex = 2;
+            lblModelParam3.Text = "鍙傛暟3";
+            lblModelParam3.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam3.Visible = false;
+            // 
+            // dtxtModelParam3
+            // 
+            dtxtModelParam3.Location = new Point(92, 87);
+            dtxtModelParam3.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam3.Name = "dtxtModelParam3";
+            dtxtModelParam3.Size = new Size(98, 23);
+            dtxtModelParam3.TabIndex = 7;
+            dtxtModelParam3.Text = "0";
+            dtxtModelParam3.Visible = false;
+            // 
+            // lblModelParam1
+            // 
+            lblModelParam1.AutoSize = true;
+            lblModelParam1.Location = new Point(2, 42);
+            lblModelParam1.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam1.MaximumSize = new Size(0, 28);
+            lblModelParam1.MinimumSize = new Size(0, 28);
+            lblModelParam1.Name = "lblModelParam1";
+            lblModelParam1.Size = new Size(39, 28);
+            lblModelParam1.TabIndex = 0;
+            lblModelParam1.Text = "鍙傛暟1";
+            lblModelParam1.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam1.Visible = false;
+            // 
+            // dtxtModelParam1
+            // 
+            dtxtModelParam1.Location = new Point(92, 45);
+            dtxtModelParam1.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam1.Name = "dtxtModelParam1";
+            dtxtModelParam1.Size = new Size(98, 23);
+            dtxtModelParam1.TabIndex = 5;
+            dtxtModelParam1.Text = "0";
+            dtxtModelParam1.Visible = false;
+            // 
+            // dtxtModelParam2
+            // 
+            dtxtModelParam2.Location = new Point(290, 45);
+            dtxtModelParam2.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam2.Name = "dtxtModelParam2";
+            dtxtModelParam2.Size = new Size(98, 23);
+            dtxtModelParam2.TabIndex = 6;
+            dtxtModelParam2.Text = "0";
+            dtxtModelParam2.Visible = false;
+            // 
+            // btnSaveModel
+            // 
+            btnSaveModel.Location = new Point(291, 3);
+            btnSaveModel.Name = "btnSaveModel";
+            btnSaveModel.Size = new Size(75, 23);
+            btnSaveModel.TabIndex = 30;
+            btnSaveModel.Text = "淇濆瓨妯℃澘";
+            btnSaveModel.UseVisualStyleBackColor = true;
+            btnSaveModel.Click += btnSaveModel_Click;
+            // 
+            // lblModelParam2
+            // 
+            lblModelParam2.AutoSize = true;
+            lblModelParam2.Location = new Point(200, 42);
+            lblModelParam2.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam2.MaximumSize = new Size(0, 28);
+            lblModelParam2.MinimumSize = new Size(0, 28);
+            lblModelParam2.Name = "lblModelParam2";
+            lblModelParam2.Size = new Size(39, 28);
+            lblModelParam2.TabIndex = 1;
+            lblModelParam2.Text = "鍙傛暟2";
+            lblModelParam2.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam2.Visible = false;
+            // 
+            // lblModelParam4
+            // 
+            lblModelParam4.AutoSize = true;
+            lblModelParam4.Location = new Point(200, 84);
+            lblModelParam4.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam4.MaximumSize = new Size(0, 28);
+            lblModelParam4.MinimumSize = new Size(0, 28);
+            lblModelParam4.Name = "lblModelParam4";
+            lblModelParam4.Size = new Size(39, 28);
+            lblModelParam4.TabIndex = 3;
+            lblModelParam4.Text = "鍙傛暟4";
+            lblModelParam4.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam4.Visible = false;
+            // 
+            // dtxtModelParam4
+            // 
+            dtxtModelParam4.Location = new Point(290, 87);
+            dtxtModelParam4.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam4.Name = "dtxtModelParam4";
+            dtxtModelParam4.Size = new Size(98, 23);
+            dtxtModelParam4.TabIndex = 8;
+            dtxtModelParam4.Text = "0";
+            dtxtModelParam4.Visible = false;
+            // 
+            // lblModelParam6
+            // 
+            lblModelParam6.AutoSize = true;
+            lblModelParam6.Location = new Point(200, 126);
+            lblModelParam6.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam6.MaximumSize = new Size(0, 28);
+            lblModelParam6.MinimumSize = new Size(0, 28);
+            lblModelParam6.Name = "lblModelParam6";
+            lblModelParam6.Size = new Size(39, 28);
+            lblModelParam6.TabIndex = 10;
+            lblModelParam6.Text = "鍙傛暟6";
+            lblModelParam6.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam6.Visible = false;
+            // 
+            // dtxtModelParam6
+            // 
+            dtxtModelParam6.Location = new Point(290, 129);
+            dtxtModelParam6.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam6.Name = "dtxtModelParam6";
+            dtxtModelParam6.Size = new Size(98, 23);
+            dtxtModelParam6.TabIndex = 9;
+            dtxtModelParam6.Text = "0";
+            dtxtModelParam6.Visible = false;
+            // 
+            // lblModelParam8
+            // 
+            lblModelParam8.AutoSize = true;
+            lblModelParam8.Location = new Point(200, 168);
+            lblModelParam8.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam8.MaximumSize = new Size(0, 28);
+            lblModelParam8.MinimumSize = new Size(0, 28);
+            lblModelParam8.Name = "lblModelParam8";
+            lblModelParam8.Size = new Size(39, 28);
+            lblModelParam8.TabIndex = 12;
+            lblModelParam8.Text = "鍙傛暟8";
+            lblModelParam8.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam8.Visible = false;
+            // 
+            // dtxtModelParam8
+            // 
+            dtxtModelParam8.Location = new Point(290, 171);
+            dtxtModelParam8.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam8.Name = "dtxtModelParam8";
+            dtxtModelParam8.Size = new Size(98, 23);
+            dtxtModelParam8.TabIndex = 9;
+            dtxtModelParam8.Text = "0";
+            dtxtModelParam8.Visible = false;
+            // 
+            // lblModelParam10
+            // 
+            lblModelParam10.AutoSize = true;
+            lblModelParam10.Location = new Point(200, 210);
+            lblModelParam10.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam10.MaximumSize = new Size(0, 28);
+            lblModelParam10.MinimumSize = new Size(0, 28);
+            lblModelParam10.Name = "lblModelParam10";
+            lblModelParam10.Size = new Size(46, 28);
+            lblModelParam10.TabIndex = 14;
+            lblModelParam10.Text = "鍙傛暟10";
+            lblModelParam10.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam10.Visible = false;
+            // 
+            // lblModelParam12
+            // 
+            lblModelParam12.AutoSize = true;
+            lblModelParam12.Location = new Point(200, 252);
+            lblModelParam12.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam12.MaximumSize = new Size(0, 28);
+            lblModelParam12.MinimumSize = new Size(0, 28);
+            lblModelParam12.Name = "lblModelParam12";
+            lblModelParam12.Size = new Size(46, 28);
+            lblModelParam12.TabIndex = 16;
+            lblModelParam12.Text = "鍙傛暟12";
+            lblModelParam12.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam12.Visible = false;
+            // 
+            // dtxtModelParam12
+            // 
+            dtxtModelParam12.Location = new Point(290, 255);
+            dtxtModelParam12.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam12.Name = "dtxtModelParam12";
+            dtxtModelParam12.Size = new Size(98, 23);
+            dtxtModelParam12.TabIndex = 10;
+            dtxtModelParam12.Text = "0";
+            dtxtModelParam12.Visible = false;
+            // 
+            // lblModelParam14
+            // 
+            lblModelParam14.AutoSize = true;
+            lblModelParam14.Location = new Point(200, 294);
+            lblModelParam14.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam14.MaximumSize = new Size(0, 28);
+            lblModelParam14.MinimumSize = new Size(0, 28);
+            lblModelParam14.Name = "lblModelParam14";
+            lblModelParam14.Size = new Size(46, 28);
+            lblModelParam14.TabIndex = 18;
+            lblModelParam14.Text = "鍙傛暟14";
+            lblModelParam14.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam14.Visible = false;
+            // 
+            // dtxtModelParam14
+            // 
+            dtxtModelParam14.Location = new Point(290, 297);
+            dtxtModelParam14.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam14.Name = "dtxtModelParam14";
+            dtxtModelParam14.Size = new Size(98, 23);
+            dtxtModelParam14.TabIndex = 24;
+            dtxtModelParam14.Text = "0";
+            dtxtModelParam14.Visible = false;
+            // 
+            // lblModelParam15
+            // 
+            lblModelParam15.AutoSize = true;
+            lblModelParam15.Location = new Point(2, 336);
+            lblModelParam15.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam15.MaximumSize = new Size(0, 28);
+            lblModelParam15.MinimumSize = new Size(0, 28);
+            lblModelParam15.Name = "lblModelParam15";
+            lblModelParam15.Size = new Size(46, 28);
+            lblModelParam15.TabIndex = 19;
+            lblModelParam15.Text = "鍙傛暟15";
+            lblModelParam15.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam15.Visible = false;
+            // 
+            // lblModelParam17
+            // 
+            lblModelParam17.AutoSize = true;
+            lblModelParam17.Location = new Point(2, 378);
+            lblModelParam17.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam17.MaximumSize = new Size(0, 28);
+            lblModelParam17.MinimumSize = new Size(0, 28);
+            lblModelParam17.Name = "lblModelParam17";
+            lblModelParam17.Size = new Size(46, 28);
+            lblModelParam17.TabIndex = 21;
+            lblModelParam17.Text = "鍙傛暟17";
+            lblModelParam17.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam17.Visible = false;
+            // 
+            // dtxtModelParam15
+            // 
+            dtxtModelParam15.Location = new Point(92, 339);
+            dtxtModelParam15.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam15.Name = "dtxtModelParam15";
+            dtxtModelParam15.Size = new Size(98, 23);
+            dtxtModelParam15.TabIndex = 25;
+            dtxtModelParam15.Text = "0";
+            dtxtModelParam15.Visible = false;
+            // 
+            // dtxtModelParam17
+            // 
+            dtxtModelParam17.Location = new Point(92, 381);
+            dtxtModelParam17.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam17.Name = "dtxtModelParam17";
+            dtxtModelParam17.Size = new Size(98, 23);
+            dtxtModelParam17.TabIndex = 27;
+            dtxtModelParam17.Text = "0";
+            dtxtModelParam17.Visible = false;
+            // 
+            // lblModelParam16
+            // 
+            lblModelParam16.AutoSize = true;
+            lblModelParam16.Location = new Point(200, 336);
+            lblModelParam16.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam16.MaximumSize = new Size(0, 28);
+            lblModelParam16.MinimumSize = new Size(0, 28);
+            lblModelParam16.Name = "lblModelParam16";
+            lblModelParam16.Size = new Size(46, 28);
+            lblModelParam16.TabIndex = 20;
+            lblModelParam16.Text = "鍙傛暟16";
+            lblModelParam16.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam16.Visible = false;
+            // 
+            // lblModelParam18
+            // 
+            lblModelParam18.AutoSize = true;
+            lblModelParam18.Location = new Point(200, 378);
+            lblModelParam18.Margin = new Padding(2, 0, 2, 0);
+            lblModelParam18.MaximumSize = new Size(0, 28);
+            lblModelParam18.MinimumSize = new Size(0, 28);
+            lblModelParam18.Name = "lblModelParam18";
+            lblModelParam18.Size = new Size(46, 28);
+            lblModelParam18.TabIndex = 22;
+            lblModelParam18.Text = "鍙傛暟18";
+            lblModelParam18.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam18.Visible = false;
+            // 
+            // dtxtModelParam16
+            // 
+            dtxtModelParam16.Location = new Point(290, 339);
+            dtxtModelParam16.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam16.Name = "dtxtModelParam16";
+            dtxtModelParam16.Size = new Size(98, 23);
+            dtxtModelParam16.TabIndex = 26;
+            dtxtModelParam16.Text = "0";
+            dtxtModelParam16.Visible = false;
+            // 
+            // dtxtModelParam18
+            // 
+            dtxtModelParam18.Location = new Point(290, 381);
+            dtxtModelParam18.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam18.Name = "dtxtModelParam18";
+            dtxtModelParam18.Size = new Size(98, 23);
+            dtxtModelParam18.TabIndex = 28;
+            dtxtModelParam18.Text = "0";
+            dtxtModelParam18.Visible = false;
+            // 
+            // btnCreateModel
+            // 
+            btnCreateModel.Location = new Point(201, 3);
+            btnCreateModel.Name = "btnCreateModel";
+            btnCreateModel.Size = new Size(75, 23);
+            btnCreateModel.TabIndex = 29;
+            btnCreateModel.Text = "鍒涘缓妯℃澘";
+            btnCreateModel.UseVisualStyleBackColor = true;
+            btnCreateModel.Click += btnCreateModel_Click;
+            // 
+            // lblModelType
+            // 
+            lblModelType.AutoSize = true;
+            lblModelType.Location = new Point(2, 0);
+            lblModelType.Margin = new Padding(2, 0, 2, 0);
+            lblModelType.MaximumSize = new Size(0, 28);
+            lblModelType.MinimumSize = new Size(0, 28);
+            lblModelType.Name = "lblModelType";
+            lblModelType.Size = new Size(56, 28);
+            lblModelType.TabIndex = 31;
+            lblModelType.Text = "鍖归厤绠楁硶";
+            lblModelType.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbModelType
+            // 
+            cmbModelType.Font = new Font("Microsoft YaHei UI", 9F);
+            cmbModelType.FormattingEnabled = true;
+            cmbModelType.Location = new Point(93, 3);
+            cmbModelType.Name = "cmbModelType";
+            cmbModelType.Size = new Size(97, 25);
+            cmbModelType.TabIndex = 32;
+            cmbModelType.SelectedIndexChanged += cmbModelType_SelectedIndexChanged;
+            // 
+            // dtxtModelParam10
+            // 
+            dtxtModelParam10.Location = new Point(290, 213);
+            dtxtModelParam10.Margin = new Padding(2, 3, 2, 3);
+            dtxtModelParam10.Name = "dtxtModelParam10";
+            dtxtModelParam10.Size = new Size(98, 23);
+            dtxtModelParam10.TabIndex = 33;
+            dtxtModelParam10.Text = "0";
+            dtxtModelParam10.Visible = false;
+            // 
+            // tabPageOutputParas
+            // 
+            tabPageOutputParas.Controls.Add(tableLayoutResults);
+            tabPageOutputParas.Location = new Point(4, 26);
+            tabPageOutputParas.Name = "tabPageOutputParas";
+            tabPageOutputParas.Padding = new Padding(3);
+            tabPageOutputParas.Size = new Size(403, 516);
+            tabPageOutputParas.TabIndex = 1;
+            tabPageOutputParas.Text = "杈撳嚭缁撴灉";
+            tabPageOutputParas.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutResults
+            // 
+            tableLayoutResults.ColumnCount = 2;
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutResults.Controls.Add(dtxtCount, 1, 4);
+            tableLayoutResults.Controls.Add(label5, 0, 0);
+            tableLayoutResults.Controls.Add(label6, 0, 1);
+            tableLayoutResults.Controls.Add(label7, 0, 2);
+            tableLayoutResults.Controls.Add(dtxtCenterX, 1, 0);
+            tableLayoutResults.Controls.Add(dtxtCenterY, 1, 1);
+            tableLayoutResults.Controls.Add(dtxtPhi, 1, 2);
+            tableLayoutResults.Controls.Add(label8, 0, 3);
+            tableLayoutResults.Controls.Add(dtxtScore, 1, 3);
+            tableLayoutResults.Controls.Add(label9, 0, 4);
+            tableLayoutResults.Dock = DockStyle.Fill;
+            tableLayoutResults.Location = new Point(3, 3);
+            tableLayoutResults.Margin = new Padding(2, 3, 2, 3);
+            tableLayoutResults.Name = "tableLayoutResults";
+            tableLayoutResults.RowCount = 10;
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.Size = new Size(397, 510);
+            tableLayoutResults.TabIndex = 1;
+            // 
+            // dtxtCount
+            // 
+            dtxtCount.Location = new Point(103, 207);
+            dtxtCount.Name = "dtxtCount";
+            dtxtCount.ReadOnly = true;
+            dtxtCount.Size = new Size(291, 23);
+            dtxtCount.TabIndex = 11;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Dock = DockStyle.Fill;
+            label5.Location = new Point(2, 0);
+            label5.Margin = new Padding(2, 0, 2, 0);
+            label5.MaximumSize = new Size(0, 28);
+            label5.MinimumSize = new Size(0, 28);
+            label5.Name = "label5";
+            label5.Size = new Size(96, 28);
+            label5.TabIndex = 0;
+            label5.Text = "X";
+            label5.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label6
+            // 
+            label6.AutoSize = true;
+            label6.Dock = DockStyle.Fill;
+            label6.Location = new Point(2, 51);
+            label6.Margin = new Padding(2, 0, 2, 0);
+            label6.MaximumSize = new Size(0, 28);
+            label6.MinimumSize = new Size(0, 28);
+            label6.Name = "label6";
+            label6.Size = new Size(96, 28);
+            label6.TabIndex = 1;
+            label6.Text = "Y";
+            label6.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label7
+            // 
+            label7.AutoSize = true;
+            label7.Dock = DockStyle.Fill;
+            label7.Location = new Point(2, 102);
+            label7.Margin = new Padding(2, 0, 2, 0);
+            label7.MaximumSize = new Size(0, 28);
+            label7.MinimumSize = new Size(0, 28);
+            label7.Name = "label7";
+            label7.Size = new Size(96, 28);
+            label7.TabIndex = 2;
+            label7.Text = "寮у害(rad)";
+            label7.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCenterX
+            // 
+            dtxtCenterX.Dock = DockStyle.Fill;
+            dtxtCenterX.Location = new Point(102, 3);
+            dtxtCenterX.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterX.Name = "dtxtCenterX";
+            dtxtCenterX.ReadOnly = true;
+            dtxtCenterX.Size = new Size(293, 23);
+            dtxtCenterX.TabIndex = 5;
+            // 
+            // dtxtCenterY
+            // 
+            dtxtCenterY.Dock = DockStyle.Fill;
+            dtxtCenterY.Location = new Point(102, 54);
+            dtxtCenterY.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterY.Name = "dtxtCenterY";
+            dtxtCenterY.ReadOnly = true;
+            dtxtCenterY.Size = new Size(293, 23);
+            dtxtCenterY.TabIndex = 6;
+            // 
+            // dtxtPhi
+            // 
+            dtxtPhi.Dock = DockStyle.Fill;
+            dtxtPhi.Location = new Point(102, 105);
+            dtxtPhi.Margin = new Padding(2, 3, 2, 3);
+            dtxtPhi.Name = "dtxtPhi";
+            dtxtPhi.ReadOnly = true;
+            dtxtPhi.Size = new Size(293, 23);
+            dtxtPhi.TabIndex = 7;
+            // 
+            // label8
+            // 
+            label8.AutoSize = true;
+            label8.Dock = DockStyle.Fill;
+            label8.Location = new Point(3, 153);
+            label8.Name = "label8";
+            label8.Size = new Size(94, 51);
+            label8.TabIndex = 8;
+            label8.Text = "鍒嗘暟";
+            label8.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtScore
+            // 
+            dtxtScore.Location = new Point(103, 156);
+            dtxtScore.Name = "dtxtScore";
+            dtxtScore.ReadOnly = true;
+            dtxtScore.Size = new Size(291, 23);
+            dtxtScore.TabIndex = 9;
+            // 
+            // label9
+            // 
+            label9.AutoSize = true;
+            label9.Dock = DockStyle.Fill;
+            label9.Location = new Point(3, 204);
+            label9.Name = "label9";
+            label9.Size = new Size(94, 51);
+            label9.TabIndex = 10;
+            label9.Text = "鏁伴噺";
+            label9.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // imgTabControl
+            // 
+            imgTabControl.Controls.Add(tabPageInputImage);
+            imgTabControl.Controls.Add(tabPageModelImage);
+            imgTabControl.Controls.Add(tabPageRecordImage);
+            imgTabControl.Dock = DockStyle.Fill;
+            imgTabControl.Location = new Point(420, 3);
+            imgTabControl.Name = "imgTabControl";
+            imgTabControl.SelectedIndex = 0;
+            imgTabControl.Size = new Size(621, 546);
+            imgTabControl.TabIndex = 49;
+            // 
+            // tabPageInputImage
+            // 
+            tabPageInputImage.Controls.Add(pnlInputImage);
+            tabPageInputImage.Location = new Point(4, 26);
+            tabPageInputImage.Name = "tabPageInputImage";
+            tabPageInputImage.Padding = new Padding(3);
+            tabPageInputImage.Size = new Size(613, 516);
+            tabPageInputImage.TabIndex = 0;
+            tabPageInputImage.Text = "杈撳叆鍥惧儚";
+            tabPageInputImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlInputImage
+            // 
+            pnlInputImage.Dock = DockStyle.Fill;
+            pnlInputImage.Location = new Point(3, 3);
+            pnlInputImage.Margin = new Padding(4);
+            pnlInputImage.Name = "pnlInputImage";
+            pnlInputImage.Size = new Size(607, 510);
+            pnlInputImage.TabIndex = 44;
+            // 
+            // tabPageModelImage
+            // 
+            tabPageModelImage.Controls.Add(pnlCreateModelImage);
+            tabPageModelImage.Location = new Point(4, 26);
+            tabPageModelImage.Name = "tabPageModelImage";
+            tabPageModelImage.Size = new Size(613, 516);
+            tabPageModelImage.TabIndex = 2;
+            tabPageModelImage.Text = "妯℃澘鍥惧儚";
+            tabPageModelImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlCreateModelImage
+            // 
+            pnlCreateModelImage.Dock = DockStyle.Fill;
+            pnlCreateModelImage.Location = new Point(0, 0);
+            pnlCreateModelImage.Name = "pnlCreateModelImage";
+            pnlCreateModelImage.Size = new Size(613, 516);
+            pnlCreateModelImage.TabIndex = 0;
+            // 
+            // tabPageRecordImage
+            // 
+            tabPageRecordImage.Controls.Add(pnlRecordImage);
+            tabPageRecordImage.Location = new Point(4, 26);
+            tabPageRecordImage.Name = "tabPageRecordImage";
+            tabPageRecordImage.Padding = new Padding(3);
+            tabPageRecordImage.Size = new Size(613, 516);
+            tabPageRecordImage.TabIndex = 1;
+            tabPageRecordImage.Text = "缁撴灉鍥惧儚";
+            tabPageRecordImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlRecordImage
+            // 
+            pnlRecordImage.Dock = DockStyle.Fill;
+            pnlRecordImage.Location = new Point(3, 3);
+            pnlRecordImage.Margin = new Padding(4);
+            pnlRecordImage.Name = "pnlRecordImage";
+            pnlRecordImage.Size = new Size(607, 510);
+            pnlRecordImage.TabIndex = 45;
+            // 
+            // HFindModelToolEdit
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(MainTableLayoutPanel);
+            Controls.Add(BtmStatusStrip);
+            Controls.Add(TopToolStrip);
+            Margin = new Padding(2, 3, 2, 3);
+            Name = "HFindModelToolEdit";
+            Size = new Size(1044, 599);
+            Load += HFindModelToolEdit_Load;
+            SizeChanged += HFindModelToolEdit_SizeChanged;
+            tablePanelParas.ResumeLayout(false);
+            tablePanelParas.PerformLayout();
+            TopToolStrip.ResumeLayout(false);
+            TopToolStrip.PerformLayout();
+            BtmStatusStrip.ResumeLayout(false);
+            BtmStatusStrip.PerformLayout();
+            MainTableLayoutPanel.ResumeLayout(false);
+            parasTabControl.ResumeLayout(false);
+            tabPageInputParas.ResumeLayout(false);
+            tabPageRunParas.ResumeLayout(false);
+            tableLayoutPanel3.ResumeLayout(false);
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel1.PerformLayout();
+            tabPageModelParas.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel2.PerformLayout();
+            tabPageOutputParas.ResumeLayout(false);
+            tableLayoutResults.ResumeLayout(false);
+            tableLayoutResults.PerformLayout();
+            imgTabControl.ResumeLayout(false);
+            tabPageInputImage.ResumeLayout(false);
+            tabPageModelImage.ResumeLayout(false);
+            tabPageRecordImage.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TableLayoutPanel tablePanelParas;
+        private System.Windows.Forms.Label lblInputParam1;
+        private System.Windows.Forms.Label lblInputParam2;
+        private System.Windows.Forms.Label lblInputParam3;
+        private System.Windows.Forms.Label lblInputParam4;
+        private System.Windows.Forms.TextBox dtxtInputParam1;
+        private System.Windows.Forms.TextBox dtxtInputParam2;
+        private System.Windows.Forms.TextBox dtxtInputParam3;
+        private System.Windows.Forms.TextBox dtxtInputParam4;
+        private ToolStrip TopToolStrip;
+        private ToolStripButton btnRun;
+        private StatusStrip BtmStatusStrip;
+        private ToolStripStatusLabel lblResult;
+        private ToolStripStatusLabel lblMsg;
+        private TableLayoutPanel MainTableLayoutPanel;
+        private ToolStripButton btnLoadImage;
+        private TabControl parasTabControl;
+        private TabPage tabPageInputParas;
+        private TabPage tabPageOutputParas;
+        private TabPage tabPageRunParas;
+        private TabControl imgTabControl;
+        private TabPage tabPageRecordImage;
+        private ToolStripButton btnSaveParas;
+        private ToolStripButton btnLoadParas;
+        private Panel pnlRecordImage;
+        private Label lblInputParam5;
+        private Label lblInputParam6;
+        private Label lblInputParam7;
+        private Label lblInputParam8;
+        private Label lblInputParam9;
+        private Label lblInputParam10;
+        private Label lblInputParam11;
+        private Label lblInputParam12;
+        private TextBox dtxtInputParam12;
+        private TextBox dtxtInputParam11;
+        private TextBox dtxtInputParam10;
+        private TextBox dtxtInputParam9;
+        private TextBox dtxtInputParam8;
+        private TextBox dtxtInputParam7;
+        private TextBox dtxtInputParam6;
+        private TextBox dtxtInputParam5;
+        private TabPage tabPageModelImage;
+        private TabPage tabPageModelParas;
+        private TableLayoutPanel tableLayoutResults;
+        private Label label5;
+        private Label label6;
+        private Label label7;
+        private TextBox dtxtCenterX;
+        private TextBox dtxtCenterY;
+        private TextBox dtxtPhi;
+        private Label lblInputParam13;
+        private Label lblInputParam14;
+        private Label lblInputParam15;
+        private Label lblInputParam16;
+        private Label lblInputParam17;
+        private Label lblInputParam18;
+        private TextBox dtxtInputParam13;
+        private TextBox dtxtInputParam14;
+        private TextBox dtxtInputParam15;
+        private TextBox dtxtInputParam16;
+        private TextBox dtxtInputParam17;
+        private TextBox dtxtInputParam18;
+        private TableLayoutPanel tableLayoutPanel2;
+        private Label lblModelParam1;
+        private TextBox dtxtModelParam1;
+        private Label lblModelParam2;
+        private TextBox dtxtModelParam2;
+        private Label lblModelParam3;
+        private TextBox dtxtModelParam3;
+        private Label lblModelParam4;
+        private TextBox dtxtModelParam4;
+        private Label lblModelParam5;
+        private TextBox dtxtModelParam5;
+        private Label lblModelParam6;
+        private TextBox dtxtModelParam6;
+        private Label lblModelParam7;
+        private TextBox dtxtModelParam7;
+        private Label lblModelParam8;
+        private TextBox dtxtModelParam8;
+        private Label lblModelParam9;
+        private TextBox dtxtModelParam9;
+        private Label lblModelParam10;
+        private Label lblModelParam11;
+        private TextBox dtxtModelParam11;
+        private Label lblModelParam12;
+        private TextBox dtxtModelParam12;
+        private Label lblModelParam13;
+        private Label lblModelParam14;
+        private Label lblModelParam15;
+        private Label lblModelParam16;
+        private Label lblModelParam17;
+        private Label lblModelParam18;
+        private TextBox dtxtModelParam13;
+        private TextBox dtxtModelParam14;
+        private TextBox dtxtModelParam15;
+        private TextBox dtxtModelParam16;
+        private TextBox dtxtModelParam17;
+        private TextBox dtxtModelParam18;
+        private Button btnCreateModel;
+        private Button btnSaveModel;
+        private GroupBox grpModel;
+        private TableLayoutPanel tableLayoutPanel3;
+        private TabPage tabPageInputImage;
+        private Panel pnlInputImage;
+        private Panel pnlCreateModelImage;
+        private Label label8;
+        private TextBox dtxtScore;
+        private TextBox dtxtCount;
+        private Label label9;
+        private ToolStripStatusLabel lblRunTime;
+        private Label lblModelType;
+        private ComboBox cmbModelType;
+        private TableLayoutPanel tableLayoutPanel1;
+        public ComboBox cmbTypeRoi;
+        private Label label21;
+        private Label label22;
+        private ComboBox cmbFixture;
+        private CheckBox ckbDrawRoi;
+        private TextBox dtxtModelParam10;
+        private CheckBox ckbStartMask;
+        private TextBox txtMaskSize;
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.cs
new file mode 100644
index 0000000..ffed42b
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.cs
@@ -0,0 +1,1459 @@
+锘縰sing HalconDotNet;
+using LB_VisionControl;
+using Newtonsoft.Json;
+using System.Diagnostics;
+using System.Reflection;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static LB_VisionProcesses.Alogrithms.Halcon.HFindModelTool;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    public partial class HFindModelToolEdit : TAlgorithmEdit
+    {
+        public HFindModelToolEdit(HFindModelTool subject = null)
+        {
+            if (subject != null && subject is HFindModelTool)
+                Subject = subject;
+            else
+                Subject = new HFindModelTool();
+
+            this.Dock = DockStyle.Fill;
+            InitializeComponent();
+        }
+
+        public HWindowControl modelImageHWindowControl = new HWindowControl();
+        public UserHSmartWindowControl createModelImageHSmartWindowControl = new UserHSmartWindowControl();
+
+        private bool isLeftDown = false;
+
+        private int MaskSize
+        {
+            get
+            {
+                if (int.TryParse(txtMaskSize.Text, out int size))
+                    return size;
+                else
+                    return 10;
+            }
+        }
+
+        private HObject Mask = new HObject();
+        private HObject FirstModelImage = new HObject();
+        private HObject TempModelImage = new HObject();
+
+        /// <summary>
+        /// 鎺т欢鍔犺浇浜嬩欢
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void HFindModelToolEdit_Load(object sender, EventArgs e)
+        {
+            pnlInputImage.Controls.Add(inputImageHSmartWindowControl);
+            inputImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            pnlRecordImage.Controls.Add(recordImageHSmartWindowControl);
+            recordImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            pnlCreateModelImage.Controls.Add(createModelImageHSmartWindowControl);
+            createModelImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            grpModel.Controls.Add(modelImageHWindowControl);
+            modelImageHWindowControl.Dock = DockStyle.Fill;
+
+            // 璁剧疆杞粨榛樿涓虹豢鑹�
+            HOperatorSet.SetColor(modelImageHWindowControl.HalconWindow, "red");
+            HOperatorSet.SetLineWidth(modelImageHWindowControl.HalconWindow, 5);
+
+            modelImageHWindowControl.MouseDown += (sender, e) =>
+            {
+                if (e.Button == MouseButtons.Left)
+                    isLeftDown = true;
+            };
+
+            modelImageHWindowControl.MouseUp += (sender, e) =>
+            {
+                if (e.Button == MouseButtons.Left)
+                    isLeftDown = true;
+            };
+
+            modelImageHWindowControl.MouseMove += (sender, e) =>
+            {
+                if (e.Button == MouseButtons.Left && isLeftDown && ckbStartMask.Checked)
+                {
+                    // 鐐瑰嚮榧犳爣
+                    if (TempModelImage != null && TempModelImage.IsInitialized())
+                    {
+                        try
+                        {
+                            HOperatorSet.GetMposition(modelImageHWindowControl.HalconWindow, out HTuple row, out HTuple col, out HTuple button_state);
+                            if (row.Length != 0 && col.Length != 0)
+                            {
+                                HTuple hv_color = new HTuple();
+                                hv_color[0] = 0;
+                                hv_color[1] = 0;
+                                hv_color[2] = 255;
+                                HOperatorSet.GenCircle(out HObject ho_Circle, row, col, MaskSize);
+                                if (!Mask.IsInitialized())
+                                    Mask = ho_Circle;
+                                else
+                                    HOperatorSet.Union2(ho_Circle, Mask, out Mask);
+
+                                HOperatorSet.GetImageSize(TempModelImage, out HTuple width, out HTuple height);
+                                HOperatorSet.GenRectangle1(out HObject allROI, 0, 0, height, width);
+                                HOperatorSet.Difference(allROI, Mask, out HObject subROI);
+                                HOperatorSet.ReduceDomain(TempModelImage, subROI, out HObject ModelImage);
+                                HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow);
+                                TAlgorithm.DispImage(ModelImage, modelImageHWindowControl.HalconWindow);
+                            }
+                        }
+                        catch { }
+                    }
+                }
+            };
+
+            ckbStartMask.CheckedChanged += (sender, e) =>
+            {
+                try
+                {
+                    if (ckbStartMask.Checked)
+                    {
+                        // 鐐瑰嚮榧犳爣
+                        if (FirstModelImage == null || !FirstModelImage.IsInitialized())
+                            FirstModelImage = ((HFindModelTool)Subject).ModelID.hoImage.CopyObj(1, -1); ;
+
+                        TempModelImage = FirstModelImage.CopyObj(1, -1);
+                        Mask.Dispose();
+                        Mask = new HObject();
+
+                        HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow);
+                        TAlgorithm.DispImage(FirstModelImage, modelImageHWindowControl.HalconWindow);
+                    }
+                    else
+                    {
+                        DialogResult res = MessageBox.Show("鏄惁浣跨敤鎺╄啘鍥剧墖淇濆瓨妯℃澘锛�", "鎻愮ず", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);  //淇濆瓨缁撴灉淇℃伅
+                        /// 鍙傛暟1锛氭樉绀烘枃鏈紝鍙傛暟2锛氭爣棰橈紝鍙傛暟3锛氭寜閿被鍨嬶紝鍙傛暟4锛氭樉绀哄浘鏍�
+                        if (res == DialogResult.Yes)  //淇濆瓨
+                        {
+                            try
+                            {
+                                if (TempModelImage != null && TempModelImage is HObject)
+                                {
+                                    if (Enum.TryParse(cmbModelType.Text, out ModelType modelType))
+                                    {
+                                        string NumLevels = this.dtxtModelParam1.Text;
+                                        string AngleStep = this.dtxtModelParam2.Text;
+
+                                        double AngleStart = Convert.ToDouble(this.dtxtModelParam3.Text);
+                                        double AngleExtent = Convert.ToDouble(this.dtxtModelParam4.Text);
+                                        double ScaleRMin = Convert.ToDouble(this.dtxtModelParam5.Text);
+                                        double ScaleRMax = Convert.ToDouble(this.dtxtModelParam6.Text);
+                                        double ScaleCMin = Convert.ToDouble(this.dtxtModelParam7.Text);
+                                        double ScaleCMax = Convert.ToDouble(this.dtxtModelParam8.Text);
+
+                                        string Optimization = this.dtxtModelParam9.Text;
+                                        string Metric = this.dtxtModelParam10.Text;
+                                        string Contrast = this.dtxtModelParam11.Text;
+                                        int MinContrast = Convert.ToInt16(this.dtxtModelParam12.Text);
+                                        //HRectangle2 ROI = (HRectangle2)createModelImageHSmartWindowControl.oRoi;
+
+                                        //HOperatorSet.GenRectangle2(out HObject hRectangle, ROI.Row, ROI.Column, ROI.Phi
+                                        //    , ROI.SemiLength1, ROI.SemiLength2);
+                                        HObject hoDomainImage = FirstModelImage as HObject;
+                                        HTuple hv_Channels = new HTuple();
+                                        //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                        {
+                                            try
+                                            {
+                                                HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                                                if (hv_Channels.TupleInt() != 1)
+                                                    HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+
+                                                //杞崲鍚庡啀娆℃鏌ユ槸鍚︿负鐏板害鍥�
+                                                HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                                                if (hv_Channels.TupleInt() != 1)
+                                                    HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+                                            }
+                                            catch { }
+                                        }
+
+                                        HOperatorSet.GetImageSize(FirstModelImage, out HTuple width, out HTuple height);
+                                        HOperatorSet.GenRectangle1(out HObject allROI, 0, 0, height, width);
+                                        HOperatorSet.Difference(allROI, Mask, out HObject subROI);
+                                        HOperatorSet.ReduceDomain(FirstModelImage, subROI, out HObject ModelImage);
+
+                                        bool bCreateModel = false;
+
+                                        switch (modelType)
+                                        {
+                                            case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                                                bCreateModel = ((HFindModelTool)Subject).CreateModel
+                                                    (ModelImage, modelType, NumLevels
+                                                    , AngleStart, AngleExtent, AngleStep
+                                                    , ScaleRMin, ScaleRMax, "auto"
+                                                    , ScaleCMin, ScaleCMax, "auto"
+                                                    , Optimization, Metric, Contrast, MinContrast);
+                                                break;
+                                            case ModelType.鍚勫悜寮傚舰妯℃澘:
+                                            default:
+                                                bCreateModel = ((HFindModelTool)Subject).CreateModel
+                                                    (ModelImage, modelType, NumLevels
+                                                    , AngleStart, AngleExtent, AngleStep
+                                                    , ScaleRMin, ScaleRMax, "auto"
+                                                    , ScaleCMin, ScaleCMax, "auto"
+                                                    , Optimization, Metric, Contrast, MinContrast);
+                                                break;
+                                        }
+
+                                        if (bCreateModel)
+                                        {
+                                            HObject ho_ModelContours = new HObject();
+                                            switch (((HFindModelTool)Subject).ModelID.Type)
+                                            {
+                                                case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                                                    HOperatorSet.GetDeformableModelContours(out ho_ModelContours, ((HFindModelTool)Subject).ModelID.hvModel, 1);
+                                                    break;
+                                                case ModelType.鍚勫悜寮傚舰妯℃澘:
+                                                default:
+                                                    HOperatorSet.GetShapeModelContours(out ho_ModelContours, ((HFindModelTool)Subject).ModelID.hvModel, 1);
+                                                    break;
+                                            }
+                                            HOperatorSet.GetImageSize(((HFindModelTool)Subject).ModelID.hoImage, out HTuple hv_Width, out HTuple hv_Height);
+                                            HOperatorSet.VectorAngleToRigid(-hv_Height / 2, -hv_Width / 2, 0, 0, 0, 0, out HTuple hv_HomMat2D);
+                                            HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ModelContours, hv_HomMat2D);
+
+                                            //寤烘ā鎴愬姛瀵艰埅鍒板瓙椤�
+                                            parasTabControl.SelectedTab = tabPageRunParas;
+                                            HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow);
+                                            TAlgorithm.DispImage(((HFindModelTool)Subject).ModelID.hoImage, modelImageHWindowControl.HalconWindow);
+                                            TAlgorithm.SetColor(modelImageHWindowControl.HalconWindow, "red");
+                                            TAlgorithm.DispObj(ho_ModelContours, modelImageHWindowControl.HalconWindow);
+                                            TAlgorithm.DispMsg("鍒涘缓妯℃澘鎴愬姛", modelImageHWindowControl.HalconWindow, true);
+                                        }
+                                        else
+                                        {
+                                            HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow);
+                                            TAlgorithm.DispMsg("鍒涘缓妯℃澘澶辫触", modelImageHWindowControl.HalconWindow, false);
+                                        }
+                                    }
+                                }
+                                TempModelImage.Dispose();
+                            }
+                            catch
+                            {
+                                HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow);
+                                TAlgorithm.DispMsg("鍒涘缓妯℃澘澶辫触", modelImageHWindowControl.HalconWindow, false);
+                            }
+                        }
+                    }
+                }
+                catch { }
+            };
+
+            //cmbModelType.SelectedIndex = cmbModelType.FindString("褰㈢姸");
+            UpdataInputsUI();
+
+            // 璁剧疆鏄剧ず鏍峰紡
+            toolTip.AutoPopDelay = 5000;//鎻愮ず淇℃伅鐨勫彲瑙佹椂闂�
+            toolTip.InitialDelay = 500;//浜嬩欢瑙﹀彂澶氫箙鍚庡嚭鐜版彁绀�
+            toolTip.ReshowDelay = 500;//鎸囬拡浠庝竴涓帶浠剁Щ鍚戝彟涓�涓帶浠舵椂锛岀粡杩囧涔呮墠浼氭樉绀轰笅涓�涓彁绀烘
+            toolTip.ShowAlways = true;//鏄惁鏄剧ず鎻愮ず妗�
+
+            //閬嶅巻鍙互閫夋嫨鐨凴oi绫诲瀷鏋氫妇
+            foreach (var value in Enum.GetValues(typeof(RoiType)))
+                cmbTypeRoi.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨凢ixture鏋氫妇
+            cmbFixture.Items.Add("");
+            foreach (string value in IProcess.dicFixtures.Keys)
+                cmbFixture.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨凪odel绫诲瀷鏋氫妇
+            foreach (var value in Enum.GetValues(typeof(ModelType)))
+                cmbModelType.Items.Add(value.ToString());
+
+            cmbTypeRoi.Text = RoiType.None.ToString();
+            LoadParas();
+
+            if (Subject.Result)
+            {
+                lblResult.BackColor = Color.Green;
+                lblResult.Text = "True";
+            }
+            else
+            {
+                lblResult.BackColor = Color.Red;
+                lblResult.Text = "False";
+            }
+
+            lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+            lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+            lblRunTime.Text = $"{Subject.RunTime}ms";
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯鍙傛暟
+        /// </summary>
+        public override void UpdataInputs()
+        {
+            //璁剧疆杩愯鍙傛暟
+            double dResult = 0;
+            int iResult = 0;
+            cmbModelType.Text = ((HFindModelTool)Subject).ModelID.Type.ToString();
+            if (Enum.TryParse(cmbModelType.SelectedItem.ToString(), out ModelType modelType))
+            {
+                switch (modelType)
+                {
+                    case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                        //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                        //, ScaleRMin, ScaleRMax
+                        //, ScaleCMin, ScaleCMax
+                        //, MinScore, NumMatches, MaxOverlap
+                        //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                        //, Greediness, ResultType, new HTuple(), new HTuple()
+                        //, out hv_Score, out hv_CenterRow, out hv_CenterColumn);
+                        #region 杈撳叆鍙傛暟
+                        Subject.Params.Inputs["AngleStart"] = dtxtInputParam1.Text;
+                        Subject.Params.Inputs["AngleExtent"] = dtxtInputParam2.Text;
+                        Subject.Params.Inputs["ScaleRMin"] = dtxtInputParam3.Text;
+                        Subject.Params.Inputs["ScaleRMax"] = dtxtInputParam4.Text;
+                        Subject.Params.Inputs["ScaleCMin"] = dtxtInputParam5.Text;
+                        Subject.Params.Inputs["ScaleCMax"] = dtxtInputParam6.Text;
+                        Subject.Params.Inputs["MinScore"] = dtxtInputParam7.Text;
+                        Subject.Params.Inputs["NumMatches"] = dtxtInputParam8.Text;
+                        Subject.Params.Inputs["MaxOverlap"] = dtxtInputParam9.Text;
+                        Subject.Params.Inputs["ResultType"] = dtxtInputParam10.Text;
+                        Subject.Params.Inputs["NumLevels"] = dtxtInputParam11.Text;
+                        Subject.Params.Inputs["Greediness"] = dtxtInputParam12.Text;
+                        Subject.Params.Inputs["MinCount"] = dtxtInputParam13.Text;
+                        Subject.Params.Inputs["MaxCount"] = dtxtInputParam14.Text;
+                        #endregion
+                        break;
+                    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                    default:
+                        //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                        //, ScaleRMin, ScaleRMax
+                        //, ScaleCMin, ScaleCMax
+                        //, MinScore, NumMatches, MaxOverlap, SubPixel
+                        //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                        //, Greediness
+                        #region 杈撳叆鍙傛暟
+                        Subject.Params.Inputs["AngleStart"] = dtxtInputParam1.Text;
+                        Subject.Params.Inputs["AngleExtent"] = dtxtInputParam2.Text;
+                        Subject.Params.Inputs["ScaleRMin"] = dtxtInputParam3.Text;
+                        Subject.Params.Inputs["ScaleRMax"] = dtxtInputParam4.Text;
+                        Subject.Params.Inputs["ScaleCMin"] = dtxtInputParam5.Text;
+                        Subject.Params.Inputs["ScaleCMax"] = dtxtInputParam6.Text;
+                        Subject.Params.Inputs["MinScore"] = dtxtInputParam7.Text;
+                        Subject.Params.Inputs["NumMatches"] = dtxtInputParam8.Text;
+                        Subject.Params.Inputs["MaxOverlap"] = dtxtInputParam9.Text;
+                        Subject.Params.Inputs["SubPixel"] = dtxtInputParam10.Text;
+                        Subject.Params.Inputs["NumLevels"] = dtxtInputParam11.Text;
+                        Subject.Params.Inputs["Greediness"] = dtxtInputParam12.Text;
+                        Subject.Params.Inputs["MinCount"] = dtxtInputParam13.Text;
+                        Subject.Params.Inputs["MaxCount"] = dtxtInputParam14.Text;
+                        #endregion
+                        break;
+                }
+
+                //if (cmbFixture.Text == "")
+                //    Subject.Params.Fixture = new Fixture();
+                //else if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                //    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+
+                Type type = inputImageHSmartWindowControl.oRoi?.GetType();
+                switch (type)
+                {
+                    case Type t when t == typeof(HRectangle2):
+                        HRectangle2 hRectangle2 = (HRectangle2)inputImageHSmartWindowControl.oRoi;
+                        Subject.Params.ROI
+                            = new HRectangle2(hRectangle2.X - Subject.Params.Fixture.X, hRectangle2.Y - Subject.Params.Fixture.Y
+                            , hRectangle2.Phi - Subject.Params.Fixture.Phi, hRectangle2.Width, hRectangle2.Height);
+                        break;
+                    case Type t when t == typeof(HCircle):
+                        HCircle hCircle = (HCircle)inputImageHSmartWindowControl.oRoi;
+                        Subject.Params.ROI
+                            = new HCircle(hCircle.X - Subject.Params.Fixture.X, hCircle.Y - Subject.Params.Fixture.Y, hCircle.Radius);
+                        break;
+                    case Type t when t == typeof(HSegment):
+                        HSegment hSegment = (HSegment)inputImageHSmartWindowControl.oRoi;
+                        Subject.Params.ROI
+                            = new HSegment(hSegment.StartX - Subject.Params.Fixture.X, hSegment.StartY - Subject.Params.Fixture.Y
+                            , hSegment.EndX - Subject.Params.Fixture.X, hSegment.EndY - Subject.Params.Fixture.Y);
+                        break;
+                    default:
+                        Subject.Params.ROI = new ROI();
+                        break;
+                }
+
+            }
+        }
+
+        /// <summary>
+        /// 鍔犺浇杩愯鍙傛暟
+        /// </summary>
+        public override void LoadParas()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                cmbModelType.Text = ((HFindModelTool)Subject).ModelID.Type.ToString();
+                if (Enum.TryParse(cmbModelType.Text, out ModelType modelType))
+                {
+                    switch (modelType)
+                    {
+                        case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                            //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                            //, ScaleRMin, ScaleRMax
+                            //, ScaleCMin, ScaleCMax
+                            //, MinScore, NumMatches, MaxOverlap
+                            //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                            //, Greediness, ResultType, new HTuple(), new HTuple()
+                            #region 杈撳叆鍙傛暟
+                            dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"].ToString();
+                            dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"].ToString();
+                            dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"].ToString();
+                            dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"].ToString();
+                            dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"].ToString();
+                            dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"].ToString();
+                            dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"].ToString();
+                            dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"].ToString();
+                            dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"].ToString();
+                            dtxtInputParam10.Text = Subject.Params.Inputs["ResultType"].ToString();
+                            dtxtInputParam11.Text = Subject.Params.Inputs["NumLevels"].ToString();
+                            dtxtInputParam12.Text = Subject.Params.Inputs["Greediness"].ToString();
+                            dtxtInputParam13.Text = Subject.Params.Inputs["MinCount"].ToString();
+                            dtxtInputParam14.Text = Subject.Params.Inputs["MaxCount"].ToString();
+                            #endregion
+                            break;
+                        case ModelType.鍚勫悜寮傚舰妯℃澘:
+                        default:
+                            #region 杈撳叆鍙傛暟
+                            dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"].ToString();
+                            dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"].ToString();
+                            dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"].ToString();
+                            dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"].ToString();
+                            dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"].ToString();
+                            dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"].ToString();
+                            dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"].ToString();
+                            dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"].ToString();
+                            dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"].ToString();
+                            dtxtInputParam10.Text = Subject.Params.Inputs["ResultType"].ToString();
+                            dtxtInputParam11.Text = Subject.Params.Inputs["NumLevels"].ToString();
+                            dtxtInputParam12.Text = Subject.Params.Inputs["Greediness"].ToString();
+                            dtxtInputParam13.Text = Subject.Params.Inputs["MinCount"].ToString();
+                            dtxtInputParam14.Text = Subject.Params.Inputs["MaxCount"].ToString();
+                            #endregion
+                            break;
+                    }
+                }
+
+                if (Subject.InputImage != null && Subject.InputImage is HObject)
+                    inputImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+
+                Type type = Subject.Params.ROI?.GetType();
+                if (Subject.Params.ROI != null)
+                {
+                    switch (type)
+                    {
+                        case Type t when t == typeof(HRectangle2):
+                            cmbTypeRoi.Text = RoiType.Rectangle2.ToString();
+                            break;
+                        case Type t when t == typeof(HCircle):
+                            cmbTypeRoi.Text = RoiType.Circle.ToString();
+                            break;
+                        case Type t when t == typeof(HSegment):
+                            cmbTypeRoi.Text = RoiType.Segment.ToString();
+                            break;
+                        default:
+                            cmbTypeRoi.Text = RoiType.None.ToString();
+                            break;
+                    }
+                    if (cmbTypeRoi.Text.ToString() != "None")
+                        ckbDrawRoi.Checked = true;
+                    else
+                        ckbDrawRoi.Checked = false;
+
+                    inputImageHSmartWindowControl.oRoi = Subject.Params.ROI;
+                }
+
+                if (Subject.Params.Fixture != null)
+                    cmbFixture.Text = Subject.Params.Fixture.strName;
+                else
+                    cmbFixture.Text = "";
+
+                switch (type)
+                {
+                    case Type t when t == typeof(HRectangle2):
+                        inputImageHSmartWindowControl.oRoi
+                             = new HRectangle2(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                             , Subject.Params.ROI.Phi + Subject.Params.Fixture.Phi, ((HRectangle2)Subject.Params.ROI).Width, ((HRectangle2)Subject.Params.ROI).Height);
+                        break;
+                    case Type t when t == typeof(HCircle):
+                        inputImageHSmartWindowControl.oRoi
+                        = new HCircle(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                        , ((HCircle)Subject.Params.ROI).Radius);
+                        break;
+                    case Type t when t == typeof(HSegment):
+                        inputImageHSmartWindowControl.oRoi
+                        = new HSegment(((HSegment)Subject.Params.ROI).StartX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).StartY + Subject.Params.Fixture.Y
+                        , ((HSegment)Subject.Params.ROI).EndX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).EndY + Subject.Params.Fixture.Y);
+                        break;
+                    default:
+                        inputImageHSmartWindowControl.oRoi = null;
+                        break;
+                }
+
+                parasTabControl.SelectedTab = tabPageRunParas;
+                ShowModel(((HFindModelTool)Subject).ModelID);
+                parasTabControl.SelectedTab = tabPageInputParas;
+            }));
+        }
+
+        /// <summary>
+        /// 鏇存柊杈撳嚭缁撴灉
+        /// </summary>
+        public override void UpdataOutputs()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                //瀛樺湪鍙嶅簭鍒楀寲閿欎贡鐨勬儏鍐甸渶瑕佷娇鐢ㄨ嚜瀹氫箟鐨勮浆鎹㈠櫒
+                dtxtCenterX.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterX"]);
+                dtxtCenterY.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterY"]);
+                dtxtPhi.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Phi"]);
+                dtxtScore.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Score"]);
+                dtxtCount.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Count"]);
+            }));
+        }
+
+        /// <summary>
+        /// 鐐瑰嚮杩愯
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        public override void btnRun_Click(object sender, EventArgs e)
+        {
+
+            if (Subject.InputImage != null)
+                InputImage = Subject.InputImage;
+
+            DateTime StartTime = DateTime.Now;
+            Run();
+
+            //鏇存柊鏃ュ織涓庣粨鏋�
+            this.BeginInvoke(new Action(() =>
+            {
+                if (Subject.Result)
+                {
+                    lblResult.BackColor = Color.Green;
+                    lblResult.Text = "True";
+                    recordImageHSmartWindowControl.SetColor("green");
+                }
+                else
+                {
+                    lblResult.BackColor = Color.Red;
+                    lblResult.Text = "False";
+                    recordImageHSmartWindowControl.SetColor("red");
+                }
+
+                lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+                lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+                lblRunTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
+
+                UpdataOutputs();
+                imgTabControl.SelectedTab = tabPageRecordImage;
+
+                if (Subject.InputImage != null && Subject.InputImage is HObject)
+                {
+                    HOperatorSet.GetImageSize((HObject)Subject.InputImage, out HTuple ho_ImageWidth, out HTuple ho_ImageHeight);
+                    recordImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+                }
+
+                //鍏堝垽鏂瓙绫诲啀鍒ゆ柇鐖剁被
+                if (Subject.Record != null && Subject.Record is MsgRecord msgRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_NG, false);
+
+                    for (int i = 0; i < msgRecord.Msg.Length; i++)
+                        recordImageHSmartWindowControl.ShowMsg(msgRecord.Msg[i]
+                            , 1 == msgRecord.Result[i] ? true : false, msgRecord.Column[i], msgRecord.Row[i]);
+                }
+                else if (Subject.Record != null && Subject.Record is ObjectRecord objRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_NG, false);
+                }
+
+                GC.Collect();
+            }));
+        }
+
+        public override void btnLoadImage_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    HOperatorSet.ReadImage(out HObject ho_Image, selectedFiles[0]);
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.CountChannels(ho_Image, out HTuple hv_Channels);
+                        if (hv_Channels.TupleInt() != 1)
+                        {
+                            HOperatorSet.Rgb1ToGray(ho_Image, out ho_Image);
+                            //鏇存柊鏃ュ織涓庣粨鏋�
+                            this.BeginInvoke(new Action(() =>
+                            {
+                                lblMsg.Text = "瀵煎叆鍥剧墖闈炵伆搴﹀浘,鑷姩杞崲涓虹伆搴﹀浘";
+                            }));
+                        }
+                        InputImage = ho_Image;
+                        imgTabControl.SelectedTab = tabPageInputImage;
+                        inputImageHSmartWindowControl.oRoi = inputImageHSmartWindowControl.oRoi;
+                    }
+                }
+            }
+        }
+
+        public override void btnSaveParas_Click(object sender, EventArgs e)
+        {
+            //淇濆瓨鍓嶉渶瑕佹洿鏂拌緭鍏ュ弬鏁癐nputs
+            UpdataInputs();
+
+            // 鍒涘缓 SaveFileDialog 瀹炰緥
+            using (SaveFileDialog saveFileDialog = new SaveFileDialog())
+            {
+                // 璁剧疆瀵硅瘽妗嗘爣棰�
+                saveFileDialog.Title = "淇濆瓨鏂囦欢";
+
+                // 璁剧疆榛樿璺緞
+                saveFileDialog.InitialDirectory = System.Windows.Forms.Application.StartupPath;
+
+                // 璁剧疆鏂囦欢绫诲瀷杩囨护鍣�
+                saveFileDialog.Filter = "鏂囨湰鏂囦欢 (*.json)|*.json|鎵�鏈夋枃浠� (*.*)|*.*";
+
+                // 璁剧疆榛樿鏂囦欢鍚�
+                saveFileDialog.FileName = Subject.strProcessName + ".json";
+
+                // 鏄剧ず瀵硅瘽妗嗗苟妫�鏌ョ敤鎴锋槸鍚︾偣鍑讳簡淇濆瓨鎸夐挳
+                if (saveFileDialog.ShowDialog() == DialogResult.OK)
+                {
+                    // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠惰矾寰�
+                    string fullPath = saveFileDialog.FileName;
+                    Debug.WriteLine("閫夋嫨鐨勬枃浠惰矾寰勬槸: " + fullPath);
+                    Subject.strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+                    ((HFindModelTool)Subject).Save(Path.GetDirectoryName(fullPath));
+                }
+            }
+        }
+
+        public override void btnLoadParas_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Ini Files (*.json)|*.json|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    ((HFindModelTool)Subject).Load(selectedFiles[0]);
+                    LoadParas();
+                }
+            }
+        }
+
+        public override void ckbDrawRoi_CheckedChanged(object sender, EventArgs e)
+        {
+            if (ckbDrawRoi.Checked)
+            {
+                inputImageHSmartWindowControl.bAollowDraw = true;
+                imgTabControl.SelectedTab = tabPageInputImage;
+            }
+            else
+            {
+                inputImageHSmartWindowControl.bAollowDraw = false;
+                Subject.Params.ROI = new ROI();
+            }
+        }
+
+        public override void cmbTypeRoi_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (Enum.TryParse(cmbTypeRoi.Text.ToString(), out RoiType type))
+                {
+                    HTuple hv_imageWidth = 0;
+                    HTuple hv_imageHeight = 0;
+                    if (InputImage != null && InputImage is HObject)
+                        HOperatorSet.GetImageSize((HObject)InputImage, out hv_imageWidth, out hv_imageHeight);
+                    switch (type)
+                    {
+                        case RoiType.Rectangle2:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, 0
+                                , hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.Circle:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HCircle(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, hv_imageWidth.TupleReal() / 4);
+                            break;
+                        case RoiType.Segment:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HSegment(0, 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.None:
+                        default:
+                            inputImageHSmartWindowControl.oRoi = null;
+                            break;
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public override void cmbFixture_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+                else
+                    Subject.Params.Fixture = new Fixture();
+            }
+            catch { }
+        }
+
+        private System.Windows.Forms.ToolTip toolTip = new System.Windows.Forms.ToolTip();
+        private void ShowToolTip(Control control, string message) => toolTip.SetToolTip(control, message);
+
+        // 閫氳繃鍙嶅皠娓呴櫎鎵�鏈変簨浠跺鐞嗙▼搴�
+        public void ClearAllEventHandlers()
+        {
+            // 鑾峰彇浜嬩欢瀛楁
+            FieldInfo field = typeof(Label).GetField("MouseHover", BindingFlags.NonPublic | BindingFlags.Instance);
+
+            if (field != null)
+            {
+                // 灏嗕簨浠跺瓧娈佃涓� null锛岀Щ闄ゆ墍鏈変簨浠跺鐞嗙▼搴�
+                field.SetValue(this, null);
+            }
+        }
+
+        private void cmbModelType_SelectedIndexChanged(object sender, EventArgs e) => UpdataInputsUI();
+
+        void UpdataInputsUI()
+        {
+            this.BeginInvoke(() =>
+            {
+                #region 娓呯┖杈撳叆
+                this.lblInputParam1.Visible = false;
+                this.lblInputParam2.Visible = false;
+                this.lblInputParam3.Visible = false;
+                this.lblInputParam4.Visible = false;
+                this.lblInputParam5.Visible = false;
+                this.lblInputParam6.Visible = false;
+                this.lblInputParam7.Visible = false;
+                this.lblInputParam8.Visible = false;
+                this.lblInputParam9.Visible = false;
+                this.lblInputParam10.Visible = false;
+                this.lblInputParam11.Visible = false;
+                this.lblInputParam12.Visible = false;
+                this.lblInputParam13.Visible = false;
+                this.lblInputParam14.Visible = false;
+                this.lblInputParam15.Visible = false;
+                this.lblInputParam16.Visible = false;
+                this.lblInputParam17.Visible = false;
+                this.lblInputParam18.Visible = false;
+
+                this.dtxtInputParam1.Visible = false;
+                this.dtxtInputParam2.Visible = false;
+                this.dtxtInputParam3.Visible = false;
+                this.dtxtInputParam4.Visible = false;
+                this.dtxtInputParam5.Visible = false;
+                this.dtxtInputParam6.Visible = false;
+                this.dtxtInputParam7.Visible = false;
+                this.dtxtInputParam8.Visible = false;
+                this.dtxtInputParam9.Visible = false;
+                this.dtxtInputParam10.Visible = false;
+                this.dtxtInputParam11.Visible = false;
+                this.dtxtInputParam12.Visible = false;
+                this.dtxtInputParam13.Visible = false;
+                this.dtxtInputParam14.Visible = false;
+                this.dtxtInputParam15.Visible = false;
+                this.dtxtInputParam16.Visible = false;
+                this.dtxtInputParam17.Visible = false;
+                this.dtxtInputParam18.Visible = false;
+                #endregion
+
+                #region 娓呯┖妯℃澘
+                this.lblModelParam1.Visible = false;
+                this.lblModelParam2.Visible = false;
+                this.lblModelParam3.Visible = false;
+                this.lblModelParam4.Visible = false;
+                this.lblModelParam5.Visible = false;
+                this.lblModelParam6.Visible = false;
+                this.lblModelParam7.Visible = false;
+                this.lblModelParam8.Visible = false;
+                this.lblModelParam9.Visible = false;
+                this.lblModelParam10.Visible = false;
+                this.lblModelParam11.Visible = false;
+                this.lblModelParam12.Visible = false;
+                this.lblModelParam13.Visible = false;
+                this.lblModelParam14.Visible = false;
+                this.lblModelParam15.Visible = false;
+                this.lblModelParam16.Visible = false;
+                this.lblModelParam17.Visible = false;
+                this.lblModelParam18.Visible = false;
+
+                this.dtxtModelParam1.Visible = false;
+                this.dtxtModelParam2.Visible = false;
+                this.dtxtModelParam3.Visible = false;
+                this.dtxtModelParam4.Visible = false;
+                this.dtxtModelParam5.Visible = false;
+                this.dtxtModelParam6.Visible = false;
+                this.dtxtModelParam7.Visible = false;
+                this.dtxtModelParam8.Visible = false;
+                this.dtxtModelParam9.Visible = false;
+                this.dtxtModelParam10.Visible = false;
+                this.dtxtModelParam11.Visible = false;
+                this.dtxtModelParam12.Visible = false;
+                this.dtxtModelParam13.Visible = false;
+                this.dtxtModelParam14.Visible = false;
+                this.dtxtModelParam15.Visible = false;
+                this.dtxtModelParam16.Visible = false;
+                this.dtxtModelParam17.Visible = false;
+                this.dtxtModelParam18.Visible = false;
+                #endregion
+
+                ClearAllEventHandlers();
+
+                if (Enum.TryParse(cmbModelType.Text, out ModelType modelType))
+                {
+                    switch (modelType)
+                    {
+                        case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                            //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                            //, ScaleRMin, ScaleRMax
+                            //, ScaleCMin, ScaleCMax
+                            //, MinScore, NumMatches, MaxOverlap
+                            //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                            //, Greediness, ResultType, new HTuple(), new HTuple()
+
+                            #region 杈撳叆鍙傛暟
+                            //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                            this.lblInputParam1.Text = "璧峰瑙掑害";
+                            this.dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"].ToString();
+                            this.lblInputParam1.Visible = true;
+                            this.dtxtInputParam1.Visible = true;
+                            this.dtxtInputParam1.Enabled = true;
+                            lblInputParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑璧峰瑙掑害AngleStart");
+
+                            this.lblInputParam2.Text = "瑙掑害鑼冨洿";
+                            this.dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"].ToString();
+                            this.lblInputParam2.Visible = true;
+                            this.dtxtInputParam2.Visible = true;
+                            this.dtxtInputParam2.Enabled = true;
+                            lblInputParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑瑙掑害鑼冨洿AngleExtent,'0'琛ㄧず鏃犺搴︽悳绱�");
+
+                            //, ScaleRMin, ScaleRMax
+                            this.lblInputParam3.Text = "绾靛悜缂╂斁鏈�灏忓��";
+                            this.dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"].ToString();
+                            this.lblInputParam3.Visible = true;
+                            this.dtxtInputParam3.Visible = true;
+                            this.dtxtInputParam3.Enabled = true;
+                            lblInputParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�灏忓�糞caleRMin");
+
+                            this.lblInputParam4.Text = "绾靛悜缂╂斁鏈�澶у��";
+                            this.dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"].ToString();
+                            this.lblInputParam4.Visible = true;
+                            this.dtxtInputParam4.Visible = true;
+                            this.dtxtInputParam4.Enabled = true;
+                            lblInputParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�澶у�糞caleRMax");
+
+                            //, ScaleCMin, ScaleCMax
+                            this.lblInputParam5.Text = "妯悜缂╂斁鏈�灏忓��";
+                            this.dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"].ToString();
+                            this.lblInputParam5.Visible = true;
+                            this.dtxtInputParam5.Visible = true;
+                            this.dtxtInputParam5.Enabled = true;
+                            lblInputParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�灏忓�糞caleCMin");
+
+                            this.lblInputParam6.Text = "妯悜缂╂斁鏈�澶у��";
+                            this.dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"].ToString();
+                            this.lblInputParam6.Visible = true;
+                            this.dtxtInputParam6.Visible = true;
+                            this.dtxtInputParam6.Enabled = true;
+                            lblInputParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�澶у�糞caleCMax");
+
+                            //, MinScore, NumMatches, MaxOverlap, ResultType
+                            this.lblInputParam7.Text = "鏈�灏忓垎鏁�";
+                            this.dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"].ToString();
+                            this.lblInputParam7.Visible = true;
+                            this.dtxtInputParam7.Visible = true;
+                            this.dtxtInputParam7.Enabled = true;
+                            lblInputParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "琚壘鍒扮殑妯℃澘鏈�灏忓垎鏁癕inScore");
+
+                            this.lblInputParam8.Text = "鏈熸湜涓暟";
+                            this.dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"].ToString();
+                            this.lblInputParam8.Visible = true;
+                            this.dtxtInputParam8.Visible = true;
+                            this.dtxtInputParam8.Enabled = true;
+                            lblInputParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "瑕佹壘鍒扮殑妯℃澘鏈�澶氱殑瀹炰緥鏁癗umMatches,'0'鍒欐壘鍒版墍鏈夊彲鑳界殑鍖归厤");
+
+                            this.lblInputParam9.Text = "鏈�澶ч噸鍙犳瘮渚�";
+                            this.dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"].ToString();
+                            this.lblInputParam9.Visible = true;
+                            this.dtxtInputParam9.Visible = true;
+                            this.dtxtInputParam9.Enabled = true;
+                            lblInputParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "鍏佽鎵惧埌鐨勬ā鍨嬪疄渚嬬殑鏈�澶ч噸鍙犳瘮渚婱axOverlap[杈冨皬鐨勫�间細閬垮厤鎵惧埌澶氫釜鐩镐技鐨勫尮閰峕");
+
+                            this.lblInputParam10.Text = "ResultType";
+                            this.dtxtInputParam10.Text = Subject.Params.Inputs["ResultType"]?.ToString();
+                            this.lblInputParam10.Visible = true;
+                            this.dtxtInputParam10.Visible = true;
+                            this.dtxtInputParam10.Enabled = false;
+                            lblInputParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "璁$畻绮惧害鐨勮缃甊esultType['1'寰楀埌浜氬儚绱犵簿搴");
+
+                            //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                            //, Greediness, , new HTuple(), new HTuple()
+                            this.lblInputParam11.Text = "鎼滅储鏃堕噾瀛楀鐨勫眰绾�";
+                            this.dtxtInputParam11.Text = "0";
+                            this.lblInputParam11.Visible = true;
+                            this.dtxtInputParam11.Visible = true;
+                            this.dtxtInputParam11.Enabled = false;
+                            lblInputParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃堕噾瀛楀鐨勫眰绾�");
+
+                            this.lblInputParam12.Text = "璐┆搴�";
+                            this.dtxtInputParam12.Text = Subject.Params.Inputs["Greediness"]?.ToString();
+                            this.lblInputParam12.Visible = true;
+                            this.dtxtInputParam12.Visible = true;
+                            this.dtxtInputParam12.Enabled = true;
+                            lblInputParam12.MouseHover += (s, e) => ShowToolTip((Control)s, "璐┆搴�,瓒婇珮閫熷害瓒婂揩[涓�鑸兘璁句负0.8,澶ぇ瀹规槗鍑虹幇鎵句笉鍒扮殑鎯呭喌]");
+
+                            this.lblInputParam13.Text = "鏈�灏忔暟閲�";
+                            this.dtxtInputParam13.Text = Subject.Params.Inputs["MinCount"]?.ToString();
+                            this.lblInputParam13.Visible = true;
+                            this.dtxtInputParam13.Visible = true;
+                            this.dtxtInputParam13.Enabled = true;
+                            lblInputParam13.MouseHover += (s, e) => ShowToolTip((Control)s, "鍖归厤缁撴灉瑕佹眰鐨勬渶灏忔暟閲�");
+
+                            this.lblInputParam14.Text = "鏈�澶ф暟閲�";
+                            this.dtxtInputParam14.Text = Subject.Params.Inputs["MaxCount"]?.ToString();
+                            this.lblInputParam14.Visible = true;
+                            this.dtxtInputParam14.Visible = true;
+                            this.dtxtInputParam14.Enabled = true;
+                            lblInputParam14.MouseHover += (s, e) => ShowToolTip((Control)s, "鍖归厤缁撴灉瑕佹眰鐨勬渶澶ф暟閲�");
+                            #endregion
+                            //UpdataInputs();
+
+                            //NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
+                            //   , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
+                            //   , ScaleRMin, ScaleRMax, ScaleRStep == "auto" ? ScaleRStep : Convert.ToDouble(ScaleRStep)
+                            //   , ScaleCMin, ScaleCMax, ScaleCStep == "auto" ? ScaleCStep : Convert.ToDouble(ScaleCStep)
+                            //   , Optimization, Metric
+                            //   , Contrast, MinContrast
+
+                            #region 妯℃澘鍙傛暟
+                            //NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
+                            this.lblModelParam1.Text = "閲戝瓧濉旂殑灞傜骇";
+                            this.dtxtModelParam1.Text = "auto";
+                            this.lblModelParam1.Visible = true;
+                            this.dtxtModelParam1.Visible = true;
+                            this.dtxtModelParam1.Enabled = false;
+                            lblModelParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃堕噾瀛楀鐨勫眰绾umLevels,'0'琛ㄧず涓嶄娇鐢ㄩ噾瀛楀");
+
+                            //   , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
+                            this.lblModelParam2.Text = "瑙掑害姝ラ暱";
+                            this.dtxtModelParam2.Text = "auto";
+                            this.lblModelParam2.Visible = true;
+                            this.dtxtModelParam2.Visible = true;
+                            this.dtxtModelParam2.Enabled = false;
+                            lblModelParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "瑙掑害鑼冨洿鍐呰繘琛屾棆杞殑姝ラ暱AngleStep,'auto'琛ㄧず鐢辩郴缁熻嚜鍔ㄩ�夋嫨鍚堥�傜殑姝ラ暱");
+
+                            this.lblModelParam3.Text = "璧峰瑙掑害";
+                            this.dtxtModelParam3.Text = "-5";
+                            this.lblModelParam3.Visible = true;
+                            this.dtxtModelParam3.Visible = true;
+                            this.dtxtModelParam3.Enabled = true;
+                            lblModelParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑璧峰瑙掑害AngleStart");
+
+                            this.lblModelParam4.Text = "瑙掑害鑼冨洿";
+                            this.dtxtModelParam4.Text = "10";
+                            this.lblModelParam4.Visible = true;
+                            this.dtxtModelParam4.Visible = true;
+                            this.dtxtModelParam4.Enabled = true;
+                            lblModelParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑瑙掑害鑼冨洿AngleExtent,'0'琛ㄧず鏃犺搴︽悳绱�");
+
+                            //, double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto"
+                            this.lblModelParam5.Text = "绾靛悜缂╂斁鏈�灏忓��";
+                            this.dtxtModelParam5.Text = "0.9";
+                            this.lblModelParam5.Visible = true;
+                            this.dtxtModelParam5.Visible = true;
+                            this.dtxtModelParam5.Enabled = true;
+                            lblModelParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�灏忓�糞caleRMin");
+
+                            this.lblModelParam6.Text = "绾靛悜缂╂斁鏈�澶у��";
+                            this.dtxtModelParam6.Text = "1.1";
+                            this.lblModelParam6.Visible = true;
+                            this.dtxtModelParam6.Visible = true;
+                            this.dtxtModelParam6.Enabled = true;
+                            lblModelParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�澶у�糞caleRMax");
+
+                            //, double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto"
+                            this.lblModelParam7.Text = "妯悜缂╂斁鏈�灏忓��";
+                            this.dtxtModelParam7.Text = "0.9";
+                            this.lblModelParam7.Visible = true;
+                            this.dtxtModelParam7.Visible = true;
+                            this.dtxtModelParam7.Enabled = true;
+                            lblModelParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�灏忓�糞caleCMin");
+
+                            this.lblModelParam8.Text = "妯悜缂╂斁鏈�澶у��";
+                            this.dtxtModelParam8.Text = "1.1";
+                            this.lblModelParam8.Visible = true;
+                            this.dtxtModelParam8.Visible = true;
+                            this.dtxtModelParam8.Enabled = true;
+                            lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�澶у�糞caleCMax");
+
+                            //, string Optimization = "auto", string Metric = "ignore_local_polarity"
+                            this.lblModelParam9.Text = "浼樺寲";
+                            this.dtxtModelParam9.Text = "none";
+                            this.lblModelParam9.Visible = true;
+                            this.dtxtModelParam9.Visible = true;
+                            this.dtxtModelParam9.Enabled = false;
+                            lblModelParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "褰卞搷褰㈢姸妯″瀷鍒涘缓鏃剁殑閫熷害鍜岀簿搴︾殑浼樺寲閫夐」Optimization");
+
+                            this.lblModelParam10.Text = "鏋佹��";
+                            this.dtxtModelParam10.Text = "ignore_local_polarity";
+                            this.lblModelParam10.Visible = true;
+                            this.dtxtModelParam10.Visible = true;
+                            this.dtxtModelParam10.Enabled = false;
+                            lblModelParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "鏋佹�т俊鎭殑搴﹂噺鏂规硶Metric");
+
+                            //, string Contrast = "auto", int MinContrast = 10
+                            this.lblModelParam11.Text = "瀵规瘮搴﹀弬鏁�";
+                            this.dtxtModelParam11.Text = "auto";
+                            this.lblModelParam11.Visible = true;
+                            this.dtxtModelParam11.Visible = true;
+                            this.dtxtModelParam11.Enabled = false;
+                            lblModelParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "鍒涘缓妯℃澘鏃剁殑瀵规瘮搴ontrast");
+
+                            this.lblModelParam12.Text = "鏈�灏忓姣斿害鍙傛暟";
+                            this.dtxtModelParam12.Text = "10";
+                            this.lblModelParam12.Visible = true;
+                            this.dtxtModelParam12.Visible = true;
+                            this.dtxtModelParam12.Enabled = true;
+                            lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "妯″瀷鍖归厤杩囩▼涓�冭檻鐨勬渶灏忓姣斿害MinContrast");
+                            #endregion
+                            break;
+                        case ModelType.鍚勫悜寮傚舰妯℃澘:
+                        default:
+                            //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                            //, ScaleRMin, ScaleRMax
+                            //, ScaleCMin, ScaleCMax
+                            //, MinScore, NumMatches, MaxOverlap, SubPixel
+                            //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                            //, Greediness
+                            #region 杈撳叆鍙傛暟
+                            //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                            this.lblInputParam1.Text = "璧峰瑙掑害";
+                            this.dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"]?.ToString();
+                            this.lblInputParam1.Visible = true;
+                            this.dtxtInputParam1.Visible = true;
+                            this.dtxtInputParam1.Enabled = true;
+                            lblInputParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑璧峰瑙掑害AngleStart");
+
+                            this.lblInputParam2.Text = "瑙掑害鑼冨洿";
+                            this.dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"]?.ToString();
+                            this.lblInputParam2.Visible = true;
+                            this.dtxtInputParam2.Visible = true;
+                            this.dtxtInputParam2.Enabled = true;
+                            lblInputParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑瑙掑害鑼冨洿AngleExtent,'0'琛ㄧず鏃犺搴︽悳绱�");
+
+                            //, ScaleRMin, ScaleRMax
+                            this.lblInputParam3.Text = "绾靛悜缂╂斁鏈�灏忓��";
+                            this.dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"]?.ToString();
+                            this.lblInputParam3.Visible = true;
+                            this.dtxtInputParam3.Visible = true;
+                            this.dtxtInputParam3.Enabled = true;
+                            lblInputParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�灏忓�糞caleRMin");
+
+                            this.lblInputParam4.Text = "绾靛悜缂╂斁鏈�澶у��";
+                            this.dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"]?.ToString();
+                            this.lblInputParam4.Visible = true;
+                            this.dtxtInputParam4.Visible = true;
+                            this.dtxtInputParam4.Enabled = true;
+                            lblInputParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�澶у�糞caleRMax");
+
+                            //, ScaleCMin, ScaleCMax
+                            this.lblInputParam5.Text = "妯悜缂╂斁鏈�灏忓��";
+                            this.dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"]?.ToString();
+                            this.lblInputParam5.Visible = true;
+                            this.dtxtInputParam5.Visible = true;
+                            this.dtxtInputParam5.Enabled = true;
+                            lblInputParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�灏忓�糞caleCMin");
+
+                            this.lblInputParam6.Text = "妯悜缂╂斁鏈�澶у��";
+                            this.dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"]?.ToString();
+                            this.lblInputParam6.Visible = true;
+                            this.dtxtInputParam6.Visible = true;
+                            this.dtxtInputParam6.Enabled = true;
+                            lblInputParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�澶у�糞caleCMax");
+
+                            //, MinScore, NumMatches, MaxOverlap, ResultType
+                            this.lblInputParam7.Text = "鏈�灏忓垎鏁�";
+                            this.dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"]?.ToString();
+                            this.lblInputParam7.Visible = true;
+                            this.dtxtInputParam7.Visible = true;
+                            this.dtxtInputParam7.Enabled = true;
+                            lblInputParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "琚壘鍒扮殑妯℃澘鏈�灏忓垎鏁癕inScore");
+
+                            this.lblInputParam8.Text = "鏈熸湜涓暟";
+                            this.dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"]?.ToString();
+                            this.lblInputParam8.Visible = true;
+                            this.dtxtInputParam8.Visible = true;
+                            this.dtxtInputParam8.Enabled = true;
+                            lblInputParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "瑕佹壘鍒扮殑妯℃澘鏈�澶氱殑瀹炰緥鏁癗umMatches,'0'鍒欐壘鍒版墍鏈夊彲鑳界殑鍖归厤");
+
+                            this.lblInputParam9.Text = "鏈�澶ч噸鍙犳瘮渚�";
+                            this.dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"]?.ToString();
+                            this.lblInputParam9.Visible = true;
+                            this.dtxtInputParam9.Visible = true;
+                            this.dtxtInputParam9.Enabled = true;
+                            lblInputParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "鍏佽鎵惧埌鐨勬ā鍨嬪疄渚嬬殑鏈�澶ч噸鍙犳瘮渚婱axOverlap[杈冨皬鐨勫�间細閬垮厤鎵惧埌澶氫釜鐩镐技鐨勫尮閰峕");
+
+                            this.lblInputParam10.Text = "璁$畻绮惧害";
+                            this.dtxtInputParam10.Text = Subject.Params.Inputs["SubPixel"]?.ToString();
+                            this.lblInputParam10.Visible = true;
+                            this.dtxtInputParam10.Visible = true;
+                            this.dtxtInputParam10.Enabled = false;
+                            lblInputParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "璁$畻绮惧害鐨勮缃甋ubPixel['none'鏈�澶ц宸负鍗婁釜鍍忕礌]");
+
+                            //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                            //, Greediness, , new HTuple(), new HTuple()
+                            this.lblInputParam11.Text = "鎼滅储鏃堕噾瀛楀鐨勫眰绾�";
+                            this.dtxtInputParam11.Text = "0";
+                            this.lblInputParam11.Visible = true;
+                            this.dtxtInputParam11.Visible = true;
+                            this.dtxtInputParam11.Enabled = false;
+                            lblInputParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃堕噾瀛楀鐨勫眰绾�");
+
+                            this.lblInputParam12.Text = "璐┆搴�";
+                            this.dtxtInputParam12.Text = Subject.Params.Inputs["Greediness"]?.ToString();
+                            this.lblInputParam12.Visible = true;
+                            this.dtxtInputParam12.Visible = true;
+                            this.dtxtInputParam12.Enabled = true;
+                            lblInputParam12.MouseHover += (s, e) => ShowToolTip((Control)s, "璐┆搴�,瓒婇珮閫熷害瓒婂揩[涓�鑸兘璁句负0.8,澶ぇ瀹规槗鍑虹幇鎵句笉鍒扮殑鎯呭喌]");
+
+                            this.lblInputParam13.Text = "鏈�灏忔暟閲�";
+                            this.dtxtInputParam13.Text = Subject.Params.Inputs["MinCount"]?.ToString();
+                            this.lblInputParam13.Visible = true;
+                            this.dtxtInputParam13.Visible = true;
+                            this.dtxtInputParam13.Enabled = true;
+                            lblInputParam13.MouseHover += (s, e) => ShowToolTip((Control)s, "鍖归厤缁撴灉瑕佹眰鐨勬渶灏忔暟閲�");
+
+                            this.lblInputParam14.Text = "鏈�澶ф暟閲�";
+                            this.dtxtInputParam14.Text = Subject.Params.Inputs["MaxCount"]?.ToString();
+                            this.lblInputParam14.Visible = true;
+                            this.dtxtInputParam14.Visible = true;
+                            this.dtxtInputParam14.Enabled = true;
+                            lblInputParam14.MouseHover += (s, e) => ShowToolTip((Control)s, "鍖归厤缁撴灉瑕佹眰鐨勬渶澶ф暟閲�");
+                            #endregion
+
+                            //UpdataInputs();
+
+                            //string NumLevels = "auto"
+                            //, double AngleStart = -5, double AngleExtent = 10, string AngleStep = "auto"
+                            //, double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto"
+                            //, double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto"
+                            //, string Optimization = "auto", string Metric = "ignore_local_polarity"
+                            //, string Contrast = "auto", int MinContrast = 10
+
+                            #region 妯℃澘鍙傛暟
+                            //NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
+                            this.lblModelParam1.Text = "閲戝瓧濉旂殑灞傜骇";
+                            this.dtxtModelParam1.Text = "auto";
+                            this.lblModelParam1.Visible = true;
+                            this.dtxtModelParam1.Visible = true;
+                            this.dtxtModelParam1.Enabled = false;
+                            lblModelParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃堕噾瀛楀鐨勫眰绾umLevels,'0'琛ㄧず涓嶄娇鐢ㄩ噾瀛楀");
+
+                            //   , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
+                            this.lblModelParam2.Text = "瑙掑害姝ラ暱";
+                            this.dtxtModelParam2.Text = "auto";
+                            this.lblModelParam2.Visible = true;
+                            this.dtxtModelParam2.Visible = true;
+                            this.dtxtModelParam2.Enabled = false;
+                            lblModelParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "瑙掑害鑼冨洿鍐呰繘琛屾棆杞殑姝ラ暱AngleStep,'auto'琛ㄧず鐢辩郴缁熻嚜鍔ㄩ�夋嫨鍚堥�傜殑姝ラ暱");
+
+                            this.lblModelParam3.Text = "璧峰瑙掑害";
+                            this.dtxtModelParam3.Text = "-5";
+                            this.lblModelParam3.Visible = true;
+                            this.dtxtModelParam3.Visible = true;
+                            this.dtxtModelParam3.Enabled = true;
+                            lblModelParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑璧峰瑙掑害AngleStart");
+
+                            this.lblModelParam4.Text = "瑙掑害鑼冨洿";
+                            this.dtxtModelParam4.Text = "10";
+                            this.lblModelParam4.Visible = true;
+                            this.dtxtModelParam4.Visible = true;
+                            this.dtxtModelParam4.Enabled = true;
+                            lblModelParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑瑙掑害鑼冨洿AngleExtent,'0'琛ㄧず鏃犺搴︽悳绱�");
+
+                            //, double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto"
+                            this.lblModelParam5.Text = "绾靛悜缂╂斁鏈�灏忓��";
+                            this.dtxtModelParam5.Text = "0.9";
+                            this.lblModelParam5.Visible = true;
+                            this.dtxtModelParam5.Visible = true;
+                            this.dtxtModelParam5.Enabled = true;
+                            lblModelParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�灏忓�糞caleRMin");
+
+                            this.lblModelParam6.Text = "绾靛悜缂╂斁鏈�澶у��";
+                            this.dtxtModelParam6.Text = "1.1";
+                            this.lblModelParam6.Visible = true;
+                            this.dtxtModelParam6.Visible = true;
+                            this.dtxtModelParam6.Enabled = true;
+                            lblModelParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�澶у�糞caleRMax");
+
+                            //, double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto"
+                            this.lblModelParam7.Text = "妯悜缂╂斁鏈�灏忓��";
+                            this.dtxtModelParam7.Text = "0.9";
+                            this.lblModelParam7.Visible = true;
+                            this.dtxtModelParam7.Visible = true;
+                            this.dtxtModelParam7.Enabled = true;
+                            lblModelParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�灏忓�糞caleCMin");
+
+                            this.lblModelParam8.Text = "妯悜缂╂斁鏈�澶у��";
+                            this.dtxtModelParam8.Text = "1.1";
+                            this.lblModelParam8.Visible = true;
+                            this.dtxtModelParam8.Visible = true;
+                            this.dtxtModelParam8.Enabled = true;
+                            lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�澶у�糞caleCMax");
+
+                            //, string Optimization = "auto", string Metric = "ignore_local_polarity"
+                            this.lblModelParam9.Text = "浼樺寲";
+                            this.dtxtModelParam9.Text = "auto";
+                            this.lblModelParam9.Visible = true;
+                            this.dtxtModelParam9.Visible = true;
+                            this.dtxtModelParam9.Enabled = false;
+                            lblModelParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "褰卞搷褰㈢姸妯″瀷鍒涘缓鏃剁殑閫熷害鍜岀簿搴︾殑浼樺寲閫夐」Optimization");
+
+                            this.lblModelParam10.Text = "鏋佹��";
+                            this.dtxtModelParam10.Text = "ignore_local_polarity";
+                            this.lblModelParam10.Visible = true;
+                            this.dtxtModelParam10.Visible = true;
+                            this.dtxtModelParam10.Enabled = false;
+                            lblModelParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "鏋佹�т俊鎭殑搴﹂噺鏂规硶Metric");
+
+                            //, string Contrast = "auto", int MinContrast = 10
+                            this.lblModelParam11.Text = "瀵规瘮搴﹀弬鏁�";
+                            this.dtxtModelParam11.Text = "auto";
+                            this.lblModelParam11.Visible = true;
+                            this.dtxtModelParam11.Visible = true;
+                            this.dtxtModelParam11.Enabled = false;
+                            lblModelParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "鍒涘缓妯℃澘鏃剁殑瀵规瘮搴ontrast");
+
+                            this.lblModelParam12.Text = "鏈�灏忓姣斿害鍙傛暟";
+                            this.dtxtModelParam12.Text = "10";
+                            this.lblModelParam12.Visible = true;
+                            this.dtxtModelParam12.Visible = true;
+                            this.dtxtModelParam12.Enabled = true;
+                            lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "妯″瀷鍖归厤杩囩▼涓�冭檻鐨勬渶灏忓姣斿害MinContrast");
+                            #endregion
+                            break;
+                    }
+                }
+
+            });
+        }
+
+        private void btnCreateModel_Click(object sender, EventArgs e)
+        {
+            if (InputImage != null && InputImage is HObject)
+            {
+                imgTabControl.SelectedTab = tabPageModelImage;
+
+                HOperatorSet.GetImageSize((HObject)InputImage, out HTuple hv_imageWidth, out HTuple hv_imageHeight);
+                createModelImageHSmartWindowControl.ShowHoImage((HObject)InputImage);
+                createModelImageHSmartWindowControl.bAollowDraw = true;
+                createModelImageHSmartWindowControl.oRoi = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2
+                    , 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+            }
+        }
+
+        private void btnSaveModel_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                if (InputImage != null && InputImage is HObject)
+                {
+                    double result = 0;
+
+                    if (Enum.TryParse(cmbModelType.Text, out ModelType modelType))
+                    {
+                        string NumLevels = this.dtxtModelParam1.Text;
+                        string AngleStep = this.dtxtModelParam2.Text;
+
+                        double AngleStart = Convert.ToDouble(this.dtxtModelParam3.Text);
+                        double AngleExtent = Convert.ToDouble(this.dtxtModelParam4.Text);
+                        double ScaleRMin = Convert.ToDouble(this.dtxtModelParam5.Text);
+                        double ScaleRMax = Convert.ToDouble(this.dtxtModelParam6.Text);
+                        double ScaleCMin = Convert.ToDouble(this.dtxtModelParam7.Text);
+                        double ScaleCMax = Convert.ToDouble(this.dtxtModelParam8.Text);
+
+                        string Optimization = this.dtxtModelParam9.Text;
+                        string Metric = this.dtxtModelParam10.Text;
+                        string Contrast = this.dtxtModelParam11.Text;
+                        int MinContrast = Convert.ToInt16(this.dtxtModelParam12.Text);
+                        HRectangle2 ROI = (HRectangle2)createModelImageHSmartWindowControl.oRoi;
+
+                        HOperatorSet.GenRectangle2(out HObject hRectangle, ROI.Row, ROI.Column, ROI.Phi, ROI.SemiLength1, ROI.SemiLength2);
+                        HObject hoDomainImage = InputImage as HObject;
+                        HTuple hv_Channels = new HTuple();
+                        //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            try
+                            {
+                                HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                                if (hv_Channels.TupleInt() != 1)
+                                    HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+
+                                //杞崲鍚庡啀娆℃鏌ユ槸鍚︿负鐏板害鍥�
+                                HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                                if (hv_Channels.TupleInt() != 1)
+                                    HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+                            }
+                            catch { }
+                        }
+                        HOperatorSet.ReduceDomain(hoDomainImage, hRectangle, out HObject hoImageReduced);
+                        HOperatorSet.CropDomain(hoImageReduced, out HObject hoModelImage);
+                        bool bCreateModel = false;
+
+                        switch (modelType)
+                        {
+                            case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                                bCreateModel = ((HFindModelTool)Subject).CreateModel
+                                    (hoModelImage, modelType, NumLevels
+                                    , AngleStart, AngleExtent, AngleStep
+                                    , ScaleRMin, ScaleRMax, "auto"
+                                    , ScaleCMin, ScaleCMax, "auto"
+                                    , Optimization, Metric, Contrast, MinContrast);
+                                break;
+                            case ModelType.鍚勫悜寮傚舰妯℃澘:
+                            default:
+                                bCreateModel = ((HFindModelTool)Subject).CreateModel
+                                    (hoModelImage, modelType, NumLevels
+                                    , AngleStart, AngleExtent, AngleStep
+                                    , ScaleRMin, ScaleRMax, "auto"
+                                    , ScaleCMin, ScaleCMax, "auto"
+                                    , Optimization, Metric, Contrast, MinContrast);
+                                break;
+                        }
+
+                        if (bCreateModel)
+                        {
+                            HObject ho_ModelContours = new HObject();
+                            switch (((HFindModelTool)Subject).ModelID.Type)
+                            {
+                                case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                                    HOperatorSet.GetDeformableModelContours(out ho_ModelContours, ((HFindModelTool)Subject).ModelID.hvModel, 1);
+                                    break;
+                                case ModelType.鍚勫悜寮傚舰妯℃澘:
+                                default:
+                                    HOperatorSet.GetShapeModelContours(out ho_ModelContours, ((HFindModelTool)Subject).ModelID.hvModel, 1);
+                                    break;
+                            }
+                            HOperatorSet.GetImageSize(((HFindModelTool)Subject).ModelID.hoImage, out HTuple hv_Width, out HTuple hv_Height);
+                            HOperatorSet.VectorAngleToRigid(-hv_Height / 2, -hv_Width / 2, 0, 0, 0, 0, out HTuple hv_HomMat2D);
+                            HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ModelContours, hv_HomMat2D);
+
+                            //寤烘ā鎴愬姛瀵艰埅鍒板瓙椤�
+                            parasTabControl.SelectedTab = tabPageRunParas;
+                            HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow);
+                            TAlgorithm.DispImage(((HFindModelTool)Subject).ModelID.hoImage, modelImageHWindowControl.HalconWindow);
+                            TAlgorithm.SetColor(modelImageHWindowControl.HalconWindow, "red");
+                            TAlgorithm.DispObj(ho_ModelContours, modelImageHWindowControl.HalconWindow);
+                            TAlgorithm.DispMsg("鍒涘缓妯℃澘鎴愬姛", modelImageHWindowControl.HalconWindow, true);
+
+                            FirstModelImage = ((HFindModelTool)Subject).ModelID.hoImage.CopyObj(1, -1);
+                        }
+                        else
+                        {
+                            HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow);
+                            TAlgorithm.DispMsg("鍒涘缓妯℃澘澶辫触", modelImageHWindowControl.HalconWindow, false);
+                        }
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public void ShowModel(HModel ModelID)
+        {
+            try
+            {
+                if (ModelID != null && ModelID.hvModel != null && ModelID.hvModel.Length > 0)
+                {
+                    HOperatorSet.GenEmptyObj(out HObject ho_ModelContours);
+                    switch (ModelID.Type)
+                    {
+                        case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                            HOperatorSet.GetDeformableModelContours(out ho_ModelContours, ModelID.hvModel, 1);
+                            break;
+                        case ModelType.鍚勫悜寮傚舰妯℃澘:
+                        default:
+                            HOperatorSet.GetShapeModelContours(out ho_ModelContours, ModelID.hvModel, 1);
+                            break;
+                    }
+
+                    HOperatorSet.GetImageSize(ModelID.hoImage, out HTuple hv_Width, out HTuple hv_Height);
+                    HOperatorSet.VectorAngleToRigid(-hv_Height / 2, -hv_Width / 2, 0, 0, 0, 0, out HTuple hv_HomMat2D);
+                    HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ModelContours, hv_HomMat2D);
+
+                    HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow);
+                    TAlgorithm.DispImage(ModelID.hoImage, modelImageHWindowControl.HalconWindow);
+                    TAlgorithm.SetColor(modelImageHWindowControl.HalconWindow, "red");
+                    TAlgorithm.DispObj(ho_ModelContours, modelImageHWindowControl.HalconWindow);
+                    TAlgorithm.DispMsg("鍒涘缓妯℃澘鎴愬姛", modelImageHWindowControl.HalconWindow, true);
+                }
+            }
+            catch { }
+        }
+
+        private void HFindModelToolEdit_SizeChanged(object sender, EventArgs e) => ShowModel(((HFindModelTool)Subject).ModelID);
+
+        private void parasTabControl_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            TabControl tabControl = sender as TabControl;
+
+            if (tabControl != null)
+            {
+                if (tabControl.SelectedTab == tabPageRunParas)
+                    ShowModel(((HFindModelTool)Subject).ModelID);
+            }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.resx b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.resx
new file mode 100644
index 0000000..1526ea6
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindModelTool/HFindModelToolEdit.resx
@@ -0,0 +1,129 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema 
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="lblMsgToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="TopToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>156, 17</value>
+  </metadata>
+  <metadata name="BtmStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>287, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelTool.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelTool.cs
new file mode 100644
index 0000000..ee6b699
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelTool.cs
@@ -0,0 +1,453 @@
+锘縰sing HalconDotNet;
+using LB_VisionProcesses.Alogrithms.Halcon;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+using static LB_VisionProcesses.Alogrithms.Halcon.HFindModelTool;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    [Process("Halcon2D澶氭ā鏉垮尮閰嶅伐鍏�", Category = "Halcon2D宸ュ叿", Description = "鍒涘缓澶氭ā鏉垮尮閰嶅伐鍏�")]
+    public class HFindMultiModelTool : TAlgorithm
+    {
+        public List<HFindModelTool> HFindModelTools = new List<HFindModelTool>();
+
+        public HFindMultiModelTool()
+        {
+            strProcessClass = "LB_VisionProcesses.Alogrithms.Halcon.HFindMultiModelTool";
+            strProcessName = "Halcon2D澶氭ā鏉垮尮閰嶅伐鍏�";
+
+            //ModelsFullPath锛氭ā鏉胯矾寰�
+            Params.Inputs.Add("ModelsFullPath", new List<string>());
+
+            //ModelType锛氭ā鏉跨被鍨�
+            Params.Inputs.Add("ModelType", "鍚勫悜寮傚舰妯℃澘");
+            //AngleStart锛氭悳绱㈡椂鐨勮捣濮嬭搴闇�瑕佽浆鎹负寮у害]
+            Params.Inputs.Add("AngleStart", -5.0);
+            //AngleExtent锛氭悳绱㈡椂鐨勮搴﹁寖鍥�,0琛ㄧず鏃犺搴︽悳绱闇�瑕佽浆鎹负寮у害]
+            Params.Inputs.Add("AngleExtent", 10.0);
+            //AngleStep锛氳搴︽闀�--寮у害[瑙掑害姝ラ暱 >= 0鍜岃搴︽闀� <= pi / 16]
+            Params.Inputs.Add("AngleStep", "auto");
+            Params.Inputs.Add("ScaleRMin", 0.9);
+            Params.Inputs.Add("ScaleRMax", 1.1);
+            Params.Inputs.Add("ScaleCMin", 0.9);
+            Params.Inputs.Add("ScaleCMax", 1.1);
+            //MinScore锛氳鎵惧埌鐨勬ā鏉挎渶灏忓垎鏁�
+            Params.Inputs.Add("MinScore", 0.5);
+            //NumMatches锛氳鎵惧埌鐨勬ā鏉挎渶澶氱殑瀹炰緥鏁�,0鍒欐壘鍒版墍鏈夊彲鑳界殑鍖归厤
+            Params.Inputs.Add("NumMatches", 0);
+            //MaxOverlap锛氬厑璁告壘鍒扮殑妯″瀷瀹炰緥鐨勬渶澶ч噸鍙犳瘮渚�, 寤鸿鍊硷細0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
+            Params.Inputs.Add("MaxOverlap", 0.2);
+            //SubPixel锛氳绠楃簿搴︾殑璁剧疆
+            //'none'    涓嶉�傜敤浜氬儚绱�,鏈�澶ц宸负鍗婁釜鍍忕礌
+            //'interpolation'   宸�煎緱鍒颁簹鍍忕礌绮惧害
+            //'least_squares', 'least_squares_high', 'least_squares_very_high'
+            //'max_deformation 1', 'max_deformation 2', 'max_deformation 3', 'max_deformation 4'
+            Params.Inputs.Add("SubPixel", "none");
+            //NumLevels锛氭悳绱㈡椂閲戝瓧濉旂殑灞傜骇,0琛ㄧず涓嶄娇鐢ㄩ噾瀛楀
+            Params.Inputs.Add("NumLevels", 0);
+            //Greediness锛氳椽濠害,鎼滅储鍚彂寮�,涓�鑸兘璁句负0.8,瓒婇珮閫熷害瓒婂揩,瀹规槗鍑虹幇鎵句笉鍒扮殑鎯呭喌
+            Params.Inputs.Add("Greediness", 0.8);
+            Params.Inputs.Add("ResultType", "");
+
+            Params.Inputs.Add("MinCount", 0);
+            Params.Inputs.Add("MaxCount", 9999);
+
+            Params.Outputs.Add("CenterX", new List<double>());
+            Params.Outputs.Add("CenterY", new List<double>());
+            Params.Outputs.Add("Phi", new List<double>());
+            Params.Outputs.Add("Score", new List<double>());
+            Params.Outputs.Add("Count", 0);
+        }
+
+        private static readonly object lockObj = new object();
+
+        /// <summary>
+        /// 杩愯绠楀瓙
+        /// </summary>
+        public override void TAlgorithmMain()
+        {
+            lock (lockObj)
+            {
+                #region 鍒濆鍖栧彉閲�
+
+                #endregion
+
+                try
+                {
+                    if (InputImage == null)
+                    {
+                        Msg = "杈撳叆鍥剧墖涓虹┖";
+                        Result = false;
+                        return;
+                    }
+                    if (!(InputImage is HObject))
+                    {
+                        Msg = "杈撳叆鍥剧墖鏍煎紡涓嶄负Mat";
+                        Result = false;
+                        return;
+                    }
+
+                    object DomainImage = null;
+
+                    #region 瑁佸壀鍖哄煙
+                    if (!ReduceDomainImage(InputImage, ref DomainImage))
+                    {
+                        Msg = "瑁佸壀鍖哄煙澶辫触";
+                        Result = false;
+                        return;
+                    }
+                    Record = new MsgRecord();
+                    #endregion
+
+                    #region 绠楀瓙閫昏緫
+                    //鍒ゆ柇鏄惁鏈夋ā鏉�
+                    if (HFindModelTools.Count <= 0)
+                    {
+                        Msg = "鏈垱寤烘ā鏉�";
+                        Result = false;
+                        return;
+                    }
+
+                    HObject hoDomainImage = DomainImage as HObject;
+                    HTuple hv_Channels = new HTuple();
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        try
+                        {
+                            HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                            if (hv_Channels.TupleInt() != 1)
+                                HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+
+                            //杞崲鍚庡啀娆℃鏌ユ槸鍚︿负鐏板害鍥�
+                            HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                            if (hv_Channels.TupleInt() != 1)
+                            {
+                                HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+                                Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥�";
+                                Result = false;
+                                return;
+                            }
+                        }
+                        catch
+                        {
+                            Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥句笖杞崲澶辫触";
+                            Result = false;
+                            return;
+                        }
+                    }
+
+                    List<double> CenterX = new List<double>();
+                    List<double> CenterY = new List<double>();
+                    List<double> Phi = new List<double>();
+                    List<double> Score = new List<double>();
+
+                    double AngleStart = Convert.ToDouble(Params.Inputs["AngleStart"]);
+                    double AngleExtent = Convert.ToDouble(Params.Inputs["AngleExtent"]);
+                    double MinScore = Convert.ToDouble(Params.Inputs["MinScore"]);
+                    int NumMatches = ProcessParams.ConvertToInt32(Params.Inputs["NumMatches"]);
+                    double MaxOverlap = Convert.ToDouble(Params.Inputs["MaxOverlap"]);
+                    string SubPixel = ProcessParams.ConvertToString(Params.Inputs["SubPixel"]);
+                    string NumLevels = ProcessParams.ConvertToString(Params.Inputs["NumLevels"]);
+                    double Greediness = Convert.ToDouble(Params.Inputs["Greediness"]);
+
+                    double ScaleRMin = Convert.ToDouble(Params.Inputs["ScaleRMin"]);
+                    double ScaleRMax = Convert.ToDouble(Params.Inputs["ScaleRMax"]);
+                    double ScaleCMin = Convert.ToDouble(Params.Inputs["ScaleCMin"]);
+                    double ScaleCMax = Convert.ToDouble(Params.Inputs["ScaleCMax"]);
+
+                    HTuple AnisoShapeModels = null;
+                    HTuple LocalDeformableModel = null;
+
+                    List<string> ModelsName = new List<string>();
+                    List<double> ModelsWidth = new List<double>();
+                    List<double> ModelsHeight = new List<double>();
+                    foreach (var HFindModelTool in HFindModelTools)
+                    {
+                        if (HFindModelTool.ModelID.Type == ModelType.鍚勫悜寮傚舰妯℃澘)
+                        {
+                            //妯℃澘涓虹┖鏃惰烦杩�
+                            if (HFindModelTool.ModelID.hvModel == null)
+                            {
+                                Msg = $"{HFindModelTool.strProcessName}鐨勬ā鏉夸负绌�";
+                                Result = false;
+                                return;
+                            }
+
+                            if (AnisoShapeModels == null)
+                                AnisoShapeModels = new HTuple();
+
+                            AnisoShapeModels = AnisoShapeModels.TupleConcat(HFindModelTool.ModelID.hvModel);
+                            ModelsName.Add(HFindModelTool.ModelID.ModelName);
+                            ModelsWidth.Add(HFindModelTool.ModelID.Width);
+                            ModelsHeight.Add(HFindModelTool.ModelID.Height);
+
+                            AngleStart = Convert.ToDouble(HFindModelTool.Params.Inputs["AngleStart"]);
+                            AngleExtent = Convert.ToDouble(HFindModelTool.Params.Inputs["AngleExtent"]);
+                            MinScore = Convert.ToDouble(HFindModelTool.Params.Inputs["MinScore"]);
+                            NumMatches = ProcessParams.ConvertToInt32(HFindModelTool.Params.Inputs["NumMatches"]);
+                            MaxOverlap = Convert.ToDouble(HFindModelTool.Params.Inputs["MaxOverlap"]);
+                            SubPixel = ProcessParams.ConvertToString(HFindModelTool.Params.Inputs["SubPixel"]);
+                            NumLevels = ProcessParams.ConvertToString(HFindModelTool.Params.Inputs["NumLevels"]);
+                            Greediness = Convert.ToDouble(HFindModelTool.Params.Inputs["Greediness"]);
+
+                            ScaleRMin = Convert.ToDouble(HFindModelTool.Params.Inputs["ScaleRMin"]);
+                            ScaleRMax = Convert.ToDouble(HFindModelTool.Params.Inputs["ScaleRMax"]);
+                            ScaleCMin = Convert.ToDouble(HFindModelTool.Params.Inputs["ScaleCMin"]);
+                            ScaleCMax = Convert.ToDouble(HFindModelTool.Params.Inputs["ScaleCMax"]);
+                        }
+                        else if (HFindModelTool.ModelID.Type == ModelType.灞�閮ㄥ彉褰㈡ā鏉�)
+                        {
+                            // 灞�閮ㄥ彉褰㈡ā鏉挎病鏈夊妯℃澘鍖归厤 鏆傛椂椤哄簭閬嶅巻
+                            if (LocalDeformableModel == null)
+                                LocalDeformableModel = new HTuple();
+
+                            LocalDeformableModel = LocalDeformableModel.TupleConcat(HFindModelTool.ModelID.hvModel);
+
+                            HFindModelTool.InputImage = hoDomainImage;
+                            if (HFindModelTool.Run())
+                            {
+                                HOperatorSet.GetImageSize(HFindModelTool.ModelID.hoImage, out HTuple ho_ModelWidth, out HTuple ho_ModelHeight);
+
+                                List<double> resultX = HFindModelTool.Params.Outputs["CenterX"] as List<double>;
+                                List<double> resultY = HFindModelTool.Params.Outputs["CenterY"] as List<double>;
+                                List<double> resultPhi = HFindModelTool.Params.Outputs["Phi"] as List<double>;
+                                List<double> resultScore = HFindModelTool.Params.Outputs["Score"] as List<double>;
+
+                                for (int i = 0; i < resultX.Count; i++)
+                                {
+                                    CenterX.Add(resultX[i]);
+                                    CenterY.Add(resultY[i]);
+                                    Phi.Add(resultPhi[i]);
+                                    Score.Add(resultScore[i]);
+
+                                    HOperatorSet.GenRectangle2(out HObject hRectangle, resultY[i], resultX[i], resultPhi[i], ho_ModelWidth / 2, ho_ModelHeight / 2);
+                                    ((MsgRecord)Record).AddRecord($"{strProcessName}.{HFindModelTool.ModelID.ModelName}-{i}"
+                                        , resultY[i] - ho_ModelHeight / 2, resultX[i] - ho_ModelWidth / 2, hRectangle);
+                                }
+                            }
+                        }
+                    }
+
+                    // 鍚勫悜寮傚舰妯℃澘鏈夊妯℃澘鍖归厤鐩存帴杩愯
+                    if (AnisoShapeModels != null)
+                    {
+                        //0.5涓烘渶浣庡垎鏁伴槇鍊硷紝鍚庣画閫氳繃MinScore杩囨护
+
+                        HOperatorSet.FindAnisoShapeModels(hoDomainImage, AnisoShapeModels
+                               , AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                               , ScaleRMin, ScaleRMax
+                               , ScaleCMin, ScaleCMax
+                               , 0.5, NumMatches, MaxOverlap, SubPixel
+                               , NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                               , Greediness
+                               , out HTuple hv_CenterRow, out HTuple hv_CenterColumn
+                               , out HTuple hv_CenterPhi
+                               , out _, out _, out HTuple hv_Score, out HTuple model);
+
+                        for (int i = 0; i < model.Length; i++)
+                        {
+                            if (hv_Score[i].D < MinScore)
+                                continue;
+
+                            int index = model[i].I;
+                            CenterX.Add(Math.Round(hv_CenterColumn[i].D, 3));
+                            CenterY.Add(Math.Round(hv_CenterRow[i].D, 3));
+
+                            if (i >= hv_CenterPhi.Length)
+                                Phi.Add(0);
+                            else
+                                Phi.Add(Math.Round(hv_CenterPhi[i].D, 3));
+
+                            Score.Add(Math.Round(hv_Score[i].D, 3));
+                            HOperatorSet.GenRectangle2(out HObject hRectangle, hv_CenterRow[i].D, hv_CenterColumn[i].D
+                                , hv_CenterPhi[i].D, ModelsWidth[index] / 2, ModelsHeight[index] / 2);
+                            ((MsgRecord)Record).AddRecord($"{strProcessName}.{ModelsName[index]}-{i}"
+                                , hv_CenterRow[i] - ModelsHeight[index] / 2
+                                , hv_CenterColumn[i] - ModelsWidth[index] / 2, hRectangle);
+                        }
+                    }
+
+                    #endregion
+
+                    #region 缁撴灉澶勭悊
+                    Params.Outputs["CenterX"] = CenterX;
+                    Params.Outputs["CenterY"] = CenterY;
+                    Params.Outputs["Phi"] = Phi;
+                    Params.Outputs["Score"] = Score;
+                    Params.Outputs["Count"] = Score.Count;
+                    #endregion
+
+                    #region 鐢熸垚OutputImage缁欏悗缁鐞�
+                    try
+                    {
+                        OutputImage = hoDomainImage;
+                    }
+                    catch (Exception ex)
+                    {
+                        Msg = "鐢熸垚OutputImage澶辫触,鍘熷洜鏄�:" + ex.ToString();
+                        Result = false;
+                        return;
+                    }
+                    #endregion
+
+                    if (Msg == "杩愯瓒呮椂")
+                    {
+                        Result = false;
+                        Record.ChangeAll2False();
+                        return;
+                    }
+
+                    int MinCount = ProcessParams.ConvertToInt32(Params.Inputs["MinCount"]);
+                    int MaxCount = ProcessParams.ConvertToInt32(Params.Inputs["MaxCount"]);
+
+                    if (CenterX.Count < MinCount || CenterX.Count > MaxCount)
+                    {
+                        Msg = string.Format("缁撴灉涓暟瓒呭嚭鑼冨洿({0},{1})", MinCount, MaxCount);
+                        Result = false;
+                        Record.ChangeAll2False();
+                        return;
+                    }
+
+                    Msg = "杩愯鎴愬姛";
+                    Result = true;
+                    return;
+                }
+                catch (Exception ex)
+                {
+                    Msg = "杩愯澶辫触,鍘熷洜鏄�:" + ex.ToString().TrimEnd();
+                    OutputImage = null;
+                    Result = false;
+                    return;
+                }
+                finally
+                {
+                    if (!Result)
+                    {
+                        Params.Outputs["CenterX"] = 0;
+                        Params.Outputs["CenterY"] = 0;
+                        Params.Outputs["Angle"] = 0;
+                        Params.Outputs["Score"] = 0;
+                        Params.Outputs["Count"] = 0;
+                    }
+                    bCompleted = true;
+                    #region 鍐呭瓨閲婃斁
+
+                    #endregion
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鍔犺浇绠楁硶
+        /// </summary>
+        /// <param name="fullPath">瀹屾暣璺緞甯�.json</param>
+        /// <returns></returns>
+        public override bool Load(string fullPath)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                if (!fullPath.Contains(".json"))
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                if (fullPath.StartsWith(".\\"))
+                {
+                    // 鍒ゆ柇鍘熷瓧绗︿覆闀垮害鏄惁澶т簬绛変簬2锛岄伩鍏嶈秺鐣�
+                    if (fullPath.Length >= 2)
+                    {
+                        // 鏇挎崲寮�澶翠袱涓瓧绗�
+                        fullPath = Application.StartupPath + fullPath.Substring(2);
+                        Debug.WriteLine($"淇敼鍚庣殑瀛楃涓�: {fullPath}");
+                    }
+                }
+
+                // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                string directoryPath = Path.GetDirectoryName(fullPath);
+                strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+                // 淇鐪熷疄璺緞,妯℃澘鍖归厤宸ュ叿鍏惰矾寰勪负涓�涓枃浠跺す,鑰屼笉鏄竴涓枃浠�
+                fullPath = directoryPath + "\\" + strProcessName + "\\" + strProcessName + ".json";
+
+                if (!File.Exists(fullPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    Save(directoryPath);
+                    return true;
+                }
+
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+                Params = JsonConvert.DeserializeObject<ProcessParams>(strJson);
+                if (Params == null)
+                    return false;
+                // 鍙嶅簭鍒楀寲鍚庝慨澶嶆暟鎹�
+                Params.FixDeserializedData();
+
+                HFindModelTools.Clear(); HFindModelTools = new List<HFindModelTool>();
+                List<string> ModelsFullPath = (JArray.FromObject(Params.Inputs["ModelsFullPath"])).ToObject<List<string>>();
+                foreach (var ModelFullPath in ModelsFullPath)
+                {
+                    HFindModelTool hFindModelTool = new HFindModelTool();
+                    hFindModelTool.Load(ModelFullPath);
+                    hFindModelTool.strProcessName = hFindModelTool.ModelID.ModelName;
+                    HFindModelTools.Add(hFindModelTool);
+                }
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨绠楁硶
+        /// </summary>
+        /// <param name="filePath">涓嶅甫.json</param>
+        /// <returns></returns>
+        public override bool Save(string filePath)
+        {
+            try
+            {
+                // 鑾峰彇鏂囦欢澶瑰悕绉�
+                string ModelFilePath = filePath + "\\" + strProcessName;
+
+                if (Directory.Exists(ModelFilePath))
+                    Directory.Delete(ModelFilePath, true);
+
+                List<string> ModelsFullPath = new List<string>();
+                foreach (var HFindModelTool in HFindModelTools)
+                {
+                    HFindModelTool.Save(ModelFilePath);
+                    ModelsFullPath.Add(ModelFilePath + "\\" + HFindModelTool.ModelID.ModelName + ".json");
+                    if (HFindModelTool.InputImage != null && HFindModelTool.InputImage is HObject)
+                    {
+                        ((HObject)HFindModelTool.InputImage).Dispose();
+                        HFindModelTool.InputImage = null;
+                    }
+                }
+                Params.Inputs["ModelsFullPath"] = ModelsFullPath;
+
+                // 淇鐪熷疄璺緞,妯℃澘鍖归厤宸ュ叿鍏惰矾寰勪负涓�涓枃浠跺す,鑰屼笉鏄竴涓枃浠�
+                filePath += ("\\" + strProcessName);
+                base.Save(filePath);
+                return true;
+            }
+            catch { return false; }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.Designer.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.Designer.cs
new file mode 100644
index 0000000..4eb6686
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.Designer.cs
@@ -0,0 +1,713 @@
+锘縩amespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    partial class HFindMultiModelToolEdit
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            TopToolStrip = new ToolStrip();
+            btnRun = new ToolStripButton();
+            btnLoadImage = new ToolStripButton();
+            btnSaveParas = new ToolStripButton();
+            btnLoadParas = new ToolStripButton();
+            BtmStatusStrip = new StatusStrip();
+            lblResult = new ToolStripStatusLabel();
+            lblMsg = new ToolStripStatusLabel();
+            lblRunTime = new ToolStripStatusLabel();
+            MainTableLayoutPanel = new TableLayoutPanel();
+            parasTabControl = new TabControl();
+            tabPage1 = new TabPage();
+            splitContainer1 = new SplitContainer();
+            tableLayoutPanel5 = new TableLayoutPanel();
+            tableLayoutPanel4 = new TableLayoutPanel();
+            label1 = new Label();
+            label2 = new Label();
+            dtxtMinCount = new TextBox();
+            dtxtMaxCount = new TextBox();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            btnDelModel = new Button();
+            btnAddModel = new Button();
+            tabPageRunParas = new TabPage();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            cmbTypeRoi = new ComboBox();
+            label21 = new Label();
+            label22 = new Label();
+            cmbFixture = new ComboBox();
+            ckbDrawRoi = new CheckBox();
+            tabPage2 = new TabPage();
+            tableLayoutResults = new TableLayoutPanel();
+            label5 = new Label();
+            label6 = new Label();
+            label7 = new Label();
+            dtxtCenterX = new TextBox();
+            dtxtCenterY = new TextBox();
+            dtxtAngle = new TextBox();
+            label8 = new Label();
+            dtxtScore = new TextBox();
+            dtxtCount = new TextBox();
+            label9 = new Label();
+            imgTabControl = new TabControl();
+            tabPageInputImage = new TabPage();
+            pnlInputImage = new Panel();
+            tabPageRecordImage = new TabPage();
+            pnlRecordImage = new Panel();
+            TopToolStrip.SuspendLayout();
+            BtmStatusStrip.SuspendLayout();
+            MainTableLayoutPanel.SuspendLayout();
+            parasTabControl.SuspendLayout();
+            tabPage1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
+            splitContainer1.Panel2.SuspendLayout();
+            splitContainer1.SuspendLayout();
+            tableLayoutPanel5.SuspendLayout();
+            tableLayoutPanel4.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tabPageRunParas.SuspendLayout();
+            tableLayoutPanel1.SuspendLayout();
+            tabPage2.SuspendLayout();
+            tableLayoutResults.SuspendLayout();
+            imgTabControl.SuspendLayout();
+            tabPageInputImage.SuspendLayout();
+            tabPageRecordImage.SuspendLayout();
+            SuspendLayout();
+            // 
+            // TopToolStrip
+            // 
+            TopToolStrip.Items.AddRange(new ToolStripItem[] { btnRun, btnLoadImage, btnSaveParas, btnLoadParas });
+            TopToolStrip.Location = new Point(0, 0);
+            TopToolStrip.Name = "TopToolStrip";
+            TopToolStrip.Size = new Size(1044, 25);
+            TopToolStrip.TabIndex = 45;
+            TopToolStrip.Text = "toolStrip1";
+            // 
+            // btnRun
+            // 
+            btnRun.BackgroundImageLayout = ImageLayout.Zoom;
+            btnRun.ImageTransparentColor = Color.Magenta;
+            btnRun.Name = "btnRun";
+            btnRun.Size = new Size(36, 22);
+            btnRun.Text = "杩愯";
+            btnRun.Click += btnRun_Click;
+            // 
+            // btnLoadImage
+            // 
+            btnLoadImage.ImageTransparentColor = Color.Magenta;
+            btnLoadImage.Name = "btnLoadImage";
+            btnLoadImage.Size = new Size(36, 22);
+            btnLoadImage.Text = "瀵煎浘";
+            btnLoadImage.Click += btnLoadImage_Click;
+            // 
+            // btnSaveParas
+            // 
+            btnSaveParas.ImageTransparentColor = Color.Magenta;
+            btnSaveParas.Name = "btnSaveParas";
+            btnSaveParas.Size = new Size(36, 22);
+            btnSaveParas.Text = "淇濆瓨";
+            btnSaveParas.Click += btnSaveParas_Click;
+            // 
+            // btnLoadParas
+            // 
+            btnLoadParas.ImageTransparentColor = Color.Magenta;
+            btnLoadParas.Name = "btnLoadParas";
+            btnLoadParas.Size = new Size(36, 22);
+            btnLoadParas.Text = "鍔犺浇";
+            btnLoadParas.Click += btnLoadParas_Click;
+            // 
+            // BtmStatusStrip
+            // 
+            BtmStatusStrip.Items.AddRange(new ToolStripItem[] { lblResult, lblMsg, lblRunTime });
+            BtmStatusStrip.Location = new Point(0, 577);
+            BtmStatusStrip.Name = "BtmStatusStrip";
+            BtmStatusStrip.Size = new Size(1044, 22);
+            BtmStatusStrip.TabIndex = 46;
+            BtmStatusStrip.Text = "statusStrip1";
+            // 
+            // lblResult
+            // 
+            lblResult.Name = "lblResult";
+            lblResult.Size = new Size(34, 17);
+            lblResult.Text = "True";
+            // 
+            // lblMsg
+            // 
+            lblMsg.Name = "lblMsg";
+            lblMsg.Size = new Size(56, 17);
+            lblMsg.Text = "杩愯鎴愬姛";
+            lblMsg.TextAlign = ContentAlignment.MiddleLeft;
+            // 
+            // lblRunTime
+            // 
+            lblRunTime.Name = "lblRunTime";
+            lblRunTime.Size = new Size(32, 17);
+            lblRunTime.Text = "0ms";
+            // 
+            // MainTableLayoutPanel
+            // 
+            MainTableLayoutPanel.ColumnCount = 2;
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F));
+            MainTableLayoutPanel.Controls.Add(parasTabControl, 0, 0);
+            MainTableLayoutPanel.Controls.Add(imgTabControl, 1, 0);
+            MainTableLayoutPanel.Dock = DockStyle.Fill;
+            MainTableLayoutPanel.Location = new Point(0, 25);
+            MainTableLayoutPanel.Name = "MainTableLayoutPanel";
+            MainTableLayoutPanel.RowCount = 1;
+            MainTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            MainTableLayoutPanel.Size = new Size(1044, 552);
+            MainTableLayoutPanel.TabIndex = 47;
+            // 
+            // parasTabControl
+            // 
+            parasTabControl.Controls.Add(tabPage1);
+            parasTabControl.Controls.Add(tabPageRunParas);
+            parasTabControl.Controls.Add(tabPage2);
+            parasTabControl.Dock = DockStyle.Fill;
+            parasTabControl.Location = new Point(3, 3);
+            parasTabControl.Name = "parasTabControl";
+            parasTabControl.SelectedIndex = 0;
+            parasTabControl.Size = new Size(411, 546);
+            parasTabControl.TabIndex = 48;
+            // 
+            // tabPage1
+            // 
+            tabPage1.AutoScroll = true;
+            tabPage1.Controls.Add(splitContainer1);
+            tabPage1.Location = new Point(4, 26);
+            tabPage1.Name = "tabPage1";
+            tabPage1.Padding = new Padding(3, 3, 3, 3);
+            tabPage1.Size = new Size(403, 516);
+            tabPage1.TabIndex = 0;
+            tabPage1.Text = "杈撳叆鍙傛暟";
+            tabPage1.UseVisualStyleBackColor = true;
+            // 
+            // splitContainer1
+            // 
+            splitContainer1.Dock = DockStyle.Fill;
+            splitContainer1.Location = new Point(3, 3);
+            splitContainer1.Name = "splitContainer1";
+            splitContainer1.Orientation = Orientation.Horizontal;
+            // 
+            // splitContainer1.Panel1
+            // 
+            splitContainer1.Panel1.AutoScroll = true;
+            // 
+            // splitContainer1.Panel2
+            // 
+            splitContainer1.Panel2.Controls.Add(tableLayoutPanel5);
+            splitContainer1.Size = new Size(397, 510);
+            splitContainer1.SplitterDistance = 338;
+            splitContainer1.TabIndex = 0;
+            // 
+            // tableLayoutPanel5
+            // 
+            tableLayoutPanel5.ColumnCount = 1;
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel5.Controls.Add(tableLayoutPanel4, 0, 0);
+            tableLayoutPanel5.Controls.Add(tableLayoutPanel2, 0, 1);
+            tableLayoutPanel5.Dock = DockStyle.Fill;
+            tableLayoutPanel5.Location = new Point(0, 0);
+            tableLayoutPanel5.Name = "tableLayoutPanel5";
+            tableLayoutPanel5.RowCount = 2;
+            tableLayoutPanel5.RowStyles.Add(new RowStyle(SizeType.Absolute, 80F));
+            tableLayoutPanel5.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F));
+            tableLayoutPanel5.Size = new Size(397, 168);
+            tableLayoutPanel5.TabIndex = 2;
+            // 
+            // tableLayoutPanel4
+            // 
+            tableLayoutPanel4.ColumnCount = 4;
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tableLayoutPanel4.Controls.Add(label1, 0, 1);
+            tableLayoutPanel4.Controls.Add(label2, 2, 1);
+            tableLayoutPanel4.Controls.Add(dtxtMinCount, 1, 1);
+            tableLayoutPanel4.Controls.Add(dtxtMaxCount, 3, 1);
+            tableLayoutPanel4.Dock = DockStyle.Fill;
+            tableLayoutPanel4.Location = new Point(3, 3);
+            tableLayoutPanel4.Name = "tableLayoutPanel4";
+            tableLayoutPanel4.RowCount = 2;
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+            tableLayoutPanel4.Size = new Size(391, 74);
+            tableLayoutPanel4.TabIndex = 1;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Dock = DockStyle.Fill;
+            label1.Location = new Point(3, 37);
+            label1.Name = "label1";
+            label1.Size = new Size(84, 37);
+            label1.TabIndex = 0;
+            label1.Text = "鏈�灏忔暟閲�";
+            label1.TextAlign = ContentAlignment.TopRight;
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.Dock = DockStyle.Fill;
+            label2.Location = new Point(198, 37);
+            label2.Name = "label2";
+            label2.Size = new Size(84, 37);
+            label2.TabIndex = 1;
+            label2.Text = "鏈�澶ф暟閲�";
+            label2.TextAlign = ContentAlignment.TopRight;
+            // 
+            // dtxtMinCount
+            // 
+            dtxtMinCount.Dock = DockStyle.Fill;
+            dtxtMinCount.Location = new Point(93, 40);
+            dtxtMinCount.Name = "dtxtMinCount";
+            dtxtMinCount.Size = new Size(99, 23);
+            dtxtMinCount.TabIndex = 2;
+            dtxtMinCount.Text = "0";
+            // 
+            // dtxtMaxCount
+            // 
+            dtxtMaxCount.Dock = DockStyle.Fill;
+            dtxtMaxCount.Location = new Point(288, 40);
+            dtxtMaxCount.Name = "dtxtMaxCount";
+            dtxtMaxCount.Size = new Size(100, 23);
+            dtxtMaxCount.TabIndex = 3;
+            dtxtMaxCount.Text = "9999";
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 4;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
+            tableLayoutPanel2.Controls.Add(btnDelModel, 1, 0);
+            tableLayoutPanel2.Controls.Add(btnAddModel, 0, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 83);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 1;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(391, 82);
+            tableLayoutPanel2.TabIndex = 0;
+            // 
+            // btnDelModel
+            // 
+            btnDelModel.Dock = DockStyle.Fill;
+            btnDelModel.Location = new Point(100, 3);
+            btnDelModel.Name = "btnDelModel";
+            btnDelModel.Size = new Size(91, 76);
+            btnDelModel.TabIndex = 1;
+            btnDelModel.Text = "绉婚櫎妯℃澘";
+            btnDelModel.UseVisualStyleBackColor = true;
+            btnDelModel.Click += btnDelModel_Click;
+            // 
+            // btnAddModel
+            // 
+            btnAddModel.Dock = DockStyle.Fill;
+            btnAddModel.Location = new Point(3, 3);
+            btnAddModel.Name = "btnAddModel";
+            btnAddModel.Size = new Size(91, 76);
+            btnAddModel.TabIndex = 0;
+            btnAddModel.Text = "娣诲姞妯℃澘";
+            btnAddModel.UseVisualStyleBackColor = true;
+            btnAddModel.Click += btnAddModel_Click;
+            // 
+            // tabPageRunParas
+            // 
+            tabPageRunParas.Controls.Add(tableLayoutPanel1);
+            tabPageRunParas.Location = new Point(4, 26);
+            tabPageRunParas.Name = "tabPageRunParas";
+            tabPageRunParas.Size = new Size(403, 516);
+            tabPageRunParas.TabIndex = 2;
+            tabPageRunParas.Text = "杩愯鍙傛暟";
+            tabPageRunParas.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 4;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 60F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 150F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(cmbTypeRoi, 1, 0);
+            tableLayoutPanel1.Controls.Add(label21, 0, 0);
+            tableLayoutPanel1.Controls.Add(label22, 0, 1);
+            tableLayoutPanel1.Controls.Add(cmbFixture, 1, 1);
+            tableLayoutPanel1.Controls.Add(ckbDrawRoi, 2, 0);
+            tableLayoutPanel1.Location = new Point(3, 3);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 3;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Size = new Size(323, 94);
+            tableLayoutPanel1.TabIndex = 7;
+            // 
+            // cmbTypeRoi
+            // 
+            cmbTypeRoi.FormattingEnabled = true;
+            cmbTypeRoi.Location = new Point(63, 3);
+            cmbTypeRoi.Name = "cmbTypeRoi";
+            cmbTypeRoi.Size = new Size(121, 25);
+            cmbTypeRoi.TabIndex = 1;
+            cmbTypeRoi.SelectedIndexChanged += cmbTypeRoi_SelectedIndexChanged;
+            // 
+            // label21
+            // 
+            label21.AutoSize = true;
+            label21.Dock = DockStyle.Fill;
+            label21.Location = new Point(3, 0);
+            label21.Name = "label21";
+            label21.Size = new Size(54, 30);
+            label21.TabIndex = 3;
+            label21.Text = "ROI";
+            label21.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label22
+            // 
+            label22.AutoSize = true;
+            label22.Dock = DockStyle.Fill;
+            label22.Location = new Point(3, 30);
+            label22.Name = "label22";
+            label22.Size = new Size(54, 30);
+            label22.TabIndex = 4;
+            label22.Text = "Fixture";
+            label22.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbFixture
+            // 
+            cmbFixture.FormattingEnabled = true;
+            cmbFixture.Location = new Point(63, 33);
+            cmbFixture.Name = "cmbFixture";
+            cmbFixture.Size = new Size(121, 25);
+            cmbFixture.TabIndex = 5;
+            cmbFixture.SelectedIndexChanged += cmbFixture_SelectedIndexChanged;
+            // 
+            // ckbDrawRoi
+            // 
+            ckbDrawRoi.AutoSize = true;
+            ckbDrawRoi.CheckAlign = ContentAlignment.MiddleCenter;
+            ckbDrawRoi.Location = new Point(213, 3);
+            ckbDrawRoi.Name = "ckbDrawRoi";
+            ckbDrawRoi.Size = new Size(14, 14);
+            ckbDrawRoi.TabIndex = 2;
+            ckbDrawRoi.UseVisualStyleBackColor = true;
+            ckbDrawRoi.CheckedChanged += ckbDrawRoi_CheckedChanged;
+            // 
+            // tabPage2
+            // 
+            tabPage2.Controls.Add(tableLayoutResults);
+            tabPage2.Location = new Point(4, 26);
+            tabPage2.Name = "tabPage2";
+            tabPage2.Padding = new Padding(3, 3, 3, 3);
+            tabPage2.Size = new Size(404, 519);
+            tabPage2.TabIndex = 1;
+            tabPage2.Text = "杈撳嚭缁撴灉";
+            tabPage2.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutResults
+            // 
+            tableLayoutResults.ColumnCount = 2;
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutResults.Controls.Add(label5, 0, 0);
+            tableLayoutResults.Controls.Add(label6, 0, 1);
+            tableLayoutResults.Controls.Add(label7, 0, 2);
+            tableLayoutResults.Controls.Add(dtxtCenterX, 1, 0);
+            tableLayoutResults.Controls.Add(dtxtCenterY, 1, 1);
+            tableLayoutResults.Controls.Add(dtxtAngle, 1, 2);
+            tableLayoutResults.Controls.Add(label8, 0, 3);
+            tableLayoutResults.Controls.Add(dtxtScore, 1, 3);
+            tableLayoutResults.Controls.Add(dtxtCount, 1, 4);
+            tableLayoutResults.Controls.Add(label9, 0, 4);
+            tableLayoutResults.Dock = DockStyle.Fill;
+            tableLayoutResults.Location = new Point(3, 3);
+            tableLayoutResults.Margin = new Padding(2, 3, 2, 3);
+            tableLayoutResults.Name = "tableLayoutResults";
+            tableLayoutResults.RowCount = 10;
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.Size = new Size(398, 513);
+            tableLayoutResults.TabIndex = 1;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Dock = DockStyle.Fill;
+            label5.Location = new Point(2, 0);
+            label5.Margin = new Padding(2, 0, 2, 0);
+            label5.MaximumSize = new Size(0, 28);
+            label5.MinimumSize = new Size(0, 28);
+            label5.Name = "label5";
+            label5.Size = new Size(96, 28);
+            label5.TabIndex = 0;
+            label5.Text = "X";
+            label5.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label6
+            // 
+            label6.AutoSize = true;
+            label6.Dock = DockStyle.Fill;
+            label6.Location = new Point(2, 51);
+            label6.Margin = new Padding(2, 0, 2, 0);
+            label6.MaximumSize = new Size(0, 28);
+            label6.MinimumSize = new Size(0, 28);
+            label6.Name = "label6";
+            label6.Size = new Size(96, 28);
+            label6.TabIndex = 1;
+            label6.Text = "Y";
+            label6.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label7
+            // 
+            label7.AutoSize = true;
+            label7.Dock = DockStyle.Fill;
+            label7.Location = new Point(2, 102);
+            label7.Margin = new Padding(2, 0, 2, 0);
+            label7.MaximumSize = new Size(0, 28);
+            label7.MinimumSize = new Size(0, 28);
+            label7.Name = "label7";
+            label7.Size = new Size(96, 28);
+            label7.TabIndex = 2;
+            label7.Text = "瑙掑害(掳)";
+            label7.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCenterX
+            // 
+            dtxtCenterX.Dock = DockStyle.Fill;
+            dtxtCenterX.Location = new Point(102, 3);
+            dtxtCenterX.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterX.Name = "dtxtCenterX";
+            dtxtCenterX.ReadOnly = true;
+            dtxtCenterX.Size = new Size(294, 23);
+            dtxtCenterX.TabIndex = 5;
+            // 
+            // dtxtCenterY
+            // 
+            dtxtCenterY.Dock = DockStyle.Fill;
+            dtxtCenterY.Location = new Point(102, 54);
+            dtxtCenterY.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterY.Name = "dtxtCenterY";
+            dtxtCenterY.ReadOnly = true;
+            dtxtCenterY.Size = new Size(294, 23);
+            dtxtCenterY.TabIndex = 6;
+            // 
+            // dtxtAngle
+            // 
+            dtxtAngle.Dock = DockStyle.Fill;
+            dtxtAngle.Location = new Point(102, 105);
+            dtxtAngle.Margin = new Padding(2, 3, 2, 3);
+            dtxtAngle.Name = "dtxtAngle";
+            dtxtAngle.ReadOnly = true;
+            dtxtAngle.Size = new Size(294, 23);
+            dtxtAngle.TabIndex = 7;
+            // 
+            // label8
+            // 
+            label8.AutoSize = true;
+            label8.Dock = DockStyle.Fill;
+            label8.Location = new Point(3, 153);
+            label8.Name = "label8";
+            label8.Size = new Size(94, 51);
+            label8.TabIndex = 8;
+            label8.Text = "鍒嗘暟";
+            label8.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtScore
+            // 
+            dtxtScore.Dock = DockStyle.Fill;
+            dtxtScore.Location = new Point(103, 156);
+            dtxtScore.Name = "dtxtScore";
+            dtxtScore.ReadOnly = true;
+            dtxtScore.Size = new Size(292, 23);
+            dtxtScore.TabIndex = 9;
+            // 
+            // dtxtCount
+            // 
+            dtxtCount.Location = new Point(103, 207);
+            dtxtCount.Name = "dtxtCount";
+            dtxtCount.ReadOnly = true;
+            dtxtCount.Size = new Size(291, 23);
+            dtxtCount.TabIndex = 12;
+            // 
+            // label9
+            // 
+            label9.AutoSize = true;
+            label9.Dock = DockStyle.Fill;
+            label9.Location = new Point(3, 204);
+            label9.Name = "label9";
+            label9.Size = new Size(94, 51);
+            label9.TabIndex = 13;
+            label9.Text = "鏁伴噺";
+            label9.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // imgTabControl
+            // 
+            imgTabControl.Controls.Add(tabPageInputImage);
+            imgTabControl.Controls.Add(tabPageRecordImage);
+            imgTabControl.Dock = DockStyle.Fill;
+            imgTabControl.Location = new Point(420, 3);
+            imgTabControl.Name = "imgTabControl";
+            imgTabControl.SelectedIndex = 0;
+            imgTabControl.Size = new Size(621, 546);
+            imgTabControl.TabIndex = 49;
+            // 
+            // tabPageInputImage
+            // 
+            tabPageInputImage.Controls.Add(pnlInputImage);
+            tabPageInputImage.Location = new Point(4, 26);
+            tabPageInputImage.Name = "tabPageInputImage";
+            tabPageInputImage.Padding = new Padding(3, 3, 3, 3);
+            tabPageInputImage.Size = new Size(613, 516);
+            tabPageInputImage.TabIndex = 0;
+            tabPageInputImage.Text = "杈撳叆鍥惧儚";
+            tabPageInputImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlInputImage
+            // 
+            pnlInputImage.Dock = DockStyle.Fill;
+            pnlInputImage.Location = new Point(3, 3);
+            pnlInputImage.Margin = new Padding(4, 4, 4, 4);
+            pnlInputImage.Name = "pnlInputImage";
+            pnlInputImage.Size = new Size(607, 510);
+            pnlInputImage.TabIndex = 44;
+            // 
+            // tabPageRecordImage
+            // 
+            tabPageRecordImage.Controls.Add(pnlRecordImage);
+            tabPageRecordImage.Location = new Point(4, 26);
+            tabPageRecordImage.Name = "tabPageRecordImage";
+            tabPageRecordImage.Padding = new Padding(3, 3, 3, 3);
+            tabPageRecordImage.Size = new Size(613, 519);
+            tabPageRecordImage.TabIndex = 1;
+            tabPageRecordImage.Text = "缁撴灉鍥惧儚";
+            tabPageRecordImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlRecordImage
+            // 
+            pnlRecordImage.Dock = DockStyle.Fill;
+            pnlRecordImage.Location = new Point(3, 3);
+            pnlRecordImage.Margin = new Padding(4, 4, 4, 4);
+            pnlRecordImage.Name = "pnlRecordImage";
+            pnlRecordImage.Size = new Size(607, 513);
+            pnlRecordImage.TabIndex = 45;
+            // 
+            // HFindMultiModelToolEdit
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(MainTableLayoutPanel);
+            Controls.Add(BtmStatusStrip);
+            Controls.Add(TopToolStrip);
+            Margin = new Padding(2, 3, 2, 3);
+            Name = "HFindMultiModelToolEdit";
+            Size = new Size(1044, 599);
+            Load += HFindModelToolEdit_Load;
+            SizeChanged += HFindMultiModelToolEdit_SizeChanged;
+            TopToolStrip.ResumeLayout(false);
+            TopToolStrip.PerformLayout();
+            BtmStatusStrip.ResumeLayout(false);
+            BtmStatusStrip.PerformLayout();
+            MainTableLayoutPanel.ResumeLayout(false);
+            parasTabControl.ResumeLayout(false);
+            tabPage1.ResumeLayout(false);
+            splitContainer1.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit();
+            splitContainer1.ResumeLayout(false);
+            tableLayoutPanel5.ResumeLayout(false);
+            tableLayoutPanel4.ResumeLayout(false);
+            tableLayoutPanel4.PerformLayout();
+            tableLayoutPanel2.ResumeLayout(false);
+            tabPageRunParas.ResumeLayout(false);
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel1.PerformLayout();
+            tabPage2.ResumeLayout(false);
+            tableLayoutResults.ResumeLayout(false);
+            tableLayoutResults.PerformLayout();
+            imgTabControl.ResumeLayout(false);
+            tabPageInputImage.ResumeLayout(false);
+            tabPageRecordImage.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+        private ToolStrip TopToolStrip;
+        private ToolStripButton btnRun;
+        private StatusStrip BtmStatusStrip;
+        private ToolStripStatusLabel lblResult;
+        private ToolStripStatusLabel lblMsg;
+        private TableLayoutPanel MainTableLayoutPanel;
+        private ToolStripButton btnLoadImage;
+        private TabControl parasTabControl;
+        private TabPage tabPage1;
+        private TabPage tabPage2;
+        private TabPage tabPageRunParas;
+        private TabControl imgTabControl;
+        private TabPage tabPageRecordImage;
+        private ToolStripButton btnSaveParas;
+        private ToolStripButton btnLoadParas;
+        private Panel pnlRecordImage;
+        private TableLayoutPanel tableLayoutResults;
+        private Label label5;
+        private Label label6;
+        private Label label7;
+        private TextBox dtxtCenterX;
+        private TextBox dtxtCenterY;
+        private TextBox dtxtAngle;
+        private TabPage tabPageInputImage;
+        private Panel pnlInputImage;
+        private Label label8;
+        private TextBox dtxtScore;
+        private SplitContainer splitContainer1;
+        private TableLayoutPanel tableLayoutPanel2;
+        private Button btnAddModel;
+        private TextBox dtxtCount;
+        private Label label9;
+        private TableLayoutPanel tableLayoutPanel5;
+        private TableLayoutPanel tableLayoutPanel4;
+        private Label label1;
+        private Label label2;
+        private TextBox dtxtMinCount;
+        private TextBox dtxtMaxCount;
+        private ToolStripStatusLabel lblRunTime;
+        private Button btnDelModel;
+        private TableLayoutPanel tableLayoutPanel1;
+        public ComboBox cmbTypeRoi;
+        private Label label21;
+        private Label label22;
+        private ComboBox cmbFixture;
+        private CheckBox ckbDrawRoi;
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.cs
new file mode 100644
index 0000000..bf95ace
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.cs
@@ -0,0 +1,506 @@
+锘縰sing HalconDotNet;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
+using System.Reflection;
+using System.Diagnostics.Contracts;
+using System.Drawing.Drawing2D;
+using Newtonsoft.Json.Linq;
+using System.Xml.Linq;
+using System.Diagnostics;
+using LB_VisionControl;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    public partial class HFindMultiModelToolEdit : TAlgorithmEdit
+    {
+        public List<HMulitModelControl> listModelToolControls = new List<HMulitModelControl>();
+
+        public HFindMultiModelToolEdit(HFindMultiModelTool subject = null)
+        {
+            if (subject != null && subject is HFindMultiModelTool)
+                Subject = subject;
+            else
+                Subject = new HFindMultiModelTool();
+
+            this.Dock = DockStyle.Fill;
+            InitializeComponent();
+        }
+
+        /// <summary>
+        /// 鎺т欢鍔犺浇浜嬩欢
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void HFindModelToolEdit_Load(object sender, EventArgs e)
+        {
+            pnlInputImage.Controls.Add(inputImageHSmartWindowControl);
+            inputImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            pnlRecordImage.Controls.Add(recordImageHSmartWindowControl);
+            recordImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            //UpdataInputsUI();
+
+            //閬嶅巻鍙互閫夋嫨鐨凴oi绫诲瀷鏋氫妇
+            foreach (var value in Enum.GetValues(typeof(RoiType)))
+            {
+                cmbTypeRoi.Items.Add(value.ToString());
+            }
+
+            //閬嶅巻鍙互閫夋嫨鐨凢ixture鏋氫妇
+            cmbFixture.Items.Add("");
+            foreach (string value in IProcess.dicFixtures.Keys)
+                cmbFixture.Items.Add(value.ToString());
+
+            //鐢变簬鎺т欢鐨勪簨浠惰繕娌″姞杞斤紝鍦↙oad閲屼笉浼氳Е鍙戝叾浠栨帶浠剁殑浜嬩欢
+            cmbTypeRoi.SelectedIndex = 0;
+            LoadParas();
+
+            if (Subject.Result)
+            {
+                lblResult.BackColor = Color.Green;
+                lblResult.Text = "True";
+            }
+            else
+            {
+                lblResult.BackColor = Color.Red;
+                lblResult.Text = "False";
+            }
+
+            lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+            lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+            lblRunTime.Text = $"{Subject.RunTime}ms";
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯鍙傛暟
+        /// </summary>
+        public override void UpdataInputs()
+        {
+            List<HFindModelTool> hFindModelTools = new List<HFindModelTool>();
+            foreach (var ModelToolControl in listModelToolControls)
+                hFindModelTools.Add(ModelToolControl.HFindModelTool);
+
+            ((HFindMultiModelTool)Subject).HFindModelTools = hFindModelTools;
+
+            int iResult = 0;
+            Subject.Params.Inputs["MinCount"] = int.TryParse(dtxtMinCount.Text, out iResult) ? iResult : Subject.Params.Inputs["MinCount"];
+            Subject.Params.Inputs["MaxCount"] = int.TryParse(dtxtMaxCount.Text, out iResult) ? iResult : Subject.Params.Inputs["MinCount"];
+
+            Subject.Params.Outputs.Add("CenterX", new List<double>());
+            Subject.Params.Outputs.Add("CenterY", new List<double>());
+            Subject.Params.Outputs.Add("Angle", new List<double>());
+            Subject.Params.Outputs.Add("Score", new List<double>());
+            Subject.Params.Outputs.Add("Count", 0);
+
+            Type type = inputImageHSmartWindowControl.oRoi?.GetType();
+            switch (type)
+            {
+                case Type t when t == typeof(HRectangle2):
+                    HRectangle2 hRectangle2 = (HRectangle2)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HRectangle2(hRectangle2.X - Subject.Params.Fixture.X, hRectangle2.Y - Subject.Params.Fixture.Y
+                        , hRectangle2.Phi - Subject.Params.Fixture.Phi, hRectangle2.Width, hRectangle2.Height);
+                    break;
+                case Type t when t == typeof(HCircle):
+                    HCircle hCircle = (HCircle)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HCircle(hCircle.X - Subject.Params.Fixture.X, hCircle.Y - Subject.Params.Fixture.Y, hCircle.Radius);
+                    break;
+                case Type t when t == typeof(HSegment):
+                    HSegment hSegment = (HSegment)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HSegment(hSegment.StartX - Subject.Params.Fixture.X, hSegment.StartY - Subject.Params.Fixture.Y
+                        , hSegment.EndX - Subject.Params.Fixture.X, hSegment.EndY - Subject.Params.Fixture.Y);
+                    break;
+                default:
+                    Subject.Params.ROI = new ROI();
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// 鍔犺浇杩愯鍙傛暟
+        /// </summary>
+        public override void LoadParas()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                dtxtMinCount.Text = Subject.Params.Inputs["MinCount"].ToString();
+                dtxtMaxCount.Text = Subject.Params.Inputs["MaxCount"].ToString();
+
+                if (Subject.InputImage != null && Subject.InputImage is HObject)
+                    inputImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+
+                Type type = Subject.Params.ROI?.GetType();
+                if (Subject.Params.ROI != null)
+                {
+                    switch (type)
+                    {
+                        case Type t when t == typeof(HRectangle2):
+                            cmbTypeRoi.Text = RoiType.Rectangle2.ToString();
+                            break;
+                        case Type t when t == typeof(HCircle):
+                            cmbTypeRoi.Text = RoiType.Circle.ToString();
+                            break;
+                        case Type t when t == typeof(HSegment):
+                            cmbTypeRoi.Text = RoiType.Segment.ToString();
+                            break;
+                        default:
+                            cmbTypeRoi.Text = RoiType.None.ToString();
+                            break;
+                    }
+                    if (cmbTypeRoi.Text.ToString() != "None")
+                        ckbDrawRoi.Checked = true;
+                    else
+                        ckbDrawRoi.Checked = false;
+
+                    inputImageHSmartWindowControl.oRoi = Subject.Params.ROI;
+                }
+
+                if (Subject.Params.Fixture != null)
+                    cmbFixture.Text = Subject.Params.Fixture.strName;
+                else
+                    cmbFixture.Text = "";
+
+                switch (type)
+                {
+                    case Type t when t == typeof(HRectangle2):
+                        inputImageHSmartWindowControl.oRoi
+                             = new HRectangle2(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                             , Subject.Params.ROI.Phi + Subject.Params.Fixture.Phi, ((HRectangle2)Subject.Params.ROI).Width, ((HRectangle2)Subject.Params.ROI).Height);
+                        break;
+                    case Type t when t == typeof(HCircle):
+                        inputImageHSmartWindowControl.oRoi
+                        = new HCircle(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                        , ((HCircle)Subject.Params.ROI).Radius);
+                        break;
+                    case Type t when t == typeof(HSegment):
+                        inputImageHSmartWindowControl.oRoi
+                        = new HSegment(((HSegment)Subject.Params.ROI).StartX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).StartY + Subject.Params.Fixture.Y
+                        , ((HSegment)Subject.Params.ROI).EndX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).EndY + Subject.Params.Fixture.Y);
+                        break;
+                    default:
+                        inputImageHSmartWindowControl.oRoi = null;
+                        break;
+                }
+
+                ShowModels((JArray.FromObject(Subject.Params.Inputs["ModelsFullPath"])).ToObject<List<string>>());
+            }));
+        }
+
+        /// <summary>
+        /// 鏇存柊杈撳嚭缁撴灉
+        /// </summary>
+        public override void UpdataOutputs()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                //瀛樺湪鍙嶅簭鍒楀寲閿欎贡鐨勬儏鍐甸渶瑕佷娇鐢ㄨ嚜瀹氫箟鐨勮浆鎹㈠櫒
+                dtxtCenterX.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterX"]);
+                dtxtCenterY.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterY"]);
+                dtxtAngle.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Angle"]);
+                dtxtScore.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Score"]);
+                dtxtCount.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Count"]);
+            }));
+        }
+
+        /// <summary>
+        /// 鐐瑰嚮杩愯
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        public override void btnRun_Click(object sender, EventArgs e)
+        {
+            if (Subject.InputImage != null)
+                InputImage = Subject.InputImage;
+
+            DateTime StartTime = DateTime.Now;
+            Run();
+
+            //鏇存柊鏃ュ織涓庣粨鏋�
+            this.BeginInvoke(new Action(() =>
+            {
+                if (Subject.Result)
+                {
+                    lblResult.BackColor = Color.Green;
+                    lblResult.Text = "True";
+                    recordImageHSmartWindowControl.SetColor("green");
+                }
+                else
+                {
+                    lblResult.BackColor = Color.Red;
+                    lblResult.Text = "False";
+                    recordImageHSmartWindowControl.SetColor("red");
+                }
+
+                lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+                lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+                lblRunTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
+
+                UpdataOutputs();
+                imgTabControl.SelectedTab = tabPageRecordImage;
+
+                if (Subject.InputImage != null && Subject.InputImage is HObject)
+                {
+                    HOperatorSet.GetImageSize((HObject)Subject.InputImage, out HTuple ho_ImageWidth, out HTuple ho_ImageHeight);
+                    recordImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
+                }
+
+                //鍏堝垽鏂瓙绫诲啀鍒ゆ柇鐖剁被
+                if (Subject.Record != null && Subject.Record is MsgRecord)
+                {
+                    MsgRecord MsgRecord = (MsgRecord)Subject.Record;
+
+                    recordImageHSmartWindowControl.DispObj(MsgRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(MsgRecord.RecordObject_NG, false);
+
+                    for (int i = 0; i < MsgRecord.Msg.Length; i++)
+                        recordImageHSmartWindowControl.ShowMsg(MsgRecord.Msg[i], 1 == MsgRecord.Result[i] ? true : false
+                            , MsgRecord.Column[i], MsgRecord.Row[i]);
+                }
+                else if (Subject.Record != null && Subject.Record is ObjectRecord record)
+                {
+                    recordImageHSmartWindowControl.DispObj(record.RecordObject_OK);
+                    recordImageHSmartWindowControl.DispObj(record.RecordObject_NG);
+                }
+
+                GC.Collect();
+            }));
+        }
+
+        public override void btnLoadImage_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    HOperatorSet.ReadImage(out HObject ho_Image, selectedFiles[0]);
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.CountChannels(ho_Image, out HTuple hv_Channels);
+                        if (hv_Channels.TupleInt() != 1)
+                        {
+                            HOperatorSet.Rgb1ToGray(ho_Image, out ho_Image);
+                            //鏇存柊鏃ュ織涓庣粨鏋�
+                            this.BeginInvoke(new Action(() =>
+                            {
+                                lblMsg.Text = "瀵煎叆鍥剧墖闈炵伆搴﹀浘,鑷姩杞崲涓虹伆搴﹀浘";
+                            }));
+                        }
+                        InputImage = ho_Image;
+                        imgTabControl.SelectedTab = tabPageInputImage;
+
+                        foreach (var ModelToolControl in listModelToolControls)
+                            ModelToolControl.HFindModelTool.InputImage = ho_Image.CopyObj(1, -1);
+
+                        inputImageHSmartWindowControl.oRoi = inputImageHSmartWindowControl.oRoi;
+                    }
+                }
+            }
+        }
+
+        public override void btnSaveParas_Click(object sender, EventArgs e)
+        {
+            //淇濆瓨鍓嶉渶瑕佹洿鏂拌緭鍏ュ弬鏁癐nputs
+            UpdataInputs();
+
+            // 鍒涘缓 SaveFileDialog 瀹炰緥
+            using (SaveFileDialog saveFileDialog = new SaveFileDialog())
+            {
+                // 璁剧疆瀵硅瘽妗嗘爣棰�
+                saveFileDialog.Title = "淇濆瓨鏂囦欢";
+
+                // 璁剧疆榛樿璺緞
+                saveFileDialog.InitialDirectory = Application.StartupPath;
+
+                // 璁剧疆鏂囦欢绫诲瀷杩囨护鍣�
+                saveFileDialog.Filter = "鏂囨湰鏂囦欢 (*.json)|*.json|鎵�鏈夋枃浠� (*.*)|*.*";
+
+                // 璁剧疆榛樿鏂囦欢鍚�
+                saveFileDialog.FileName = Subject.strProcessName + ".json";
+
+                // 鏄剧ず瀵硅瘽妗嗗苟妫�鏌ョ敤鎴锋槸鍚︾偣鍑讳簡淇濆瓨鎸夐挳
+                if (saveFileDialog.ShowDialog() == DialogResult.OK)
+                {
+                    // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠惰矾寰�
+                    string fullPath = saveFileDialog.FileName;
+                    Debug.WriteLine("閫夋嫨鐨勬枃浠惰矾寰勬槸: " + fullPath);
+                    Subject.strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+                    ((HFindMultiModelTool)Subject).Save(Path.GetDirectoryName(fullPath));
+                }
+            }
+        }
+
+        public override void btnLoadParas_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Ini Files (*.json)|*.json|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    ((HFindMultiModelTool)Subject).Load(selectedFiles[0]);
+                    LoadParas();
+                }
+            }
+        }
+
+        public override void ckbDrawRoi_CheckedChanged(object sender, EventArgs e)
+        {
+            if (ckbDrawRoi.Checked)
+            {
+                inputImageHSmartWindowControl.bAollowDraw = true;
+                imgTabControl.SelectedTab = tabPageInputImage;
+            }
+            else
+            {
+                inputImageHSmartWindowControl.bAollowDraw = false;
+                Subject.Params.ROI = new ROI();
+            }
+        }
+
+        public override void cmbTypeRoi_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (Enum.TryParse(cmbTypeRoi.Text.ToString(), out RoiType type))
+                {
+                    HTuple hv_imageWidth = 0;
+                    HTuple hv_imageHeight = 0;
+                    if (InputImage != null && InputImage is HObject)
+                        HOperatorSet.GetImageSize((HObject)InputImage, out hv_imageWidth, out hv_imageHeight);
+                    switch (type)
+                    {
+                        case RoiType.Rectangle2:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, 0
+                                , hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.Circle:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HCircle(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, hv_imageWidth.TupleReal() / 4);
+                            break;
+                        case RoiType.Segment:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HSegment(0, 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.None:
+                        default:
+                            inputImageHSmartWindowControl.oRoi = null;
+                            break;
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public override void cmbFixture_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+                else
+                    Subject.Params.Fixture = new Fixture();
+            }
+            catch { }
+        }
+
+        public void ShowModels(List<string> ModelsFullPath)
+        {
+            try
+            {
+                if (ModelsFullPath == null)
+                    return;
+
+                splitContainer1.Panel1.Controls.Clear();
+                listModelToolControls.Clear();
+                foreach (string ModelFullPath in ModelsFullPath)
+                {
+                    int index = listModelToolControls.Count + 1;
+                    string name = Path.GetFileNameWithoutExtension(ModelFullPath);
+                    HMulitModelControl hMulitModelControl = new HMulitModelControl(index, name);
+                    hMulitModelControl.HFindModelTool.Load(ModelFullPath);
+
+                    if (InputImage != null && InputImage is HObject image && image.IsInitialized())
+                        hMulitModelControl.HFindModelTool.InputImage = image.CopyObj(1, -1);
+                    splitContainer1.Panel1.Controls.Add(hMulitModelControl);
+                    hMulitModelControl.Dock = DockStyle.Top;
+                    listModelToolControls.Add(hMulitModelControl);
+
+                    //鍒锋柊鏄剧ず
+                    hMulitModelControl.UpdataModelUI();
+                }
+            }
+            catch { }
+        }
+
+        private void btnAddModel_Click(object sender, EventArgs e)
+        {
+            int index = listModelToolControls.Count + 1;
+            string name = "妯℃澘" + index.ToString();
+            HMulitModelControl hMulitModelControl = new HMulitModelControl(index, name);
+            splitContainer1.Panel1.Controls.Add(hMulitModelControl);
+            hMulitModelControl.Dock = DockStyle.Top;
+            listModelToolControls.Add(hMulitModelControl);
+
+            //鍒锋柊鏄剧ず
+            if (InputImage != null && InputImage is HObject)
+                hMulitModelControl.HFindModelTool.InputImage = ((HObject)InputImage).CopyObj(1, -1);
+
+            ((HFindMultiModelTool)Subject).HFindModelTools.Add(hMulitModelControl.HFindModelTool);
+        }
+
+        private void btnDelModel_Click(object sender, EventArgs e)
+        {
+            int index = listModelToolControls.Count - 1;
+            splitContainer1.Panel1.Controls.Remove(listModelToolControls[index]);
+            listModelToolControls[index].Dispose();
+            listModelToolControls.RemoveAt(index);
+            ((HFindMultiModelTool)Subject).HFindModelTools.RemoveAt(index);
+        }
+
+        private void HFindMultiModelToolEdit_SizeChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                //鍒锋柊鏄剧ず
+                foreach (HMulitModelControl ModelToolControl in listModelToolControls)
+                    ModelToolControl.UpdataModelUI();
+            }
+            catch { }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.resx b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.resx
new file mode 100644
index 0000000..ebc4d95
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HFindMultiModelToolEdit.resx
@@ -0,0 +1,132 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema 
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="lblMsgToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="TopToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>156, 17</value>
+  </metadata>
+  <metadata name="BtmStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>287, 17</value>
+  </metadata>
+  <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>81</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.Designer.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.Designer.cs
new file mode 100644
index 0000000..edf8273
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.Designer.cs
@@ -0,0 +1,196 @@
+锘縩amespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    partial class HMulitModelControl
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            btnEditModel = new Button();
+            pnlModelImg = new Panel();
+            txtModelName = new TextBox();
+            lblIndex = new Label();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            tableLayoutPanel3 = new TableLayoutPanel();
+            tableLayoutPanel4 = new TableLayoutPanel();
+            btnDelModel = new Button();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tableLayoutPanel3.SuspendLayout();
+            tableLayoutPanel4.SuspendLayout();
+            SuspendLayout();
+            // 
+            // btnEditModel
+            // 
+            btnEditModel.Dock = DockStyle.Fill;
+            btnEditModel.Location = new Point(3, 63);
+            btnEditModel.Name = "btnEditModel";
+            btnEditModel.Size = new Size(68, 24);
+            btnEditModel.TabIndex = 0;
+            btnEditModel.Text = "缂栬緫";
+            btnEditModel.UseVisualStyleBackColor = true;
+            btnEditModel.Click += btnEditModel_Click;
+            // 
+            // pnlModelImg
+            // 
+            pnlModelImg.Dock = DockStyle.Fill;
+            pnlModelImg.Location = new Point(123, 3);
+            pnlModelImg.Name = "pnlModelImg";
+            pnlModelImg.Size = new Size(113, 151);
+            pnlModelImg.TabIndex = 2;
+            // 
+            // txtModelName
+            // 
+            txtModelName.Location = new Point(3, 63);
+            txtModelName.Name = "txtModelName";
+            txtModelName.ReadOnly = true;
+            txtModelName.Size = new Size(88, 23);
+            txtModelName.TabIndex = 3;
+            // 
+            // lblIndex
+            // 
+            lblIndex.AutoSize = true;
+            lblIndex.Dock = DockStyle.Fill;
+            lblIndex.Location = new Point(3, 0);
+            lblIndex.Name = "lblIndex";
+            lblIndex.Size = new Size(14, 157);
+            lblIndex.TabIndex = 4;
+            lblIndex.Text = "0";
+            lblIndex.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 5;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 80F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 80F));
+            tableLayoutPanel1.Controls.Add(pnlModelImg, 2, 0);
+            tableLayoutPanel1.Controls.Add(lblIndex, 0, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 1, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel3, 3, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel4, 4, 0);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 1;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Size = new Size(399, 157);
+            tableLayoutPanel1.TabIndex = 5;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 1;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(txtModelName, 0, 2);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(23, 3);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 5;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel2.Size = new Size(94, 151);
+            tableLayoutPanel2.TabIndex = 5;
+            // 
+            // tableLayoutPanel3
+            // 
+            tableLayoutPanel3.ColumnCount = 1;
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Controls.Add(btnEditModel, 0, 2);
+            tableLayoutPanel3.Dock = DockStyle.Fill;
+            tableLayoutPanel3.Location = new Point(242, 3);
+            tableLayoutPanel3.Name = "tableLayoutPanel3";
+            tableLayoutPanel3.RowCount = 5;
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel3.Size = new Size(74, 151);
+            tableLayoutPanel3.TabIndex = 6;
+            // 
+            // tableLayoutPanel4
+            // 
+            tableLayoutPanel4.ColumnCount = 1;
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel4.Controls.Add(btnDelModel, 0, 2);
+            tableLayoutPanel4.Dock = DockStyle.Fill;
+            tableLayoutPanel4.Location = new Point(322, 3);
+            tableLayoutPanel4.Name = "tableLayoutPanel4";
+            tableLayoutPanel4.RowCount = 5;
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 25F));
+            tableLayoutPanel4.Size = new Size(74, 151);
+            tableLayoutPanel4.TabIndex = 7;
+            // 
+            // btnDelModel
+            // 
+            btnDelModel.Dock = DockStyle.Fill;
+            btnDelModel.Location = new Point(3, 63);
+            btnDelModel.Name = "btnDelModel";
+            btnDelModel.Size = new Size(68, 24);
+            btnDelModel.TabIndex = 0;
+            btnDelModel.Text = "鍒犻櫎";
+            btnDelModel.UseVisualStyleBackColor = true;
+            btnDelModel.Visible = false;
+            btnDelModel.Click += btnDelModel_Click;
+            // 
+            // HMulitModelControl
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(tableLayoutPanel1);
+            Name = "HMulitModelControl";
+            Size = new Size(399, 157);
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel1.PerformLayout();
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel2.PerformLayout();
+            tableLayoutPanel3.ResumeLayout(false);
+            tableLayoutPanel4.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private Button btnEditModel;
+        private Panel pnlModelImg;
+        private TextBox txtModelName;
+        private Label lblIndex;
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel2;
+        private TableLayoutPanel tableLayoutPanel3;
+        private TableLayoutPanel tableLayoutPanel4;
+        private Button btnDelModel;
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.cs b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.cs
new file mode 100644
index 0000000..4d57328
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.cs
@@ -0,0 +1,149 @@
+锘縰sing HalconDotNet;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static LB_VisionProcesses.Alogrithms.Halcon.HFindModelTool;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    public partial class HMulitModelControl : UserControl
+    {
+        public HFindModelTool HFindModelTool = new HFindModelTool();
+        public string fullPath = string.Empty;
+
+        public Action<string> DeleteModel;
+        public Action<string> RenameModel;
+        HWindowControl hWindowControl = new HWindowControl();
+
+        public HMulitModelControl()
+        {
+            InitializeComponent();
+        }
+
+        public HMulitModelControl(string fullPath)
+        {
+            InitializeComponent();
+            pnlModelImg.Controls.Clear();
+            pnlModelImg.Controls.Add(hWindowControl);
+            hWindowControl.Dock = DockStyle.Fill;
+
+            this.fullPath = fullPath;
+            HFindModelTool.Load(fullPath);
+
+            if (HFindModelTool.ModelID.hvModel != null && HFindModelTool.ModelID.hvModel.Length > 0)
+            {
+                HModel hModel = HFindModelTool.ModelID;
+                HObject ho_ModelContours = new HObject();
+                switch (HFindModelTool.ModelID.Type)
+                {
+                    case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                        HOperatorSet.GetDeformableModelContours(out ho_ModelContours, HFindModelTool.ModelID.hvModel, 1);
+                        break;
+                    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                    default:
+                        HOperatorSet.GetShapeModelContours(out ho_ModelContours, HFindModelTool.ModelID.hvModel, 1);
+                        break;
+                }
+                HOperatorSet.GetImageSize(HFindModelTool.ModelID.hoImage, out HTuple hv_Width, out HTuple hv_Height);
+                HOperatorSet.VectorAngleToRigid(-hv_Height / 2, -hv_Width / 2, 0, 0, 0, 0, out HTuple hv_HomMat2D);
+                HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ModelContours, hv_HomMat2D);
+
+                if (HFindModelTool.ModelID.hoImage != null)
+                {
+                    hWindowControl.Dock = DockStyle.Fill;
+
+                    HOperatorSet.ClearWindow(hWindowControl.HalconWindow);
+                    HOperatorSet.GetImageSize(HFindModelTool.ModelID.hoImage, out HTuple hv_imageWidth, out HTuple hv_imageHeight);
+                    HOperatorSet.SetPart(hWindowControl.HalconWindow, 0, 0, hv_imageHeight - 1, hv_imageWidth - 1);
+                    HOperatorSet.DispObj(HFindModelTool.ModelID.hoImage, hWindowControl.HalconWindow);
+                    HOperatorSet.SetColor(hWindowControl.HalconWindow, "red");
+                    HOperatorSet.DispObj(ho_ModelContours, hWindowControl.HalconWindow);
+
+                    txtModelName.Text = HFindModelTool.ModelID.ModelName;
+                }
+            }
+        }
+
+        public HMulitModelControl(int index, string name)
+        {
+            InitializeComponent();
+            pnlModelImg.Controls.Clear();
+            pnlModelImg.Controls.Add(hWindowControl);
+            hWindowControl.Dock = DockStyle.Fill;
+
+            lblIndex.Text = index.ToString();
+            txtModelName.Text = name;
+            HFindModelTool = new HFindModelTool();
+            HFindModelTool.strProcessName = name;
+            HFindModelTool.ModelID.ModelName = name;
+        }
+
+        private void btnEditModel_Click(object sender, EventArgs e)
+        {
+            if (HFindModelTool != null)
+            {
+                //HFindModelTool鐨処nputImage鏈夊�煎垯浼氭樉绀哄浘鐗�
+                ProcessEditForm processEditForm = new ProcessEditForm(HFindModelTool, fullPath);
+                processEditForm.ShowDialog();
+
+                UpdataModelUI();
+            }
+        }
+
+        private void btnDelModel_Click(object sender, EventArgs e)
+        {
+            DeleteModel?.Invoke(lblIndex.Text);
+        }
+
+        public void UpdataModelUI()
+        {
+            if (HFindModelTool.ModelID.hvModel != null && HFindModelTool.ModelID.hvModel.Length > 0)
+            {
+                HModel hModel = HFindModelTool.ModelID;
+                HObject ho_ModelContours = new HObject();
+                switch (HFindModelTool.ModelID.Type)
+                {
+                    case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                        HOperatorSet.GetDeformableModelContours(out ho_ModelContours, HFindModelTool.ModelID.hvModel, 1);
+                        break;
+                    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                    default:
+                        HOperatorSet.GetShapeModelContours(out ho_ModelContours, HFindModelTool.ModelID.hvModel, 1);
+                        break;
+                }
+
+                if (HFindModelTool.ModelID.hoImage != null)
+                {
+                    HOperatorSet.GetImageSize(HFindModelTool.ModelID.hoImage, out HTuple hv_Width, out HTuple hv_Height);
+                    HOperatorSet.VectorAngleToRigid(-hv_Height / 2, -hv_Width / 2, 0, 0, 0, 0, out HTuple hv_HomMat2D);
+                    HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ModelContours, hv_HomMat2D);
+
+                    HOperatorSet.ClearWindow(hWindowControl.HalconWindow);
+                    HOperatorSet.GetImageSize(HFindModelTool.ModelID.hoImage, out HTuple hv_imageWidth, out HTuple hv_imageHeight);
+                    HOperatorSet.SetPart(hWindowControl.HalconWindow, 0, 0, hv_imageHeight - 1, hv_imageWidth - 1);
+                    HOperatorSet.DispObj(HFindModelTool.ModelID.hoImage, hWindowControl.HalconWindow);
+                    HOperatorSet.SetColor(hWindowControl.HalconWindow, "red");
+                    HOperatorSet.DispObj(ho_ModelContours, hWindowControl.HalconWindow);
+                }
+            }
+        }
+
+        public void Rename(int index, string newName)
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                lblIndex.Text = index.ToString();
+                txtModelName.Text = newName;
+
+                HFindModelTool.strProcessName = newName;
+                HFindModelTool.ModelID.ModelName = newName;
+            }));
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.resx b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/2D/HFindMultiModelTool/HMulitModelControl.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/LB_VisionProcesses/Alogrithms/Halcon/HDevelopExport.cs b/LB_VisionProcesses/Alogrithms/Halcon/HDevelopExport.cs
new file mode 100644
index 0000000..15a500e
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/Halcon/HDevelopExport.cs
@@ -0,0 +1,8637 @@
+锘縰sing HalconDotNet;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Alogrithms.Halcon
+{
+    public partial class HDevelopExport
+    {
+
+        public static HTuple gIsSinglePose;
+        public static HTuple gTerminationButtonLabel;
+        public static HTuple gInfoDecor;
+        public static HTuple gInfoPos;
+        public static HTuple gTitlePos;
+        public static HTuple gTitleDecor;
+        public static HTuple gAlphaDeselected;
+        public static HTuple gDispObjOffset;
+        public static HTuple gLabelsDecor;
+        public static HTuple gUsesOpenGL;
+        public static HTuple ExpGetGlobalVar_gIsSinglePose()
+        {
+            return gIsSinglePose;
+        }
+        public static void ExpSetGlobalVar_gIsSinglePose(HTuple val)
+        {
+            if (gIsSinglePose != val)
+            {
+                if (gIsSinglePose != null)
+                    gIsSinglePose.Dispose();
+                gIsSinglePose = val;
+            }
+        }
+
+        public static HTuple ExpGetGlobalVar_gTerminationButtonLabel()
+        {
+            return gTerminationButtonLabel;
+        }
+        public static void ExpSetGlobalVar_gTerminationButtonLabel(HTuple val)
+        {
+            if (gTerminationButtonLabel != val)
+            {
+                if (gTerminationButtonLabel != null)
+                    gTerminationButtonLabel.Dispose();
+                gTerminationButtonLabel = val;
+            }
+        }
+
+        public static HTuple ExpGetGlobalVar_gInfoDecor()
+        {
+            return gInfoDecor;
+        }
+        public static void ExpSetGlobalVar_gInfoDecor(HTuple val)
+        {
+            if (gInfoDecor != val)
+            {
+                if (gInfoDecor != null)
+                    gInfoDecor.Dispose();
+                gInfoDecor = val;
+            }
+        }
+
+        public static HTuple ExpGetGlobalVar_gInfoPos()
+        {
+            return gInfoPos;
+        }
+        public static void ExpSetGlobalVar_gInfoPos(HTuple val)
+        {
+            if (gInfoPos != val)
+            {
+                if (gInfoPos != null)
+                    gInfoPos.Dispose();
+                gInfoPos = val;
+            }
+        }
+
+        public static HTuple ExpGetGlobalVar_gTitlePos()
+        {
+            return gTitlePos;
+        }
+        public static void ExpSetGlobalVar_gTitlePos(HTuple val)
+        {
+            if (gTitlePos != val)
+            {
+                if (gTitlePos != null)
+                    gTitlePos.Dispose();
+                gTitlePos = val;
+            }
+        }
+
+        public static HTuple ExpGetGlobalVar_gTitleDecor()
+        {
+            return gTitleDecor;
+        }
+        public static void ExpSetGlobalVar_gTitleDecor(HTuple val)
+        {
+            if (gTitleDecor != val)
+            {
+                if (gTitleDecor != null)
+                    gTitleDecor.Dispose();
+                gTitleDecor = val;
+            }
+        }
+
+        public static HTuple ExpGetGlobalVar_gAlphaDeselected()
+        {
+            return gAlphaDeselected;
+        }
+        public static void ExpSetGlobalVar_gAlphaDeselected(HTuple val)
+        {
+            if (gAlphaDeselected != val)
+            {
+                if (gAlphaDeselected != null)
+                    gAlphaDeselected.Dispose();
+                gAlphaDeselected = val;
+            }
+        }
+
+        public static HTuple ExpGetGlobalVar_gDispObjOffset()
+        {
+            return gDispObjOffset;
+        }
+        public static void ExpSetGlobalVar_gDispObjOffset(HTuple val)
+        {
+            if (gDispObjOffset != val)
+            {
+                if (gDispObjOffset != null)
+                    gDispObjOffset.Dispose();
+                gDispObjOffset = val;
+            }
+        }
+
+        public static HTuple ExpGetGlobalVar_gLabelsDecor()
+        {
+            return gLabelsDecor;
+        }
+        public static void ExpSetGlobalVar_gLabelsDecor(HTuple val)
+        {
+            if (gLabelsDecor != val)
+            {
+                if (gLabelsDecor != null)
+                    gLabelsDecor.Dispose();
+                gLabelsDecor = val;
+            }
+        }
+
+        public static HTuple ExpGetGlobalVar_gUsesOpenGL()
+        {
+            return gUsesOpenGL;
+        }
+        public static void ExpSetGlobalVar_gUsesOpenGL(HTuple val)
+        {
+            if (gUsesOpenGL != val)
+            {
+                if (gUsesOpenGL != null)
+                    gUsesOpenGL.Dispose();
+                gUsesOpenGL = val;
+            }
+        }
+
+        // Procedures 
+        // External procedures 
+        // Chapter: Graphics / Output
+        // Short Description: Reflect the pose change that was introduced by the user by moving the mouse 
+        public static void analyze_graph_event(HObject ho_BackgroundImage, HTuple hv_MouseMapping,
+            HTuple hv_Button, HTuple hv_Row, HTuple hv_Column, HTuple hv_WindowHandle, HTuple hv_WindowHandleBuffer,
+            HTuple hv_VirtualTrackball, HTuple hv_TrackballSize, HTuple hv_SelectedObjectIn,
+            HTuple hv_Scene3D, HTuple hv_AlphaOrig, HTuple hv_ObjectModel3DID, HTuple hv_CamParam,
+            HTuple hv_Labels, HTuple hv_Title, HTuple hv_Information, HTuple hv_GenParamName,
+            HTuple hv_GenParamValue, HTuple hv_PosesIn, HTuple hv_ButtonHoldIn, HTuple hv_TBCenter,
+            HTuple hv_TBSize, HTuple hv_WindowCenteredRotationlIn, HTuple hv_MaxNumModels,
+            out HTuple hv_PosesOut, out HTuple hv_SelectedObjectOut, out HTuple hv_ButtonHoldOut,
+            out HTuple hv_WindowCenteredRotationOut)
+        {
+
+
+
+
+            // Local iconic variables 
+
+            HObject ho_ImageDump = null;
+
+            // Local control variables 
+
+            HTuple ExpTmpLocalVar_gIsSinglePose = new HTuple();
+            HTuple hv_VisualizeTB = new HTuple(), hv_InvLog2 = new HTuple();
+            HTuple hv_Seconds = new HTuple(), hv_ModelIndex = new HTuple();
+            HTuple hv_Exception1 = new HTuple(), hv_HomMat3DIdentity = new HTuple();
+            HTuple hv_NumModels = new HTuple(), hv_Width = new HTuple();
+            HTuple hv_Height = new HTuple(), hv_MinImageSize = new HTuple();
+            HTuple hv_TrackballRadiusPixel = new HTuple(), hv_TrackballCenterRow = new HTuple();
+            HTuple hv_TrackballCenterCol = new HTuple(), hv_NumChannels = new HTuple();
+            HTuple hv_ColorImage = new HTuple(), hv_BAnd = new HTuple();
+            HTuple hv_SensFactor = new HTuple(), hv_IsButtonTrans = new HTuple();
+            HTuple hv_IsButtonRot = new HTuple(), hv_IsButtonDist = new HTuple();
+            HTuple hv_MRow1 = new HTuple(), hv_MCol1 = new HTuple();
+            HTuple hv_ButtonLoop = new HTuple(), hv_MRow2 = new HTuple();
+            HTuple hv_MCol2 = new HTuple(), hv_PX = new HTuple(), hv_PY = new HTuple();
+            HTuple hv_PZ = new HTuple(), hv_QX1 = new HTuple(), hv_QY1 = new HTuple();
+            HTuple hv_QZ1 = new HTuple(), hv_QX2 = new HTuple(), hv_QY2 = new HTuple();
+            HTuple hv_QZ2 = new HTuple(), hv_Len = new HTuple(), hv_Dist = new HTuple();
+            HTuple hv_Translate = new HTuple(), hv_Index = new HTuple();
+            HTuple hv_PoseIn = new HTuple(), hv_HomMat3DIn = new HTuple();
+            HTuple hv_HomMat3DOut = new HTuple(), hv_PoseOut = new HTuple();
+            HTuple hv_Indices = new HTuple(), hv_Sequence = new HTuple();
+            HTuple hv_Mod = new HTuple(), hv_SequenceReal = new HTuple();
+            HTuple hv_Sequence2Int = new HTuple(), hv_Selected = new HTuple();
+            HTuple hv_InvSelected = new HTuple(), hv_Exception = new HTuple();
+            HTuple hv_DRow = new HTuple(), hv_TranslateZ = new HTuple();
+            HTuple hv_MX1 = new HTuple(), hv_MY1 = new HTuple(), hv_MX2 = new HTuple();
+            HTuple hv_MY2 = new HTuple(), hv_RelQuaternion = new HTuple();
+            HTuple hv_HomMat3DRotRel = new HTuple(), hv_HomMat3DInTmp1 = new HTuple();
+            HTuple hv_HomMat3DInTmp = new HTuple(), hv_PosesOut2 = new HTuple();
+            HTuple hv_Column_COPY_INP_TMP = new HTuple(hv_Column);
+            HTuple hv_PosesIn_COPY_INP_TMP = new HTuple(hv_PosesIn);
+            HTuple hv_Row_COPY_INP_TMP = new HTuple(hv_Row);
+            HTuple hv_TBCenter_COPY_INP_TMP = new HTuple(hv_TBCenter);
+            HTuple hv_TBSize_COPY_INP_TMP = new HTuple(hv_TBSize);
+
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_ImageDump);
+            hv_PosesOut = new HTuple();
+            hv_SelectedObjectOut = new HTuple();
+            hv_ButtonHoldOut = new HTuple();
+            hv_WindowCenteredRotationOut = new HTuple();
+            try
+            {
+                //This procedure reflects
+                //- the pose change that was introduced by the user by
+                //  moving the mouse
+                //- the selection of a single object
+                //
+                //global tuple gIsSinglePose
+                //
+                hv_ButtonHoldOut.Dispose();
+                hv_ButtonHoldOut = new HTuple(hv_ButtonHoldIn);
+                hv_PosesOut.Dispose();
+                hv_PosesOut = new HTuple(hv_PosesIn_COPY_INP_TMP);
+                hv_SelectedObjectOut.Dispose();
+                hv_SelectedObjectOut = new HTuple(hv_SelectedObjectIn);
+                hv_WindowCenteredRotationOut.Dispose();
+                hv_WindowCenteredRotationOut = new HTuple(hv_WindowCenteredRotationlIn);
+                hv_VisualizeTB.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_VisualizeTB = new HTuple(hv_SelectedObjectOut.TupleMax()
+                        .TupleNotEqual(0));
+                }
+                hv_InvLog2.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_InvLog2 = 1.0 / new HTuple(2).TupleLog()
+                        ;
+                }
+                //
+                if ((int)new HTuple(hv_Button.TupleEqual(hv_MouseMapping.TupleSelect(6))) != 0)
+                {
+                    if ((int)hv_ButtonHoldOut != 0)
+                    {
+                        ho_ImageDump.Dispose();
+
+                        hv_Column_COPY_INP_TMP.Dispose();
+                        hv_PosesIn_COPY_INP_TMP.Dispose();
+                        hv_Row_COPY_INP_TMP.Dispose();
+                        hv_TBCenter_COPY_INP_TMP.Dispose();
+                        hv_TBSize_COPY_INP_TMP.Dispose();
+                        hv_VisualizeTB.Dispose();
+                        hv_InvLog2.Dispose();
+                        hv_Seconds.Dispose();
+                        hv_ModelIndex.Dispose();
+                        hv_Exception1.Dispose();
+                        hv_HomMat3DIdentity.Dispose();
+                        hv_NumModels.Dispose();
+                        hv_Width.Dispose();
+                        hv_Height.Dispose();
+                        hv_MinImageSize.Dispose();
+                        hv_TrackballRadiusPixel.Dispose();
+                        hv_TrackballCenterRow.Dispose();
+                        hv_TrackballCenterCol.Dispose();
+                        hv_NumChannels.Dispose();
+                        hv_ColorImage.Dispose();
+                        hv_BAnd.Dispose();
+                        hv_SensFactor.Dispose();
+                        hv_IsButtonTrans.Dispose();
+                        hv_IsButtonRot.Dispose();
+                        hv_IsButtonDist.Dispose();
+                        hv_MRow1.Dispose();
+                        hv_MCol1.Dispose();
+                        hv_ButtonLoop.Dispose();
+                        hv_MRow2.Dispose();
+                        hv_MCol2.Dispose();
+                        hv_PX.Dispose();
+                        hv_PY.Dispose();
+                        hv_PZ.Dispose();
+                        hv_QX1.Dispose();
+                        hv_QY1.Dispose();
+                        hv_QZ1.Dispose();
+                        hv_QX2.Dispose();
+                        hv_QY2.Dispose();
+                        hv_QZ2.Dispose();
+                        hv_Len.Dispose();
+                        hv_Dist.Dispose();
+                        hv_Translate.Dispose();
+                        hv_Index.Dispose();
+                        hv_PoseIn.Dispose();
+                        hv_HomMat3DIn.Dispose();
+                        hv_HomMat3DOut.Dispose();
+                        hv_PoseOut.Dispose();
+                        hv_Indices.Dispose();
+                        hv_Sequence.Dispose();
+                        hv_Mod.Dispose();
+                        hv_SequenceReal.Dispose();
+                        hv_Sequence2Int.Dispose();
+                        hv_Selected.Dispose();
+                        hv_InvSelected.Dispose();
+                        hv_Exception.Dispose();
+                        hv_DRow.Dispose();
+                        hv_TranslateZ.Dispose();
+                        hv_MX1.Dispose();
+                        hv_MY1.Dispose();
+                        hv_MX2.Dispose();
+                        hv_MY2.Dispose();
+                        hv_RelQuaternion.Dispose();
+                        hv_HomMat3DRotRel.Dispose();
+                        hv_HomMat3DInTmp1.Dispose();
+                        hv_HomMat3DInTmp.Dispose();
+                        hv_PosesOut2.Dispose();
+
+                        return;
+                    }
+                    //Ctrl (16) + Alt (32) + left mouse button (1) => Toggle rotation center position
+                    //If WindowCenteredRotation is not 1, set it to 1, otherwise, set it to 2
+                    hv_Seconds.Dispose();
+                    HOperatorSet.CountSeconds(out hv_Seconds);
+                    if ((int)new HTuple(hv_WindowCenteredRotationOut.TupleEqual(1)) != 0)
+                    {
+                        hv_WindowCenteredRotationOut.Dispose();
+                        hv_WindowCenteredRotationOut = 2;
+                    }
+                    else
+                    {
+                        hv_WindowCenteredRotationOut.Dispose();
+                        hv_WindowCenteredRotationOut = 1;
+                    }
+                    hv_ButtonHoldOut.Dispose();
+                    hv_ButtonHoldOut = 1;
+                    ho_ImageDump.Dispose();
+
+                    hv_Column_COPY_INP_TMP.Dispose();
+                    hv_PosesIn_COPY_INP_TMP.Dispose();
+                    hv_Row_COPY_INP_TMP.Dispose();
+                    hv_TBCenter_COPY_INP_TMP.Dispose();
+                    hv_TBSize_COPY_INP_TMP.Dispose();
+                    hv_VisualizeTB.Dispose();
+                    hv_InvLog2.Dispose();
+                    hv_Seconds.Dispose();
+                    hv_ModelIndex.Dispose();
+                    hv_Exception1.Dispose();
+                    hv_HomMat3DIdentity.Dispose();
+                    hv_NumModels.Dispose();
+                    hv_Width.Dispose();
+                    hv_Height.Dispose();
+                    hv_MinImageSize.Dispose();
+                    hv_TrackballRadiusPixel.Dispose();
+                    hv_TrackballCenterRow.Dispose();
+                    hv_TrackballCenterCol.Dispose();
+                    hv_NumChannels.Dispose();
+                    hv_ColorImage.Dispose();
+                    hv_BAnd.Dispose();
+                    hv_SensFactor.Dispose();
+                    hv_IsButtonTrans.Dispose();
+                    hv_IsButtonRot.Dispose();
+                    hv_IsButtonDist.Dispose();
+                    hv_MRow1.Dispose();
+                    hv_MCol1.Dispose();
+                    hv_ButtonLoop.Dispose();
+                    hv_MRow2.Dispose();
+                    hv_MCol2.Dispose();
+                    hv_PX.Dispose();
+                    hv_PY.Dispose();
+                    hv_PZ.Dispose();
+                    hv_QX1.Dispose();
+                    hv_QY1.Dispose();
+                    hv_QZ1.Dispose();
+                    hv_QX2.Dispose();
+                    hv_QY2.Dispose();
+                    hv_QZ2.Dispose();
+                    hv_Len.Dispose();
+                    hv_Dist.Dispose();
+                    hv_Translate.Dispose();
+                    hv_Index.Dispose();
+                    hv_PoseIn.Dispose();
+                    hv_HomMat3DIn.Dispose();
+                    hv_HomMat3DOut.Dispose();
+                    hv_PoseOut.Dispose();
+                    hv_Indices.Dispose();
+                    hv_Sequence.Dispose();
+                    hv_Mod.Dispose();
+                    hv_SequenceReal.Dispose();
+                    hv_Sequence2Int.Dispose();
+                    hv_Selected.Dispose();
+                    hv_InvSelected.Dispose();
+                    hv_Exception.Dispose();
+                    hv_DRow.Dispose();
+                    hv_TranslateZ.Dispose();
+                    hv_MX1.Dispose();
+                    hv_MY1.Dispose();
+                    hv_MX2.Dispose();
+                    hv_MY2.Dispose();
+                    hv_RelQuaternion.Dispose();
+                    hv_HomMat3DRotRel.Dispose();
+                    hv_HomMat3DInTmp1.Dispose();
+                    hv_HomMat3DInTmp.Dispose();
+                    hv_PosesOut2.Dispose();
+
+                    return;
+                }
+                if ((int)new HTuple(hv_Button.TupleEqual(hv_MouseMapping.TupleSelect(5))).TupleAnd(
+                    new HTuple(new HTuple(hv_ObjectModel3DID.TupleLength()).TupleLessEqual(
+                    hv_MaxNumModels))) != 0)
+                {
+                    if ((int)hv_ButtonHoldOut != 0)
+                    {
+                        ho_ImageDump.Dispose();
+
+                        hv_Column_COPY_INP_TMP.Dispose();
+                        hv_PosesIn_COPY_INP_TMP.Dispose();
+                        hv_Row_COPY_INP_TMP.Dispose();
+                        hv_TBCenter_COPY_INP_TMP.Dispose();
+                        hv_TBSize_COPY_INP_TMP.Dispose();
+                        hv_VisualizeTB.Dispose();
+                        hv_InvLog2.Dispose();
+                        hv_Seconds.Dispose();
+                        hv_ModelIndex.Dispose();
+                        hv_Exception1.Dispose();
+                        hv_HomMat3DIdentity.Dispose();
+                        hv_NumModels.Dispose();
+                        hv_Width.Dispose();
+                        hv_Height.Dispose();
+                        hv_MinImageSize.Dispose();
+                        hv_TrackballRadiusPixel.Dispose();
+                        hv_TrackballCenterRow.Dispose();
+                        hv_TrackballCenterCol.Dispose();
+                        hv_NumChannels.Dispose();
+                        hv_ColorImage.Dispose();
+                        hv_BAnd.Dispose();
+                        hv_SensFactor.Dispose();
+                        hv_IsButtonTrans.Dispose();
+                        hv_IsButtonRot.Dispose();
+                        hv_IsButtonDist.Dispose();
+                        hv_MRow1.Dispose();
+                        hv_MCol1.Dispose();
+                        hv_ButtonLoop.Dispose();
+                        hv_MRow2.Dispose();
+                        hv_MCol2.Dispose();
+                        hv_PX.Dispose();
+                        hv_PY.Dispose();
+                        hv_PZ.Dispose();
+                        hv_QX1.Dispose();
+                        hv_QY1.Dispose();
+                        hv_QZ1.Dispose();
+                        hv_QX2.Dispose();
+                        hv_QY2.Dispose();
+                        hv_QZ2.Dispose();
+                        hv_Len.Dispose();
+                        hv_Dist.Dispose();
+                        hv_Translate.Dispose();
+                        hv_Index.Dispose();
+                        hv_PoseIn.Dispose();
+                        hv_HomMat3DIn.Dispose();
+                        hv_HomMat3DOut.Dispose();
+                        hv_PoseOut.Dispose();
+                        hv_Indices.Dispose();
+                        hv_Sequence.Dispose();
+                        hv_Mod.Dispose();
+                        hv_SequenceReal.Dispose();
+                        hv_Sequence2Int.Dispose();
+                        hv_Selected.Dispose();
+                        hv_InvSelected.Dispose();
+                        hv_Exception.Dispose();
+                        hv_DRow.Dispose();
+                        hv_TranslateZ.Dispose();
+                        hv_MX1.Dispose();
+                        hv_MY1.Dispose();
+                        hv_MX2.Dispose();
+                        hv_MY2.Dispose();
+                        hv_RelQuaternion.Dispose();
+                        hv_HomMat3DRotRel.Dispose();
+                        hv_HomMat3DInTmp1.Dispose();
+                        hv_HomMat3DInTmp.Dispose();
+                        hv_PosesOut2.Dispose();
+
+                        return;
+                    }
+                    //Ctrl (16) + left mouse button (1) => Select an object
+                    try
+                    {
+                        HOperatorSet.SetScene3dParam(hv_Scene3D, "object_index_persistence", "true");
+                        HOperatorSet.DisplayScene3d(hv_WindowHandleBuffer, hv_Scene3D, 0);
+                        hv_ModelIndex.Dispose();
+                        HOperatorSet.GetDisplayScene3dInfo(hv_WindowHandleBuffer, hv_Scene3D, hv_Row_COPY_INP_TMP,
+                            hv_Column_COPY_INP_TMP, "object_index", out hv_ModelIndex);
+                        HOperatorSet.SetScene3dParam(hv_Scene3D, "object_index_persistence", "false");
+                    }
+                    // catch (Exception1) 
+                    catch (HalconException HDevExpDefaultException1)
+                    {
+                        HDevExpDefaultException1.ToHTuple(out hv_Exception1);
+                        //* NO OpenGL, no selection possible
+                        ho_ImageDump.Dispose();
+
+                        hv_Column_COPY_INP_TMP.Dispose();
+                        hv_PosesIn_COPY_INP_TMP.Dispose();
+                        hv_Row_COPY_INP_TMP.Dispose();
+                        hv_TBCenter_COPY_INP_TMP.Dispose();
+                        hv_TBSize_COPY_INP_TMP.Dispose();
+                        hv_VisualizeTB.Dispose();
+                        hv_InvLog2.Dispose();
+                        hv_Seconds.Dispose();
+                        hv_ModelIndex.Dispose();
+                        hv_Exception1.Dispose();
+                        hv_HomMat3DIdentity.Dispose();
+                        hv_NumModels.Dispose();
+                        hv_Width.Dispose();
+                        hv_Height.Dispose();
+                        hv_MinImageSize.Dispose();
+                        hv_TrackballRadiusPixel.Dispose();
+                        hv_TrackballCenterRow.Dispose();
+                        hv_TrackballCenterCol.Dispose();
+                        hv_NumChannels.Dispose();
+                        hv_ColorImage.Dispose();
+                        hv_BAnd.Dispose();
+                        hv_SensFactor.Dispose();
+                        hv_IsButtonTrans.Dispose();
+                        hv_IsButtonRot.Dispose();
+                        hv_IsButtonDist.Dispose();
+                        hv_MRow1.Dispose();
+                        hv_MCol1.Dispose();
+                        hv_ButtonLoop.Dispose();
+                        hv_MRow2.Dispose();
+                        hv_MCol2.Dispose();
+                        hv_PX.Dispose();
+                        hv_PY.Dispose();
+                        hv_PZ.Dispose();
+                        hv_QX1.Dispose();
+                        hv_QY1.Dispose();
+                        hv_QZ1.Dispose();
+                        hv_QX2.Dispose();
+                        hv_QY2.Dispose();
+                        hv_QZ2.Dispose();
+                        hv_Len.Dispose();
+                        hv_Dist.Dispose();
+                        hv_Translate.Dispose();
+                        hv_Index.Dispose();
+                        hv_PoseIn.Dispose();
+                        hv_HomMat3DIn.Dispose();
+                        hv_HomMat3DOut.Dispose();
+                        hv_PoseOut.Dispose();
+                        hv_Indices.Dispose();
+                        hv_Sequence.Dispose();
+                        hv_Mod.Dispose();
+                        hv_SequenceReal.Dispose();
+                        hv_Sequence2Int.Dispose();
+                        hv_Selected.Dispose();
+                        hv_InvSelected.Dispose();
+                        hv_Exception.Dispose();
+                        hv_DRow.Dispose();
+                        hv_TranslateZ.Dispose();
+                        hv_MX1.Dispose();
+                        hv_MY1.Dispose();
+                        hv_MX2.Dispose();
+                        hv_MY2.Dispose();
+                        hv_RelQuaternion.Dispose();
+                        hv_HomMat3DRotRel.Dispose();
+                        hv_HomMat3DInTmp1.Dispose();
+                        hv_HomMat3DInTmp.Dispose();
+                        hv_PosesOut2.Dispose();
+
+                        return;
+                    }
+                    if ((int)new HTuple(hv_ModelIndex.TupleEqual(-1)) != 0)
+                    {
+                        //Background click:
+                        if ((int)new HTuple(hv_SelectedObjectOut.TupleSum().TupleEqual(new HTuple(hv_SelectedObjectOut.TupleLength()
+                            ))) != 0)
+                        {
+                            //If all objects are already selected, deselect all
+                            hv_SelectedObjectOut.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_SelectedObjectOut = HTuple.TupleGenConst(
+                                    new HTuple(hv_ObjectModel3DID.TupleLength()), 0);
+                            }
+                        }
+                        else
+                        {
+                            //Otherwise select all
+                            hv_SelectedObjectOut.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_SelectedObjectOut = HTuple.TupleGenConst(
+                                    new HTuple(hv_ObjectModel3DID.TupleLength()), 1);
+                            }
+                        }
+                    }
+                    else
+                    {
+                        //Object click:
+                        if (hv_SelectedObjectOut == null)
+                            hv_SelectedObjectOut = new HTuple();
+                        hv_SelectedObjectOut[hv_ModelIndex] = hv_SelectedObjectOut.TupleSelect(
+                            hv_ModelIndex).TupleNot();
+                    }
+                    hv_ButtonHoldOut.Dispose();
+                    hv_ButtonHoldOut = 1;
+                }
+                else
+                {
+                    //Change the pose
+                    hv_HomMat3DIdentity.Dispose();
+                    HOperatorSet.HomMat3dIdentity(out hv_HomMat3DIdentity);
+                    hv_NumModels.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_NumModels = new HTuple(hv_ObjectModel3DID.TupleLength()
+                            );
+                    }
+                    hv_Width.Dispose();
+                    get_cam_par_data(hv_CamParam, "image_width", out hv_Width);
+                    hv_Height.Dispose();
+                    get_cam_par_data(hv_CamParam, "image_height", out hv_Height);
+                    hv_MinImageSize.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_MinImageSize = hv_Width.TupleConcat(
+                            hv_Height).TupleMin();
+                    }
+                    hv_TrackballRadiusPixel.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TrackballRadiusPixel = hv_TrackballSize * hv_MinImageSize / 2.0;
+                    }
+                    //Set trackball fixed in the center of the window
+                    hv_TrackballCenterRow.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TrackballCenterRow = hv_Height / 2;
+                    }
+                    hv_TrackballCenterCol.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TrackballCenterCol = hv_Width / 2;
+                    }
+                    if ((int)new HTuple(new HTuple(hv_ObjectModel3DID.TupleLength()).TupleLess(
+                        hv_MaxNumModels)) != 0)
+                    {
+                        if ((int)new HTuple(hv_WindowCenteredRotationOut.TupleEqual(1)) != 0)
+                        {
+                            hv_TBCenter_COPY_INP_TMP.Dispose(); hv_TBSize_COPY_INP_TMP.Dispose();
+                            get_trackball_center_fixed(hv_SelectedObjectIn, hv_TrackballCenterRow,
+                                hv_TrackballCenterCol, hv_TrackballRadiusPixel, hv_Scene3D, hv_ObjectModel3DID,
+                                hv_PosesIn_COPY_INP_TMP, hv_WindowHandleBuffer, hv_CamParam, hv_GenParamName,
+                                hv_GenParamValue, out hv_TBCenter_COPY_INP_TMP, out hv_TBSize_COPY_INP_TMP);
+                        }
+                        else
+                        {
+                            hv_TBCenter_COPY_INP_TMP.Dispose(); hv_TBSize_COPY_INP_TMP.Dispose();
+                            get_trackball_center(hv_SelectedObjectIn, hv_TrackballRadiusPixel, hv_ObjectModel3DID,
+                                hv_PosesIn_COPY_INP_TMP, out hv_TBCenter_COPY_INP_TMP, out hv_TBSize_COPY_INP_TMP);
+                        }
+                    }
+                    if ((int)new HTuple(hv_SelectedObjectOut.TupleMin().TupleEqual(0)).TupleAnd(
+                        new HTuple(hv_SelectedObjectOut.TupleMax().TupleEqual(1))) != 0)
+                    {
+                        //At this point, multiple objects do not necessary have the same
+                        //pose any more. Consequently, we have to return a tuple of poses
+                        //as output of visualize_object_model_3d
+                        ExpTmpLocalVar_gIsSinglePose = 0;
+                        ExpSetGlobalVar_gIsSinglePose(ExpTmpLocalVar_gIsSinglePose);
+                    }
+                    hv_NumChannels.Dispose();
+                    HOperatorSet.CountChannels(ho_BackgroundImage, out hv_NumChannels);
+                    hv_ColorImage.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_ColorImage = new HTuple(hv_NumChannels.TupleEqual(
+                            3));
+                    }
+                    //Alt (32) => lower sensitivity
+                    hv_BAnd.Dispose();
+                    HOperatorSet.TupleRsh(hv_Button, 5, out hv_BAnd);
+                    if ((int)(hv_BAnd % 2) != 0)
+                    {
+                        hv_SensFactor.Dispose();
+                        hv_SensFactor = 0.1;
+                    }
+                    else
+                    {
+                        hv_SensFactor.Dispose();
+                        hv_SensFactor = 1.0;
+                    }
+                    hv_IsButtonTrans.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_IsButtonTrans = new HTuple(hv_MouseMapping.TupleSelect(
+                            0).TupleEqual(hv_Button)).TupleOr(new HTuple((32 + hv_MouseMapping.TupleSelect(
+                            0)).TupleEqual(hv_Button)));
+                    }
+                    hv_IsButtonRot.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_IsButtonRot = new HTuple(hv_MouseMapping.TupleSelect(
+                            1).TupleEqual(hv_Button)).TupleOr(new HTuple((32 + hv_MouseMapping.TupleSelect(
+                            1)).TupleEqual(hv_Button)));
+                    }
+                    hv_IsButtonDist.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_IsButtonDist = new HTuple(new HTuple(new HTuple(new HTuple(new HTuple(hv_MouseMapping.TupleSelect(
+                            2).TupleEqual(hv_Button)).TupleOr(new HTuple((32 + hv_MouseMapping.TupleSelect(
+                            2)).TupleEqual(hv_Button)))).TupleOr(new HTuple(hv_MouseMapping.TupleSelect(
+                            3).TupleEqual(hv_Button)))).TupleOr(new HTuple((32 + hv_MouseMapping.TupleSelect(
+                            3)).TupleEqual(hv_Button)))).TupleOr(new HTuple(hv_MouseMapping.TupleSelect(
+                            4).TupleEqual(hv_Button)))).TupleOr(new HTuple((32 + hv_MouseMapping.TupleSelect(
+                            4)).TupleEqual(hv_Button)));
+                    }
+                    if ((int)hv_IsButtonTrans != 0)
+                    {
+                        //Translate in XY-direction
+                        hv_MRow1.Dispose();
+                        hv_MRow1 = new HTuple(hv_Row_COPY_INP_TMP);
+                        hv_MCol1.Dispose();
+                        hv_MCol1 = new HTuple(hv_Column_COPY_INP_TMP);
+                        while ((int)hv_IsButtonTrans != 0)
+                        {
+                            try
+                            {
+                                hv_Row_COPY_INP_TMP.Dispose(); hv_Column_COPY_INP_TMP.Dispose(); hv_ButtonLoop.Dispose();
+                                HOperatorSet.GetMpositionSubPix(hv_WindowHandle, out hv_Row_COPY_INP_TMP,
+                                    out hv_Column_COPY_INP_TMP, out hv_ButtonLoop);
+                                hv_IsButtonTrans.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_IsButtonTrans = new HTuple(hv_ButtonLoop.TupleEqual(
+                                        hv_Button));
+                                }
+                                hv_MRow2.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_MRow2 = hv_MRow1 + (hv_Row_COPY_INP_TMP - hv_MRow1) * hv_SensFactor;
+                                }
+                                hv_MCol2.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_MCol2 = hv_MCol1 + (hv_Column_COPY_INP_TMP - hv_MCol1) * hv_SensFactor;
+                                }
+                                hv_PX.Dispose(); hv_PY.Dispose(); hv_PZ.Dispose(); hv_QX1.Dispose(); hv_QY1.Dispose(); hv_QZ1.Dispose();
+                                HOperatorSet.GetLineOfSight(hv_MRow1, hv_MCol1, hv_CamParam, out hv_PX,
+                                    out hv_PY, out hv_PZ, out hv_QX1, out hv_QY1, out hv_QZ1);
+                                hv_PX.Dispose(); hv_PY.Dispose(); hv_PZ.Dispose(); hv_QX2.Dispose(); hv_QY2.Dispose(); hv_QZ2.Dispose();
+                                HOperatorSet.GetLineOfSight(hv_MRow2, hv_MCol2, hv_CamParam, out hv_PX,
+                                    out hv_PY, out hv_PZ, out hv_QX2, out hv_QY2, out hv_QZ2);
+                                hv_Len.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_Len = (hv_QX1 * hv_QX1 + hv_QY1 * hv_QY1 + hv_QZ1 * hv_QZ1).TupleSqrt()
+                                        ;
+                                }
+                                hv_Dist.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_Dist = (hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                        0) * hv_TBCenter_COPY_INP_TMP.TupleSelect(0) + hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                        1) * hv_TBCenter_COPY_INP_TMP.TupleSelect(1) + hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                        2) * hv_TBCenter_COPY_INP_TMP.TupleSelect(2)).TupleSqrt();
+                                }
+                                hv_Translate.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_Translate = (hv_QX2 - hv_QX1).TupleConcat(
+                                        hv_QY2 - hv_QY1).TupleConcat(hv_QZ2 - hv_QZ1) * hv_Dist / hv_Len;
+                                }
+                                hv_PosesOut.Dispose();
+                                hv_PosesOut = new HTuple();
+                                if ((int)new HTuple(hv_NumModels.TupleLessEqual(hv_MaxNumModels)) != 0)
+                                {
+                                    HTuple end_val110 = hv_NumModels - 1;
+                                    HTuple step_val110 = 1;
+                                    for (hv_Index = 0; hv_Index.Continue(end_val110, step_val110); hv_Index = hv_Index.TupleAdd(step_val110))
+                                    {
+                                        hv_PoseIn.Dispose();
+                                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                        {
+                                            hv_PoseIn = hv_PosesIn_COPY_INP_TMP.TupleSelectRange(
+                                                hv_Index * 7, hv_Index * 7 + 6);
+                                        }
+                                        if ((int)hv_SelectedObjectOut.TupleSelect(hv_Index) != 0)
+                                        {
+                                            hv_HomMat3DIn.Dispose();
+                                            HOperatorSet.PoseToHomMat3d(hv_PoseIn, out hv_HomMat3DIn);
+                                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                            {
+                                                hv_HomMat3DOut.Dispose();
+                                                HOperatorSet.HomMat3dTranslate(hv_HomMat3DIn, hv_Translate.TupleSelect(
+                                                    0), hv_Translate.TupleSelect(1), hv_Translate.TupleSelect(
+                                                    2), out hv_HomMat3DOut);
+                                            }
+                                            hv_PoseOut.Dispose();
+                                            HOperatorSet.HomMat3dToPose(hv_HomMat3DOut, out hv_PoseOut);
+                                            HOperatorSet.SetScene3dInstancePose(hv_Scene3D, hv_Index, hv_PoseOut);
+                                        }
+                                        else
+                                        {
+                                            hv_PoseOut.Dispose();
+                                            hv_PoseOut = new HTuple(hv_PoseIn);
+                                        }
+                                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                        {
+                                            {
+                                                HTuple
+                                                  ExpTmpLocalVar_PosesOut = hv_PosesOut.TupleConcat(
+                                                    hv_PoseOut);
+                                                hv_PosesOut.Dispose();
+                                                hv_PosesOut = ExpTmpLocalVar_PosesOut;
+                                            }
+                                        }
+                                    }
+                                }
+                                else
+                                {
+                                    hv_Indices.Dispose();
+                                    HOperatorSet.TupleFind(hv_SelectedObjectOut, 1, out hv_Indices);
+                                    hv_PoseIn.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_PoseIn = hv_PosesIn_COPY_INP_TMP.TupleSelectRange(
+                                            hv_Indices.TupleSelect(0) * 7, hv_Indices.TupleSelect(0) * 7 + 6);
+                                    }
+                                    hv_HomMat3DIn.Dispose();
+                                    HOperatorSet.PoseToHomMat3d(hv_PoseIn, out hv_HomMat3DIn);
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_HomMat3DOut.Dispose();
+                                        HOperatorSet.HomMat3dTranslate(hv_HomMat3DIn, hv_Translate.TupleSelect(
+                                            0), hv_Translate.TupleSelect(1), hv_Translate.TupleSelect(2),
+                                            out hv_HomMat3DOut);
+                                    }
+                                    hv_PoseOut.Dispose();
+                                    HOperatorSet.HomMat3dToPose(hv_HomMat3DOut, out hv_PoseOut);
+                                    hv_Sequence.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_Sequence = HTuple.TupleGenSequence(
+                                            0, hv_NumModels * 7 - 1, 1);
+                                    }
+                                    hv_Mod.Dispose();
+                                    HOperatorSet.TupleMod(hv_Sequence, 7, out hv_Mod);
+                                    hv_SequenceReal.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_SequenceReal = HTuple.TupleGenSequence(
+                                            0, hv_NumModels - 1.0 / 7.0, 1.0 / 7.0);
+                                    }
+                                    hv_Sequence2Int.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_Sequence2Int = hv_SequenceReal.TupleInt()
+                                            ;
+                                    }
+                                    hv_Selected.Dispose();
+                                    HOperatorSet.TupleSelect(hv_SelectedObjectOut, hv_Sequence2Int, out hv_Selected);
+                                    hv_InvSelected.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_InvSelected = 1 - hv_Selected;
+                                    }
+                                    hv_PosesOut.Dispose();
+                                    HOperatorSet.TupleSelect(hv_PoseOut, hv_Mod, out hv_PosesOut);
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        {
+                                            HTuple
+                                              ExpTmpLocalVar_PosesOut = hv_PosesOut * hv_Selected + hv_PosesIn_COPY_INP_TMP * hv_InvSelected;
+                                            hv_PosesOut.Dispose();
+                                            hv_PosesOut = ExpTmpLocalVar_PosesOut;
+                                        }
+                                    }
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        HOperatorSet.SetScene3dInstancePose(hv_Scene3D, HTuple.TupleGenSequence(
+                                            0, hv_NumModels - 1, 1), hv_PosesOut);
+                                    }
+                                }
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    dump_image_output(ho_BackgroundImage, hv_WindowHandleBuffer, hv_Scene3D,
+                                        hv_AlphaOrig, hv_ObjectModel3DID, hv_GenParamName, hv_GenParamValue,
+                                        hv_CamParam, hv_PosesOut, hv_ColorImage, hv_Title, hv_Information,
+                                        hv_Labels, hv_VisualizeTB, "true", hv_TrackballCenterRow, hv_TrackballCenterCol,
+                                        hv_TBSize_COPY_INP_TMP, hv_SelectedObjectOut, new HTuple(hv_WindowCenteredRotationOut.TupleEqual(
+                                        1)), hv_TBCenter_COPY_INP_TMP);
+                                }
+                                ho_ImageDump.Dispose();
+                                HOperatorSet.DumpWindowImage(out ho_ImageDump, hv_WindowHandleBuffer);
+                                HDevWindowStack.SetActive(hv_WindowHandle);
+                                if (HDevWindowStack.IsOpen())
+                                {
+                                    HOperatorSet.DispObj(ho_ImageDump, HDevWindowStack.GetActive());
+                                }
+                                //
+                                hv_MRow1.Dispose();
+                                hv_MRow1 = new HTuple(hv_Row_COPY_INP_TMP);
+                                hv_MCol1.Dispose();
+                                hv_MCol1 = new HTuple(hv_Column_COPY_INP_TMP);
+                                hv_PosesIn_COPY_INP_TMP.Dispose();
+                                hv_PosesIn_COPY_INP_TMP = new HTuple(hv_PosesOut);
+                            }
+                            // catch (Exception) 
+                            catch (HalconException HDevExpDefaultException1)
+                            {
+                                HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                                //Keep waiting
+                            }
+                        }
+                    }
+                    else if ((int)hv_IsButtonDist != 0)
+                    {
+                        //Change the Z distance
+                        hv_MRow1.Dispose();
+                        hv_MRow1 = new HTuple(hv_Row_COPY_INP_TMP);
+                        while ((int)hv_IsButtonDist != 0)
+                        {
+                            try
+                            {
+                                hv_Row_COPY_INP_TMP.Dispose(); hv_Column_COPY_INP_TMP.Dispose(); hv_ButtonLoop.Dispose();
+                                HOperatorSet.GetMpositionSubPix(hv_WindowHandle, out hv_Row_COPY_INP_TMP,
+                                    out hv_Column_COPY_INP_TMP, out hv_ButtonLoop);
+                                hv_IsButtonDist.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_IsButtonDist = new HTuple(hv_ButtonLoop.TupleEqual(
+                                        hv_Button));
+                                }
+                                hv_MRow2.Dispose();
+                                hv_MRow2 = new HTuple(hv_Row_COPY_INP_TMP);
+                                hv_DRow.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_DRow = hv_MRow2 - hv_MRow1;
+                                }
+                                hv_Dist.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_Dist = (hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                        0) * hv_TBCenter_COPY_INP_TMP.TupleSelect(0) + hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                        1) * hv_TBCenter_COPY_INP_TMP.TupleSelect(1) + hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                        2) * hv_TBCenter_COPY_INP_TMP.TupleSelect(2)).TupleSqrt();
+                                }
+                                hv_TranslateZ.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_TranslateZ = -hv_Dist * hv_DRow * 0.003 * hv_SensFactor;
+                                }
+                                if (hv_TBCenter_COPY_INP_TMP == null)
+                                    hv_TBCenter_COPY_INP_TMP = new HTuple();
+                                hv_TBCenter_COPY_INP_TMP[2] = hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                    2) + hv_TranslateZ;
+                                hv_PosesOut.Dispose();
+                                hv_PosesOut = new HTuple();
+                                if ((int)new HTuple(hv_NumModels.TupleLessEqual(hv_MaxNumModels)) != 0)
+                                {
+                                    HTuple end_val164 = hv_NumModels - 1;
+                                    HTuple step_val164 = 1;
+                                    for (hv_Index = 0; hv_Index.Continue(end_val164, step_val164); hv_Index = hv_Index.TupleAdd(step_val164))
+                                    {
+                                        hv_PoseIn.Dispose();
+                                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                        {
+                                            hv_PoseIn = hv_PosesIn_COPY_INP_TMP.TupleSelectRange(
+                                                hv_Index * 7, hv_Index * 7 + 6);
+                                        }
+                                        if ((int)hv_SelectedObjectOut.TupleSelect(hv_Index) != 0)
+                                        {
+                                            //Transform the whole scene or selected object only
+                                            hv_HomMat3DIn.Dispose();
+                                            HOperatorSet.PoseToHomMat3d(hv_PoseIn, out hv_HomMat3DIn);
+                                            hv_HomMat3DOut.Dispose();
+                                            HOperatorSet.HomMat3dTranslate(hv_HomMat3DIn, 0, 0, hv_TranslateZ,
+                                                out hv_HomMat3DOut);
+                                            hv_PoseOut.Dispose();
+                                            HOperatorSet.HomMat3dToPose(hv_HomMat3DOut, out hv_PoseOut);
+                                            HOperatorSet.SetScene3dInstancePose(hv_Scene3D, hv_Index, hv_PoseOut);
+                                        }
+                                        else
+                                        {
+                                            hv_PoseOut.Dispose();
+                                            hv_PoseOut = new HTuple(hv_PoseIn);
+                                        }
+                                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                        {
+                                            {
+                                                HTuple
+                                                  ExpTmpLocalVar_PosesOut = hv_PosesOut.TupleConcat(
+                                                    hv_PoseOut);
+                                                hv_PosesOut.Dispose();
+                                                hv_PosesOut = ExpTmpLocalVar_PosesOut;
+                                            }
+                                        }
+                                    }
+                                }
+                                else
+                                {
+                                    hv_Indices.Dispose();
+                                    HOperatorSet.TupleFind(hv_SelectedObjectOut, 1, out hv_Indices);
+                                    hv_PoseIn.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_PoseIn = hv_PosesIn_COPY_INP_TMP.TupleSelectRange(
+                                            hv_Indices.TupleSelect(0) * 7, hv_Indices.TupleSelect(0) * 7 + 6);
+                                    }
+                                    hv_HomMat3DIn.Dispose();
+                                    HOperatorSet.PoseToHomMat3d(hv_PoseIn, out hv_HomMat3DIn);
+                                    hv_HomMat3DOut.Dispose();
+                                    HOperatorSet.HomMat3dTranslate(hv_HomMat3DIn, 0, 0, hv_TranslateZ,
+                                        out hv_HomMat3DOut);
+                                    hv_PoseOut.Dispose();
+                                    HOperatorSet.HomMat3dToPose(hv_HomMat3DOut, out hv_PoseOut);
+                                    hv_Sequence.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_Sequence = HTuple.TupleGenSequence(
+                                            0, hv_NumModels * 7 - 1, 1);
+                                    }
+                                    hv_Mod.Dispose();
+                                    HOperatorSet.TupleMod(hv_Sequence, 7, out hv_Mod);
+                                    hv_SequenceReal.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_SequenceReal = HTuple.TupleGenSequence(
+                                            0, hv_NumModels - 1.0 / 7.0, 1.0 / 7.0);
+                                    }
+                                    hv_Sequence2Int.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_Sequence2Int = hv_SequenceReal.TupleInt()
+                                            ;
+                                    }
+                                    hv_Selected.Dispose();
+                                    HOperatorSet.TupleSelect(hv_SelectedObjectOut, hv_Sequence2Int, out hv_Selected);
+                                    hv_InvSelected.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_InvSelected = 1 - hv_Selected;
+                                    }
+                                    hv_PosesOut.Dispose();
+                                    HOperatorSet.TupleSelect(hv_PoseOut, hv_Mod, out hv_PosesOut);
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        {
+                                            HTuple
+                                              ExpTmpLocalVar_PosesOut = hv_PosesOut * hv_Selected + hv_PosesIn_COPY_INP_TMP * hv_InvSelected;
+                                            hv_PosesOut.Dispose();
+                                            hv_PosesOut = ExpTmpLocalVar_PosesOut;
+                                        }
+                                    }
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        HOperatorSet.SetScene3dInstancePose(hv_Scene3D, HTuple.TupleGenSequence(
+                                            0, hv_NumModels - 1, 1), hv_PosesOut);
+                                    }
+                                }
+                                dump_image_output(ho_BackgroundImage, hv_WindowHandleBuffer, hv_Scene3D,
+                                    hv_AlphaOrig, hv_ObjectModel3DID, hv_GenParamName, hv_GenParamValue,
+                                    hv_CamParam, hv_PosesOut, hv_ColorImage, hv_Title, hv_Information,
+                                    hv_Labels, hv_VisualizeTB, "true", hv_TrackballCenterRow, hv_TrackballCenterCol,
+                                    hv_TBSize_COPY_INP_TMP, hv_SelectedObjectOut, hv_WindowCenteredRotationOut,
+                                    hv_TBCenter_COPY_INP_TMP);
+                                ho_ImageDump.Dispose();
+                                HOperatorSet.DumpWindowImage(out ho_ImageDump, hv_WindowHandleBuffer);
+                                HDevWindowStack.SetActive(hv_WindowHandle);
+                                if (HDevWindowStack.IsOpen())
+                                {
+                                    HOperatorSet.DispObj(ho_ImageDump, HDevWindowStack.GetActive());
+                                }
+                                //
+                                hv_MRow1.Dispose();
+                                hv_MRow1 = new HTuple(hv_Row_COPY_INP_TMP);
+                                hv_PosesIn_COPY_INP_TMP.Dispose();
+                                hv_PosesIn_COPY_INP_TMP = new HTuple(hv_PosesOut);
+                            }
+                            // catch (Exception) 
+                            catch (HalconException HDevExpDefaultException1)
+                            {
+                                HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                                //Keep waiting
+                            }
+                        }
+                    }
+                    else if ((int)hv_IsButtonRot != 0)
+                    {
+                        //Rotate the object
+                        hv_MRow1.Dispose();
+                        hv_MRow1 = new HTuple(hv_Row_COPY_INP_TMP);
+                        hv_MCol1.Dispose();
+                        hv_MCol1 = new HTuple(hv_Column_COPY_INP_TMP);
+                        while ((int)hv_IsButtonRot != 0)
+                        {
+                            try
+                            {
+                                hv_Row_COPY_INP_TMP.Dispose(); hv_Column_COPY_INP_TMP.Dispose(); hv_ButtonLoop.Dispose();
+                                HOperatorSet.GetMpositionSubPix(hv_WindowHandle, out hv_Row_COPY_INP_TMP,
+                                    out hv_Column_COPY_INP_TMP, out hv_ButtonLoop);
+                                hv_IsButtonRot.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_IsButtonRot = new HTuple(hv_ButtonLoop.TupleEqual(
+                                        hv_Button));
+                                }
+                                hv_MRow2.Dispose();
+                                hv_MRow2 = new HTuple(hv_Row_COPY_INP_TMP);
+                                hv_MCol2.Dispose();
+                                hv_MCol2 = new HTuple(hv_Column_COPY_INP_TMP);
+                                //Transform the pixel coordinates to relative image coordinates
+                                hv_MX1.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_MX1 = (hv_TrackballCenterCol - hv_MCol1) / (0.5 * hv_MinImageSize);
+                                }
+                                hv_MY1.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_MY1 = (hv_TrackballCenterRow - hv_MRow1) / (0.5 * hv_MinImageSize);
+                                }
+                                hv_MX2.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_MX2 = (hv_TrackballCenterCol - hv_MCol2) / (0.5 * hv_MinImageSize);
+                                }
+                                hv_MY2.Dispose();
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_MY2 = (hv_TrackballCenterRow - hv_MRow2) / (0.5 * hv_MinImageSize);
+                                }
+                                //Compute the quaternion rotation that corresponds to the mouse
+                                //movement
+                                hv_RelQuaternion.Dispose();
+                                trackball(hv_MX1, hv_MY1, hv_MX2, hv_MY2, hv_VirtualTrackball, hv_TrackballSize,
+                                    hv_SensFactor, out hv_RelQuaternion);
+                                //Transform the quaternion to a rotation matrix
+                                hv_HomMat3DRotRel.Dispose();
+                                HOperatorSet.QuatToHomMat3d(hv_RelQuaternion, out hv_HomMat3DRotRel);
+                                hv_PosesOut.Dispose();
+                                hv_PosesOut = new HTuple();
+                                if ((int)new HTuple(hv_NumModels.TupleLessEqual(hv_MaxNumModels)) != 0)
+                                {
+                                    HTuple end_val226 = hv_NumModels - 1;
+                                    HTuple step_val226 = 1;
+                                    for (hv_Index = 0; hv_Index.Continue(end_val226, step_val226); hv_Index = hv_Index.TupleAdd(step_val226))
+                                    {
+                                        hv_PoseIn.Dispose();
+                                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                        {
+                                            hv_PoseIn = hv_PosesIn_COPY_INP_TMP.TupleSelectRange(
+                                                hv_Index * 7, hv_Index * 7 + 6);
+                                        }
+                                        if ((int)hv_SelectedObjectOut.TupleSelect(hv_Index) != 0)
+                                        {
+                                            //Transform the whole scene or selected object only
+                                            hv_HomMat3DIn.Dispose();
+                                            HOperatorSet.PoseToHomMat3d(hv_PoseIn, out hv_HomMat3DIn);
+                                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                            {
+                                                HTuple ExpTmpOutVar_0;
+                                                HOperatorSet.HomMat3dTranslate(hv_HomMat3DIn, -hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                                    0), -hv_TBCenter_COPY_INP_TMP.TupleSelect(1), -hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                                    2), out ExpTmpOutVar_0);
+                                                hv_HomMat3DIn.Dispose();
+                                                hv_HomMat3DIn = ExpTmpOutVar_0;
+                                            }
+                                            {
+                                                HTuple ExpTmpOutVar_0;
+                                                HOperatorSet.HomMat3dCompose(hv_HomMat3DRotRel, hv_HomMat3DIn,
+                                                    out ExpTmpOutVar_0);
+                                                hv_HomMat3DIn.Dispose();
+                                                hv_HomMat3DIn = ExpTmpOutVar_0;
+                                            }
+                                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                            {
+                                                hv_HomMat3DOut.Dispose();
+                                                HOperatorSet.HomMat3dTranslate(hv_HomMat3DIn, hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                                    0), hv_TBCenter_COPY_INP_TMP.TupleSelect(1), hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                                    2), out hv_HomMat3DOut);
+                                            }
+                                            hv_PoseOut.Dispose();
+                                            HOperatorSet.HomMat3dToPose(hv_HomMat3DOut, out hv_PoseOut);
+                                            HOperatorSet.SetScene3dInstancePose(hv_Scene3D, hv_Index, hv_PoseOut);
+                                        }
+                                        else
+                                        {
+                                            hv_PoseOut.Dispose();
+                                            hv_PoseOut = new HTuple(hv_PoseIn);
+                                        }
+                                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                        {
+                                            {
+                                                HTuple
+                                                  ExpTmpLocalVar_PosesOut = hv_PosesOut.TupleConcat(
+                                                    hv_PoseOut);
+                                                hv_PosesOut.Dispose();
+                                                hv_PosesOut = ExpTmpLocalVar_PosesOut;
+                                            }
+                                        }
+                                    }
+                                }
+                                else
+                                {
+                                    hv_Indices.Dispose();
+                                    HOperatorSet.TupleFind(hv_SelectedObjectOut, 1, out hv_Indices);
+                                    hv_PoseIn.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_PoseIn = hv_PosesIn_COPY_INP_TMP.TupleSelectRange(
+                                            hv_Indices.TupleSelect(0) * 7, hv_Indices.TupleSelect(0) * 7 + 6);
+                                    }
+                                    hv_HomMat3DIn.Dispose();
+                                    HOperatorSet.PoseToHomMat3d(hv_PoseIn, out hv_HomMat3DIn);
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_HomMat3DInTmp1.Dispose();
+                                        HOperatorSet.HomMat3dTranslate(hv_HomMat3DIn, -hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                            0), -hv_TBCenter_COPY_INP_TMP.TupleSelect(1), -hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                            2), out hv_HomMat3DInTmp1);
+                                    }
+                                    hv_HomMat3DInTmp.Dispose();
+                                    HOperatorSet.HomMat3dCompose(hv_HomMat3DRotRel, hv_HomMat3DInTmp1,
+                                        out hv_HomMat3DInTmp);
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_HomMat3DOut.Dispose();
+                                        HOperatorSet.HomMat3dTranslate(hv_HomMat3DInTmp, hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                            0), hv_TBCenter_COPY_INP_TMP.TupleSelect(1), hv_TBCenter_COPY_INP_TMP.TupleSelect(
+                                            2), out hv_HomMat3DOut);
+                                    }
+                                    hv_PoseOut.Dispose();
+                                    HOperatorSet.HomMat3dToPose(hv_HomMat3DOut, out hv_PoseOut);
+                                    hv_Sequence.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_Sequence = HTuple.TupleGenSequence(
+                                            0, hv_NumModels * 7 - 1, 1);
+                                    }
+                                    hv_Mod.Dispose();
+                                    HOperatorSet.TupleMod(hv_Sequence, 7, out hv_Mod);
+                                    hv_SequenceReal.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_SequenceReal = HTuple.TupleGenSequence(
+                                            0, hv_NumModels - 1.0 / 7.0, 1.0 / 7.0);
+                                    }
+                                    hv_Sequence2Int.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_Sequence2Int = hv_SequenceReal.TupleInt()
+                                            ;
+                                    }
+                                    hv_Selected.Dispose();
+                                    HOperatorSet.TupleSelect(hv_SelectedObjectOut, hv_Sequence2Int, out hv_Selected);
+                                    hv_InvSelected.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_InvSelected = 1 - hv_Selected;
+                                    }
+                                    hv_PosesOut.Dispose();
+                                    HOperatorSet.TupleSelect(hv_PoseOut, hv_Mod, out hv_PosesOut);
+                                    hv_PosesOut2.Dispose();
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_PosesOut2 = hv_PosesOut * hv_Selected + hv_PosesIn_COPY_INP_TMP * hv_InvSelected;
+                                    }
+                                    hv_PosesOut.Dispose();
+                                    hv_PosesOut = new HTuple(hv_PosesOut2);
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        HOperatorSet.SetScene3dInstancePose(hv_Scene3D, HTuple.TupleGenSequence(
+                                            0, hv_NumModels - 1, 1), hv_PosesOut);
+                                    }
+                                }
+                                dump_image_output(ho_BackgroundImage, hv_WindowHandleBuffer, hv_Scene3D,
+                                    hv_AlphaOrig, hv_ObjectModel3DID, hv_GenParamName, hv_GenParamValue,
+                                    hv_CamParam, hv_PosesOut, hv_ColorImage, hv_Title, hv_Information,
+                                    hv_Labels, hv_VisualizeTB, "true", hv_TrackballCenterRow, hv_TrackballCenterCol,
+                                    hv_TBSize_COPY_INP_TMP, hv_SelectedObjectOut, hv_WindowCenteredRotationOut,
+                                    hv_TBCenter_COPY_INP_TMP);
+                                ho_ImageDump.Dispose();
+                                HOperatorSet.DumpWindowImage(out ho_ImageDump, hv_WindowHandleBuffer);
+                                HDevWindowStack.SetActive(hv_WindowHandle);
+                                if (HDevWindowStack.IsOpen())
+                                {
+                                    HOperatorSet.DispObj(ho_ImageDump, HDevWindowStack.GetActive());
+                                }
+                                //
+                                hv_MRow1.Dispose();
+                                hv_MRow1 = new HTuple(hv_Row_COPY_INP_TMP);
+                                hv_MCol1.Dispose();
+                                hv_MCol1 = new HTuple(hv_Column_COPY_INP_TMP);
+                                hv_PosesIn_COPY_INP_TMP.Dispose();
+                                hv_PosesIn_COPY_INP_TMP = new HTuple(hv_PosesOut);
+                            }
+                            // catch (Exception) 
+                            catch (HalconException HDevExpDefaultException1)
+                            {
+                                HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                                //Keep waiting
+                            }
+                        }
+                    }
+                    hv_PosesOut.Dispose();
+                    hv_PosesOut = new HTuple(hv_PosesIn_COPY_INP_TMP);
+                }
+                ho_ImageDump.Dispose();
+
+                hv_Column_COPY_INP_TMP.Dispose();
+                hv_PosesIn_COPY_INP_TMP.Dispose();
+                hv_Row_COPY_INP_TMP.Dispose();
+                hv_TBCenter_COPY_INP_TMP.Dispose();
+                hv_TBSize_COPY_INP_TMP.Dispose();
+                hv_VisualizeTB.Dispose();
+                hv_InvLog2.Dispose();
+                hv_Seconds.Dispose();
+                hv_ModelIndex.Dispose();
+                hv_Exception1.Dispose();
+                hv_HomMat3DIdentity.Dispose();
+                hv_NumModels.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_MinImageSize.Dispose();
+                hv_TrackballRadiusPixel.Dispose();
+                hv_TrackballCenterRow.Dispose();
+                hv_TrackballCenterCol.Dispose();
+                hv_NumChannels.Dispose();
+                hv_ColorImage.Dispose();
+                hv_BAnd.Dispose();
+                hv_SensFactor.Dispose();
+                hv_IsButtonTrans.Dispose();
+                hv_IsButtonRot.Dispose();
+                hv_IsButtonDist.Dispose();
+                hv_MRow1.Dispose();
+                hv_MCol1.Dispose();
+                hv_ButtonLoop.Dispose();
+                hv_MRow2.Dispose();
+                hv_MCol2.Dispose();
+                hv_PX.Dispose();
+                hv_PY.Dispose();
+                hv_PZ.Dispose();
+                hv_QX1.Dispose();
+                hv_QY1.Dispose();
+                hv_QZ1.Dispose();
+                hv_QX2.Dispose();
+                hv_QY2.Dispose();
+                hv_QZ2.Dispose();
+                hv_Len.Dispose();
+                hv_Dist.Dispose();
+                hv_Translate.Dispose();
+                hv_Index.Dispose();
+                hv_PoseIn.Dispose();
+                hv_HomMat3DIn.Dispose();
+                hv_HomMat3DOut.Dispose();
+                hv_PoseOut.Dispose();
+                hv_Indices.Dispose();
+                hv_Sequence.Dispose();
+                hv_Mod.Dispose();
+                hv_SequenceReal.Dispose();
+                hv_Sequence2Int.Dispose();
+                hv_Selected.Dispose();
+                hv_InvSelected.Dispose();
+                hv_Exception.Dispose();
+                hv_DRow.Dispose();
+                hv_TranslateZ.Dispose();
+                hv_MX1.Dispose();
+                hv_MY1.Dispose();
+                hv_MX2.Dispose();
+                hv_MY2.Dispose();
+                hv_RelQuaternion.Dispose();
+                hv_HomMat3DRotRel.Dispose();
+                hv_HomMat3DInTmp1.Dispose();
+                hv_HomMat3DInTmp.Dispose();
+                hv_PosesOut2.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_ImageDump.Dispose();
+
+                hv_Column_COPY_INP_TMP.Dispose();
+                hv_PosesIn_COPY_INP_TMP.Dispose();
+                hv_Row_COPY_INP_TMP.Dispose();
+                hv_TBCenter_COPY_INP_TMP.Dispose();
+                hv_TBSize_COPY_INP_TMP.Dispose();
+                hv_VisualizeTB.Dispose();
+                hv_InvLog2.Dispose();
+                hv_Seconds.Dispose();
+                hv_ModelIndex.Dispose();
+                hv_Exception1.Dispose();
+                hv_HomMat3DIdentity.Dispose();
+                hv_NumModels.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_MinImageSize.Dispose();
+                hv_TrackballRadiusPixel.Dispose();
+                hv_TrackballCenterRow.Dispose();
+                hv_TrackballCenterCol.Dispose();
+                hv_NumChannels.Dispose();
+                hv_ColorImage.Dispose();
+                hv_BAnd.Dispose();
+                hv_SensFactor.Dispose();
+                hv_IsButtonTrans.Dispose();
+                hv_IsButtonRot.Dispose();
+                hv_IsButtonDist.Dispose();
+                hv_MRow1.Dispose();
+                hv_MCol1.Dispose();
+                hv_ButtonLoop.Dispose();
+                hv_MRow2.Dispose();
+                hv_MCol2.Dispose();
+                hv_PX.Dispose();
+                hv_PY.Dispose();
+                hv_PZ.Dispose();
+                hv_QX1.Dispose();
+                hv_QY1.Dispose();
+                hv_QZ1.Dispose();
+                hv_QX2.Dispose();
+                hv_QY2.Dispose();
+                hv_QZ2.Dispose();
+                hv_Len.Dispose();
+                hv_Dist.Dispose();
+                hv_Translate.Dispose();
+                hv_Index.Dispose();
+                hv_PoseIn.Dispose();
+                hv_HomMat3DIn.Dispose();
+                hv_HomMat3DOut.Dispose();
+                hv_PoseOut.Dispose();
+                hv_Indices.Dispose();
+                hv_Sequence.Dispose();
+                hv_Mod.Dispose();
+                hv_SequenceReal.Dispose();
+                hv_Sequence2Int.Dispose();
+                hv_Selected.Dispose();
+                hv_InvSelected.Dispose();
+                hv_Exception.Dispose();
+                hv_DRow.Dispose();
+                hv_TranslateZ.Dispose();
+                hv_MX1.Dispose();
+                hv_MY1.Dispose();
+                hv_MX2.Dispose();
+                hv_MY2.Dispose();
+                hv_RelQuaternion.Dispose();
+                hv_HomMat3DRotRel.Dispose();
+                hv_HomMat3DInTmp1.Dispose();
+                hv_HomMat3DInTmp.Dispose();
+                hv_PosesOut2.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Parameters
+        public static void color_string_to_rgb(HTuple hv_Color, out HTuple hv_RGB)
+        {
+
+
+
+            // Local iconic variables 
+
+            HObject ho_Rectangle, ho_Image;
+
+            // Local control variables 
+
+            HTuple hv_WindowHandleBuffer = new HTuple();
+            HTuple hv_Exception = new HTuple();
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_Rectangle);
+            HOperatorSet.GenEmptyObj(out ho_Image);
+            hv_RGB = new HTuple();
+            try
+            {
+                hv_WindowHandleBuffer.Dispose();
+                HOperatorSet.OpenWindow(0, 0, 1, 1, 0, "buffer", "", out hv_WindowHandleBuffer);
+                HOperatorSet.SetPart(hv_WindowHandleBuffer, 0, 0, -1, -1);
+                ho_Rectangle.Dispose();
+                HOperatorSet.GenRectangle1(out ho_Rectangle, 0, 0, 0, 0);
+                try
+                {
+                    HOperatorSet.SetColor(hv_WindowHandleBuffer, hv_Color);
+                }
+                // catch (Exception) 
+                catch (HalconException HDevExpDefaultException1)
+                {
+                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                    hv_Exception.Dispose();
+                    hv_Exception = "Wrong value of control parameter Color (must be a valid color string)";
+                    throw new HalconException(hv_Exception);
+                }
+                HOperatorSet.DispObj(ho_Rectangle, hv_WindowHandleBuffer);
+                ho_Image.Dispose();
+                HOperatorSet.DumpWindowImage(out ho_Image, hv_WindowHandleBuffer);
+                HOperatorSet.CloseWindow(hv_WindowHandleBuffer);
+                hv_RGB.Dispose();
+                HOperatorSet.GetGrayval(ho_Image, 0, 0, out hv_RGB);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_RGB = hv_RGB +
+                            new HTuple(0).TupleConcat(0).TupleConcat(0);
+                        hv_RGB.Dispose();
+                        hv_RGB = ExpTmpLocalVar_RGB;
+                    }
+                }
+                ho_Rectangle.Dispose();
+                ho_Image.Dispose();
+
+                hv_WindowHandleBuffer.Dispose();
+                hv_Exception.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_Rectangle.Dispose();
+                ho_Image.Dispose();
+
+                hv_WindowHandleBuffer.Dispose();
+                hv_Exception.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Output
+        // Short Description: Determine the optimum distance of the object to obtain a reasonable visualization 
+        public static void determine_optimum_pose_distance(HTuple hv_ObjectModel3DID, HTuple hv_CamParam,
+            HTuple hv_ImageCoverage, HTuple hv_PoseIn, out HTuple hv_PoseOut)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_Rows = new HTuple(), hv_Cols = new HTuple();
+            HTuple hv_MinMinZ = new HTuple(), hv_BB = new HTuple();
+            HTuple hv_Index = new HTuple(), hv_CurrBB = new HTuple();
+            HTuple hv_Exception = new HTuple(), hv_Seq = new HTuple();
+            HTuple hv_DXMax = new HTuple(), hv_DYMax = new HTuple();
+            HTuple hv_DZMax = new HTuple(), hv_Diameter = new HTuple();
+            HTuple hv_ZAdd = new HTuple(), hv_BBX0 = new HTuple();
+            HTuple hv_BBX1 = new HTuple(), hv_BBY0 = new HTuple();
+            HTuple hv_BBY1 = new HTuple(), hv_BBZ0 = new HTuple();
+            HTuple hv_BBZ1 = new HTuple(), hv_X = new HTuple(), hv_Y = new HTuple();
+            HTuple hv_Z = new HTuple(), hv_HomMat3DIn = new HTuple();
+            HTuple hv_QX_In = new HTuple(), hv_QY_In = new HTuple();
+            HTuple hv_QZ_In = new HTuple(), hv_PoseInter = new HTuple();
+            HTuple hv_HomMat3D = new HTuple(), hv_QX = new HTuple();
+            HTuple hv_QY = new HTuple(), hv_QZ = new HTuple(), hv_Cx = new HTuple();
+            HTuple hv_Cy = new HTuple(), hv_DR = new HTuple(), hv_DC = new HTuple();
+            HTuple hv_MaxDist = new HTuple(), hv_HomMat3DRotate = new HTuple();
+            HTuple hv_ImageWidth = new HTuple(), hv_ImageHeight = new HTuple();
+            HTuple hv_MinImageSize = new HTuple(), hv_Zs = new HTuple();
+            HTuple hv_ZDiff = new HTuple(), hv_ScaleZ = new HTuple();
+            HTuple hv_ZNew = new HTuple();
+            // Initialize local and output iconic variables 
+            hv_PoseOut = new HTuple();
+            try
+            {
+                //Determine the optimum distance of the object to obtain
+                //a reasonable visualization
+                //
+                hv_Rows.Dispose();
+                hv_Rows = new HTuple();
+                hv_Cols.Dispose();
+                hv_Cols = new HTuple();
+                hv_MinMinZ.Dispose();
+                hv_MinMinZ = 1e30;
+                hv_BB.Dispose();
+                hv_BB = new HTuple();
+                for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_ObjectModel3DID.TupleLength()
+                    ) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    try
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_CurrBB.Dispose();
+                            HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID.TupleSelect(hv_Index),
+                                "bounding_box1", out hv_CurrBB);
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_BB = hv_BB.TupleConcat(
+                                    hv_CurrBB);
+                                hv_BB.Dispose();
+                                hv_BB = ExpTmpLocalVar_BB;
+                            }
+                        }
+                    }
+                    // catch (Exception) 
+                    catch (HalconException HDevExpDefaultException1)
+                    {
+                        HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                        //3D object model is empty / has no bounding box -> ignore it
+                    }
+                }
+                if ((int)new HTuple(hv_BB.TupleAbs().TupleConcat(0).TupleSum().TupleEqual(
+                    0.0)) != 0)
+                {
+                    hv_BB.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_BB = new HTuple();
+                        hv_BB = hv_BB.TupleConcat(-new HTuple(HTuple.TupleRand(
+                            3) * 1e-20).TupleAbs());
+                        hv_BB = hv_BB.TupleConcat(new HTuple(HTuple.TupleRand(
+                            3) * 1e-20).TupleAbs());
+                    }
+                }
+                //Calculate diameter over all objects to be visualized
+                hv_Seq.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Seq = HTuple.TupleGenSequence(
+                        0, new HTuple(hv_BB.TupleLength()) - 1, 6);
+                }
+                hv_DXMax.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_DXMax = hv_BB.TupleSelect(
+                        hv_Seq + 3).TupleMax() - hv_BB.TupleSelect(hv_Seq).TupleMin();
+                }
+                hv_DYMax.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_DYMax = hv_BB.TupleSelect(
+                        hv_Seq + 4).TupleMax() - hv_BB.TupleSelect(hv_Seq + 1).TupleMin();
+                }
+                hv_DZMax.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_DZMax = hv_BB.TupleSelect(
+                        hv_Seq + 5).TupleMax() - hv_BB.TupleSelect(hv_Seq + 2).TupleMin();
+                }
+                hv_Diameter.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Diameter = (hv_DXMax * hv_DXMax + hv_DYMax * hv_DYMax + hv_DZMax * hv_DZMax).TupleSqrt()
+                        ;
+                }
+                //Allow the visualization of single points or extremely small objects
+                hv_ZAdd.Dispose();
+                hv_ZAdd = 0.0;
+                if ((int)new HTuple(hv_Diameter.TupleMax().TupleLess(1e-10)) != 0)
+                {
+                    hv_ZAdd.Dispose();
+                    hv_ZAdd = 0.01;
+                }
+                //Set extremely small diameters to 1e-10 to avoid CZ == 0.0, which would lead
+                //to projection errors
+                if ((int)new HTuple(hv_Diameter.TupleMin().TupleLess(1e-10)) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Diameter = hv_Diameter - ((hv_Diameter - 1e-10).TupleSgn()
+                                 - 1).TupleSgn() * 1e-10;
+                            hv_Diameter.Dispose();
+                            hv_Diameter = ExpTmpLocalVar_Diameter;
+                        }
+                    }
+                }
+                //Move all points in front of the camera
+                hv_BBX0.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_BBX0 = hv_BB.TupleSelect(
+                        hv_Seq + 0);
+                }
+                hv_BBX1.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_BBX1 = hv_BB.TupleSelect(
+                        hv_Seq + 3);
+                }
+                hv_BBY0.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_BBY0 = hv_BB.TupleSelect(
+                        hv_Seq + 1);
+                }
+                hv_BBY1.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_BBY1 = hv_BB.TupleSelect(
+                        hv_Seq + 4);
+                }
+                hv_BBZ0.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_BBZ0 = hv_BB.TupleSelect(
+                        hv_Seq + 2);
+                }
+                hv_BBZ1.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_BBZ1 = hv_BB.TupleSelect(
+                        hv_Seq + 5);
+                }
+                hv_X.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_X = new HTuple();
+                    hv_X = hv_X.TupleConcat(hv_BBX0, hv_BBX0, hv_BBX0, hv_BBX0, hv_BBX1, hv_BBX1, hv_BBX1, hv_BBX1);
+                }
+                hv_Y.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Y = new HTuple();
+                    hv_Y = hv_Y.TupleConcat(hv_BBY0, hv_BBY0, hv_BBY1, hv_BBY1, hv_BBY0, hv_BBY0, hv_BBY1, hv_BBY1);
+                }
+                hv_Z.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Z = new HTuple();
+                    hv_Z = hv_Z.TupleConcat(hv_BBZ0, hv_BBZ1, hv_BBZ0, hv_BBZ1, hv_BBZ0, hv_BBZ1, hv_BBZ0, hv_BBZ1);
+                }
+                hv_HomMat3DIn.Dispose();
+                HOperatorSet.PoseToHomMat3d(hv_PoseIn, out hv_HomMat3DIn);
+                hv_QX_In.Dispose(); hv_QY_In.Dispose(); hv_QZ_In.Dispose();
+                HOperatorSet.AffineTransPoint3d(hv_HomMat3DIn, hv_X, hv_Y, hv_Z, out hv_QX_In,
+                    out hv_QY_In, out hv_QZ_In);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_PoseInter.Dispose();
+                    HOperatorSet.PoseCompose(new HTuple(0).TupleConcat(0).TupleConcat(-hv_QZ_In.TupleMin()
+                         + 2 * hv_Diameter.TupleMax()).TupleConcat(new HTuple(0).TupleConcat(
+                        0).TupleConcat(0).TupleConcat(0)), hv_PoseIn, out hv_PoseInter);
+                }
+                hv_HomMat3D.Dispose();
+                HOperatorSet.PoseToHomMat3d(hv_PoseInter, out hv_HomMat3D);
+                //Determine the maximum extension of the projection
+                hv_QX.Dispose(); hv_QY.Dispose(); hv_QZ.Dispose();
+                HOperatorSet.AffineTransPoint3d(hv_HomMat3D, hv_X, hv_Y, hv_Z, out hv_QX, out hv_QY,
+                    out hv_QZ);
+                hv_Rows.Dispose(); hv_Cols.Dispose();
+                HOperatorSet.Project3dPoint(hv_QX, hv_QY, hv_QZ, hv_CamParam, out hv_Rows,
+                    out hv_Cols);
+                hv_MinMinZ.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_MinMinZ = hv_QZ.TupleMin()
+                        ;
+                }
+                hv_Cx.Dispose();
+                get_cam_par_data(hv_CamParam, "cx", out hv_Cx);
+                hv_Cy.Dispose();
+                get_cam_par_data(hv_CamParam, "cy", out hv_Cy);
+                hv_DR.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_DR = hv_Rows - hv_Cy;
+                }
+                hv_DC.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_DC = hv_Cols - hv_Cx;
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_DR = hv_DR.TupleMax()
+                             - hv_DR.TupleMin();
+                        hv_DR.Dispose();
+                        hv_DR = ExpTmpLocalVar_DR;
+                    }
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_DC = hv_DC.TupleMax()
+                             - hv_DC.TupleMin();
+                        hv_DC.Dispose();
+                        hv_DC = ExpTmpLocalVar_DC;
+                    }
+                }
+                hv_MaxDist.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_MaxDist = (hv_DR * hv_DR + hv_DC * hv_DC).TupleSqrt()
+                        ;
+                }
+                //
+                if ((int)new HTuple(hv_MaxDist.TupleLess(1e-10)) != 0)
+                {
+                    //If the object has no extension in the above projection (looking along
+                    //a line), we determine the extension of the object in a rotated view
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_HomMat3DRotate.Dispose();
+                        HOperatorSet.HomMat3dRotateLocal(hv_HomMat3D, new HTuple(90).TupleRad()
+                            , "x", out hv_HomMat3DRotate);
+                    }
+                    hv_QX.Dispose(); hv_QY.Dispose(); hv_QZ.Dispose();
+                    HOperatorSet.AffineTransPoint3d(hv_HomMat3DRotate, hv_X, hv_Y, hv_Z, out hv_QX,
+                        out hv_QY, out hv_QZ);
+                    hv_Rows.Dispose(); hv_Cols.Dispose();
+                    HOperatorSet.Project3dPoint(hv_QX, hv_QY, hv_QZ, hv_CamParam, out hv_Rows,
+                        out hv_Cols);
+                    hv_DR.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_DR = hv_Rows - hv_Cy;
+                    }
+                    hv_DC.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_DC = hv_Cols - hv_Cx;
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_DR = hv_DR.TupleMax()
+                                 - hv_DR.TupleMin();
+                            hv_DR.Dispose();
+                            hv_DR = ExpTmpLocalVar_DR;
+                        }
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_DC = hv_DC.TupleMax()
+                                 - hv_DC.TupleMin();
+                            hv_DC.Dispose();
+                            hv_DC = ExpTmpLocalVar_DC;
+                        }
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_MaxDist = hv_MaxDist.TupleConcat(
+                                (hv_DR * hv_DR + hv_DC * hv_DC).TupleSqrt()).TupleMax();
+                            hv_MaxDist.Dispose();
+                            hv_MaxDist = ExpTmpLocalVar_MaxDist;
+                        }
+                    }
+                }
+                //
+                hv_ImageWidth.Dispose();
+                get_cam_par_data(hv_CamParam, "image_width", out hv_ImageWidth);
+                hv_ImageHeight.Dispose();
+                get_cam_par_data(hv_CamParam, "image_height", out hv_ImageHeight);
+                hv_MinImageSize.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_MinImageSize = hv_ImageWidth.TupleConcat(
+                        hv_ImageHeight).TupleMin();
+                }
+                //
+                hv_Z.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Z = hv_PoseInter.TupleSelect(
+                        2);
+                }
+                hv_Zs.Dispose();
+                hv_Zs = new HTuple(hv_MinMinZ);
+                hv_ZDiff.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_ZDiff = hv_Z - hv_Zs;
+                }
+                hv_ScaleZ.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_ScaleZ = hv_MaxDist / (0.5 * hv_MinImageSize * hv_ImageCoverage * 2.0);
+                }
+                hv_ZNew.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_ZNew = hv_ScaleZ * hv_Zs + hv_ZDiff + hv_ZAdd;
+                }
+                hv_PoseOut.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_PoseOut = hv_PoseInter.TupleReplace(
+                        2, hv_ZNew);
+                }
+                //
+
+                hv_Rows.Dispose();
+                hv_Cols.Dispose();
+                hv_MinMinZ.Dispose();
+                hv_BB.Dispose();
+                hv_Index.Dispose();
+                hv_CurrBB.Dispose();
+                hv_Exception.Dispose();
+                hv_Seq.Dispose();
+                hv_DXMax.Dispose();
+                hv_DYMax.Dispose();
+                hv_DZMax.Dispose();
+                hv_Diameter.Dispose();
+                hv_ZAdd.Dispose();
+                hv_BBX0.Dispose();
+                hv_BBX1.Dispose();
+                hv_BBY0.Dispose();
+                hv_BBY1.Dispose();
+                hv_BBZ0.Dispose();
+                hv_BBZ1.Dispose();
+                hv_X.Dispose();
+                hv_Y.Dispose();
+                hv_Z.Dispose();
+                hv_HomMat3DIn.Dispose();
+                hv_QX_In.Dispose();
+                hv_QY_In.Dispose();
+                hv_QZ_In.Dispose();
+                hv_PoseInter.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_QX.Dispose();
+                hv_QY.Dispose();
+                hv_QZ.Dispose();
+                hv_Cx.Dispose();
+                hv_Cy.Dispose();
+                hv_DR.Dispose();
+                hv_DC.Dispose();
+                hv_MaxDist.Dispose();
+                hv_HomMat3DRotate.Dispose();
+                hv_ImageWidth.Dispose();
+                hv_ImageHeight.Dispose();
+                hv_MinImageSize.Dispose();
+                hv_Zs.Dispose();
+                hv_ZDiff.Dispose();
+                hv_ScaleZ.Dispose();
+                hv_ZNew.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Rows.Dispose();
+                hv_Cols.Dispose();
+                hv_MinMinZ.Dispose();
+                hv_BB.Dispose();
+                hv_Index.Dispose();
+                hv_CurrBB.Dispose();
+                hv_Exception.Dispose();
+                hv_Seq.Dispose();
+                hv_DXMax.Dispose();
+                hv_DYMax.Dispose();
+                hv_DZMax.Dispose();
+                hv_Diameter.Dispose();
+                hv_ZAdd.Dispose();
+                hv_BBX0.Dispose();
+                hv_BBX1.Dispose();
+                hv_BBY0.Dispose();
+                hv_BBY1.Dispose();
+                hv_BBZ0.Dispose();
+                hv_BBZ1.Dispose();
+                hv_X.Dispose();
+                hv_Y.Dispose();
+                hv_Z.Dispose();
+                hv_HomMat3DIn.Dispose();
+                hv_QX_In.Dispose();
+                hv_QY_In.Dispose();
+                hv_QZ_In.Dispose();
+                hv_PoseInter.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_QX.Dispose();
+                hv_QY.Dispose();
+                hv_QZ.Dispose();
+                hv_Cx.Dispose();
+                hv_Cy.Dispose();
+                hv_DR.Dispose();
+                hv_DC.Dispose();
+                hv_MaxDist.Dispose();
+                hv_HomMat3DRotate.Dispose();
+                hv_ImageWidth.Dispose();
+                hv_ImageHeight.Dispose();
+                hv_MinImageSize.Dispose();
+                hv_Zs.Dispose();
+                hv_ZDiff.Dispose();
+                hv_ScaleZ.Dispose();
+                hv_ZNew.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Develop
+        // Short Description: Switch dev_update_pc, dev_update_var, and dev_update_window to 'off'. 
+        public static void dev_update_off()
+        {
+
+            // Initialize local and output iconic variables 
+            //This procedure sets different update settings to 'off'.
+            //This is useful to get the best performance and reduce overhead.
+            //
+            // dev_update_pc(...); only in hdevelop
+            // dev_update_var(...); only in hdevelop
+            // dev_update_window(...); only in hdevelop
+
+
+            return;
+        }
+
+        // Chapter: Graphics / Output
+        // Short Description: Display a continue button. 
+        public static void disp_continue_button(HTuple hv_WindowHandle)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_ContinueMessage = new HTuple(), hv_Exception = new HTuple();
+            HTuple hv_Row = new HTuple(), hv_Column = new HTuple();
+            HTuple hv_Width = new HTuple(), hv_Height = new HTuple();
+            HTuple hv_Ascent = new HTuple(), hv_Descent = new HTuple();
+            HTuple hv_TextWidth = new HTuple(), hv_TextHeight = new HTuple();
+            // Initialize local and output iconic variables 
+            try
+            {
+                //This procedure displays a 'Continue' text button
+                //in the lower right corner of the screen.
+                //It uses the procedure disp_message.
+                //
+                //Input parameters:
+                //WindowHandle: The window, where the text shall be displayed
+                //
+                //Use the continue message set in the global variable gTerminationButtonLabel.
+                //If this variable is not defined, set a standard text instead.
+                //global tuple gTerminationButtonLabel
+                try
+                {
+                    hv_ContinueMessage.Dispose();
+                    hv_ContinueMessage = new HTuple(ExpGetGlobalVar_gTerminationButtonLabel());
+                }
+                // catch (Exception) 
+                catch (HalconException HDevExpDefaultException1)
+                {
+                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                    hv_ContinueMessage.Dispose();
+                    hv_ContinueMessage = "Continue";
+                }
+                //Display the continue button
+                hv_Row.Dispose(); hv_Column.Dispose(); hv_Width.Dispose(); hv_Height.Dispose();
+                HOperatorSet.GetWindowExtents(hv_WindowHandle, out hv_Row, out hv_Column, out hv_Width,
+                    out hv_Height);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Ascent.Dispose(); hv_Descent.Dispose(); hv_TextWidth.Dispose(); hv_TextHeight.Dispose();
+                    HOperatorSet.GetStringExtents(hv_WindowHandle, " " + hv_ContinueMessage + " ",
+                        out hv_Ascent, out hv_Descent, out hv_TextWidth, out hv_TextHeight);
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    disp_text_button(hv_WindowHandle, hv_ContinueMessage, "window", hv_Height - hv_TextHeight - 22,
+                        hv_Width - hv_TextWidth - 12, "black", "#f28f26");
+                }
+
+                hv_ContinueMessage.Dispose();
+                hv_Exception.Dispose();
+                hv_Row.Dispose();
+                hv_Column.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_TextWidth.Dispose();
+                hv_TextHeight.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_ContinueMessage.Dispose();
+                hv_Exception.Dispose();
+                hv_Row.Dispose();
+                hv_Column.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_TextWidth.Dispose();
+                hv_TextHeight.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Text
+        // Short Description: Write one or multiple text messages. 
+        public static void disp_message(HTuple hv_WindowHandle, HTuple hv_String, HTuple hv_CoordSystem,
+            HTuple hv_Row, HTuple hv_Column, HTuple hv_Color, HTuple hv_Box)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_GenParamName = new HTuple(), hv_GenParamValue = new HTuple();
+            HTuple hv_Color_COPY_INP_TMP = new HTuple(hv_Color);
+            HTuple hv_Column_COPY_INP_TMP = new HTuple(hv_Column);
+            HTuple hv_CoordSystem_COPY_INP_TMP = new HTuple(hv_CoordSystem);
+            HTuple hv_Row_COPY_INP_TMP = new HTuple(hv_Row);
+
+            // Initialize local and output iconic variables 
+            try
+            {
+                //This procedure displays text in a graphics window.
+                //
+                //Input parameters:
+                //WindowHandle: The WindowHandle of the graphics window, where
+                //   the message should be displayed.
+                //String: A tuple of strings containing the text messages to be displayed.
+                //CoordSystem: If set to 'window', the text position is given
+                //   with respect to the window coordinate system.
+                //   If set to 'image', image coordinates are used.
+                //   (This may be useful in zoomed images.)
+                //Row: The row coordinate of the desired text position.
+                //   You can pass a single value or a tuple of values.
+                //   See the explanation below.
+                //   Default: 12.
+                //Column: The column coordinate of the desired text position.
+                //   You can pass a single value or a tuple of values.
+                //   See the explanation below.
+                //   Default: 12.
+                //Color: defines the color of the text as string.
+                //   If set to [] or '' the currently set color is used.
+                //   If a tuple of strings is passed, the colors are used cyclically
+                //   for every text position defined by Row and Column,
+                //   or every new text line in case of |Row| == |Column| == 1.
+                //Box: A tuple controlling a possible box surrounding the text.
+                //   Its entries:
+                //   - Box[0]: Controls the box and its color. Possible values:
+                //     -- 'true' (Default): An orange box is displayed.
+                //     -- 'false': No box is displayed.
+                //     -- color string: A box is displayed in the given color, e.g., 'white', '#FF00CC'.
+                //   - Box[1] (Optional): Controls the shadow of the box. Possible values:
+                //     -- 'true' (Default): A shadow is displayed in
+                //               darker orange if Box[0] is not a color and in 'white' otherwise.
+                //     -- 'false': No shadow is displayed.
+                //     -- color string: A shadow is displayed in the given color, e.g., 'white', '#FF00CC'.
+                //
+                //It is possible to display multiple text strings in a single call.
+                //In this case, some restrictions apply on the
+                //parameters String, Row, and Column:
+                //They can only have either 1 entry or n entries.
+                //Behavior in the different cases:
+                //   - Multiple text positions are specified, i.e.,
+                //       - |Row| == n, |Column| == n
+                //       - |Row| == n, |Column| == 1
+                //       - |Row| == 1, |Column| == n
+                //     In this case we distinguish:
+                //       - |String| == n: Each element of String is displayed
+                //                        at the corresponding position.
+                //       - |String| == 1: String is displayed n times
+                //                        at the corresponding positions.
+                //   - Exactly one text position is specified,
+                //      i.e., |Row| == |Column| == 1:
+                //      Each element of String is display in a new textline.
+                //
+                //
+                //Convert the parameters for disp_text.
+                if ((int)new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(new HTuple())).TupleOr(
+                    new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(new HTuple()))) != 0)
+                {
+
+                    hv_Color_COPY_INP_TMP.Dispose();
+                    hv_Column_COPY_INP_TMP.Dispose();
+                    hv_CoordSystem_COPY_INP_TMP.Dispose();
+                    hv_Row_COPY_INP_TMP.Dispose();
+                    hv_GenParamName.Dispose();
+                    hv_GenParamValue.Dispose();
+
+                    return;
+                }
+                if ((int)new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(-1)) != 0)
+                {
+                    hv_Row_COPY_INP_TMP.Dispose();
+                    hv_Row_COPY_INP_TMP = 12;
+                }
+                if ((int)new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(-1)) != 0)
+                {
+                    hv_Column_COPY_INP_TMP.Dispose();
+                    hv_Column_COPY_INP_TMP = 12;
+                }
+                //
+                //Convert the parameter Box to generic parameters.
+                hv_GenParamName.Dispose();
+                hv_GenParamName = new HTuple();
+                hv_GenParamValue.Dispose();
+                hv_GenParamValue = new HTuple();
+                if ((int)new HTuple(new HTuple(hv_Box.TupleLength()).TupleGreater(0)) != 0)
+                {
+                    if ((int)new HTuple(hv_Box.TupleSelect(0).TupleEqual("false")) != 0)
+                    {
+                        //Display no box
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "box");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    "false");
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    else if ((int)new HTuple(hv_Box.TupleSelect(0).TupleNotEqual(
+                        "true")) != 0)
+                    {
+                        //Set a color other than the default.
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "box_color");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    hv_Box.TupleSelect(0));
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                }
+                if ((int)new HTuple(new HTuple(hv_Box.TupleLength()).TupleGreater(1)) != 0)
+                {
+                    if ((int)new HTuple(hv_Box.TupleSelect(1).TupleEqual("false")) != 0)
+                    {
+                        //Display no shadow.
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "shadow");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    "false");
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    else if ((int)new HTuple(hv_Box.TupleSelect(1).TupleNotEqual(
+                        "true")) != 0)
+                    {
+                        //Set a shadow color other than the default.
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
+                                    "shadow_color");
+                                hv_GenParamName.Dispose();
+                                hv_GenParamName = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
+                                    hv_Box.TupleSelect(1));
+                                hv_GenParamValue.Dispose();
+                                hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                }
+                //Restore default CoordSystem behavior.
+                if ((int)new HTuple(hv_CoordSystem_COPY_INP_TMP.TupleNotEqual("window")) != 0)
+                {
+                    hv_CoordSystem_COPY_INP_TMP.Dispose();
+                    hv_CoordSystem_COPY_INP_TMP = "image";
+                }
+                //
+                if ((int)new HTuple(hv_Color_COPY_INP_TMP.TupleEqual("")) != 0)
+                {
+                    //disp_text does not accept an empty string for Color.
+                    hv_Color_COPY_INP_TMP.Dispose();
+                    hv_Color_COPY_INP_TMP = new HTuple();
+                }
+                //
+                HOperatorSet.DispText(hv_WindowHandle, hv_String, hv_CoordSystem_COPY_INP_TMP,
+                    hv_Row_COPY_INP_TMP, hv_Column_COPY_INP_TMP, hv_Color_COPY_INP_TMP, hv_GenParamName,
+                    hv_GenParamValue);
+
+                hv_Color_COPY_INP_TMP.Dispose();
+                hv_Column_COPY_INP_TMP.Dispose();
+                hv_CoordSystem_COPY_INP_TMP.Dispose();
+                hv_Row_COPY_INP_TMP.Dispose();
+                hv_GenParamName.Dispose();
+                hv_GenParamValue.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Color_COPY_INP_TMP.Dispose();
+                hv_Column_COPY_INP_TMP.Dispose();
+                hv_CoordSystem_COPY_INP_TMP.Dispose();
+                hv_Row_COPY_INP_TMP.Dispose();
+                hv_GenParamName.Dispose();
+                hv_GenParamValue.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Output
+        // Short Description: Replace disp_object_model_3d if there is no OpenGL available. 
+        public static void disp_object_model_no_opengl(out HObject ho_ModelContours, HTuple hv_ObjectModel3DID,
+            HTuple hv_GenParamName, HTuple hv_GenParamValue, HTuple hv_WindowHandleBuffer,
+            HTuple hv_CamParam, HTuple hv_PosesOut)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_Idx = new HTuple(), hv_CustomParamName = new HTuple();
+            HTuple hv_CustomParamValue = new HTuple(), hv_Font = new HTuple();
+            HTuple hv_IndicesDispBackGround = new HTuple(), hv_Indices = new HTuple();
+            HTuple hv_ImageWidth = new HTuple(), hv_HasPolygons = new HTuple();
+            HTuple hv_HasTri = new HTuple(), hv_HasPoints = new HTuple();
+            HTuple hv_HasLines = new HTuple(), hv_NumPoints = new HTuple();
+            HTuple hv_IsPrimitive = new HTuple(), hv_Center = new HTuple();
+            HTuple hv_Diameter = new HTuple(), hv_OpenGlHiddenSurface = new HTuple();
+            HTuple hv_CenterX = new HTuple(), hv_CenterY = new HTuple();
+            HTuple hv_CenterZ = new HTuple(), hv_PosObjectsZ = new HTuple();
+            HTuple hv_I = new HTuple(), hv_Pose = new HTuple(), hv_HomMat3DObj = new HTuple();
+            HTuple hv_PosObjCenterX = new HTuple(), hv_PosObjCenterY = new HTuple();
+            HTuple hv_PosObjCenterZ = new HTuple(), hv_PosObjectsX = new HTuple();
+            HTuple hv_PosObjectsY = new HTuple(), hv_Color = new HTuple();
+            HTuple hv_Indices1 = new HTuple(), hv_Indices2 = new HTuple();
+            HTuple hv_J = new HTuple(), hv_Indices3 = new HTuple();
+            HTuple hv_HomMat3D = new HTuple(), hv_SampledObjectModel3D = new HTuple();
+            HTuple hv_X = new HTuple(), hv_Y = new HTuple(), hv_Z = new HTuple();
+            HTuple hv_HomMat3D1 = new HTuple(), hv_Qx = new HTuple();
+            HTuple hv_Qy = new HTuple(), hv_Qz = new HTuple(), hv_Row = new HTuple();
+            HTuple hv_Column = new HTuple(), hv_ObjectModel3DConvexHull = new HTuple();
+            HTuple hv_Exception = new HTuple();
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_ModelContours);
+            try
+            {
+                //This procedure allows to use project_object_model_3d to simulate a disp_object_model_3d
+                //call for small objects. Large objects are sampled down to display.
+                hv_Idx.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Idx = hv_GenParamName.TupleFind(
+                        "point_size");
+                }
+                if ((int)new HTuple(hv_Idx.TupleLength()).TupleAnd(new HTuple(hv_Idx.TupleNotEqual(
+                    -1))) != 0)
+                {
+                    hv_CustomParamName.Dispose();
+                    hv_CustomParamName = "point_size";
+                    hv_CustomParamValue.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_CustomParamValue = hv_GenParamValue.TupleSelect(
+                            hv_Idx);
+                    }
+                    if ((int)new HTuple(hv_CustomParamValue.TupleEqual(1)) != 0)
+                    {
+                        hv_CustomParamValue.Dispose();
+                        hv_CustomParamValue = 0;
+                    }
+                }
+                else
+                {
+                    hv_CustomParamName.Dispose();
+                    hv_CustomParamName = new HTuple();
+                    hv_CustomParamValue.Dispose();
+                    hv_CustomParamValue = new HTuple();
+                }
+                hv_Font.Dispose();
+                HOperatorSet.GetFont(hv_WindowHandleBuffer, out hv_Font);
+                hv_IndicesDispBackGround.Dispose();
+                HOperatorSet.TupleFind(hv_GenParamName, "disp_background", out hv_IndicesDispBackGround);
+                if ((int)new HTuple(hv_IndicesDispBackGround.TupleNotEqual(-1)) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices.Dispose();
+                        HOperatorSet.TupleFind(hv_GenParamName.TupleSelect(hv_IndicesDispBackGround),
+                            "false", out hv_Indices);
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)) != 0)
+                    {
+                        HOperatorSet.ClearWindow(hv_WindowHandleBuffer);
+                    }
+                }
+                set_display_font(hv_WindowHandleBuffer, 11, "mono", "false", "false");
+                hv_ImageWidth.Dispose();
+                get_cam_par_data(hv_CamParam, "image_width", out hv_ImageWidth);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    disp_message(hv_WindowHandleBuffer, "OpenGL missing!", "image", 5, hv_ImageWidth - 130,
+                        "red", "false");
+                }
+                HOperatorSet.SetFont(hv_WindowHandleBuffer, hv_Font);
+                hv_HasPolygons.Dispose();
+                HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID, "has_polygons", out hv_HasPolygons);
+                hv_HasTri.Dispose();
+                HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID, "has_triangles", out hv_HasTri);
+                hv_HasPoints.Dispose();
+                HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID, "has_points", out hv_HasPoints);
+                hv_HasLines.Dispose();
+                HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID, "has_lines", out hv_HasLines);
+                hv_NumPoints.Dispose();
+                HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID, "num_points", out hv_NumPoints);
+                hv_IsPrimitive.Dispose();
+                HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID, "has_primitive_data",
+                    out hv_IsPrimitive);
+                hv_Center.Dispose();
+                HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID, "center", out hv_Center);
+                hv_Diameter.Dispose();
+                HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID, "diameter", out hv_Diameter);
+                hv_OpenGlHiddenSurface.Dispose();
+                HOperatorSet.GetSystem("opengl_hidden_surface_removal_enable", out hv_OpenGlHiddenSurface);
+                HOperatorSet.SetSystem("opengl_hidden_surface_removal_enable", "false");
+                //Sort the objects by inverse z
+                hv_CenterX.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_CenterX = hv_Center.TupleSelect(
+                        HTuple.TupleGenSequence(0, new HTuple(hv_Center.TupleLength()) - 1, 3));
+                }
+                hv_CenterY.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_CenterY = hv_Center.TupleSelect(
+                        HTuple.TupleGenSequence(0, new HTuple(hv_Center.TupleLength()) - 1, 3) + 1);
+                }
+                hv_CenterZ.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_CenterZ = hv_Center.TupleSelect(
+                        HTuple.TupleGenSequence(0, new HTuple(hv_Center.TupleLength()) - 1, 3) + 2);
+                }
+                hv_PosObjectsZ.Dispose();
+                hv_PosObjectsZ = new HTuple();
+                if ((int)new HTuple(new HTuple(hv_PosesOut.TupleLength()).TupleGreater(7)) != 0)
+                {
+                    for (hv_I = 0; (int)hv_I <= (int)(new HTuple(hv_ObjectModel3DID.TupleLength()
+                        ) - 1); hv_I = (int)hv_I + 1)
+                    {
+                        hv_Pose.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Pose = hv_PosesOut.TupleSelectRange(
+                                hv_I * 7, hv_I * 7 + 6);
+                        }
+                        hv_HomMat3DObj.Dispose();
+                        HOperatorSet.PoseToHomMat3d(hv_Pose, out hv_HomMat3DObj);
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_PosObjCenterX.Dispose(); hv_PosObjCenterY.Dispose(); hv_PosObjCenterZ.Dispose();
+                            HOperatorSet.AffineTransPoint3d(hv_HomMat3DObj, hv_CenterX.TupleSelect(
+                                hv_I), hv_CenterY.TupleSelect(hv_I), hv_CenterZ.TupleSelect(hv_I),
+                                out hv_PosObjCenterX, out hv_PosObjCenterY, out hv_PosObjCenterZ);
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_PosObjectsZ = hv_PosObjectsZ.TupleConcat(
+                                    hv_PosObjCenterZ);
+                                hv_PosObjectsZ.Dispose();
+                                hv_PosObjectsZ = ExpTmpLocalVar_PosObjectsZ;
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    hv_Pose.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Pose = hv_PosesOut.TupleSelectRange(
+                            0, 6);
+                    }
+                    hv_HomMat3DObj.Dispose();
+                    HOperatorSet.PoseToHomMat3d(hv_Pose, out hv_HomMat3DObj);
+                    hv_PosObjectsX.Dispose(); hv_PosObjectsY.Dispose(); hv_PosObjectsZ.Dispose();
+                    HOperatorSet.AffineTransPoint3d(hv_HomMat3DObj, hv_CenterX, hv_CenterY, hv_CenterZ,
+                        out hv_PosObjectsX, out hv_PosObjectsY, out hv_PosObjectsZ);
+                }
+                hv_Idx.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Idx = new HTuple(hv_PosObjectsZ.TupleSortIndex()
+                        ).TupleInverse();
+                }
+                hv_Color.Dispose();
+                hv_Color = "white";
+                HOperatorSet.SetColor(hv_WindowHandleBuffer, hv_Color);
+                if ((int)new HTuple(new HTuple(hv_GenParamName.TupleLength()).TupleGreater(
+                    0)) != 0)
+                {
+                    hv_Indices1.Dispose();
+                    HOperatorSet.TupleFind(hv_GenParamName, "colored", out hv_Indices1);
+                    hv_Indices2.Dispose();
+                    HOperatorSet.TupleFind(hv_GenParamName, "color", out hv_Indices2);
+                    if ((int)new HTuple(hv_Indices1.TupleSelect(0).TupleNotEqual(-1)) != 0)
+                    {
+                        if ((int)new HTuple(hv_GenParamValue.TupleSelect(hv_Indices1.TupleSelect(
+                            0)).TupleEqual(3)) != 0)
+                        {
+                            hv_Color.Dispose();
+                            hv_Color = new HTuple();
+                            hv_Color[0] = "red";
+                            hv_Color[1] = "green";
+                            hv_Color[2] = "blue";
+                        }
+                        else if ((int)new HTuple(hv_GenParamValue.TupleSelect(hv_Indices1.TupleSelect(
+                            0)).TupleEqual(6)) != 0)
+                        {
+                            hv_Color.Dispose();
+                            hv_Color = new HTuple();
+                            hv_Color[0] = "red";
+                            hv_Color[1] = "green";
+                            hv_Color[2] = "blue";
+                            hv_Color[3] = "cyan";
+                            hv_Color[4] = "magenta";
+                            hv_Color[5] = "yellow";
+                        }
+                        else if ((int)new HTuple(hv_GenParamValue.TupleSelect(hv_Indices1.TupleSelect(
+                            0)).TupleEqual(12)) != 0)
+                        {
+                            hv_Color.Dispose();
+                            hv_Color = new HTuple();
+                            hv_Color[0] = "red";
+                            hv_Color[1] = "green";
+                            hv_Color[2] = "blue";
+                            hv_Color[3] = "cyan";
+                            hv_Color[4] = "magenta";
+                            hv_Color[5] = "yellow";
+                            hv_Color[6] = "coral";
+                            hv_Color[7] = "slate blue";
+                            hv_Color[8] = "spring green";
+                            hv_Color[9] = "orange red";
+                            hv_Color[10] = "pink";
+                            hv_Color[11] = "gold";
+                        }
+                    }
+                    else if ((int)new HTuple(hv_Indices2.TupleSelect(0).TupleNotEqual(
+                        -1)) != 0)
+                    {
+                        hv_Color.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Color = hv_GenParamValue.TupleSelect(
+                                hv_Indices2.TupleSelect(0));
+                        }
+                    }
+                }
+                for (hv_J = 0; (int)hv_J <= (int)(new HTuple(hv_ObjectModel3DID.TupleLength()) - 1); hv_J = (int)hv_J + 1)
+                {
+                    hv_I.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_I = hv_Idx.TupleSelect(
+                            hv_J);
+                    }
+                    if ((int)new HTuple(new HTuple(new HTuple(hv_HasPolygons.TupleSelect(
+                        hv_I).TupleEqual("true")).TupleOr(new HTuple(hv_HasTri.TupleSelect(
+                        hv_I).TupleEqual("true")))).TupleOr(new HTuple(hv_HasPoints.TupleSelect(
+                        hv_I).TupleEqual("true")))).TupleOr(new HTuple(hv_HasLines.TupleSelect(
+                        hv_I).TupleEqual("true"))) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_GenParamName.TupleLength()).TupleGreater(
+                            0)) != 0)
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Indices3.Dispose();
+                                HOperatorSet.TupleFind(hv_GenParamName, "color_" + hv_I, out hv_Indices3);
+                            }
+                            if ((int)new HTuple(hv_Indices3.TupleSelect(0).TupleNotEqual(-1)) != 0)
+                            {
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    HOperatorSet.SetColor(hv_WindowHandleBuffer, hv_GenParamValue.TupleSelect(
+                                        hv_Indices3.TupleSelect(0)));
+                                }
+                            }
+                            else
+                            {
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    HOperatorSet.SetColor(hv_WindowHandleBuffer, hv_Color.TupleSelect(hv_I % new HTuple(hv_Color.TupleLength()
+                                        )));
+                                }
+                            }
+                        }
+                        if ((int)new HTuple(new HTuple(hv_PosesOut.TupleLength()).TupleGreaterEqual(
+                            hv_I * 7 + 6)) != 0)
+                        {
+                            hv_Pose.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Pose = hv_PosesOut.TupleSelectRange(
+                                    hv_I * 7, hv_I * 7 + 6);
+                            }
+                        }
+                        else
+                        {
+                            hv_Pose.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Pose = hv_PosesOut.TupleSelectRange(
+                                    0, 6);
+                            }
+                        }
+                        if ((int)new HTuple(hv_NumPoints.TupleSelect(hv_I).TupleLess(10000)) != 0)
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                ho_ModelContours.Dispose();
+                                HOperatorSet.ProjectObjectModel3d(out ho_ModelContours, hv_ObjectModel3DID.TupleSelect(
+                                    hv_I), hv_CamParam, hv_Pose, hv_CustomParamName, hv_CustomParamValue);
+                            }
+                            HOperatorSet.DispObj(ho_ModelContours, hv_WindowHandleBuffer);
+                        }
+                        else
+                        {
+                            hv_HomMat3D.Dispose();
+                            HOperatorSet.PoseToHomMat3d(hv_Pose, out hv_HomMat3D);
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_SampledObjectModel3D.Dispose();
+                                HOperatorSet.SampleObjectModel3d(hv_ObjectModel3DID.TupleSelect(hv_I),
+                                    "fast", 0.01 * hv_Diameter.TupleSelect(hv_I), new HTuple(), new HTuple(),
+                                    out hv_SampledObjectModel3D);
+                            }
+                            ho_ModelContours.Dispose();
+                            HOperatorSet.ProjectObjectModel3d(out ho_ModelContours, hv_SampledObjectModel3D,
+                                hv_CamParam, hv_Pose, "point_size", 1);
+                            hv_X.Dispose();
+                            HOperatorSet.GetObjectModel3dParams(hv_SampledObjectModel3D, "point_coord_x",
+                                out hv_X);
+                            hv_Y.Dispose();
+                            HOperatorSet.GetObjectModel3dParams(hv_SampledObjectModel3D, "point_coord_y",
+                                out hv_Y);
+                            hv_Z.Dispose();
+                            HOperatorSet.GetObjectModel3dParams(hv_SampledObjectModel3D, "point_coord_z",
+                                out hv_Z);
+                            hv_HomMat3D1.Dispose();
+                            HOperatorSet.PoseToHomMat3d(hv_Pose, out hv_HomMat3D1);
+                            hv_Qx.Dispose(); hv_Qy.Dispose(); hv_Qz.Dispose();
+                            HOperatorSet.AffineTransPoint3d(hv_HomMat3D1, hv_X, hv_Y, hv_Z, out hv_Qx,
+                                out hv_Qy, out hv_Qz);
+                            hv_Row.Dispose(); hv_Column.Dispose();
+                            HOperatorSet.Project3dPoint(hv_Qx, hv_Qy, hv_Qz, hv_CamParam, out hv_Row,
+                                out hv_Column);
+                            HOperatorSet.DispObj(ho_ModelContours, hv_WindowHandleBuffer);
+                            HOperatorSet.ClearObjectModel3d(hv_SampledObjectModel3D);
+                        }
+                    }
+                    else
+                    {
+                        if ((int)new HTuple(new HTuple(hv_GenParamName.TupleLength()).TupleGreater(
+                            0)) != 0)
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Indices3.Dispose();
+                                HOperatorSet.TupleFind(hv_GenParamName, "color_" + hv_I, out hv_Indices3);
+                            }
+                            if ((int)new HTuple(hv_Indices3.TupleSelect(0).TupleNotEqual(-1)) != 0)
+                            {
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    HOperatorSet.SetColor(hv_WindowHandleBuffer, hv_GenParamValue.TupleSelect(
+                                        hv_Indices3.TupleSelect(0)));
+                                }
+                            }
+                            else
+                            {
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    HOperatorSet.SetColor(hv_WindowHandleBuffer, hv_Color.TupleSelect(hv_I % new HTuple(hv_Color.TupleLength()
+                                        )));
+                                }
+                            }
+                        }
+                        if ((int)new HTuple(new HTuple(hv_PosesOut.TupleLength()).TupleGreaterEqual(
+                            hv_I * 7 + 6)) != 0)
+                        {
+                            hv_Pose.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Pose = hv_PosesOut.TupleSelectRange(
+                                    hv_I * 7, hv_I * 7 + 6);
+                            }
+                        }
+                        else
+                        {
+                            hv_Pose.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Pose = hv_PosesOut.TupleSelectRange(
+                                    0, 6);
+                            }
+                        }
+                        if ((int)new HTuple(hv_IsPrimitive.TupleSelect(hv_I).TupleEqual("true")) != 0)
+                        {
+                            try
+                            {
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_ObjectModel3DConvexHull.Dispose();
+                                    HOperatorSet.ConvexHullObjectModel3d(hv_ObjectModel3DID.TupleSelect(
+                                        hv_I), out hv_ObjectModel3DConvexHull);
+                                }
+                                if ((int)new HTuple(hv_NumPoints.TupleSelect(hv_I).TupleLess(10000)) != 0)
+                                {
+                                    ho_ModelContours.Dispose();
+                                    HOperatorSet.ProjectObjectModel3d(out ho_ModelContours, hv_ObjectModel3DConvexHull,
+                                        hv_CamParam, hv_Pose, hv_CustomParamName, hv_CustomParamValue);
+                                    HOperatorSet.DispObj(ho_ModelContours, hv_WindowHandleBuffer);
+                                }
+                                else
+                                {
+                                    hv_HomMat3D.Dispose();
+                                    HOperatorSet.PoseToHomMat3d(hv_Pose, out hv_HomMat3D);
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_SampledObjectModel3D.Dispose();
+                                        HOperatorSet.SampleObjectModel3d(hv_ObjectModel3DConvexHull, "fast",
+                                            0.01 * hv_Diameter.TupleSelect(hv_I), new HTuple(), new HTuple(),
+                                            out hv_SampledObjectModel3D);
+                                    }
+                                    ho_ModelContours.Dispose();
+                                    HOperatorSet.ProjectObjectModel3d(out ho_ModelContours, hv_SampledObjectModel3D,
+                                        hv_CamParam, hv_Pose, "point_size", 1);
+                                    HOperatorSet.DispObj(ho_ModelContours, hv_WindowHandleBuffer);
+                                    HOperatorSet.ClearObjectModel3d(hv_SampledObjectModel3D);
+                                }
+                                HOperatorSet.ClearObjectModel3d(hv_ObjectModel3DConvexHull);
+                            }
+                            // catch (Exception) 
+                            catch (HalconException HDevExpDefaultException1)
+                            {
+                                HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                            }
+                        }
+                    }
+                }
+                HOperatorSet.SetSystem("opengl_hidden_surface_removal_enable", hv_OpenGlHiddenSurface);
+
+                hv_Idx.Dispose();
+                hv_CustomParamName.Dispose();
+                hv_CustomParamValue.Dispose();
+                hv_Font.Dispose();
+                hv_IndicesDispBackGround.Dispose();
+                hv_Indices.Dispose();
+                hv_ImageWidth.Dispose();
+                hv_HasPolygons.Dispose();
+                hv_HasTri.Dispose();
+                hv_HasPoints.Dispose();
+                hv_HasLines.Dispose();
+                hv_NumPoints.Dispose();
+                hv_IsPrimitive.Dispose();
+                hv_Center.Dispose();
+                hv_Diameter.Dispose();
+                hv_OpenGlHiddenSurface.Dispose();
+                hv_CenterX.Dispose();
+                hv_CenterY.Dispose();
+                hv_CenterZ.Dispose();
+                hv_PosObjectsZ.Dispose();
+                hv_I.Dispose();
+                hv_Pose.Dispose();
+                hv_HomMat3DObj.Dispose();
+                hv_PosObjCenterX.Dispose();
+                hv_PosObjCenterY.Dispose();
+                hv_PosObjCenterZ.Dispose();
+                hv_PosObjectsX.Dispose();
+                hv_PosObjectsY.Dispose();
+                hv_Color.Dispose();
+                hv_Indices1.Dispose();
+                hv_Indices2.Dispose();
+                hv_J.Dispose();
+                hv_Indices3.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_SampledObjectModel3D.Dispose();
+                hv_X.Dispose();
+                hv_Y.Dispose();
+                hv_Z.Dispose();
+                hv_HomMat3D1.Dispose();
+                hv_Qx.Dispose();
+                hv_Qy.Dispose();
+                hv_Qz.Dispose();
+                hv_Row.Dispose();
+                hv_Column.Dispose();
+                hv_ObjectModel3DConvexHull.Dispose();
+                hv_Exception.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Idx.Dispose();
+                hv_CustomParamName.Dispose();
+                hv_CustomParamValue.Dispose();
+                hv_Font.Dispose();
+                hv_IndicesDispBackGround.Dispose();
+                hv_Indices.Dispose();
+                hv_ImageWidth.Dispose();
+                hv_HasPolygons.Dispose();
+                hv_HasTri.Dispose();
+                hv_HasPoints.Dispose();
+                hv_HasLines.Dispose();
+                hv_NumPoints.Dispose();
+                hv_IsPrimitive.Dispose();
+                hv_Center.Dispose();
+                hv_Diameter.Dispose();
+                hv_OpenGlHiddenSurface.Dispose();
+                hv_CenterX.Dispose();
+                hv_CenterY.Dispose();
+                hv_CenterZ.Dispose();
+                hv_PosObjectsZ.Dispose();
+                hv_I.Dispose();
+                hv_Pose.Dispose();
+                hv_HomMat3DObj.Dispose();
+                hv_PosObjCenterX.Dispose();
+                hv_PosObjCenterY.Dispose();
+                hv_PosObjCenterZ.Dispose();
+                hv_PosObjectsX.Dispose();
+                hv_PosObjectsY.Dispose();
+                hv_Color.Dispose();
+                hv_Indices1.Dispose();
+                hv_Indices2.Dispose();
+                hv_J.Dispose();
+                hv_Indices3.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_SampledObjectModel3D.Dispose();
+                hv_X.Dispose();
+                hv_Y.Dispose();
+                hv_Z.Dispose();
+                hv_HomMat3D1.Dispose();
+                hv_Qx.Dispose();
+                hv_Qy.Dispose();
+                hv_Qz.Dispose();
+                hv_Row.Dispose();
+                hv_Column.Dispose();
+                hv_ObjectModel3DConvexHull.Dispose();
+                hv_Exception.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Text
+        // Short Description: Display a text message. 
+        public static void disp_text_button(HTuple hv_WindowHandle, HTuple hv_String, HTuple hv_CoordSystem,
+            HTuple hv_Row, HTuple hv_Column, HTuple hv_TextColor, HTuple hv_ButtonColor)
+        {
+
+
+
+            // Local iconic variables 
+
+            HObject ho_UpperLeft, ho_LowerRight, ho_Rectangle;
+
+            // Local control variables 
+
+            HTuple hv_Red = new HTuple(), hv_Green = new HTuple();
+            HTuple hv_Blue = new HTuple(), hv_Row1Part = new HTuple();
+            HTuple hv_Column1Part = new HTuple(), hv_Row2Part = new HTuple();
+            HTuple hv_Column2Part = new HTuple(), hv_RowWin = new HTuple();
+            HTuple hv_ColumnWin = new HTuple(), hv_WidthWin = new HTuple();
+            HTuple hv_HeightWin = new HTuple(), hv_RGB = new HTuple();
+            HTuple hv_Exception = new HTuple(), hv_Fac = new HTuple();
+            HTuple hv_RGBL = new HTuple(), hv_RGBD = new HTuple();
+            HTuple hv_ButtonColorBorderL = new HTuple(), hv_ButtonColorBorderD = new HTuple();
+            HTuple hv_MaxAscent = new HTuple(), hv_MaxDescent = new HTuple();
+            HTuple hv_MaxWidth = new HTuple(), hv_MaxHeight = new HTuple();
+            HTuple hv_R1 = new HTuple(), hv_C1 = new HTuple(), hv_FactorRow = new HTuple();
+            HTuple hv_FactorColumn = new HTuple(), hv_Width = new HTuple();
+            HTuple hv_Index = new HTuple(), hv_Ascent = new HTuple();
+            HTuple hv_Descent = new HTuple(), hv_W = new HTuple();
+            HTuple hv_H = new HTuple(), hv_FrameHeight = new HTuple();
+            HTuple hv_FrameWidth = new HTuple(), hv_R2 = new HTuple();
+            HTuple hv_C2 = new HTuple(), hv_ClipRegion = new HTuple();
+            HTuple hv_DrawMode = new HTuple(), hv_BorderWidth = new HTuple();
+            HTuple hv_CurrentColor = new HTuple();
+            HTuple hv_Column_COPY_INP_TMP = new HTuple(hv_Column);
+            HTuple hv_Row_COPY_INP_TMP = new HTuple(hv_Row);
+            HTuple hv_String_COPY_INP_TMP = new HTuple(hv_String);
+            HTuple hv_TextColor_COPY_INP_TMP = new HTuple(hv_TextColor);
+
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_UpperLeft);
+            HOperatorSet.GenEmptyObj(out ho_LowerRight);
+            HOperatorSet.GenEmptyObj(out ho_Rectangle);
+            try
+            {
+                //This procedure displays text in a graphics window.
+                //
+                //Input parameters:
+                //WindowHandle: The WindowHandle of the graphics window, where
+                //   the message should be displayed
+                //String: A tuple of strings containing the text message to be displayed
+                //CoordSystem: If set to 'window', the text position is given
+                //   with respect to the window coordinate system.
+                //   If set to 'image', image coordinates are used.
+                //   (This may be useful in zoomed images.)
+                //Row: The row coordinate of the desired text position
+                //   If set to -1, a default value of 12 is used.
+                //Column: The column coordinate of the desired text position
+                //   If set to -1, a default value of 12 is used.
+                //Color: defines the color of the text as string.
+                //   If set to [], '' or 'auto' the currently set color is used.
+                //   If a tuple of strings is passed, the colors are used cyclically
+                //   for each new textline.
+                //ButtonColor: Must be set to a color string (e.g. 'white', '#FF00CC', etc.).
+                //             The text is written in a box of that color.
+                //
+                //Prepare window.
+                hv_Red.Dispose(); hv_Green.Dispose(); hv_Blue.Dispose();
+                HOperatorSet.GetRgb(hv_WindowHandle, out hv_Red, out hv_Green, out hv_Blue);
+                hv_Row1Part.Dispose(); hv_Column1Part.Dispose(); hv_Row2Part.Dispose(); hv_Column2Part.Dispose();
+                HOperatorSet.GetPart(hv_WindowHandle, out hv_Row1Part, out hv_Column1Part,
+                    out hv_Row2Part, out hv_Column2Part);
+                hv_RowWin.Dispose(); hv_ColumnWin.Dispose(); hv_WidthWin.Dispose(); hv_HeightWin.Dispose();
+                HOperatorSet.GetWindowExtents(hv_WindowHandle, out hv_RowWin, out hv_ColumnWin,
+                    out hv_WidthWin, out hv_HeightWin);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    HOperatorSet.SetPart(hv_WindowHandle, 0, 0, hv_HeightWin - 1, hv_WidthWin - 1);
+                }
+                //
+                //Default settings.
+                if ((int)new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(-1)) != 0)
+                {
+                    hv_Row_COPY_INP_TMP.Dispose();
+                    hv_Row_COPY_INP_TMP = 12;
+                }
+                if ((int)new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(-1)) != 0)
+                {
+                    hv_Column_COPY_INP_TMP.Dispose();
+                    hv_Column_COPY_INP_TMP = 12;
+                }
+                if ((int)new HTuple(hv_TextColor_COPY_INP_TMP.TupleEqual(new HTuple())) != 0)
+                {
+                    hv_TextColor_COPY_INP_TMP.Dispose();
+                    hv_TextColor_COPY_INP_TMP = "";
+                }
+                //
+                try
+                {
+                    hv_RGB.Dispose();
+                    color_string_to_rgb(hv_ButtonColor, out hv_RGB);
+                }
+                // catch (Exception) 
+                catch (HalconException HDevExpDefaultException1)
+                {
+                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                    hv_Exception.Dispose();
+                    hv_Exception = "Wrong value of control parameter ButtonColor (must be a valid color string)";
+                    throw new HalconException(hv_Exception);
+                }
+                hv_Fac.Dispose();
+                hv_Fac = 0.4;
+                hv_RGBL.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_RGBL = hv_RGB + ((255.0 - hv_RGB) * hv_Fac + 0.5).TupleInt()
+                        ;
+                }
+                hv_RGBD.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_RGBD = hv_RGB - (hv_RGB * hv_Fac + 0.5).TupleInt()
+                        ;
+                }
+                hv_ButtonColorBorderL.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_ButtonColorBorderL = "#" + ("" + hv_RGBL.TupleString(
+                        "02x")).TupleSum();
+                }
+                hv_ButtonColorBorderD.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_ButtonColorBorderD = "#" + ("" + hv_RGBD.TupleString(
+                        "02x")).TupleSum();
+                }
+                //
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_String = ("" + hv_String_COPY_INP_TMP + "").TupleSplit(
+                            "\n");
+                        hv_String_COPY_INP_TMP.Dispose();
+                        hv_String_COPY_INP_TMP = ExpTmpLocalVar_String;
+                    }
+                }
+                //
+                //Estimate extensions of text depending on font size.
+                hv_MaxAscent.Dispose(); hv_MaxDescent.Dispose(); hv_MaxWidth.Dispose(); hv_MaxHeight.Dispose();
+                HOperatorSet.GetFontExtents(hv_WindowHandle, out hv_MaxAscent, out hv_MaxDescent,
+                    out hv_MaxWidth, out hv_MaxHeight);
+                if ((int)new HTuple(hv_CoordSystem.TupleEqual("window")) != 0)
+                {
+                    hv_R1.Dispose();
+                    hv_R1 = new HTuple(hv_Row_COPY_INP_TMP);
+                    hv_C1.Dispose();
+                    hv_C1 = new HTuple(hv_Column_COPY_INP_TMP);
+                }
+                else
+                {
+                    //Transform image to window coordinates.
+                    hv_FactorRow.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_FactorRow = 1.0 * hv_HeightWin / (hv_Row2Part - hv_Row1Part + 1);
+                    }
+                    hv_FactorColumn.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_FactorColumn = 1.0 * hv_WidthWin / (hv_Column2Part - hv_Column1Part + 1);
+                    }
+                    hv_R1.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_R1 = (hv_Row_COPY_INP_TMP - hv_Row1Part + 0.5) * hv_FactorRow;
+                    }
+                    hv_C1.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_C1 = (hv_Column_COPY_INP_TMP - hv_Column1Part + 0.5) * hv_FactorColumn;
+                    }
+                }
+                //
+                //Display text box depending on text size.
+                //
+                //Calculate box extents.
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_String = " " + hv_String_COPY_INP_TMP + " ";
+                        hv_String_COPY_INP_TMP.Dispose();
+                        hv_String_COPY_INP_TMP = ExpTmpLocalVar_String;
+                    }
+                }
+                hv_Width.Dispose();
+                hv_Width = new HTuple();
+                for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_String_COPY_INP_TMP.TupleLength()
+                    ) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Ascent.Dispose(); hv_Descent.Dispose(); hv_W.Dispose(); hv_H.Dispose();
+                        HOperatorSet.GetStringExtents(hv_WindowHandle, hv_String_COPY_INP_TMP.TupleSelect(
+                            hv_Index), out hv_Ascent, out hv_Descent, out hv_W, out hv_H);
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Width = hv_Width.TupleConcat(
+                                hv_W);
+                            hv_Width.Dispose();
+                            hv_Width = ExpTmpLocalVar_Width;
+                        }
+                    }
+                }
+                hv_FrameHeight.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_FrameHeight = hv_MaxHeight * new HTuple(hv_String_COPY_INP_TMP.TupleLength()
+                        );
+                }
+                hv_FrameWidth.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_FrameWidth = new HTuple(0).TupleConcat(
+                        hv_Width).TupleMax();
+                }
+                hv_R2.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_R2 = hv_R1 + hv_FrameHeight;
+                }
+                hv_C2.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_C2 = hv_C1 + hv_FrameWidth;
+                }
+                //Display rectangles.
+                hv_ClipRegion.Dispose();
+                HOperatorSet.GetSystem("clip_region", out hv_ClipRegion);
+                HOperatorSet.SetSystem("clip_region", "false");
+                hv_DrawMode.Dispose();
+                HOperatorSet.GetDraw(hv_WindowHandle, out hv_DrawMode);
+                HOperatorSet.SetDraw(hv_WindowHandle, "fill");
+                hv_BorderWidth.Dispose();
+                hv_BorderWidth = 2;
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    ho_UpperLeft.Dispose();
+                    HOperatorSet.GenRegionPolygonFilled(out ho_UpperLeft, (hv_R1 - hv_BorderWidth).TupleConcat(
+                        hv_R1 - hv_BorderWidth).TupleConcat(hv_R1).TupleConcat(hv_R2).TupleConcat(
+                        hv_R2 + hv_BorderWidth), (hv_C1 - hv_BorderWidth).TupleConcat(hv_C2 + hv_BorderWidth).TupleConcat(
+                        hv_C2).TupleConcat(hv_C1).TupleConcat(hv_C1 - hv_BorderWidth));
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    ho_LowerRight.Dispose();
+                    HOperatorSet.GenRegionPolygonFilled(out ho_LowerRight, (hv_R2 + hv_BorderWidth).TupleConcat(
+                        hv_R1 - hv_BorderWidth).TupleConcat(hv_R1).TupleConcat(hv_R2).TupleConcat(
+                        hv_R2 + hv_BorderWidth), (hv_C2 + hv_BorderWidth).TupleConcat(hv_C2 + hv_BorderWidth).TupleConcat(
+                        hv_C2).TupleConcat(hv_C1).TupleConcat(hv_C1 - hv_BorderWidth));
+                }
+                ho_Rectangle.Dispose();
+                HOperatorSet.GenRectangle1(out ho_Rectangle, hv_R1, hv_C1, hv_R2, hv_C2);
+                HOperatorSet.SetColor(hv_WindowHandle, hv_ButtonColorBorderL);
+                HOperatorSet.DispObj(ho_UpperLeft, hv_WindowHandle);
+                HOperatorSet.SetColor(hv_WindowHandle, hv_ButtonColorBorderD);
+                HOperatorSet.DispObj(ho_LowerRight, hv_WindowHandle);
+                HOperatorSet.SetColor(hv_WindowHandle, hv_ButtonColor);
+                HOperatorSet.DispObj(ho_Rectangle, hv_WindowHandle);
+                HOperatorSet.SetDraw(hv_WindowHandle, hv_DrawMode);
+                HOperatorSet.SetSystem("clip_region", hv_ClipRegion);
+                //Write text.
+                for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_String_COPY_INP_TMP.TupleLength()
+                    ) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    hv_CurrentColor.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_CurrentColor = hv_TextColor_COPY_INP_TMP.TupleSelect(
+                            hv_Index % new HTuple(hv_TextColor_COPY_INP_TMP.TupleLength()));
+                    }
+                    if ((int)new HTuple(hv_CurrentColor.TupleNotEqual("")).TupleAnd(new HTuple(hv_CurrentColor.TupleNotEqual(
+                        "auto"))) != 0)
+                    {
+                        HOperatorSet.SetColor(hv_WindowHandle, hv_CurrentColor);
+                    }
+                    else
+                    {
+                        HOperatorSet.SetRgb(hv_WindowHandle, hv_Red, hv_Green, hv_Blue);
+                    }
+                    hv_Row_COPY_INP_TMP.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Row_COPY_INP_TMP = hv_R1 + hv_MaxHeight * hv_Index;
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.DispText(hv_WindowHandle, hv_String_COPY_INP_TMP.TupleSelect(
+                            hv_Index), "window", hv_Row_COPY_INP_TMP, hv_C1, hv_CurrentColor, "box",
+                            "false");
+                    }
+                }
+                //Reset changed window settings.
+                HOperatorSet.SetRgb(hv_WindowHandle, hv_Red, hv_Green, hv_Blue);
+                HOperatorSet.SetPart(hv_WindowHandle, hv_Row1Part, hv_Column1Part, hv_Row2Part,
+                    hv_Column2Part);
+                ho_UpperLeft.Dispose();
+                ho_LowerRight.Dispose();
+                ho_Rectangle.Dispose();
+
+                hv_Column_COPY_INP_TMP.Dispose();
+                hv_Row_COPY_INP_TMP.Dispose();
+                hv_String_COPY_INP_TMP.Dispose();
+                hv_TextColor_COPY_INP_TMP.Dispose();
+                hv_Red.Dispose();
+                hv_Green.Dispose();
+                hv_Blue.Dispose();
+                hv_Row1Part.Dispose();
+                hv_Column1Part.Dispose();
+                hv_Row2Part.Dispose();
+                hv_Column2Part.Dispose();
+                hv_RowWin.Dispose();
+                hv_ColumnWin.Dispose();
+                hv_WidthWin.Dispose();
+                hv_HeightWin.Dispose();
+                hv_RGB.Dispose();
+                hv_Exception.Dispose();
+                hv_Fac.Dispose();
+                hv_RGBL.Dispose();
+                hv_RGBD.Dispose();
+                hv_ButtonColorBorderL.Dispose();
+                hv_ButtonColorBorderD.Dispose();
+                hv_MaxAscent.Dispose();
+                hv_MaxDescent.Dispose();
+                hv_MaxWidth.Dispose();
+                hv_MaxHeight.Dispose();
+                hv_R1.Dispose();
+                hv_C1.Dispose();
+                hv_FactorRow.Dispose();
+                hv_FactorColumn.Dispose();
+                hv_Width.Dispose();
+                hv_Index.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_W.Dispose();
+                hv_H.Dispose();
+                hv_FrameHeight.Dispose();
+                hv_FrameWidth.Dispose();
+                hv_R2.Dispose();
+                hv_C2.Dispose();
+                hv_ClipRegion.Dispose();
+                hv_DrawMode.Dispose();
+                hv_BorderWidth.Dispose();
+                hv_CurrentColor.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_UpperLeft.Dispose();
+                ho_LowerRight.Dispose();
+                ho_Rectangle.Dispose();
+
+                hv_Column_COPY_INP_TMP.Dispose();
+                hv_Row_COPY_INP_TMP.Dispose();
+                hv_String_COPY_INP_TMP.Dispose();
+                hv_TextColor_COPY_INP_TMP.Dispose();
+                hv_Red.Dispose();
+                hv_Green.Dispose();
+                hv_Blue.Dispose();
+                hv_Row1Part.Dispose();
+                hv_Column1Part.Dispose();
+                hv_Row2Part.Dispose();
+                hv_Column2Part.Dispose();
+                hv_RowWin.Dispose();
+                hv_ColumnWin.Dispose();
+                hv_WidthWin.Dispose();
+                hv_HeightWin.Dispose();
+                hv_RGB.Dispose();
+                hv_Exception.Dispose();
+                hv_Fac.Dispose();
+                hv_RGBL.Dispose();
+                hv_RGBD.Dispose();
+                hv_ButtonColorBorderL.Dispose();
+                hv_ButtonColorBorderD.Dispose();
+                hv_MaxAscent.Dispose();
+                hv_MaxDescent.Dispose();
+                hv_MaxWidth.Dispose();
+                hv_MaxHeight.Dispose();
+                hv_R1.Dispose();
+                hv_C1.Dispose();
+                hv_FactorRow.Dispose();
+                hv_FactorColumn.Dispose();
+                hv_Width.Dispose();
+                hv_Index.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_W.Dispose();
+                hv_H.Dispose();
+                hv_FrameHeight.Dispose();
+                hv_FrameWidth.Dispose();
+                hv_R2.Dispose();
+                hv_C2.Dispose();
+                hv_ClipRegion.Dispose();
+                hv_DrawMode.Dispose();
+                hv_BorderWidth.Dispose();
+                hv_CurrentColor.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Output
+        public static void disp_title_and_information(HTuple hv_WindowHandle, HTuple hv_Title,
+            HTuple hv_Information)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_WinRow = new HTuple(), hv_WinColumn = new HTuple();
+            HTuple hv_WinWidth = new HTuple(), hv_WinHeight = new HTuple();
+            HTuple hv_NumTitleLines = new HTuple(), hv_Row = new HTuple();
+            HTuple hv_Column = new HTuple(), hv_TextWidth = new HTuple();
+            HTuple hv_NumInfoLines = new HTuple(), hv_Ascent = new HTuple();
+            HTuple hv_Descent = new HTuple(), hv_Width = new HTuple();
+            HTuple hv_Height = new HTuple();
+            HTuple hv_Information_COPY_INP_TMP = new HTuple(hv_Information);
+            HTuple hv_Title_COPY_INP_TMP = new HTuple(hv_Title);
+
+            // Initialize local and output iconic variables 
+            try
+            {
+                //
+                //global tuple gInfoDecor
+                //global tuple gInfoPos
+                //global tuple gTitlePos
+                //global tuple gTitleDecor
+                //
+                hv_WinRow.Dispose(); hv_WinColumn.Dispose(); hv_WinWidth.Dispose(); hv_WinHeight.Dispose();
+                HOperatorSet.GetWindowExtents(hv_WindowHandle, out hv_WinRow, out hv_WinColumn,
+                    out hv_WinWidth, out hv_WinHeight);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_Title = ("" + hv_Title_COPY_INP_TMP + "").TupleSplit(
+                            "\n");
+                        hv_Title_COPY_INP_TMP.Dispose();
+                        hv_Title_COPY_INP_TMP = ExpTmpLocalVar_Title;
+                    }
+                }
+                hv_NumTitleLines.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_NumTitleLines = new HTuple(hv_Title_COPY_INP_TMP.TupleLength()
+                        );
+                }
+                if ((int)new HTuple(hv_NumTitleLines.TupleGreater(0)) != 0)
+                {
+                    hv_Row.Dispose();
+                    hv_Row = 12;
+                    if ((int)new HTuple(ExpGetGlobalVar_gTitlePos().TupleEqual("UpperLeft")) != 0)
+                    {
+                        hv_Column.Dispose();
+                        hv_Column = 12;
+                    }
+                    else if ((int)new HTuple(ExpGetGlobalVar_gTitlePos().TupleEqual(
+                        "UpperCenter")) != 0)
+                    {
+                        hv_TextWidth.Dispose();
+                        max_line_width(hv_WindowHandle, hv_Title_COPY_INP_TMP, out hv_TextWidth);
+                        hv_Column.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Column = hv_WinWidth / 2 - hv_TextWidth / 2;
+                        }
+                    }
+                    else if ((int)new HTuple(ExpGetGlobalVar_gTitlePos().TupleEqual(
+                        "UpperRight")) != 0)
+                    {
+                        if ((int)new HTuple(ExpGetGlobalVar_gTitleDecor().TupleSelect(1).TupleEqual(
+                            "true")) != 0)
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_TextWidth.Dispose();
+                                max_line_width(hv_WindowHandle, hv_Title_COPY_INP_TMP + "  ", out hv_TextWidth);
+                            }
+                        }
+                        else
+                        {
+                            hv_TextWidth.Dispose();
+                            max_line_width(hv_WindowHandle, hv_Title_COPY_INP_TMP, out hv_TextWidth);
+                        }
+                        hv_Column.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Column = hv_WinWidth - hv_TextWidth - 10;
+                        }
+                    }
+                    else
+                    {
+                        //Unknown position!
+                        // stop(...); only in hdevelop
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        disp_message(hv_WindowHandle, hv_Title_COPY_INP_TMP, "window", hv_Row, hv_Column,
+                            ExpGetGlobalVar_gTitleDecor().TupleSelect(0), ExpGetGlobalVar_gTitleDecor().TupleSelect(
+                            1));
+                    }
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_Information = ("" + hv_Information_COPY_INP_TMP + "").TupleSplit(
+                            "\n");
+                        hv_Information_COPY_INP_TMP.Dispose();
+                        hv_Information_COPY_INP_TMP = ExpTmpLocalVar_Information;
+                    }
+                }
+                hv_NumInfoLines.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_NumInfoLines = new HTuple(hv_Information_COPY_INP_TMP.TupleLength()
+                        );
+                }
+                if ((int)new HTuple(hv_NumInfoLines.TupleGreater(0)) != 0)
+                {
+                    if ((int)new HTuple(ExpGetGlobalVar_gInfoPos().TupleEqual("UpperLeft")) != 0)
+                    {
+                        hv_Row.Dispose();
+                        hv_Row = 12;
+                        hv_Column.Dispose();
+                        hv_Column = 12;
+                    }
+                    else if ((int)new HTuple(ExpGetGlobalVar_gInfoPos().TupleEqual(
+                        "UpperRight")) != 0)
+                    {
+                        if ((int)new HTuple(ExpGetGlobalVar_gInfoDecor().TupleSelect(1).TupleEqual(
+                            "true")) != 0)
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_TextWidth.Dispose();
+                                max_line_width(hv_WindowHandle, hv_Information_COPY_INP_TMP + "  ", out hv_TextWidth);
+                            }
+                        }
+                        else
+                        {
+                            hv_TextWidth.Dispose();
+                            max_line_width(hv_WindowHandle, hv_Information_COPY_INP_TMP, out hv_TextWidth);
+                        }
+                        hv_Row.Dispose();
+                        hv_Row = 12;
+                        hv_Column.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Column = hv_WinWidth - hv_TextWidth - 12;
+                        }
+                    }
+                    else if ((int)new HTuple(ExpGetGlobalVar_gInfoPos().TupleEqual(
+                        "LowerLeft")) != 0)
+                    {
+                        hv_Ascent.Dispose(); hv_Descent.Dispose(); hv_Width.Dispose(); hv_Height.Dispose();
+                        HOperatorSet.GetStringExtents(hv_WindowHandle, hv_Information_COPY_INP_TMP,
+                            out hv_Ascent, out hv_Descent, out hv_Width, out hv_Height);
+                        hv_Row.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Row = hv_WinHeight - (new HTuple(0).TupleMax2(
+                                hv_NumInfoLines - 1) * (hv_Ascent + hv_Descent) + hv_Height) - 12;
+                        }
+                        hv_Column.Dispose();
+                        hv_Column = 12;
+                    }
+                    else
+                    {
+                        //Unknown position!
+                        // stop(...); only in hdevelop
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        disp_message(hv_WindowHandle, hv_Information_COPY_INP_TMP, "window", hv_Row,
+                            hv_Column, ExpGetGlobalVar_gInfoDecor().TupleSelect(0), ExpGetGlobalVar_gInfoDecor().TupleSelect(
+                            1));
+                    }
+                }
+                //
+
+                hv_Information_COPY_INP_TMP.Dispose();
+                hv_Title_COPY_INP_TMP.Dispose();
+                hv_WinRow.Dispose();
+                hv_WinColumn.Dispose();
+                hv_WinWidth.Dispose();
+                hv_WinHeight.Dispose();
+                hv_NumTitleLines.Dispose();
+                hv_Row.Dispose();
+                hv_Column.Dispose();
+                hv_TextWidth.Dispose();
+                hv_NumInfoLines.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Information_COPY_INP_TMP.Dispose();
+                hv_Title_COPY_INP_TMP.Dispose();
+                hv_WinRow.Dispose();
+                hv_WinColumn.Dispose();
+                hv_WinWidth.Dispose();
+                hv_WinHeight.Dispose();
+                hv_NumTitleLines.Dispose();
+                hv_Row.Dispose();
+                hv_Column.Dispose();
+                hv_TextWidth.Dispose();
+                hv_NumInfoLines.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Output
+        // Short Description: Render 3D object models in a buffer window. 
+        public static void dump_image_output(HObject ho_BackgroundImage, HTuple hv_WindowHandleBuffer,
+            HTuple hv_Scene3D, HTuple hv_AlphaOrig, HTuple hv_ObjectModel3DID, HTuple hv_GenParamName,
+            HTuple hv_GenParamValue, HTuple hv_CamParam, HTuple hv_Poses, HTuple hv_ColorImage,
+            HTuple hv_Title, HTuple hv_Information, HTuple hv_Labels, HTuple hv_VisualizeTrackball,
+            HTuple hv_DisplayContinueButton, HTuple hv_TrackballCenterRow, HTuple hv_TrackballCenterCol,
+            HTuple hv_TrackballRadiusPixel, HTuple hv_SelectedObject, HTuple hv_VisualizeRotationCenter,
+            HTuple hv_RotationCenter)
+        {
+
+
+
+
+            // Local iconic variables 
+
+            HObject ho_ModelContours = null, ho_TrackballContour = null;
+            HObject ho_CrossRotCenter = null;
+
+            // Local control variables 
+
+            HTuple ExpTmpLocalVar_gUsesOpenGL = new HTuple();
+            HTuple hv_Exception = new HTuple(), hv_Index = new HTuple();
+            HTuple hv_Exception1 = new HTuple(), hv_DeselectedIdx = new HTuple();
+            HTuple hv_DeselectedName = new HTuple(), hv_DeselectedValue = new HTuple();
+            HTuple hv_Pose = new HTuple(), hv_HomMat3D = new HTuple();
+            HTuple hv_Center = new HTuple(), hv_CenterCamX = new HTuple();
+            HTuple hv_CenterCamY = new HTuple(), hv_CenterCamZ = new HTuple();
+            HTuple hv_CenterRow = new HTuple(), hv_CenterCol = new HTuple();
+            HTuple hv_Label = new HTuple(), hv_Sublabels = new HTuple();
+            HTuple hv_Ascent = new HTuple(), hv_Descent = new HTuple();
+            HTuple hv_TextWidth = new HTuple(), hv_TextHeight = new HTuple();
+            HTuple hv_Index2 = new HTuple(), hv_TextWidth2 = new HTuple();
+            HTuple hv_TextHeight2 = new HTuple(), hv_RotCenterRow = new HTuple();
+            HTuple hv_RotCenterCol = new HTuple(), hv_Orientation = new HTuple();
+            HTuple hv_Colors = new HTuple();
+            HTuple hv_RotationCenter_COPY_INP_TMP = new HTuple(hv_RotationCenter);
+
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_ModelContours);
+            HOperatorSet.GenEmptyObj(out ho_TrackballContour);
+            HOperatorSet.GenEmptyObj(out ho_CrossRotCenter);
+            try
+            {
+                //global tuple gAlphaDeselected
+                //global tuple gTerminationButtonLabel
+                //global tuple gDispObjOffset
+                //global tuple gLabelsDecor
+                //global tuple gUsesOpenGL
+                //
+                //Display background image
+                HOperatorSet.ClearWindow(hv_WindowHandleBuffer);
+                if ((int)hv_ColorImage != 0)
+                {
+                    HOperatorSet.DispColor(ho_BackgroundImage, hv_WindowHandleBuffer);
+                }
+                else
+                {
+                    HOperatorSet.DispImage(ho_BackgroundImage, hv_WindowHandleBuffer);
+                }
+                //
+                //Display objects
+                if ((int)new HTuple(hv_SelectedObject.TupleSum().TupleEqual(new HTuple(hv_SelectedObject.TupleLength()
+                    ))) != 0)
+                {
+                    if ((int)new HTuple(ExpGetGlobalVar_gUsesOpenGL().TupleEqual("true")) != 0)
+                    {
+                        try
+                        {
+                            HOperatorSet.DisplayScene3d(hv_WindowHandleBuffer, hv_Scene3D, 0);
+                        }
+                        // catch (Exception) 
+                        catch (HalconException HDevExpDefaultException1)
+                        {
+                            HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                            if ((int)new HTuple(new HTuple(hv_Exception.TupleSelect(0).TupleEqual(
+                                5185)).TupleOr(new HTuple(hv_Exception.TupleSelect(0).TupleEqual(
+                                5188)))).TupleOr(new HTuple(hv_Exception.TupleSelect(0).TupleEqual(
+                                5187))) != 0)
+                            {
+                                ExpTmpLocalVar_gUsesOpenGL = "false";
+                                ExpSetGlobalVar_gUsesOpenGL(ExpTmpLocalVar_gUsesOpenGL);
+                            }
+                            else
+                            {
+                                throw new HalconException(hv_Exception);
+                            }
+                        }
+                    }
+                    if ((int)new HTuple(ExpGetGlobalVar_gUsesOpenGL().TupleEqual("false")) != 0)
+                    {
+                        //* NO OpenGL, use fallback
+                        ho_ModelContours.Dispose();
+                        disp_object_model_no_opengl(out ho_ModelContours, hv_ObjectModel3DID, hv_GenParamName,
+                            hv_GenParamValue, hv_WindowHandleBuffer, hv_CamParam, hv_Poses);
+                    }
+                }
+                else
+                {
+                    for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_AlphaOrig.TupleLength()
+                        ) - 1); hv_Index = (int)hv_Index + 1)
+                    {
+                        if ((int)new HTuple(hv_SelectedObject.TupleSelect(hv_Index).TupleEqual(
+                            1)) != 0)
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                HOperatorSet.SetScene3dInstanceParam(hv_Scene3D, hv_Index, "alpha", hv_AlphaOrig.TupleSelect(
+                                    hv_Index));
+                            }
+                        }
+                        else
+                        {
+                            HOperatorSet.SetScene3dInstanceParam(hv_Scene3D, hv_Index, "alpha", ExpGetGlobalVar_gAlphaDeselected());
+                        }
+                    }
+                    try
+                    {
+                        if ((int)new HTuple(ExpGetGlobalVar_gUsesOpenGL().TupleEqual("false")) != 0)
+                        {
+                            throw new HalconException(new HTuple());
+                        }
+                        HOperatorSet.DisplayScene3d(hv_WindowHandleBuffer, hv_Scene3D, 0);
+                    }
+                    // catch (Exception1) 
+                    catch (HalconException HDevExpDefaultException1)
+                    {
+                        HDevExpDefaultException1.ToHTuple(out hv_Exception1);
+                        //* NO OpenGL, use fallback
+                        hv_DeselectedIdx.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_DeselectedIdx = hv_SelectedObject.TupleFind(
+                                0);
+                        }
+                        if ((int)new HTuple(hv_DeselectedIdx.TupleNotEqual(-1)) != 0)
+                        {
+                            hv_DeselectedName.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_DeselectedName = "color_" + hv_DeselectedIdx;
+                            }
+                            hv_DeselectedValue.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_DeselectedValue = HTuple.TupleGenConst(
+                                    new HTuple(hv_DeselectedName.TupleLength()), "gray");
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            ho_ModelContours.Dispose();
+                            disp_object_model_no_opengl(out ho_ModelContours, hv_ObjectModel3DID, hv_GenParamName.TupleConcat(
+                                hv_DeselectedName), hv_GenParamValue.TupleConcat(hv_DeselectedValue),
+                                hv_WindowHandleBuffer, hv_CamParam, hv_Poses);
+                        }
+                    }
+                    for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_AlphaOrig.TupleLength()
+                        ) - 1); hv_Index = (int)hv_Index + 1)
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HOperatorSet.SetScene3dInstanceParam(hv_Scene3D, hv_Index, "alpha", hv_AlphaOrig.TupleSelect(
+                                hv_Index));
+                        }
+                    }
+                }
+                //
+                //Display labels
+                if ((int)new HTuple(hv_Labels.TupleNotEqual(new HTuple())) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.SetColor(hv_WindowHandleBuffer, ExpGetGlobalVar_gLabelsDecor().TupleSelect(
+                            0));
+                    }
+                    for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_ObjectModel3DID.TupleLength()
+                        ) - 1); hv_Index = (int)hv_Index + 1)
+                    {
+                        //Project the center point of the current model
+                        hv_Pose.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Pose = hv_Poses.TupleSelectRange(
+                                hv_Index * 7, hv_Index * 7 + 6);
+                        }
+                        hv_HomMat3D.Dispose();
+                        HOperatorSet.PoseToHomMat3d(hv_Pose, out hv_HomMat3D);
+                        try
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Center.Dispose();
+                                HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID.TupleSelect(hv_Index),
+                                    "center", out hv_Center);
+                            }
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_CenterCamX.Dispose(); hv_CenterCamY.Dispose(); hv_CenterCamZ.Dispose();
+                                HOperatorSet.AffineTransPoint3d(hv_HomMat3D, hv_Center.TupleSelect(0),
+                                    hv_Center.TupleSelect(1), hv_Center.TupleSelect(2), out hv_CenterCamX,
+                                    out hv_CenterCamY, out hv_CenterCamZ);
+                            }
+                            hv_CenterRow.Dispose(); hv_CenterCol.Dispose();
+                            HOperatorSet.Project3dPoint(hv_CenterCamX, hv_CenterCamY, hv_CenterCamZ,
+                                hv_CamParam, out hv_CenterRow, out hv_CenterCol);
+                            hv_Label.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Label = hv_Labels.TupleSelect(
+                                    hv_Index);
+                            }
+                            if ((int)new HTuple(hv_Label.TupleNotEqual("")) != 0)
+                            {
+                                //Work around the fact that get_string_extents() does not handle newlines as we want
+                                hv_Sublabels.Dispose();
+                                HOperatorSet.TupleSplit(hv_Label, "\n", out hv_Sublabels);
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_Ascent.Dispose(); hv_Descent.Dispose(); hv_TextWidth.Dispose(); hv_TextHeight.Dispose();
+                                    HOperatorSet.GetStringExtents(hv_WindowHandleBuffer, hv_Sublabels.TupleSelect(
+                                        0), out hv_Ascent, out hv_Descent, out hv_TextWidth, out hv_TextHeight);
+                                }
+                                for (hv_Index2 = 1; (int)hv_Index2 <= (int)(new HTuple(hv_Sublabels.TupleLength()
+                                    ) - 1); hv_Index2 = (int)hv_Index2 + 1)
+                                {
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        hv_Ascent.Dispose(); hv_Descent.Dispose(); hv_TextWidth2.Dispose(); hv_TextHeight2.Dispose();
+                                        HOperatorSet.GetStringExtents(hv_WindowHandleBuffer, hv_Sublabels.TupleSelect(
+                                            hv_Index2), out hv_Ascent, out hv_Descent, out hv_TextWidth2,
+                                            out hv_TextHeight2);
+                                    }
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        {
+                                            HTuple
+                                              ExpTmpLocalVar_TextHeight = hv_TextHeight + hv_TextHeight2;
+                                            hv_TextHeight.Dispose();
+                                            hv_TextHeight = ExpTmpLocalVar_TextHeight;
+                                        }
+                                    }
+                                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                    {
+                                        {
+                                            HTuple
+                                              ExpTmpLocalVar_TextWidth = hv_TextWidth.TupleMax2(
+                                                hv_TextWidth2);
+                                            hv_TextWidth.Dispose();
+                                            hv_TextWidth = ExpTmpLocalVar_TextWidth;
+                                        }
+                                    }
+                                }
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    disp_message(hv_WindowHandleBuffer, hv_Label, "window", hv_CenterRow - hv_TextHeight / 2 + ExpGetGlobalVar_gDispObjOffset().TupleSelect(
+                                        0), hv_CenterCol - hv_TextWidth / 2 + ExpGetGlobalVar_gDispObjOffset().TupleSelect(
+                                        1), new HTuple(), ExpGetGlobalVar_gLabelsDecor().TupleSelect(1));
+                                }
+                            }
+                        }
+                        // catch (Exception) 
+                        catch (HalconException HDevExpDefaultException1)
+                        {
+                            HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                            //The 3D object model might not have a center because it is empty
+                            //-> do not display any label
+                        }
+                    }
+                }
+                //
+                //Visualize the trackball if desired
+                if ((int)hv_VisualizeTrackball != 0)
+                {
+                    HOperatorSet.SetLineWidth(hv_WindowHandleBuffer, 1);
+                    ho_TrackballContour.Dispose();
+                    HOperatorSet.GenEllipseContourXld(out ho_TrackballContour, hv_TrackballCenterRow,
+                        hv_TrackballCenterCol, 0, hv_TrackballRadiusPixel, hv_TrackballRadiusPixel,
+                        0, 6.28318, "positive", 1.5);
+                    HOperatorSet.SetColor(hv_WindowHandleBuffer, "dim gray");
+                    HOperatorSet.DispXld(ho_TrackballContour, hv_WindowHandleBuffer);
+                }
+                //
+                //Visualize the rotation center if desired
+                if ((int)new HTuple(hv_VisualizeRotationCenter.TupleNotEqual(0)).TupleAnd(
+                    new HTuple(new HTuple(hv_RotationCenter_COPY_INP_TMP.TupleLength()).TupleEqual(
+                    3))) != 0)
+                {
+                    if ((int)new HTuple(hv_RotationCenter_COPY_INP_TMP.TupleSelect(2).TupleLess(
+                        1e-10)) != 0)
+                    {
+                        if (hv_RotationCenter_COPY_INP_TMP == null)
+                            hv_RotationCenter_COPY_INP_TMP = new HTuple();
+                        hv_RotationCenter_COPY_INP_TMP[2] = 1e-10;
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_RotCenterRow.Dispose(); hv_RotCenterCol.Dispose();
+                        HOperatorSet.Project3dPoint(hv_RotationCenter_COPY_INP_TMP.TupleSelect(0),
+                            hv_RotationCenter_COPY_INP_TMP.TupleSelect(1), hv_RotationCenter_COPY_INP_TMP.TupleSelect(
+                            2), hv_CamParam, out hv_RotCenterRow, out hv_RotCenterCol);
+                    }
+                    hv_Orientation.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Orientation = new HTuple(90).TupleRad()
+                            ;
+                    }
+                    if ((int)new HTuple(hv_VisualizeRotationCenter.TupleEqual(1)) != 0)
+                    {
+                        hv_Orientation.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Orientation = new HTuple(45).TupleRad()
+                                ;
+                        }
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        ho_CrossRotCenter.Dispose();
+                        HOperatorSet.GenCrossContourXld(out ho_CrossRotCenter, hv_RotCenterRow, hv_RotCenterCol,
+                            hv_TrackballRadiusPixel / 25.0, hv_Orientation);
+                    }
+                    HOperatorSet.SetLineWidth(hv_WindowHandleBuffer, 3);
+                    hv_Colors.Dispose();
+                    HOperatorSet.QueryColor(hv_WindowHandleBuffer, out hv_Colors);
+                    HOperatorSet.SetColor(hv_WindowHandleBuffer, "light gray");
+                    HOperatorSet.DispXld(ho_CrossRotCenter, hv_WindowHandleBuffer);
+                    HOperatorSet.SetLineWidth(hv_WindowHandleBuffer, 1);
+                    HOperatorSet.SetColor(hv_WindowHandleBuffer, "dim gray");
+                    HOperatorSet.DispXld(ho_CrossRotCenter, hv_WindowHandleBuffer);
+                }
+                //
+                //Display title
+                disp_title_and_information(hv_WindowHandleBuffer, hv_Title, hv_Information);
+                //
+                //Display the 'Exit' button
+                if ((int)new HTuple(hv_DisplayContinueButton.TupleEqual("true")) != 0)
+                {
+                    disp_continue_button(hv_WindowHandleBuffer);
+                }
+                //
+                ho_ModelContours.Dispose();
+                ho_TrackballContour.Dispose();
+                ho_CrossRotCenter.Dispose();
+
+                hv_RotationCenter_COPY_INP_TMP.Dispose();
+                hv_Exception.Dispose();
+                hv_Index.Dispose();
+                hv_Exception1.Dispose();
+                hv_DeselectedIdx.Dispose();
+                hv_DeselectedName.Dispose();
+                hv_DeselectedValue.Dispose();
+                hv_Pose.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_Center.Dispose();
+                hv_CenterCamX.Dispose();
+                hv_CenterCamY.Dispose();
+                hv_CenterCamZ.Dispose();
+                hv_CenterRow.Dispose();
+                hv_CenterCol.Dispose();
+                hv_Label.Dispose();
+                hv_Sublabels.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_TextWidth.Dispose();
+                hv_TextHeight.Dispose();
+                hv_Index2.Dispose();
+                hv_TextWidth2.Dispose();
+                hv_TextHeight2.Dispose();
+                hv_RotCenterRow.Dispose();
+                hv_RotCenterCol.Dispose();
+                hv_Orientation.Dispose();
+                hv_Colors.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_ModelContours.Dispose();
+                ho_TrackballContour.Dispose();
+                ho_CrossRotCenter.Dispose();
+
+                hv_RotationCenter_COPY_INP_TMP.Dispose();
+                hv_Exception.Dispose();
+                hv_Index.Dispose();
+                hv_Exception1.Dispose();
+                hv_DeselectedIdx.Dispose();
+                hv_DeselectedName.Dispose();
+                hv_DeselectedValue.Dispose();
+                hv_Pose.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_Center.Dispose();
+                hv_CenterCamX.Dispose();
+                hv_CenterCamY.Dispose();
+                hv_CenterCamZ.Dispose();
+                hv_CenterRow.Dispose();
+                hv_CenterCol.Dispose();
+                hv_Label.Dispose();
+                hv_Sublabels.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_TextWidth.Dispose();
+                hv_TextHeight.Dispose();
+                hv_Index2.Dispose();
+                hv_TextWidth2.Dispose();
+                hv_TextHeight2.Dispose();
+                hv_RotCenterRow.Dispose();
+                hv_RotCenterCol.Dispose();
+                hv_Orientation.Dispose();
+                hv_Colors.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Calibration / Camera Parameters
+        // Short Description: Generate a camera parameter tuple for an area scan camera with distortions modeled by the division model. 
+        public static void gen_cam_par_area_scan_division(HTuple hv_Focus, HTuple hv_Kappa, HTuple hv_Sx,
+            HTuple hv_Sy, HTuple hv_Cx, HTuple hv_Cy, HTuple hv_ImageWidth, HTuple hv_ImageHeight,
+            out HTuple hv_CameraParam)
+        {
+
+
+
+            // Local iconic variables 
+            // Initialize local and output iconic variables 
+            hv_CameraParam = new HTuple();
+            //Generate a camera parameter tuple for an area scan camera
+            //with distortions modeled by the division model.
+            //
+            hv_CameraParam.Dispose();
+            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+            {
+                hv_CameraParam = new HTuple();
+                hv_CameraParam[0] = "area_scan_division";
+                hv_CameraParam = hv_CameraParam.TupleConcat(hv_Focus, hv_Kappa, hv_Sx, hv_Sy, hv_Cx, hv_Cy, hv_ImageWidth, hv_ImageHeight);
+            }
+
+
+            return;
+        }
+
+        // Chapter: Calibration / Camera Parameters
+        // Short Description: Get the value of a specified camera parameter from the camera parameter tuple. 
+        public static void get_cam_par_data(HTuple hv_CameraParam, HTuple hv_ParamName, out HTuple hv_ParamValue)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_CameraType = new HTuple(), hv_CameraParamNames = new HTuple();
+            HTuple hv_Index = new HTuple(), hv_ParamNameInd = new HTuple();
+            HTuple hv_I = new HTuple();
+            // Initialize local and output iconic variables 
+            hv_ParamValue = new HTuple();
+            try
+            {
+                //get_cam_par_data returns in ParamValue the value of the
+                //parameter that is given in ParamName from the tuple of
+                //camera parameters that is given in CameraParam.
+                //
+                //Get the parameter names that correspond to the
+                //elements in the input camera parameter tuple.
+                hv_CameraType.Dispose(); hv_CameraParamNames.Dispose();
+                get_cam_par_names(hv_CameraParam, out hv_CameraType, out hv_CameraParamNames);
+                //
+                //Find the index of the requested camera data and return
+                //the corresponding value.
+                hv_ParamValue.Dispose();
+                hv_ParamValue = new HTuple();
+                for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_ParamName.TupleLength()
+                    ) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    hv_ParamNameInd.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_ParamNameInd = hv_ParamName.TupleSelect(
+                            hv_Index);
+                    }
+                    if ((int)new HTuple(hv_ParamNameInd.TupleEqual("camera_type")) != 0)
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_ParamValue = hv_ParamValue.TupleConcat(
+                                    hv_CameraType);
+                                hv_ParamValue.Dispose();
+                                hv_ParamValue = ExpTmpLocalVar_ParamValue;
+                            }
+                        }
+                        continue;
+                    }
+                    hv_I.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_I = hv_CameraParamNames.TupleFind(
+                            hv_ParamNameInd);
+                    }
+                    if ((int)new HTuple(hv_I.TupleNotEqual(-1)) != 0)
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_ParamValue = hv_ParamValue.TupleConcat(
+                                    hv_CameraParam.TupleSelect(hv_I));
+                                hv_ParamValue.Dispose();
+                                hv_ParamValue = ExpTmpLocalVar_ParamValue;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        throw new HalconException("Unknown camera parameter " + hv_ParamNameInd);
+                    }
+                }
+
+                hv_CameraType.Dispose();
+                hv_CameraParamNames.Dispose();
+                hv_Index.Dispose();
+                hv_ParamNameInd.Dispose();
+                hv_I.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_CameraType.Dispose();
+                hv_CameraParamNames.Dispose();
+                hv_Index.Dispose();
+                hv_ParamNameInd.Dispose();
+                hv_I.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Calibration / Camera Parameters
+        // Short Description: Get the names of the parameters in a camera parameter tuple. 
+        public static void get_cam_par_names(HTuple hv_CameraParam, out HTuple hv_CameraType,
+            out HTuple hv_ParamNames)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_CameraParamAreaScanDivision = new HTuple();
+            HTuple hv_CameraParamAreaScanPolynomial = new HTuple();
+            HTuple hv_CameraParamAreaScanTelecentricDivision = new HTuple();
+            HTuple hv_CameraParamAreaScanTelecentricPolynomial = new HTuple();
+            HTuple hv_CameraParamAreaScanTiltDivision = new HTuple();
+            HTuple hv_CameraParamAreaScanTiltPolynomial = new HTuple();
+            HTuple hv_CameraParamAreaScanImageSideTelecentricTiltDivision = new HTuple();
+            HTuple hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial = new HTuple();
+            HTuple hv_CameraParamAreaScanBilateralTelecentricTiltDivision = new HTuple();
+            HTuple hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial = new HTuple();
+            HTuple hv_CameraParamAreaScanObjectSideTelecentricTiltDivision = new HTuple();
+            HTuple hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial = new HTuple();
+            HTuple hv_CameraParamAreaScanHypercentricDivision = new HTuple();
+            HTuple hv_CameraParamAreaScanHypercentricPolynomial = new HTuple();
+            HTuple hv_CameraParamLinesScanDivision = new HTuple();
+            HTuple hv_CameraParamLinesScanPolynomial = new HTuple();
+            HTuple hv_CameraParamLinesScanTelecentricDivision = new HTuple();
+            HTuple hv_CameraParamLinesScanTelecentricPolynomial = new HTuple();
+            HTuple hv_CameraParamAreaScanTiltDivisionLegacy = new HTuple();
+            HTuple hv_CameraParamAreaScanTiltPolynomialLegacy = new HTuple();
+            HTuple hv_CameraParamAreaScanTelecentricDivisionLegacy = new HTuple();
+            HTuple hv_CameraParamAreaScanTelecentricPolynomialLegacy = new HTuple();
+            HTuple hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy = new HTuple();
+            HTuple hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy = new HTuple();
+            // Initialize local and output iconic variables 
+            hv_CameraType = new HTuple();
+            hv_ParamNames = new HTuple();
+            try
+            {
+                //get_cam_par_names returns for each element in the camera
+                //parameter tuple that is passed in CameraParam the name
+                //of the respective camera parameter. The parameter names
+                //are returned in ParamNames. Additionally, the camera
+                //type is returned in CameraType. Alternatively, instead of
+                //the camera parameters, the camera type can be passed in
+                //CameraParam in form of one of the following strings:
+                //  - 'area_scan_division'
+                //  - 'area_scan_polynomial'
+                //  - 'area_scan_tilt_division'
+                //  - 'area_scan_tilt_polynomial'
+                //  - 'area_scan_telecentric_division'
+                //  - 'area_scan_telecentric_polynomial'
+                //  - 'area_scan_tilt_bilateral_telecentric_division'
+                //  - 'area_scan_tilt_bilateral_telecentric_polynomial'
+                //  - 'area_scan_tilt_object_side_telecentric_division'
+                //  - 'area_scan_tilt_object_side_telecentric_polynomial'
+                //  - 'area_scan_hypercentric_division'
+                //  - 'area_scan_hypercentric_polynomial'
+                //  - 'line_scan_division'
+                //  - 'line_scan_polynomial'
+                //  - 'line_scan_telecentric_division'
+                //  - 'line_scan_telecentric_polynomial'
+                //
+                hv_CameraParamAreaScanDivision.Dispose();
+                hv_CameraParamAreaScanDivision = new HTuple();
+                hv_CameraParamAreaScanDivision[0] = "focus";
+                hv_CameraParamAreaScanDivision[1] = "kappa";
+                hv_CameraParamAreaScanDivision[2] = "sx";
+                hv_CameraParamAreaScanDivision[3] = "sy";
+                hv_CameraParamAreaScanDivision[4] = "cx";
+                hv_CameraParamAreaScanDivision[5] = "cy";
+                hv_CameraParamAreaScanDivision[6] = "image_width";
+                hv_CameraParamAreaScanDivision[7] = "image_height";
+                hv_CameraParamAreaScanPolynomial.Dispose();
+                hv_CameraParamAreaScanPolynomial = new HTuple();
+                hv_CameraParamAreaScanPolynomial[0] = "focus";
+                hv_CameraParamAreaScanPolynomial[1] = "k1";
+                hv_CameraParamAreaScanPolynomial[2] = "k2";
+                hv_CameraParamAreaScanPolynomial[3] = "k3";
+                hv_CameraParamAreaScanPolynomial[4] = "p1";
+                hv_CameraParamAreaScanPolynomial[5] = "p2";
+                hv_CameraParamAreaScanPolynomial[6] = "sx";
+                hv_CameraParamAreaScanPolynomial[7] = "sy";
+                hv_CameraParamAreaScanPolynomial[8] = "cx";
+                hv_CameraParamAreaScanPolynomial[9] = "cy";
+                hv_CameraParamAreaScanPolynomial[10] = "image_width";
+                hv_CameraParamAreaScanPolynomial[11] = "image_height";
+                hv_CameraParamAreaScanTelecentricDivision.Dispose();
+                hv_CameraParamAreaScanTelecentricDivision = new HTuple();
+                hv_CameraParamAreaScanTelecentricDivision[0] = "magnification";
+                hv_CameraParamAreaScanTelecentricDivision[1] = "kappa";
+                hv_CameraParamAreaScanTelecentricDivision[2] = "sx";
+                hv_CameraParamAreaScanTelecentricDivision[3] = "sy";
+                hv_CameraParamAreaScanTelecentricDivision[4] = "cx";
+                hv_CameraParamAreaScanTelecentricDivision[5] = "cy";
+                hv_CameraParamAreaScanTelecentricDivision[6] = "image_width";
+                hv_CameraParamAreaScanTelecentricDivision[7] = "image_height";
+                hv_CameraParamAreaScanTelecentricPolynomial.Dispose();
+                hv_CameraParamAreaScanTelecentricPolynomial = new HTuple();
+                hv_CameraParamAreaScanTelecentricPolynomial[0] = "magnification";
+                hv_CameraParamAreaScanTelecentricPolynomial[1] = "k1";
+                hv_CameraParamAreaScanTelecentricPolynomial[2] = "k2";
+                hv_CameraParamAreaScanTelecentricPolynomial[3] = "k3";
+                hv_CameraParamAreaScanTelecentricPolynomial[4] = "p1";
+                hv_CameraParamAreaScanTelecentricPolynomial[5] = "p2";
+                hv_CameraParamAreaScanTelecentricPolynomial[6] = "sx";
+                hv_CameraParamAreaScanTelecentricPolynomial[7] = "sy";
+                hv_CameraParamAreaScanTelecentricPolynomial[8] = "cx";
+                hv_CameraParamAreaScanTelecentricPolynomial[9] = "cy";
+                hv_CameraParamAreaScanTelecentricPolynomial[10] = "image_width";
+                hv_CameraParamAreaScanTelecentricPolynomial[11] = "image_height";
+                hv_CameraParamAreaScanTiltDivision.Dispose();
+                hv_CameraParamAreaScanTiltDivision = new HTuple();
+                hv_CameraParamAreaScanTiltDivision[0] = "focus";
+                hv_CameraParamAreaScanTiltDivision[1] = "kappa";
+                hv_CameraParamAreaScanTiltDivision[2] = "image_plane_dist";
+                hv_CameraParamAreaScanTiltDivision[3] = "tilt";
+                hv_CameraParamAreaScanTiltDivision[4] = "rot";
+                hv_CameraParamAreaScanTiltDivision[5] = "sx";
+                hv_CameraParamAreaScanTiltDivision[6] = "sy";
+                hv_CameraParamAreaScanTiltDivision[7] = "cx";
+                hv_CameraParamAreaScanTiltDivision[8] = "cy";
+                hv_CameraParamAreaScanTiltDivision[9] = "image_width";
+                hv_CameraParamAreaScanTiltDivision[10] = "image_height";
+                hv_CameraParamAreaScanTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanTiltPolynomial = new HTuple();
+                hv_CameraParamAreaScanTiltPolynomial[0] = "focus";
+                hv_CameraParamAreaScanTiltPolynomial[1] = "k1";
+                hv_CameraParamAreaScanTiltPolynomial[2] = "k2";
+                hv_CameraParamAreaScanTiltPolynomial[3] = "k3";
+                hv_CameraParamAreaScanTiltPolynomial[4] = "p1";
+                hv_CameraParamAreaScanTiltPolynomial[5] = "p2";
+                hv_CameraParamAreaScanTiltPolynomial[6] = "image_plane_dist";
+                hv_CameraParamAreaScanTiltPolynomial[7] = "tilt";
+                hv_CameraParamAreaScanTiltPolynomial[8] = "rot";
+                hv_CameraParamAreaScanTiltPolynomial[9] = "sx";
+                hv_CameraParamAreaScanTiltPolynomial[10] = "sy";
+                hv_CameraParamAreaScanTiltPolynomial[11] = "cx";
+                hv_CameraParamAreaScanTiltPolynomial[12] = "cy";
+                hv_CameraParamAreaScanTiltPolynomial[13] = "image_width";
+                hv_CameraParamAreaScanTiltPolynomial[14] = "image_height";
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision.Dispose();
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision = new HTuple();
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision[0] = "focus";
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision[1] = "kappa";
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision[2] = "tilt";
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision[3] = "rot";
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision[4] = "sx";
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision[5] = "sy";
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision[6] = "cx";
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision[7] = "cy";
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision[8] = "image_width";
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision[9] = "image_height";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial = new HTuple();
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[0] = "focus";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[1] = "k1";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[2] = "k2";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[3] = "k3";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[4] = "p1";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[5] = "p2";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[6] = "tilt";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[7] = "rot";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[8] = "sx";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[9] = "sy";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[10] = "cx";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[11] = "cy";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[12] = "image_width";
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial[13] = "image_height";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision = new HTuple();
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision[0] = "magnification";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision[1] = "kappa";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision[2] = "tilt";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision[3] = "rot";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision[4] = "sx";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision[5] = "sy";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision[6] = "cx";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision[7] = "cy";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision[8] = "image_width";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision[9] = "image_height";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial = new HTuple();
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[0] = "magnification";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[1] = "k1";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[2] = "k2";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[3] = "k3";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[4] = "p1";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[5] = "p2";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[6] = "tilt";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[7] = "rot";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[8] = "sx";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[9] = "sy";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[10] = "cx";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[11] = "cy";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[12] = "image_width";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial[13] = "image_height";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision.Dispose();
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision = new HTuple();
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision[0] = "magnification";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision[1] = "kappa";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision[2] = "image_plane_dist";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision[3] = "tilt";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision[4] = "rot";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision[5] = "sx";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision[6] = "sy";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision[7] = "cx";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision[8] = "cy";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision[9] = "image_width";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision[10] = "image_height";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial = new HTuple();
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[0] = "magnification";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[1] = "k1";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[2] = "k2";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[3] = "k3";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[4] = "p1";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[5] = "p2";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[6] = "image_plane_dist";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[7] = "tilt";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[8] = "rot";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[9] = "sx";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[10] = "sy";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[11] = "cx";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[12] = "cy";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[13] = "image_width";
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial[14] = "image_height";
+                hv_CameraParamAreaScanHypercentricDivision.Dispose();
+                hv_CameraParamAreaScanHypercentricDivision = new HTuple();
+                hv_CameraParamAreaScanHypercentricDivision[0] = "focus";
+                hv_CameraParamAreaScanHypercentricDivision[1] = "kappa";
+                hv_CameraParamAreaScanHypercentricDivision[2] = "sx";
+                hv_CameraParamAreaScanHypercentricDivision[3] = "sy";
+                hv_CameraParamAreaScanHypercentricDivision[4] = "cx";
+                hv_CameraParamAreaScanHypercentricDivision[5] = "cy";
+                hv_CameraParamAreaScanHypercentricDivision[6] = "image_width";
+                hv_CameraParamAreaScanHypercentricDivision[7] = "image_height";
+                hv_CameraParamAreaScanHypercentricPolynomial.Dispose();
+                hv_CameraParamAreaScanHypercentricPolynomial = new HTuple();
+                hv_CameraParamAreaScanHypercentricPolynomial[0] = "focus";
+                hv_CameraParamAreaScanHypercentricPolynomial[1] = "k1";
+                hv_CameraParamAreaScanHypercentricPolynomial[2] = "k2";
+                hv_CameraParamAreaScanHypercentricPolynomial[3] = "k3";
+                hv_CameraParamAreaScanHypercentricPolynomial[4] = "p1";
+                hv_CameraParamAreaScanHypercentricPolynomial[5] = "p2";
+                hv_CameraParamAreaScanHypercentricPolynomial[6] = "sx";
+                hv_CameraParamAreaScanHypercentricPolynomial[7] = "sy";
+                hv_CameraParamAreaScanHypercentricPolynomial[8] = "cx";
+                hv_CameraParamAreaScanHypercentricPolynomial[9] = "cy";
+                hv_CameraParamAreaScanHypercentricPolynomial[10] = "image_width";
+                hv_CameraParamAreaScanHypercentricPolynomial[11] = "image_height";
+                hv_CameraParamLinesScanDivision.Dispose();
+                hv_CameraParamLinesScanDivision = new HTuple();
+                hv_CameraParamLinesScanDivision[0] = "focus";
+                hv_CameraParamLinesScanDivision[1] = "kappa";
+                hv_CameraParamLinesScanDivision[2] = "sx";
+                hv_CameraParamLinesScanDivision[3] = "sy";
+                hv_CameraParamLinesScanDivision[4] = "cx";
+                hv_CameraParamLinesScanDivision[5] = "cy";
+                hv_CameraParamLinesScanDivision[6] = "image_width";
+                hv_CameraParamLinesScanDivision[7] = "image_height";
+                hv_CameraParamLinesScanDivision[8] = "vx";
+                hv_CameraParamLinesScanDivision[9] = "vy";
+                hv_CameraParamLinesScanDivision[10] = "vz";
+                hv_CameraParamLinesScanPolynomial.Dispose();
+                hv_CameraParamLinesScanPolynomial = new HTuple();
+                hv_CameraParamLinesScanPolynomial[0] = "focus";
+                hv_CameraParamLinesScanPolynomial[1] = "k1";
+                hv_CameraParamLinesScanPolynomial[2] = "k2";
+                hv_CameraParamLinesScanPolynomial[3] = "k3";
+                hv_CameraParamLinesScanPolynomial[4] = "p1";
+                hv_CameraParamLinesScanPolynomial[5] = "p2";
+                hv_CameraParamLinesScanPolynomial[6] = "sx";
+                hv_CameraParamLinesScanPolynomial[7] = "sy";
+                hv_CameraParamLinesScanPolynomial[8] = "cx";
+                hv_CameraParamLinesScanPolynomial[9] = "cy";
+                hv_CameraParamLinesScanPolynomial[10] = "image_width";
+                hv_CameraParamLinesScanPolynomial[11] = "image_height";
+                hv_CameraParamLinesScanPolynomial[12] = "vx";
+                hv_CameraParamLinesScanPolynomial[13] = "vy";
+                hv_CameraParamLinesScanPolynomial[14] = "vz";
+                hv_CameraParamLinesScanTelecentricDivision.Dispose();
+                hv_CameraParamLinesScanTelecentricDivision = new HTuple();
+                hv_CameraParamLinesScanTelecentricDivision[0] = "magnification";
+                hv_CameraParamLinesScanTelecentricDivision[1] = "kappa";
+                hv_CameraParamLinesScanTelecentricDivision[2] = "sx";
+                hv_CameraParamLinesScanTelecentricDivision[3] = "sy";
+                hv_CameraParamLinesScanTelecentricDivision[4] = "cx";
+                hv_CameraParamLinesScanTelecentricDivision[5] = "cy";
+                hv_CameraParamLinesScanTelecentricDivision[6] = "image_width";
+                hv_CameraParamLinesScanTelecentricDivision[7] = "image_height";
+                hv_CameraParamLinesScanTelecentricDivision[8] = "vx";
+                hv_CameraParamLinesScanTelecentricDivision[9] = "vy";
+                hv_CameraParamLinesScanTelecentricDivision[10] = "vz";
+                hv_CameraParamLinesScanTelecentricPolynomial.Dispose();
+                hv_CameraParamLinesScanTelecentricPolynomial = new HTuple();
+                hv_CameraParamLinesScanTelecentricPolynomial[0] = "magnification";
+                hv_CameraParamLinesScanTelecentricPolynomial[1] = "k1";
+                hv_CameraParamLinesScanTelecentricPolynomial[2] = "k2";
+                hv_CameraParamLinesScanTelecentricPolynomial[3] = "k3";
+                hv_CameraParamLinesScanTelecentricPolynomial[4] = "p1";
+                hv_CameraParamLinesScanTelecentricPolynomial[5] = "p2";
+                hv_CameraParamLinesScanTelecentricPolynomial[6] = "sx";
+                hv_CameraParamLinesScanTelecentricPolynomial[7] = "sy";
+                hv_CameraParamLinesScanTelecentricPolynomial[8] = "cx";
+                hv_CameraParamLinesScanTelecentricPolynomial[9] = "cy";
+                hv_CameraParamLinesScanTelecentricPolynomial[10] = "image_width";
+                hv_CameraParamLinesScanTelecentricPolynomial[11] = "image_height";
+                hv_CameraParamLinesScanTelecentricPolynomial[12] = "vx";
+                hv_CameraParamLinesScanTelecentricPolynomial[13] = "vy";
+                hv_CameraParamLinesScanTelecentricPolynomial[14] = "vz";
+                //Legacy parameter names
+                hv_CameraParamAreaScanTiltDivisionLegacy.Dispose();
+                hv_CameraParamAreaScanTiltDivisionLegacy = new HTuple();
+                hv_CameraParamAreaScanTiltDivisionLegacy[0] = "focus";
+                hv_CameraParamAreaScanTiltDivisionLegacy[1] = "kappa";
+                hv_CameraParamAreaScanTiltDivisionLegacy[2] = "tilt";
+                hv_CameraParamAreaScanTiltDivisionLegacy[3] = "rot";
+                hv_CameraParamAreaScanTiltDivisionLegacy[4] = "sx";
+                hv_CameraParamAreaScanTiltDivisionLegacy[5] = "sy";
+                hv_CameraParamAreaScanTiltDivisionLegacy[6] = "cx";
+                hv_CameraParamAreaScanTiltDivisionLegacy[7] = "cy";
+                hv_CameraParamAreaScanTiltDivisionLegacy[8] = "image_width";
+                hv_CameraParamAreaScanTiltDivisionLegacy[9] = "image_height";
+                hv_CameraParamAreaScanTiltPolynomialLegacy.Dispose();
+                hv_CameraParamAreaScanTiltPolynomialLegacy = new HTuple();
+                hv_CameraParamAreaScanTiltPolynomialLegacy[0] = "focus";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[1] = "k1";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[2] = "k2";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[3] = "k3";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[4] = "p1";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[5] = "p2";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[6] = "tilt";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[7] = "rot";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[8] = "sx";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[9] = "sy";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[10] = "cx";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[11] = "cy";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[12] = "image_width";
+                hv_CameraParamAreaScanTiltPolynomialLegacy[13] = "image_height";
+                hv_CameraParamAreaScanTelecentricDivisionLegacy.Dispose();
+                hv_CameraParamAreaScanTelecentricDivisionLegacy = new HTuple();
+                hv_CameraParamAreaScanTelecentricDivisionLegacy[0] = "focus";
+                hv_CameraParamAreaScanTelecentricDivisionLegacy[1] = "kappa";
+                hv_CameraParamAreaScanTelecentricDivisionLegacy[2] = "sx";
+                hv_CameraParamAreaScanTelecentricDivisionLegacy[3] = "sy";
+                hv_CameraParamAreaScanTelecentricDivisionLegacy[4] = "cx";
+                hv_CameraParamAreaScanTelecentricDivisionLegacy[5] = "cy";
+                hv_CameraParamAreaScanTelecentricDivisionLegacy[6] = "image_width";
+                hv_CameraParamAreaScanTelecentricDivisionLegacy[7] = "image_height";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy.Dispose();
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy = new HTuple();
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[0] = "focus";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[1] = "k1";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[2] = "k2";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[3] = "k3";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[4] = "p1";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[5] = "p2";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[6] = "sx";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[7] = "sy";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[8] = "cx";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[9] = "cy";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[10] = "image_width";
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy[11] = "image_height";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy = new HTuple();
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy[0] = "focus";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy[1] = "kappa";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy[2] = "tilt";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy[3] = "rot";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy[4] = "sx";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy[5] = "sy";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy[6] = "cx";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy[7] = "cy";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy[8] = "image_width";
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy[9] = "image_height";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy = new HTuple();
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[0] = "focus";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[1] = "k1";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[2] = "k2";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[3] = "k3";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[4] = "p1";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[5] = "p2";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[6] = "tilt";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[7] = "rot";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[8] = "sx";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[9] = "sy";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[10] = "cx";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[11] = "cy";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[12] = "image_width";
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy[13] = "image_height";
+                //
+                //If the camera type is passed in CameraParam
+                if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleEqual(
+                    1)) != 0)
+                {
+                    if ((int)hv_CameraParam.TupleSelect(0).TupleIsString() != 0)
+                    {
+                        hv_CameraType.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_CameraType = hv_CameraParam.TupleSelect(
+                                0);
+                        }
+                        if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_division")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanDivision);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_polynomial")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanPolynomial);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_telecentric_division")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanTelecentricDivision);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_telecentric_polynomial")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanTelecentricPolynomial);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_division")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanTiltDivision);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_polynomial")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanTiltPolynomial);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_image_side_telecentric_division")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanImageSideTelecentricTiltDivision);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_image_side_telecentric_polynomial")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_bilateral_telecentric_division")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanBilateralTelecentricTiltDivision);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_bilateral_telecentric_polynomial")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_object_side_telecentric_division")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanObjectSideTelecentricTiltDivision);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_object_side_telecentric_polynomial")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_hypercentric_division")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanHypercentricDivision);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_hypercentric_polynomial")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanHypercentricPolynomial);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("line_scan_division")).TupleOr(
+                            new HTuple(hv_CameraType.TupleEqual("line_scan"))) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamLinesScanDivision);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("line_scan_polynomial")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamLinesScanPolynomial);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("line_scan_telecentric_division")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamLinesScanTelecentricDivision);
+                            }
+                        }
+                        else if ((int)new HTuple(hv_CameraType.TupleEqual("line_scan_telecentric_polynomial")) != 0)
+                        {
+                            hv_ParamNames.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ParamNames = new HTuple();
+                                hv_ParamNames[0] = "camera_type";
+                                hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamLinesScanTelecentricPolynomial);
+                            }
+                        }
+                        else
+                        {
+                            throw new HalconException("Unknown camera type '" + hv_CameraType + "' passed in CameraParam.");
+                        }
+
+                        hv_CameraParamAreaScanDivision.Dispose();
+                        hv_CameraParamAreaScanPolynomial.Dispose();
+                        hv_CameraParamAreaScanTelecentricDivision.Dispose();
+                        hv_CameraParamAreaScanTelecentricPolynomial.Dispose();
+                        hv_CameraParamAreaScanTiltDivision.Dispose();
+                        hv_CameraParamAreaScanTiltPolynomial.Dispose();
+                        hv_CameraParamAreaScanImageSideTelecentricTiltDivision.Dispose();
+                        hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial.Dispose();
+                        hv_CameraParamAreaScanBilateralTelecentricTiltDivision.Dispose();
+                        hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial.Dispose();
+                        hv_CameraParamAreaScanObjectSideTelecentricTiltDivision.Dispose();
+                        hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial.Dispose();
+                        hv_CameraParamAreaScanHypercentricDivision.Dispose();
+                        hv_CameraParamAreaScanHypercentricPolynomial.Dispose();
+                        hv_CameraParamLinesScanDivision.Dispose();
+                        hv_CameraParamLinesScanPolynomial.Dispose();
+                        hv_CameraParamLinesScanTelecentricDivision.Dispose();
+                        hv_CameraParamLinesScanTelecentricPolynomial.Dispose();
+                        hv_CameraParamAreaScanTiltDivisionLegacy.Dispose();
+                        hv_CameraParamAreaScanTiltPolynomialLegacy.Dispose();
+                        hv_CameraParamAreaScanTelecentricDivisionLegacy.Dispose();
+                        hv_CameraParamAreaScanTelecentricPolynomialLegacy.Dispose();
+                        hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy.Dispose();
+                        hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy.Dispose();
+
+                        return;
+                    }
+                }
+                //
+                //If the camera parameters are passed in CameraParam
+                if ((int)hv_CameraParam.TupleSelect(0).TupleIsString().TupleNot() != 0)
+                {
+                    //Format of camera parameters for HALCON 12 and earlier
+                    switch (new HTuple(hv_CameraParam.TupleLength()
+                        ).I)
+                    {
+                        //
+                        //Area Scan
+                        case 8:
+                            //CameraType: 'area_scan_division' or 'area_scan_telecentric_division'
+                            if ((int)new HTuple(hv_CameraParam.TupleSelect(0).TupleNotEqual(0.0)) != 0)
+                            {
+                                hv_ParamNames.Dispose();
+                                hv_ParamNames = new HTuple(hv_CameraParamAreaScanDivision);
+                                hv_CameraType.Dispose();
+                                hv_CameraType = "area_scan_division";
+                            }
+                            else
+                            {
+                                hv_ParamNames.Dispose();
+                                hv_ParamNames = new HTuple(hv_CameraParamAreaScanTelecentricDivisionLegacy);
+                                hv_CameraType.Dispose();
+                                hv_CameraType = "area_scan_telecentric_division";
+                            }
+                            break;
+                        case 10:
+                            //CameraType: 'area_scan_tilt_division' or 'area_scan_telecentric_tilt_division'
+                            if ((int)new HTuple(hv_CameraParam.TupleSelect(0).TupleNotEqual(0.0)) != 0)
+                            {
+                                hv_ParamNames.Dispose();
+                                hv_ParamNames = new HTuple(hv_CameraParamAreaScanTiltDivisionLegacy);
+                                hv_CameraType.Dispose();
+                                hv_CameraType = "area_scan_tilt_division";
+                            }
+                            else
+                            {
+                                hv_ParamNames.Dispose();
+                                hv_ParamNames = new HTuple(hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy);
+                                hv_CameraType.Dispose();
+                                hv_CameraType = "area_scan_tilt_bilateral_telecentric_division";
+                            }
+                            break;
+                        case 12:
+                            //CameraType: 'area_scan_polynomial' or 'area_scan_telecentric_polynomial'
+                            if ((int)new HTuple(hv_CameraParam.TupleSelect(0).TupleNotEqual(0.0)) != 0)
+                            {
+                                hv_ParamNames.Dispose();
+                                hv_ParamNames = new HTuple(hv_CameraParamAreaScanPolynomial);
+                                hv_CameraType.Dispose();
+                                hv_CameraType = "area_scan_polynomial";
+                            }
+                            else
+                            {
+                                hv_ParamNames.Dispose();
+                                hv_ParamNames = new HTuple(hv_CameraParamAreaScanTelecentricPolynomialLegacy);
+                                hv_CameraType.Dispose();
+                                hv_CameraType = "area_scan_telecentric_polynomial";
+                            }
+                            break;
+                        case 14:
+                            //CameraType: 'area_scan_tilt_polynomial' or 'area_scan_telecentric_tilt_polynomial'
+                            if ((int)new HTuple(hv_CameraParam.TupleSelect(0).TupleNotEqual(0.0)) != 0)
+                            {
+                                hv_ParamNames.Dispose();
+                                hv_ParamNames = new HTuple(hv_CameraParamAreaScanTiltPolynomialLegacy);
+                                hv_CameraType.Dispose();
+                                hv_CameraType = "area_scan_tilt_polynomial";
+                            }
+                            else
+                            {
+                                hv_ParamNames.Dispose();
+                                hv_ParamNames = new HTuple(hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy);
+                                hv_CameraType.Dispose();
+                                hv_CameraType = "area_scan_tilt_bilateral_telecentric_polynomial";
+                            }
+                            break;
+                        //
+                        //Line Scan
+                        case 11:
+                            //CameraType: 'line_scan' or 'line_scan_telecentric'
+                            if ((int)new HTuple(hv_CameraParam.TupleSelect(0).TupleNotEqual(0.0)) != 0)
+                            {
+                                hv_ParamNames.Dispose();
+                                hv_ParamNames = new HTuple(hv_CameraParamLinesScanDivision);
+                                hv_CameraType.Dispose();
+                                hv_CameraType = "line_scan_division";
+                            }
+                            else
+                            {
+                                hv_ParamNames.Dispose();
+                                hv_ParamNames = new HTuple(hv_CameraParamLinesScanTelecentricDivision);
+                                hv_CameraType.Dispose();
+                                hv_CameraType = "line_scan_telecentric_division";
+                            }
+                            break;
+                        default:
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                    }
+                }
+                else
+                {
+                    //Format of camera parameters since HALCON 13
+                    hv_CameraType.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_CameraType = hv_CameraParam.TupleSelect(
+                            0);
+                    }
+                    if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_division")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            9)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanDivision);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_polynomial")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            13)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanPolynomial);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_telecentric_division")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            9)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanTelecentricDivision);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_telecentric_polynomial")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            13)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanTelecentricPolynomial);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_division")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            12)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanTiltDivision);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_polynomial")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            16)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanTiltPolynomial);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_image_side_telecentric_division")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            11)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanImageSideTelecentricTiltDivision);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_image_side_telecentric_polynomial")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            15)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_bilateral_telecentric_division")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            11)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanBilateralTelecentricTiltDivision);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_bilateral_telecentric_polynomial")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            15)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_object_side_telecentric_division")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            12)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanObjectSideTelecentricTiltDivision);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_tilt_object_side_telecentric_polynomial")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            16)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_hypercentric_division")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            9)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanHypercentricDivision);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("area_scan_hypercentric_polynomial")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            13)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamAreaScanHypercentricPolynomial);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("line_scan_division")).TupleOr(
+                        new HTuple(hv_CameraType.TupleEqual("line_scan"))) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            12)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamLinesScanDivision);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("line_scan_polynomial")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            16)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamLinesScanPolynomial);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("line_scan_telecentric_division")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            12)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamLinesScanTelecentricDivision);
+                        }
+                    }
+                    else if ((int)new HTuple(hv_CameraType.TupleEqual("line_scan_telecentric_polynomial")) != 0)
+                    {
+                        if ((int)new HTuple(new HTuple(hv_CameraParam.TupleLength()).TupleNotEqual(
+                            16)) != 0)
+                        {
+                            throw new HalconException("Wrong number of values in CameraParam.");
+                        }
+                        hv_ParamNames.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNames = new HTuple();
+                            hv_ParamNames[0] = "camera_type";
+                            hv_ParamNames = hv_ParamNames.TupleConcat(hv_CameraParamLinesScanTelecentricPolynomial);
+                        }
+                    }
+                    else
+                    {
+                        throw new HalconException("Unknown camera type in CameraParam.");
+                    }
+                }
+
+                hv_CameraParamAreaScanDivision.Dispose();
+                hv_CameraParamAreaScanPolynomial.Dispose();
+                hv_CameraParamAreaScanTelecentricDivision.Dispose();
+                hv_CameraParamAreaScanTelecentricPolynomial.Dispose();
+                hv_CameraParamAreaScanTiltDivision.Dispose();
+                hv_CameraParamAreaScanTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision.Dispose();
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision.Dispose();
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanHypercentricDivision.Dispose();
+                hv_CameraParamAreaScanHypercentricPolynomial.Dispose();
+                hv_CameraParamLinesScanDivision.Dispose();
+                hv_CameraParamLinesScanPolynomial.Dispose();
+                hv_CameraParamLinesScanTelecentricDivision.Dispose();
+                hv_CameraParamLinesScanTelecentricPolynomial.Dispose();
+                hv_CameraParamAreaScanTiltDivisionLegacy.Dispose();
+                hv_CameraParamAreaScanTiltPolynomialLegacy.Dispose();
+                hv_CameraParamAreaScanTelecentricDivisionLegacy.Dispose();
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_CameraParamAreaScanDivision.Dispose();
+                hv_CameraParamAreaScanPolynomial.Dispose();
+                hv_CameraParamAreaScanTelecentricDivision.Dispose();
+                hv_CameraParamAreaScanTelecentricPolynomial.Dispose();
+                hv_CameraParamAreaScanTiltDivision.Dispose();
+                hv_CameraParamAreaScanTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanImageSideTelecentricTiltDivision.Dispose();
+                hv_CameraParamAreaScanImageSideTelecentricTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivision.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanObjectSideTelecentricTiltDivision.Dispose();
+                hv_CameraParamAreaScanObjectSideTelecentricTiltPolynomial.Dispose();
+                hv_CameraParamAreaScanHypercentricDivision.Dispose();
+                hv_CameraParamAreaScanHypercentricPolynomial.Dispose();
+                hv_CameraParamLinesScanDivision.Dispose();
+                hv_CameraParamLinesScanPolynomial.Dispose();
+                hv_CameraParamLinesScanTelecentricDivision.Dispose();
+                hv_CameraParamLinesScanTelecentricPolynomial.Dispose();
+                hv_CameraParamAreaScanTiltDivisionLegacy.Dispose();
+                hv_CameraParamAreaScanTiltPolynomialLegacy.Dispose();
+                hv_CameraParamAreaScanTelecentricDivisionLegacy.Dispose();
+                hv_CameraParamAreaScanTelecentricPolynomialLegacy.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltDivisionLegacy.Dispose();
+                hv_CameraParamAreaScanBilateralTelecentricTiltPolynomialLegacy.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Output
+        // Short Description: Compute the center of all given 3D object models. 
+        public static void get_object_models_center(HTuple hv_ObjectModel3DID, out HTuple hv_Center)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_Diameters = new HTuple(), hv_Index = new HTuple();
+            HTuple hv_Diameter = new HTuple(), hv_C = new HTuple();
+            HTuple hv_Exception = new HTuple(), hv_MD = new HTuple();
+            HTuple hv_Weight = new HTuple(), hv_SumW = new HTuple();
+            HTuple hv_ObjectModel3DIDSelected = new HTuple(), hv_InvSum = new HTuple();
+            // Initialize local and output iconic variables 
+            hv_Center = new HTuple();
+            try
+            {
+                //Compute the mean of all model centers (weighted by the diameter of the object models)
+                hv_Diameters.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Diameters = HTuple.TupleGenConst(
+                        new HTuple(hv_ObjectModel3DID.TupleLength()), 0.0);
+                }
+                for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_ObjectModel3DID.TupleLength()
+                    ) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    try
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Diameter.Dispose();
+                            HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID.TupleSelect(hv_Index),
+                                "diameter_axis_aligned_bounding_box", out hv_Diameter);
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_C.Dispose();
+                            HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID.TupleSelect(hv_Index),
+                                "center", out hv_C);
+                        }
+                        if (hv_Diameters == null)
+                            hv_Diameters = new HTuple();
+                        hv_Diameters[hv_Index] = hv_Diameter;
+                    }
+                    // catch (Exception) 
+                    catch (HalconException HDevExpDefaultException1)
+                    {
+                        HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                        //Object model is empty, has no center etc. -> ignore it by leaving its diameter at zero
+                    }
+                }
+
+                if ((int)new HTuple(hv_Diameters.TupleSum().TupleGreater(0)) != 0)
+                {
+                    //Normalize Diameter to use it as weights for a weighted mean of the individual centers
+                    hv_MD.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_MD = hv_Diameters.TupleSelectMask(
+                            hv_Diameters.TupleGreaterElem(0)).TupleMean();
+                    }
+                    if ((int)new HTuple(hv_MD.TupleGreater(1e-10)) != 0)
+                    {
+                        hv_Weight.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Weight = hv_Diameters / hv_MD;
+                        }
+                    }
+                    else
+                    {
+                        hv_Weight.Dispose();
+                        hv_Weight = new HTuple(hv_Diameters);
+                    }
+                    hv_SumW.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_SumW = hv_Weight.TupleSum()
+                            ;
+                    }
+                    if ((int)new HTuple(hv_SumW.TupleLess(1e-10)) != 0)
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_Weight = HTuple.TupleGenConst(
+                                    new HTuple(hv_Weight.TupleLength()), 1.0);
+                                hv_Weight.Dispose();
+                                hv_Weight = ExpTmpLocalVar_Weight;
+                            }
+                        }
+                        hv_SumW.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_SumW = hv_Weight.TupleSum()
+                                ;
+                        }
+                    }
+                    hv_Center.Dispose();
+                    hv_Center = new HTuple();
+                    hv_Center[0] = 0;
+                    hv_Center[1] = 0;
+                    hv_Center[2] = 0;
+                    for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_ObjectModel3DID.TupleLength()
+                        ) - 1); hv_Index = (int)hv_Index + 1)
+                    {
+                        if ((int)new HTuple(hv_Diameters.TupleSelect(hv_Index).TupleGreater(
+                            0)) != 0)
+                        {
+                            hv_ObjectModel3DIDSelected.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_ObjectModel3DIDSelected = hv_ObjectModel3DID.TupleSelect(
+                                    hv_Index);
+                            }
+                            hv_C.Dispose();
+                            HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DIDSelected, "center",
+                                out hv_C);
+                            if (hv_Center == null)
+                                hv_Center = new HTuple();
+                            hv_Center[0] = hv_Center.TupleSelect(0) + hv_C.TupleSelect(0) * hv_Weight.TupleSelect(
+                                hv_Index);
+                            if (hv_Center == null)
+                                hv_Center = new HTuple();
+                            hv_Center[1] = hv_Center.TupleSelect(1) + hv_C.TupleSelect(1) * hv_Weight.TupleSelect(
+                                hv_Index);
+                            if (hv_Center == null)
+                                hv_Center = new HTuple();
+                            hv_Center[2] = hv_Center.TupleSelect(2) + hv_C.TupleSelect(2) * hv_Weight.TupleSelect(
+                                hv_Index);
+                        }
+                    }
+                    hv_InvSum.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_InvSum = 1.0 / hv_SumW;
+                    }
+                    if (hv_Center == null)
+                        hv_Center = new HTuple();
+                    hv_Center[0] = hv_Center.TupleSelect(0) * hv_InvSum;
+                    if (hv_Center == null)
+                        hv_Center = new HTuple();
+                    hv_Center[1] = hv_Center.TupleSelect(1) * hv_InvSum;
+                    if (hv_Center == null)
+                        hv_Center = new HTuple();
+                    hv_Center[2] = hv_Center.TupleSelect(2) * hv_InvSum;
+                }
+                else
+                {
+                    hv_Center.Dispose();
+                    hv_Center = new HTuple();
+                }
+
+                hv_Diameters.Dispose();
+                hv_Index.Dispose();
+                hv_Diameter.Dispose();
+                hv_C.Dispose();
+                hv_Exception.Dispose();
+                hv_MD.Dispose();
+                hv_Weight.Dispose();
+                hv_SumW.Dispose();
+                hv_ObjectModel3DIDSelected.Dispose();
+                hv_InvSum.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Diameters.Dispose();
+                hv_Index.Dispose();
+                hv_Diameter.Dispose();
+                hv_C.Dispose();
+                hv_Exception.Dispose();
+                hv_MD.Dispose();
+                hv_Weight.Dispose();
+                hv_SumW.Dispose();
+                hv_ObjectModel3DIDSelected.Dispose();
+                hv_InvSum.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Output
+        // Short Description: Get the center of the virtual trackback that is used to move the camera. 
+        public static void get_trackball_center(HTuple hv_SelectedObject, HTuple hv_TrackballRadiusPixel,
+            HTuple hv_ObjectModel3D, HTuple hv_Poses, out HTuple hv_TBCenter, out HTuple hv_TBSize)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_NumModels = new HTuple(), hv_Diameter = new HTuple();
+            HTuple hv_Index = new HTuple(), hv_Center = new HTuple();
+            HTuple hv_CurrDiameter = new HTuple(), hv_Exception = new HTuple();
+            HTuple hv_MD = new HTuple(), hv_Weight = new HTuple();
+            HTuple hv_SumW = new HTuple(), hv_PoseSelected = new HTuple();
+            HTuple hv_HomMat3D = new HTuple(), hv_TBCenterCamX = new HTuple();
+            HTuple hv_TBCenterCamY = new HTuple(), hv_TBCenterCamZ = new HTuple();
+            HTuple hv_InvSum = new HTuple();
+            // Initialize local and output iconic variables 
+            hv_TBCenter = new HTuple();
+            hv_TBSize = new HTuple();
+            try
+            {
+                //
+                hv_NumModels.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_NumModels = new HTuple(hv_ObjectModel3D.TupleLength()
+                        );
+                }
+                if (hv_TBCenter == null)
+                    hv_TBCenter = new HTuple();
+                hv_TBCenter[0] = 0;
+                if (hv_TBCenter == null)
+                    hv_TBCenter = new HTuple();
+                hv_TBCenter[1] = 0;
+                if (hv_TBCenter == null)
+                    hv_TBCenter = new HTuple();
+                hv_TBCenter[2] = 0;
+                hv_Diameter.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Diameter = HTuple.TupleGenConst(
+                        new HTuple(hv_ObjectModel3D.TupleLength()), 0.0);
+                }
+                for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_ObjectModel3D.TupleLength()
+                    ) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    try
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Center.Dispose();
+                            HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3D.TupleSelect(hv_Index),
+                                "center", out hv_Center);
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_CurrDiameter.Dispose();
+                            HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3D.TupleSelect(hv_Index),
+                                "diameter_axis_aligned_bounding_box", out hv_CurrDiameter);
+                        }
+                        if (hv_Diameter == null)
+                            hv_Diameter = new HTuple();
+                        hv_Diameter[hv_Index] = hv_CurrDiameter;
+                    }
+                    // catch (Exception) 
+                    catch (HalconException HDevExpDefaultException1)
+                    {
+                        HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                        //3D object model is empty or otherwise malformed -> ignore
+                    }
+                }
+                //Normalize Diameter to use it as weights for a weighted mean of the individual centers
+                hv_MD.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_MD = hv_Diameter.TupleMean()
+                        ;
+                }
+                if ((int)new HTuple(hv_MD.TupleGreater(1e-10)) != 0)
+                {
+                    hv_Weight.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Weight = hv_Diameter / hv_MD;
+                    }
+                }
+                else
+                {
+                    hv_Weight.Dispose();
+                    hv_Weight = new HTuple(hv_Diameter);
+                }
+                hv_SumW.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_SumW = hv_Weight.TupleSelectMask(
+                        hv_SelectedObject.TupleSgn().TupleAbs()).TupleSum();
+                }
+                if ((int)new HTuple(hv_SumW.TupleLess(1e-10)) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Weight = HTuple.TupleGenConst(
+                                new HTuple(hv_Weight.TupleLength()), 1.0);
+                            hv_Weight.Dispose();
+                            hv_Weight = ExpTmpLocalVar_Weight;
+                        }
+                    }
+                    hv_SumW.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_SumW = hv_Weight.TupleSelectMask(
+                            hv_SelectedObject.TupleSgn().TupleAbs()).TupleSum();
+                    }
+                }
+                if ((int)new HTuple(hv_SumW.TupleLess(1e-10)) != 0)
+                {
+                    hv_SumW.Dispose();
+                    hv_SumW = 1.0;
+                }
+                HTuple end_val30 = hv_NumModels - 1;
+                HTuple step_val30 = 1;
+                for (hv_Index = 0; hv_Index.Continue(end_val30, step_val30); hv_Index = hv_Index.TupleAdd(step_val30))
+                {
+                    if ((int)hv_SelectedObject.TupleSelect(hv_Index).TupleAnd(new HTuple(hv_Diameter.TupleSelect(
+                        hv_Index).TupleGreater(0))) != 0)
+                    {
+                        hv_PoseSelected.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_PoseSelected = hv_Poses.TupleSelectRange(
+                                hv_Index * 7, hv_Index * 7 + 6);
+                        }
+                        hv_HomMat3D.Dispose();
+                        HOperatorSet.PoseToHomMat3d(hv_PoseSelected, out hv_HomMat3D);
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Center.Dispose();
+                            HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3D.TupleSelect(hv_Index),
+                                "center", out hv_Center);
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_TBCenterCamX.Dispose(); hv_TBCenterCamY.Dispose(); hv_TBCenterCamZ.Dispose();
+                            HOperatorSet.AffineTransPoint3d(hv_HomMat3D, hv_Center.TupleSelect(0),
+                                hv_Center.TupleSelect(1), hv_Center.TupleSelect(2), out hv_TBCenterCamX,
+                                out hv_TBCenterCamY, out hv_TBCenterCamZ);
+                        }
+                        if (hv_TBCenter == null)
+                            hv_TBCenter = new HTuple();
+                        hv_TBCenter[0] = hv_TBCenter.TupleSelect(0) + hv_TBCenterCamX * hv_Weight.TupleSelect(
+                            hv_Index);
+                        if (hv_TBCenter == null)
+                            hv_TBCenter = new HTuple();
+                        hv_TBCenter[1] = hv_TBCenter.TupleSelect(1) + hv_TBCenterCamY * hv_Weight.TupleSelect(
+                            hv_Index);
+                        if (hv_TBCenter == null)
+                            hv_TBCenter = new HTuple();
+                        hv_TBCenter[2] = hv_TBCenter.TupleSelect(2) + hv_TBCenterCamZ * hv_Weight.TupleSelect(
+                            hv_Index);
+                    }
+                }
+                if ((int)new HTuple(hv_SelectedObject.TupleMax().TupleNotEqual(0)) != 0)
+                {
+                    hv_InvSum.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_InvSum = 1.0 / hv_SumW;
+                    }
+                    if (hv_TBCenter == null)
+                        hv_TBCenter = new HTuple();
+                    hv_TBCenter[0] = hv_TBCenter.TupleSelect(0) * hv_InvSum;
+                    if (hv_TBCenter == null)
+                        hv_TBCenter = new HTuple();
+                    hv_TBCenter[1] = hv_TBCenter.TupleSelect(1) * hv_InvSum;
+                    if (hv_TBCenter == null)
+                        hv_TBCenter = new HTuple();
+                    hv_TBCenter[2] = hv_TBCenter.TupleSelect(2) * hv_InvSum;
+                    hv_TBSize.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TBSize = (0.5 + 0.5 * hv_SelectedObject.TupleSum()
+                             / hv_NumModels) * hv_TrackballRadiusPixel;
+                    }
+                }
+                else
+                {
+                    hv_TBCenter.Dispose();
+                    hv_TBCenter = new HTuple();
+                    hv_TBSize.Dispose();
+                    hv_TBSize = 0;
+                }
+
+                hv_NumModels.Dispose();
+                hv_Diameter.Dispose();
+                hv_Index.Dispose();
+                hv_Center.Dispose();
+                hv_CurrDiameter.Dispose();
+                hv_Exception.Dispose();
+                hv_MD.Dispose();
+                hv_Weight.Dispose();
+                hv_SumW.Dispose();
+                hv_PoseSelected.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_TBCenterCamX.Dispose();
+                hv_TBCenterCamY.Dispose();
+                hv_TBCenterCamZ.Dispose();
+                hv_InvSum.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_NumModels.Dispose();
+                hv_Diameter.Dispose();
+                hv_Index.Dispose();
+                hv_Center.Dispose();
+                hv_CurrDiameter.Dispose();
+                hv_Exception.Dispose();
+                hv_MD.Dispose();
+                hv_Weight.Dispose();
+                hv_SumW.Dispose();
+                hv_PoseSelected.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_TBCenterCamX.Dispose();
+                hv_TBCenterCamY.Dispose();
+                hv_TBCenterCamZ.Dispose();
+                hv_InvSum.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Output
+        // Short Description: Get the center of the virtual trackback that is used to move the camera (version for inspection_mode = 'surface'). 
+        public static void get_trackball_center_fixed(HTuple hv_SelectedObject, HTuple hv_TrackballCenterRow,
+            HTuple hv_TrackballCenterCol, HTuple hv_TrackballRadiusPixel, HTuple hv_Scene3D,
+            HTuple hv_ObjectModel3DID, HTuple hv_Poses, HTuple hv_WindowHandleBuffer, HTuple hv_CamParam,
+            HTuple hv_GenParamName, HTuple hv_GenParamValue, out HTuple hv_TBCenter, out HTuple hv_TBSize)
+        {
+
+
+
+            // Local iconic variables 
+
+            HObject ho_RegionCenter, ho_DistanceImage;
+            HObject ho_Domain;
+
+            // Local control variables 
+
+            HTuple hv_NumModels = new HTuple(), hv_Width = new HTuple();
+            HTuple hv_Height = new HTuple(), hv_SelectPose = new HTuple();
+            HTuple hv_Index1 = new HTuple(), hv_Rows = new HTuple();
+            HTuple hv_Columns = new HTuple(), hv_Grayval = new HTuple();
+            HTuple hv_IndicesG = new HTuple(), hv_Value = new HTuple();
+            HTuple hv_Pos = new HTuple();
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_RegionCenter);
+            HOperatorSet.GenEmptyObj(out ho_DistanceImage);
+            HOperatorSet.GenEmptyObj(out ho_Domain);
+            hv_TBCenter = new HTuple();
+            hv_TBSize = new HTuple();
+            try
+            {
+                //
+                //Determine the trackball center for the fixed trackball
+                hv_NumModels.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_NumModels = new HTuple(hv_ObjectModel3DID.TupleLength()
+                        );
+                }
+                hv_Width.Dispose();
+                get_cam_par_data(hv_CamParam, "image_width", out hv_Width);
+                hv_Height.Dispose();
+                get_cam_par_data(hv_CamParam, "image_height", out hv_Height);
+                //
+                //Project the selected objects
+                hv_SelectPose.Dispose();
+                hv_SelectPose = new HTuple();
+                for (hv_Index1 = 0; (int)hv_Index1 <= (int)(new HTuple(hv_SelectedObject.TupleLength()
+                    ) - 1); hv_Index1 = (int)hv_Index1 + 1)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_SelectPose = hv_SelectPose.TupleConcat(
+                                HTuple.TupleGenConst(7, hv_SelectedObject.TupleSelect(hv_Index1)));
+                            hv_SelectPose.Dispose();
+                            hv_SelectPose = ExpTmpLocalVar_SelectPose;
+                        }
+                    }
+                    if ((int)new HTuple(hv_SelectedObject.TupleSelect(hv_Index1).TupleEqual(
+                        0)) != 0)
+                    {
+                        HOperatorSet.SetScene3dInstanceParam(hv_Scene3D, hv_Index1, "visible",
+                            "false");
+                    }
+                }
+                HOperatorSet.SetScene3dParam(hv_Scene3D, "depth_persistence", "true");
+                HOperatorSet.DisplayScene3d(hv_WindowHandleBuffer, hv_Scene3D, 0);
+                HOperatorSet.SetScene3dParam(hv_Scene3D, "visible", "true");
+                //
+                //determine the depth of the object point that appears closest to the trackball
+                //center
+                ho_RegionCenter.Dispose();
+                HOperatorSet.GenRegionPoints(out ho_RegionCenter, hv_TrackballCenterRow, hv_TrackballCenterCol);
+                ho_DistanceImage.Dispose();
+                HOperatorSet.DistanceTransform(ho_RegionCenter, out ho_DistanceImage, "chamfer-3-4-unnormalized",
+                    "false", hv_Width, hv_Height);
+                ho_Domain.Dispose();
+                HOperatorSet.GetDomain(ho_DistanceImage, out ho_Domain);
+                hv_Rows.Dispose(); hv_Columns.Dispose();
+                HOperatorSet.GetRegionPoints(ho_Domain, out hv_Rows, out hv_Columns);
+                hv_Grayval.Dispose();
+                HOperatorSet.GetGrayval(ho_DistanceImage, hv_Rows, hv_Columns, out hv_Grayval);
+                hv_IndicesG.Dispose();
+                HOperatorSet.TupleSortIndex(hv_Grayval, out hv_IndicesG);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Value.Dispose();
+                    HOperatorSet.GetDisplayScene3dInfo(hv_WindowHandleBuffer, hv_Scene3D, hv_Rows.TupleSelect(
+                        hv_IndicesG), hv_Columns.TupleSelect(hv_IndicesG), "depth", out hv_Value);
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Pos.Dispose();
+                    HOperatorSet.TupleFind(hv_Value.TupleSgn(), 1, out hv_Pos);
+                }
+                //
+                HOperatorSet.SetScene3dParam(hv_Scene3D, "depth_persistence", "false");
+                //
+                //
+                //set TBCenter
+                if ((int)new HTuple(hv_Pos.TupleNotEqual(-1)) != 0)
+                {
+                    //if the object is visible in the image
+                    hv_TBCenter.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TBCenter = new HTuple();
+                        hv_TBCenter[0] = 0;
+                        hv_TBCenter[1] = 0;
+                        hv_TBCenter = hv_TBCenter.TupleConcat(hv_Value.TupleSelect(
+                            hv_Pos.TupleSelect(0)));
+                    }
+                }
+                else
+                {
+                    //if the object is not visible in the image, set the z coordinate to -1
+                    //to indicate, that the previous z value should be used instead
+                    hv_TBCenter.Dispose();
+                    hv_TBCenter = new HTuple();
+                    hv_TBCenter[0] = 0;
+                    hv_TBCenter[1] = 0;
+                    hv_TBCenter[2] = -1;
+                }
+                //
+                if ((int)new HTuple(hv_SelectedObject.TupleMax().TupleNotEqual(0)) != 0)
+                {
+                    hv_TBSize.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TBSize = (0.5 + 0.5 * hv_SelectedObject.TupleSum()
+                             / hv_NumModels) * hv_TrackballRadiusPixel;
+                    }
+                }
+                else
+                {
+                    hv_TBCenter.Dispose();
+                    hv_TBCenter = new HTuple();
+                    hv_TBSize.Dispose();
+                    hv_TBSize = 0;
+                }
+                ho_RegionCenter.Dispose();
+                ho_DistanceImage.Dispose();
+                ho_Domain.Dispose();
+
+                hv_NumModels.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_SelectPose.Dispose();
+                hv_Index1.Dispose();
+                hv_Rows.Dispose();
+                hv_Columns.Dispose();
+                hv_Grayval.Dispose();
+                hv_IndicesG.Dispose();
+                hv_Value.Dispose();
+                hv_Pos.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_RegionCenter.Dispose();
+                ho_DistanceImage.Dispose();
+                ho_Domain.Dispose();
+
+                hv_NumModels.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_SelectPose.Dispose();
+                hv_Index1.Dispose();
+                hv_Rows.Dispose();
+                hv_Columns.Dispose();
+                hv_Grayval.Dispose();
+                hv_IndicesG.Dispose();
+                hv_Value.Dispose();
+                hv_Pos.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Output
+        // Short Description: Get string extends of several lines. 
+        public static void max_line_width(HTuple hv_WindowHandle, HTuple hv_Lines, out HTuple hv_MaxWidth)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_Index = new HTuple(), hv_Ascent = new HTuple();
+            HTuple hv_Descent = new HTuple(), hv_LineWidth = new HTuple();
+            HTuple hv_LineHeight = new HTuple();
+            // Initialize local and output iconic variables 
+            hv_MaxWidth = new HTuple();
+            try
+            {
+                //
+                hv_MaxWidth.Dispose();
+                hv_MaxWidth = 0;
+                for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_Lines.TupleLength()) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Ascent.Dispose(); hv_Descent.Dispose(); hv_LineWidth.Dispose(); hv_LineHeight.Dispose();
+                        HOperatorSet.GetStringExtents(hv_WindowHandle, hv_Lines.TupleSelect(hv_Index),
+                            out hv_Ascent, out hv_Descent, out hv_LineWidth, out hv_LineHeight);
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_MaxWidth = hv_LineWidth.TupleConcat(
+                                hv_MaxWidth).TupleMax();
+                            hv_MaxWidth.Dispose();
+                            hv_MaxWidth = ExpTmpLocalVar_MaxWidth;
+                        }
+                    }
+                }
+
+                hv_Index.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_LineWidth.Dispose();
+                hv_LineHeight.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Index.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_LineWidth.Dispose();
+                hv_LineHeight.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Output
+        // Short Description: Project an image point onto the trackball 
+        public static void project_point_on_trackball(HTuple hv_X, HTuple hv_Y, HTuple hv_VirtualTrackball,
+            HTuple hv_TrackballSize, out HTuple hv_V)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_R = new HTuple(), hv_XP = new HTuple();
+            HTuple hv_YP = new HTuple(), hv_ZP = new HTuple();
+            // Initialize local and output iconic variables 
+            hv_V = new HTuple();
+            try
+            {
+                //
+                if ((int)new HTuple(hv_VirtualTrackball.TupleEqual("shoemake")) != 0)
+                {
+                    //Virtual Trackball according to Shoemake
+                    hv_R.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_R = (hv_X * hv_X + hv_Y * hv_Y).TupleSqrt()
+                            ;
+                    }
+                    if ((int)new HTuple(hv_R.TupleLessEqual(hv_TrackballSize)) != 0)
+                    {
+                        hv_XP.Dispose();
+                        hv_XP = new HTuple(hv_X);
+                        hv_YP.Dispose();
+                        hv_YP = new HTuple(hv_Y);
+                        hv_ZP.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ZP = (hv_TrackballSize * hv_TrackballSize - hv_R * hv_R).TupleSqrt()
+                                ;
+                        }
+                    }
+                    else
+                    {
+                        hv_XP.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_XP = hv_X * hv_TrackballSize / hv_R;
+                        }
+                        hv_YP.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_YP = hv_Y * hv_TrackballSize / hv_R;
+                        }
+                        hv_ZP.Dispose();
+                        hv_ZP = 0;
+                    }
+                }
+                else
+                {
+                    //Virtual Trackball according to Bell
+                    hv_R.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_R = (hv_X * hv_X + hv_Y * hv_Y).TupleSqrt()
+                            ;
+                    }
+                    if ((int)new HTuple(hv_R.TupleLessEqual(hv_TrackballSize * 0.70710678)) != 0)
+                    {
+                        hv_XP.Dispose();
+                        hv_XP = new HTuple(hv_X);
+                        hv_YP.Dispose();
+                        hv_YP = new HTuple(hv_Y);
+                        hv_ZP.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ZP = (hv_TrackballSize * hv_TrackballSize - hv_R * hv_R).TupleSqrt()
+                                ;
+                        }
+                    }
+                    else
+                    {
+                        hv_XP.Dispose();
+                        hv_XP = new HTuple(hv_X);
+                        hv_YP.Dispose();
+                        hv_YP = new HTuple(hv_Y);
+                        hv_ZP.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ZP = 0.6 * hv_TrackballSize * hv_TrackballSize / hv_R;
+                        }
+                    }
+                }
+                hv_V.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_V = new HTuple();
+                    hv_V = hv_V.TupleConcat(hv_XP, hv_YP, hv_ZP);
+                }
+
+                hv_R.Dispose();
+                hv_XP.Dispose();
+                hv_YP.Dispose();
+                hv_ZP.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_R.Dispose();
+                hv_XP.Dispose();
+                hv_YP.Dispose();
+                hv_ZP.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Calibration / Camera Parameters
+        // Short Description: Set the value of a specified camera parameter in the camera parameter tuple. 
+        public void set_cam_par_data(HTuple hv_CameraParamIn, HTuple hv_ParamName, HTuple hv_ParamValue,
+            out HTuple hv_CameraParamOut)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_CameraType = new HTuple(), hv_CameraParamNames = new HTuple();
+            HTuple hv_Index = new HTuple(), hv_ParamNameInd = new HTuple();
+            HTuple hv_I = new HTuple(), hv_IsTelecentric = new HTuple();
+            // Initialize local and output iconic variables 
+            hv_CameraParamOut = new HTuple();
+            try
+            {
+                //set_cam_par_data sets the value of the parameter that
+                //is given in ParamName in the tuple of camera parameters
+                //given in CameraParamIn. The modified camera parameters
+                //are returned in CameraParamOut.
+                //
+                //Check for consistent length of input parameters
+                if ((int)new HTuple(new HTuple(hv_ParamName.TupleLength()).TupleNotEqual(
+                    new HTuple(hv_ParamValue.TupleLength()))) != 0)
+                {
+                    throw new HalconException("Different number of values in ParamName and ParamValue");
+                }
+                //First, get the parameter names that correspond to the
+                //elements in the input camera parameter tuple.
+                hv_CameraType.Dispose(); hv_CameraParamNames.Dispose();
+                get_cam_par_names(hv_CameraParamIn, out hv_CameraType, out hv_CameraParamNames);
+                //
+                //Find the index of the requested camera data and return
+                //the corresponding value.
+                hv_CameraParamOut.Dispose();
+                hv_CameraParamOut = new HTuple(hv_CameraParamIn);
+                for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_ParamName.TupleLength()
+                    ) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    hv_ParamNameInd.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_ParamNameInd = hv_ParamName.TupleSelect(
+                            hv_Index);
+                    }
+                    hv_I.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_I = hv_CameraParamNames.TupleFind(
+                            hv_ParamNameInd);
+                    }
+                    if ((int)new HTuple(hv_I.TupleNotEqual(-1)) != 0)
+                    {
+                        if (hv_CameraParamOut == null)
+                            hv_CameraParamOut = new HTuple();
+                        hv_CameraParamOut[hv_I] = hv_ParamValue.TupleSelect(hv_Index);
+                    }
+                    else
+                    {
+                        throw new HalconException("Wrong ParamName " + hv_ParamNameInd);
+                    }
+                    //Check the consistency of focus and telecentricity
+                    if ((int)new HTuple(hv_ParamNameInd.TupleEqual("focus")) != 0)
+                    {
+                        hv_IsTelecentric.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_IsTelecentric = new HTuple(hv_CameraType.TupleStrstr(
+                                "telecentric").TupleNotEqual(-1)).TupleAnd(new HTuple(hv_CameraType.TupleStrstr(
+                                "image_side_telecentric").TupleEqual(-1)));
+                        }
+                        if ((int)hv_IsTelecentric != 0)
+                        {
+                            throw new HalconException(new HTuple("Focus for telecentric lenses is always 0, and hence, cannot be changed."));
+                        }
+                        if ((int)new HTuple(hv_IsTelecentric.TupleNot()).TupleAnd(new HTuple(hv_ParamValue.TupleSelect(
+                            hv_Index).TupleEqual(0.0))) != 0)
+                        {
+                            throw new HalconException("Focus for non-telecentric lenses must not be 0.");
+                        }
+                    }
+                }
+
+                hv_CameraType.Dispose();
+                hv_CameraParamNames.Dispose();
+                hv_Index.Dispose();
+                hv_ParamNameInd.Dispose();
+                hv_I.Dispose();
+                hv_IsTelecentric.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_CameraType.Dispose();
+                hv_CameraParamNames.Dispose();
+                hv_Index.Dispose();
+                hv_ParamNameInd.Dispose();
+                hv_I.Dispose();
+                hv_IsTelecentric.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Text
+        // Short Description: Set font independent of OS 
+        public static void set_display_font(HTuple hv_WindowHandle, HTuple hv_Size, HTuple hv_Font,
+            HTuple hv_Bold, HTuple hv_Slant)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_OS = new HTuple(), hv_Fonts = new HTuple();
+            HTuple hv_Style = new HTuple(), hv_Exception = new HTuple();
+            HTuple hv_AvailableFonts = new HTuple(), hv_Fdx = new HTuple();
+            HTuple hv_Indices = new HTuple();
+            HTuple hv_Font_COPY_INP_TMP = new HTuple(hv_Font);
+            HTuple hv_Size_COPY_INP_TMP = new HTuple(hv_Size);
+
+            // Initialize local and output iconic variables 
+            try
+            {
+                //This procedure sets the text font of the current window with
+                //the specified attributes.
+                //
+                //Input parameters:
+                //WindowHandle: The graphics window for which the font will be set
+                //Size: The font size. If Size=-1, the default of 16 is used.
+                //Bold: If set to 'true', a bold font is used
+                //Slant: If set to 'true', a slanted font is used
+                //
+                hv_OS.Dispose();
+                HOperatorSet.GetSystem("operating_system", out hv_OS);
+                if ((int)new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(new HTuple())).TupleOr(
+                    new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(-1))) != 0)
+                {
+                    hv_Size_COPY_INP_TMP.Dispose();
+                    hv_Size_COPY_INP_TMP = 16;
+                }
+                if ((int)new HTuple(hv_OS.TupleSubstr(0, 2).TupleEqual("Win")) != 0)
+                {
+                    //Restore previous behavior
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Size = (1.13677 * hv_Size_COPY_INP_TMP).TupleInt()
+                                ;
+                            hv_Size_COPY_INP_TMP.Dispose();
+                            hv_Size_COPY_INP_TMP = ExpTmpLocalVar_Size;
+                        }
+                    }
+                }
+                else
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Size = hv_Size_COPY_INP_TMP.TupleInt()
+                                ;
+                            hv_Size_COPY_INP_TMP.Dispose();
+                            hv_Size_COPY_INP_TMP = ExpTmpLocalVar_Size;
+                        }
+                    }
+                }
+                if ((int)new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("Courier")) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Courier";
+                    hv_Fonts[1] = "Courier 10 Pitch";
+                    hv_Fonts[2] = "Courier New";
+                    hv_Fonts[3] = "CourierNew";
+                    hv_Fonts[4] = "Liberation Mono";
+                }
+                else if ((int)new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("mono")) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Consolas";
+                    hv_Fonts[1] = "Menlo";
+                    hv_Fonts[2] = "Courier";
+                    hv_Fonts[3] = "Courier 10 Pitch";
+                    hv_Fonts[4] = "FreeMono";
+                    hv_Fonts[5] = "Liberation Mono";
+                }
+                else if ((int)new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("sans")) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Luxi Sans";
+                    hv_Fonts[1] = "DejaVu Sans";
+                    hv_Fonts[2] = "FreeSans";
+                    hv_Fonts[3] = "Arial";
+                    hv_Fonts[4] = "Liberation Sans";
+                }
+                else if ((int)new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("serif")) != 0)
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple();
+                    hv_Fonts[0] = "Times New Roman";
+                    hv_Fonts[1] = "Luxi Serif";
+                    hv_Fonts[2] = "DejaVu Serif";
+                    hv_Fonts[3] = "FreeSerif";
+                    hv_Fonts[4] = "Utopia";
+                    hv_Fonts[5] = "Liberation Serif";
+                }
+                else
+                {
+                    hv_Fonts.Dispose();
+                    hv_Fonts = new HTuple(hv_Font_COPY_INP_TMP);
+                }
+                hv_Style.Dispose();
+                hv_Style = "";
+                if ((int)new HTuple(hv_Bold.TupleEqual("true")) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Style = hv_Style + "Bold";
+                            hv_Style.Dispose();
+                            hv_Style = ExpTmpLocalVar_Style;
+                        }
+                    }
+                }
+                else if ((int)new HTuple(hv_Bold.TupleNotEqual("false")) != 0)
+                {
+                    hv_Exception.Dispose();
+                    hv_Exception = "Wrong value of control parameter Bold";
+                    throw new HalconException(hv_Exception);
+                }
+                if ((int)new HTuple(hv_Slant.TupleEqual("true")) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Style = hv_Style + "Italic";
+                            hv_Style.Dispose();
+                            hv_Style = ExpTmpLocalVar_Style;
+                        }
+                    }
+                }
+                else if ((int)new HTuple(hv_Slant.TupleNotEqual("false")) != 0)
+                {
+                    hv_Exception.Dispose();
+                    hv_Exception = "Wrong value of control parameter Slant";
+                    throw new HalconException(hv_Exception);
+                }
+                if ((int)new HTuple(hv_Style.TupleEqual("")) != 0)
+                {
+                    hv_Style.Dispose();
+                    hv_Style = "Normal";
+                }
+                hv_AvailableFonts.Dispose();
+                HOperatorSet.QueryFont(hv_WindowHandle, out hv_AvailableFonts);
+                hv_Font_COPY_INP_TMP.Dispose();
+                hv_Font_COPY_INP_TMP = "";
+                for (hv_Fdx = 0; (int)hv_Fdx <= (int)(new HTuple(hv_Fonts.TupleLength()) - 1); hv_Fdx = (int)hv_Fdx + 1)
+                {
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_AvailableFonts.TupleFind(
+                            hv_Fonts.TupleSelect(hv_Fdx));
+                    }
+                    if ((int)new HTuple(new HTuple(hv_Indices.TupleLength()).TupleGreater(
+                        0)) != 0)
+                    {
+                        if ((int)new HTuple(hv_Indices.TupleSelect(0).TupleGreaterEqual(0)) != 0)
+                        {
+                            hv_Font_COPY_INP_TMP.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Font_COPY_INP_TMP = hv_Fonts.TupleSelect(
+                                    hv_Fdx);
+                            }
+                            break;
+                        }
+                    }
+                }
+                if ((int)new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("")) != 0)
+                {
+                    throw new HalconException("Wrong value of control parameter Font");
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_Font = hv_Font_COPY_INP_TMP + "-" + hv_Style + "-" + hv_Size_COPY_INP_TMP;
+                        hv_Font_COPY_INP_TMP.Dispose();
+                        hv_Font_COPY_INP_TMP = ExpTmpLocalVar_Font;
+                    }
+                }
+                HOperatorSet.SetFont(hv_WindowHandle, hv_Font_COPY_INP_TMP);
+
+                hv_Font_COPY_INP_TMP.Dispose();
+                hv_Size_COPY_INP_TMP.Dispose();
+                hv_OS.Dispose();
+                hv_Fonts.Dispose();
+                hv_Style.Dispose();
+                hv_Exception.Dispose();
+                hv_AvailableFonts.Dispose();
+                hv_Fdx.Dispose();
+                hv_Indices.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_Font_COPY_INP_TMP.Dispose();
+                hv_Size_COPY_INP_TMP.Dispose();
+                hv_OS.Dispose();
+                hv_Fonts.Dispose();
+                hv_Style.Dispose();
+                hv_Exception.Dispose();
+                hv_AvailableFonts.Dispose();
+                hv_Fdx.Dispose();
+                hv_Indices.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Graphics / Output
+        // Short Description: Compute the 3D rotation from the mouse movement 
+        public static void trackball(HTuple hv_MX1, HTuple hv_MY1, HTuple hv_MX2, HTuple hv_MY2,
+            HTuple hv_VirtualTrackball, HTuple hv_TrackballSize, HTuple hv_SensFactor, out HTuple hv_QuatRotation)
+        {
+
+
+
+            // Local iconic variables 
+
+            // Local control variables 
+
+            HTuple hv_P1 = new HTuple(), hv_P2 = new HTuple();
+            HTuple hv_RotAxis = new HTuple(), hv_D = new HTuple();
+            HTuple hv_T = new HTuple(), hv_RotAngle = new HTuple();
+            HTuple hv_Len = new HTuple();
+            // Initialize local and output iconic variables 
+            hv_QuatRotation = new HTuple();
+            try
+            {
+                //
+                //Compute the 3D rotation from the mouse movement
+                //
+                if ((int)new HTuple(hv_MX1.TupleEqual(hv_MX2)).TupleAnd(new HTuple(hv_MY1.TupleEqual(
+                    hv_MY2))) != 0)
+                {
+                    hv_QuatRotation.Dispose();
+                    hv_QuatRotation = new HTuple();
+                    hv_QuatRotation[0] = 1;
+                    hv_QuatRotation[1] = 0;
+                    hv_QuatRotation[2] = 0;
+                    hv_QuatRotation[3] = 0;
+
+                    hv_P1.Dispose();
+                    hv_P2.Dispose();
+                    hv_RotAxis.Dispose();
+                    hv_D.Dispose();
+                    hv_T.Dispose();
+                    hv_RotAngle.Dispose();
+                    hv_Len.Dispose();
+
+                    return;
+                }
+                //Project the image point onto the trackball
+                hv_P1.Dispose();
+                project_point_on_trackball(hv_MX1, hv_MY1, hv_VirtualTrackball, hv_TrackballSize,
+                    out hv_P1);
+                hv_P2.Dispose();
+                project_point_on_trackball(hv_MX2, hv_MY2, hv_VirtualTrackball, hv_TrackballSize,
+                    out hv_P2);
+                //The cross product of the projected points defines the rotation axis
+                hv_RotAxis.Dispose();
+                tuple_vector_cross_product(hv_P1, hv_P2, out hv_RotAxis);
+                //Compute the rotation angle
+                hv_D.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_D = hv_P2 - hv_P1;
+                }
+                hv_T.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_T = (hv_D * hv_D).TupleSum()
+                        .TupleSqrt() / (2.0 * hv_TrackballSize);
+                }
+                if ((int)new HTuple(hv_T.TupleGreater(1.0)) != 0)
+                {
+                    hv_T.Dispose();
+                    hv_T = 1.0;
+                }
+                if ((int)new HTuple(hv_T.TupleLess(-1.0)) != 0)
+                {
+                    hv_T.Dispose();
+                    hv_T = -1.0;
+                }
+                hv_RotAngle.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_RotAngle = 2.0 * hv_T.TupleAsin()
+                         * hv_SensFactor;
+                }
+                hv_Len.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Len = (hv_RotAxis * hv_RotAxis).TupleSum()
+                        .TupleSqrt();
+                }
+                if ((int)new HTuple(hv_Len.TupleGreater(0.0)) != 0)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_RotAxis = hv_RotAxis / hv_Len;
+                            hv_RotAxis.Dispose();
+                            hv_RotAxis = ExpTmpLocalVar_RotAxis;
+                        }
+                    }
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_QuatRotation.Dispose();
+                    HOperatorSet.AxisAngleToQuat(hv_RotAxis.TupleSelect(0), hv_RotAxis.TupleSelect(
+                        1), hv_RotAxis.TupleSelect(2), hv_RotAngle, out hv_QuatRotation);
+                }
+
+                hv_P1.Dispose();
+                hv_P2.Dispose();
+                hv_RotAxis.Dispose();
+                hv_D.Dispose();
+                hv_T.Dispose();
+                hv_RotAngle.Dispose();
+                hv_Len.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+
+                hv_P1.Dispose();
+                hv_P2.Dispose();
+                hv_RotAxis.Dispose();
+                hv_D.Dispose();
+                hv_T.Dispose();
+                hv_RotAngle.Dispose();
+                hv_Len.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+        // Chapter: Tuple / Arithmetic
+        // Short Description: Calculate the cross product of two vectors of length 3. 
+        public static void tuple_vector_cross_product(HTuple hv_V1, HTuple hv_V2, out HTuple hv_VC)
+        {
+
+
+
+            // Local iconic variables 
+            // Initialize local and output iconic variables 
+            hv_VC = new HTuple();
+            //The caller must ensure that the length of both input vectors is 3
+            hv_VC.Dispose();
+            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+            {
+                hv_VC = hv_V1.TupleSelect(
+                    1) * hv_V2.TupleSelect(2) - hv_V1.TupleSelect(2) * hv_V2.TupleSelect(1);
+            }
+            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+            {
+                {
+                    HTuple
+                      ExpTmpLocalVar_VC = hv_VC.TupleConcat(
+                        hv_V1.TupleSelect(2) * hv_V2.TupleSelect(0) - hv_V1.TupleSelect(0) * hv_V2.TupleSelect(
+                        2));
+                    hv_VC.Dispose();
+                    hv_VC = ExpTmpLocalVar_VC;
+                }
+            }
+            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+            {
+                {
+                    HTuple
+                      ExpTmpLocalVar_VC = hv_VC.TupleConcat(
+                        hv_V1.TupleSelect(0) * hv_V2.TupleSelect(1) - hv_V1.TupleSelect(1) * hv_V2.TupleSelect(
+                        0));
+                    hv_VC.Dispose();
+                    hv_VC = ExpTmpLocalVar_VC;
+                }
+            }
+
+
+            return;
+        }
+
+        // Chapter: Graphics / Output
+        // Short Description: Display 3D object models 
+        public void visualize_object_model_3d(HTuple hv_WindowHandle, HTuple hv_ObjectModel3D,
+            HTuple hv_CamParam, HTuple hv_PoseIn, HTuple hv_GenParamName, HTuple hv_GenParamValue,
+            HTuple hv_Title, HTuple hv_Label, HTuple hv_Information, out HTuple hv_PoseOut)
+        {
+
+
+
+            // Local iconic variables 
+
+            HObject ho_Image = null, ho_ImageDump = null;
+
+            // Local control variables 
+
+            HTuple ExpTmpLocalVar_gDispObjOffset = new HTuple();
+            HTuple ExpTmpLocalVar_gLabelsDecor = new HTuple(), ExpTmpLocalVar_gInfoDecor = new HTuple();
+            HTuple ExpTmpLocalVar_gInfoPos = new HTuple(), ExpTmpLocalVar_gTitlePos = new HTuple();
+            HTuple ExpTmpLocalVar_gTitleDecor = new HTuple(), ExpTmpLocalVar_gTerminationButtonLabel = new HTuple();
+            HTuple ExpTmpLocalVar_gAlphaDeselected = new HTuple();
+            HTuple ExpTmpLocalVar_gIsSinglePose = new HTuple(), ExpTmpLocalVar_gUsesOpenGL = new HTuple();
+            HTuple hv_Scene3DTest = new HTuple(), hv_Scene3D = new HTuple();
+            HTuple hv_WindowHandleBuffer = new HTuple(), hv_TrackballSize = new HTuple();
+            HTuple hv_VirtualTrackball = new HTuple(), hv_MouseMapping = new HTuple();
+            HTuple hv_WaitForButtonRelease = new HTuple(), hv_MaxNumModels = new HTuple();
+            HTuple hv_WindowCenteredRotation = new HTuple(), hv_NumModels = new HTuple();
+            HTuple hv_SelectedObject = new HTuple(), hv_ClipRegion = new HTuple();
+            HTuple hv_CPLength = new HTuple(), hv_RowNotUsed = new HTuple();
+            HTuple hv_ColumnNotUsed = new HTuple(), hv_Width = new HTuple();
+            HTuple hv_Height = new HTuple(), hv_WPRow1 = new HTuple();
+            HTuple hv_WPColumn1 = new HTuple(), hv_WPRow2 = new HTuple();
+            HTuple hv_WPColumn2 = new HTuple(), hv_CamParamValue = new HTuple();
+            HTuple hv_CamWidth = new HTuple(), hv_CamHeight = new HTuple();
+            HTuple hv_Scale = new HTuple(), hv_Indices = new HTuple();
+            HTuple hv_DispBackground = new HTuple(), hv_Mask = new HTuple();
+            HTuple hv_Center = new HTuple(), hv_PoseEstimated = new HTuple();
+            HTuple hv_Poses = new HTuple(), hv_HomMat3Ds = new HTuple();
+            HTuple hv_Sequence = new HTuple(), hv_Font = new HTuple();
+            HTuple hv_Exception = new HTuple(), hv_OpenGLInfo = new HTuple();
+            HTuple hv_DummyObjectModel3D = new HTuple(), hv_CameraIndexTest = new HTuple();
+            HTuple hv_PoseTest = new HTuple(), hv_InstanceIndexTest = new HTuple();
+            HTuple hv_MinImageSize = new HTuple(), hv_TrackballRadiusPixel = new HTuple();
+            HTuple hv_Ascent = new HTuple(), hv_Descent = new HTuple();
+            HTuple hv_TextWidth = new HTuple(), hv_TextHeight = new HTuple();
+            HTuple hv_NumChannels = new HTuple(), hv_ColorImage = new HTuple();
+            HTuple hv_CameraIndex = new HTuple(), hv_AllInstances = new HTuple();
+            HTuple hv_SetLight = new HTuple(), hv_LightParam = new HTuple();
+            HTuple hv_LightPosition = new HTuple(), hv_LightKind = new HTuple();
+            HTuple hv_LightIndex = new HTuple(), hv_PersistenceParamName = new HTuple();
+            HTuple hv_PersistenceParamValue = new HTuple(), hv_AlphaOrig = new HTuple();
+            HTuple hv_I = new HTuple(), hv_ParamName = new HTuple();
+            HTuple hv_ParamValue = new HTuple(), hv_ParamNameTrunk = new HTuple();
+            HTuple hv_Instance = new HTuple(), hv_HomMat3D = new HTuple();
+            HTuple hv_Qx = new HTuple(), hv_Qy = new HTuple(), hv_Qz = new HTuple();
+            HTuple hv_TBCenter = new HTuple(), hv_TBSize = new HTuple();
+            HTuple hv_ButtonHold = new HTuple(), hv_VisualizeTB = new HTuple();
+            HTuple hv_MaxIndex = new HTuple(), hv_TrackballCenterRow = new HTuple();
+            HTuple hv_TrackballCenterCol = new HTuple(), hv_GraphEvent = new HTuple();
+            HTuple hv_Exit = new HTuple(), hv_GraphButtonRow = new HTuple();
+            HTuple hv_GraphButtonColumn = new HTuple(), hv_GraphButton = new HTuple();
+            HTuple hv_ButtonReleased = new HTuple(), hv_e = new HTuple();
+            HTuple hv_CamParam_COPY_INP_TMP = new HTuple(hv_CamParam);
+            HTuple hv_GenParamName_COPY_INP_TMP = new HTuple(hv_GenParamName);
+            HTuple hv_GenParamValue_COPY_INP_TMP = new HTuple(hv_GenParamValue);
+            HTuple hv_Label_COPY_INP_TMP = new HTuple(hv_Label);
+            HTuple hv_PoseIn_COPY_INP_TMP = new HTuple(hv_PoseIn);
+
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_Image);
+            HOperatorSet.GenEmptyObj(out ho_ImageDump);
+            hv_PoseOut = new HTuple();
+            try
+            {
+                //The procedure visualize_object_model_3d can be used to display
+                //one or more 3d object models and to interactively modify
+                //the object poses by using the mouse.
+                //
+                //The pose can be modified by moving the mouse while
+                //pressing a mouse button. The default settings are:
+                //
+                // Rotate: Left mouse button
+                // Zoom: Shift + Left mouse button (or Center mouse button)
+                // Pan: Ctrl + Left mouse button
+                //
+                //Furthermore, it is possible to select and deselect objects,
+                //to decrease the mouse sensitivity, and to toggle the
+                //inspection mode (see the description of the generic parameter
+                //'inspection_mode' below):
+                //
+                // (De-)select object(s): Right mouse button
+                // Low mouse sensitivity: Alt + mouse button
+                // Toggle inspection mode: Ctrl + Alt + Left mouse button
+                //
+                //In GenParamName and GenParamValue all generic Parameters
+                //of disp_object_model_3d are supported.
+                //
+                //**********************************************************
+                //Define global variables
+                //**********************************************************
+                //
+                //global def tuple gDispObjOffset
+                //global def tuple gLabelsDecor
+                //global def tuple gInfoDecor
+                //global def tuple gInfoPos
+                //global def tuple gTitlePos
+                //global def tuple gTitleDecor
+                //global def tuple gTerminationButtonLabel
+                //global def tuple gAlphaDeselected
+                //global def tuple gIsSinglePose
+                //global def tuple gUsesOpenGL
+                //
+                //**********************************************************
+                //Initialize Handles to enable correct handling in error case
+                //**********************************************************
+                hv_Scene3DTest.Dispose();
+                hv_Scene3DTest = new HTuple();
+                hv_Scene3D.Dispose();
+                hv_Scene3D = new HTuple();
+                hv_WindowHandleBuffer.Dispose();
+                hv_WindowHandleBuffer = new HTuple();
+
+                //**********************************************************
+                //Some user defines that may be adapted if desired
+                //**********************************************************
+                //
+                //TrackballSize defines the diameter of the trackball in
+                //the image with respect to the smaller image dimension.
+                hv_TrackballSize.Dispose();
+                hv_TrackballSize = 0.8;
+                //
+                //VirtualTrackball defines the type of virtual trackball that
+                //shall be used ('shoemake' or 'bell').
+                hv_VirtualTrackball.Dispose();
+                hv_VirtualTrackball = "shoemake";
+                //VirtualTrackball := 'bell'
+                //
+                //Functionality of mouse buttons
+                //    1: Left mouse button
+                //    2: Middle mouse button
+                //    4: Right mouse button
+                //    5: Left+Right mouse button
+                //  8+x: Shift + mouse button
+                // 16+x: Ctrl + mouse button
+                // 48+x: Ctrl + Alt + mouse button
+                //in the order [Translate, Rotate, Scale, ScaleAlternative1, ScaleAlternative2, SelectObjects, ToggleSelectionMode]
+                hv_MouseMapping.Dispose();
+                hv_MouseMapping = new HTuple();
+                hv_MouseMapping[0] = 17;
+                hv_MouseMapping[1] = 1;
+                hv_MouseMapping[2] = 2;
+                hv_MouseMapping[3] = 5;
+                hv_MouseMapping[4] = 9;
+                hv_MouseMapping[5] = 4;
+                hv_MouseMapping[6] = 49;
+                //
+                //The labels of the objects appear next to their projected
+                //center. With gDispObjOffset a fixed offset is added
+                //                  R,  C
+                ExpTmpLocalVar_gDispObjOffset = new HTuple();
+                ExpTmpLocalVar_gDispObjOffset[0] = -30;
+                ExpTmpLocalVar_gDispObjOffset[1] = 0;
+                ExpSetGlobalVar_gDispObjOffset(ExpTmpLocalVar_gDispObjOffset);
+                //
+                //Customize the decoration of the different text elements
+                //              Color,   Box
+                ExpTmpLocalVar_gInfoDecor = new HTuple();
+                ExpTmpLocalVar_gInfoDecor[0] = "white";
+                ExpTmpLocalVar_gInfoDecor[1] = "false";
+                ExpSetGlobalVar_gInfoDecor(ExpTmpLocalVar_gInfoDecor);
+                ExpTmpLocalVar_gLabelsDecor = new HTuple();
+                ExpTmpLocalVar_gLabelsDecor[0] = "white";
+                ExpTmpLocalVar_gLabelsDecor[1] = "false";
+                ExpSetGlobalVar_gLabelsDecor(ExpTmpLocalVar_gLabelsDecor);
+                ExpTmpLocalVar_gTitleDecor = new HTuple();
+                ExpTmpLocalVar_gTitleDecor[0] = "black";
+                ExpTmpLocalVar_gTitleDecor[1] = "true";
+                ExpSetGlobalVar_gTitleDecor(ExpTmpLocalVar_gTitleDecor);
+                //
+                //Customize the position of some text elements
+                //  gInfoPos has one of the values
+                //  {'UpperLeft', 'LowerLeft', 'UpperRight'}
+                ExpTmpLocalVar_gInfoPos = "LowerLeft";
+                ExpSetGlobalVar_gInfoPos(ExpTmpLocalVar_gInfoPos);
+                //  gTitlePos has one of the values
+                //  {'UpperLeft', 'UpperCenter', 'UpperRight'}
+                ExpTmpLocalVar_gTitlePos = "UpperLeft";
+                ExpSetGlobalVar_gTitlePos(ExpTmpLocalVar_gTitlePos);
+                //Alpha value (=1-transparency) that is used for visualizing
+                //the objects that are not selected
+                ExpTmpLocalVar_gAlphaDeselected = 0.3;
+                ExpSetGlobalVar_gAlphaDeselected(ExpTmpLocalVar_gAlphaDeselected);
+                //Customize the label of the continue button
+                ExpTmpLocalVar_gTerminationButtonLabel = " Continue ";
+                ExpSetGlobalVar_gTerminationButtonLabel(ExpTmpLocalVar_gTerminationButtonLabel);
+                //Define if the continue button responds to a single click event or
+                //if it responds only if the mouse button is released while being placed
+                //over the continue button.
+                //'true':  Wait until the continue button has been released.
+                //         This should be used to avoid unwanted continuations of
+                //         subsequent calls of visualize_object_model_3d, which can
+                //         otherwise occur if the mouse button remains pressed while the
+                //         next visualization is active.
+                //'false': Continue the execution already if the continue button is
+                //         pressed. This option allows a fast forwarding through
+                //         subsequent calls of visualize_object_model_3d.
+                hv_WaitForButtonRelease.Dispose();
+                hv_WaitForButtonRelease = "true";
+                //Number of 3D Object models that can be selected and handled individually.
+                //If there are more models passed then this number, some calculations
+                //are performed differently and the individual selection and handling
+                //of models is not supported anymore. Note that the value of MaxNumModels
+                //can be overwritten with the generic parameter max_num_selectable_models.
+                hv_MaxNumModels.Dispose();
+                hv_MaxNumModels = 1000;
+                //Defines the default for the initial state of the rotation center:
+                //(1) The rotation center is fixed in the center of the image and lies
+                //    on the surface of the object.
+                //(2) The rotation center lies in the center of the object.
+                hv_WindowCenteredRotation.Dispose();
+                hv_WindowCenteredRotation = 2;
+                //
+                //**********************************************************
+                //
+                //Initialize some values
+                hv_NumModels.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_NumModels = new HTuple(hv_ObjectModel3D.TupleLength()
+                        );
+                }
+                hv_SelectedObject.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_SelectedObject = HTuple.TupleGenConst(
+                        hv_NumModels, 1);
+                }
+                //
+                //Apply some system settings
+                // dev_get_preferences(...); only in hdevelop
+                // dev_set_preferences(...); only in hdevelop
+                // dev_get_preferences(...); only in hdevelop
+                // dev_set_preferences(...); only in hdevelop
+                hv_ClipRegion.Dispose();
+                HOperatorSet.GetSystem("clip_region", out hv_ClipRegion);
+                HOperatorSet.SetSystem("clip_region", "false");
+                dev_update_off();
+                //
+                //Check if GenParamName matches GenParamValue
+                if ((int)new HTuple(new HTuple(hv_GenParamName_COPY_INP_TMP.TupleLength()
+                    ).TupleNotEqual(new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleLength()
+                    ))) != 0)
+                {
+                    throw new HalconException("Number of generic parameters does not match number of generic parameter values");
+                }
+                //
+                try
+                {
+                    //
+                    //Refactor camera parameters to fit to window size
+                    //
+                    hv_CPLength.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_CPLength = new HTuple(hv_CamParam_COPY_INP_TMP.TupleLength()
+                            );
+                    }
+                    hv_RowNotUsed.Dispose(); hv_ColumnNotUsed.Dispose(); hv_Width.Dispose(); hv_Height.Dispose();
+                    HOperatorSet.GetWindowExtents(hv_WindowHandle, out hv_RowNotUsed, out hv_ColumnNotUsed,
+                        out hv_Width, out hv_Height);
+                    hv_WPRow1.Dispose(); hv_WPColumn1.Dispose(); hv_WPRow2.Dispose(); hv_WPColumn2.Dispose();
+                    HOperatorSet.GetPart(hv_WindowHandle, out hv_WPRow1, out hv_WPColumn1, out hv_WPRow2,
+                        out hv_WPColumn2);
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.SetPart(hv_WindowHandle, 0, 0, hv_Height - 1, hv_Width - 1);
+                    }
+                    if ((int)new HTuple(hv_CPLength.TupleEqual(0)) != 0)
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            gen_cam_par_area_scan_division(0.06, 0, 8.5e-6, 8.5e-6, hv_Width / 2, hv_Height / 2,
+                                hv_Width, hv_Height, out hv_CamParam_COPY_INP_TMP);
+                        }
+                    }
+                    else
+                    {
+                        hv_CamParamValue.Dispose();
+                        get_cam_par_data(hv_CamParam_COPY_INP_TMP, new HTuple("sx").TupleConcat(
+                            "sy").TupleConcat("cx").TupleConcat("cy").TupleConcat("image_width").TupleConcat(
+                            "image_height"), out hv_CamParamValue);
+                        hv_CamWidth.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_CamWidth = hv_CamParamValue.TupleSelect(
+                                4).TupleReal();
+                        }
+                        hv_CamHeight.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_CamHeight = hv_CamParamValue.TupleSelect(
+                                5).TupleReal();
+                        }
+                        hv_Scale.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Scale = (hv_Width / hv_CamWidth).TupleConcat(
+                                hv_Height / hv_CamHeight).TupleMin();
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "sx", hv_CamParamValue.TupleSelect(
+                                0) / hv_Scale, out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "sy", hv_CamParamValue.TupleSelect(
+                                1) / hv_Scale, out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "cx", hv_CamParamValue.TupleSelect(
+                                2) * hv_Scale, out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "cy", hv_CamParamValue.TupleSelect(
+                                3) * hv_Scale, out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "image_width", (hv_CamParamValue.TupleSelect(
+                                4) * hv_Scale).TupleInt(), out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            set_cam_par_data(hv_CamParam_COPY_INP_TMP, "image_height", (hv_CamParamValue.TupleSelect(
+                                5) * hv_Scale).TupleInt(), out ExpTmpOutVar_0);
+                            hv_CamParam_COPY_INP_TMP.Dispose();
+                            hv_CamParam_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                    }
+                    //
+                    //Check the generic parameters for max_num_selectable_models
+                    //(Note that the default is set above to MaxNumModels := 1000)
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                            "max_num_selectable_models");
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        if ((int)hv_GenParamValue_COPY_INP_TMP.TupleSelect(hv_Indices.TupleSelect(
+                            0)).TupleIsNumber() != 0)
+                        {
+                            if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                hv_Indices.TupleSelect(0)).TupleNumber().TupleInt().TupleLess(
+                                1)) != 0)
+                            {
+                                //Wrong parameter value: Only integer values greater than 0 are allowed
+                                throw new HalconException("Wrong value for parameter 'max_num_selectable_models' (must be an integer value greater than 0)");
+                            }
+                        }
+                        else
+                        {
+                            //Wrong parameter value: Only integer values greater than 0 are allowed
+                            throw new HalconException("Wrong value for parameter 'max_num_selectable_models' (must be an integer value greater than 0)");
+                        }
+                        hv_MaxNumModels.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_MaxNumModels = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                hv_Indices.TupleSelect(0)).TupleNumber().TupleInt();
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    //
+                    //Check the generic parameters for window_centered_rotation
+                    //(Note that the default is set above to WindowCenteredRotation := 2)
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                            "inspection_mode");
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(hv_Indices.TupleSelect(
+                            0)).TupleEqual("surface")) != 0)
+                        {
+                            hv_WindowCenteredRotation.Dispose();
+                            hv_WindowCenteredRotation = 1;
+                        }
+                        else if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                            hv_Indices.TupleSelect(0)).TupleEqual("standard")) != 0)
+                        {
+                            hv_WindowCenteredRotation.Dispose();
+                            hv_WindowCenteredRotation = 2;
+                        }
+                        else
+                        {
+                            //Wrong parameter value, use default value
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    //
+                    //Check the generic parameters for disp_background
+                    //(The former parameter name 'use_background' is still supported
+                    // for compatibility reasons)
+                    hv_DispBackground.Dispose();
+                    hv_DispBackground = "false";
+                    if ((int)new HTuple(new HTuple(hv_GenParamName_COPY_INP_TMP.TupleLength()
+                        ).TupleGreater(0)) != 0)
+                    {
+                        hv_Mask.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Mask = hv_GenParamName_COPY_INP_TMP.TupleEqualElem(
+                                "disp_background").TupleOr(hv_GenParamName_COPY_INP_TMP.TupleEqualElem(
+                                "use_background"));
+                        }
+                        hv_Indices.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Indices = hv_Mask.TupleFind(
+                                1);
+                        }
+                    }
+                    else
+                    {
+                        hv_Indices.Dispose();
+                        hv_Indices = -1;
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        hv_DispBackground.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_DispBackground = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                hv_Indices.TupleSelect(0));
+                        }
+                        if ((int)new HTuple(hv_DispBackground.TupleNotEqual("true")).TupleAnd(
+                            new HTuple(hv_DispBackground.TupleNotEqual("false"))) != 0)
+                        {
+                            //Wrong parameter value: Only 'true' and 'false' are allowed
+                            throw new HalconException("Wrong value for parameter 'disp_background' (must be either 'true' or 'false')");
+                        }
+                        //Note that the background is handled explicitly in this procedure
+                        //and therefore, the parameter is removed from the list of
+                        //parameters and disp_background is always set to true (see below)
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                    }
+                    //
+                    //Read and check the parameter Label for each object
+                    if ((int)new HTuple(new HTuple(hv_Label_COPY_INP_TMP.TupleLength()).TupleEqual(
+                        0)) != 0)
+                    {
+                        //no labels set -> leave as []
+                    }
+                    else if ((int)new HTuple(new HTuple(hv_Label_COPY_INP_TMP.TupleLength()
+                        ).TupleEqual(1)) != 0)
+                    {
+                        //a single label set for all models
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_Label = HTuple.TupleGenConst(
+                                    hv_NumModels, hv_Label_COPY_INP_TMP);
+                                hv_Label_COPY_INP_TMP.Dispose();
+                                hv_Label_COPY_INP_TMP = ExpTmpLocalVar_Label;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        if ((int)new HTuple(new HTuple(hv_Label_COPY_INP_TMP.TupleLength()).TupleNotEqual(
+                            hv_NumModels)) != 0)
+                        {
+                            //Number of elements in Label does not match
+                            //the number of object models.
+                            throw new HalconException(new HTuple(new HTuple("Number of elements in Label (") + new HTuple(hv_Label_COPY_INP_TMP.TupleLength()
+                                )) + ") does not match the number of object models(" + hv_NumModels + ").");
+                        }
+                    }
+                    //Convert labels into strings
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Label = "" + hv_Label_COPY_INP_TMP;
+                            hv_Label_COPY_INP_TMP.Dispose();
+                            hv_Label_COPY_INP_TMP = ExpTmpLocalVar_Label;
+                        }
+                    }
+                    //
+                    //Read and check the parameter PoseIn for each object
+                    hv_Center.Dispose();
+                    get_object_models_center(hv_ObjectModel3D, out hv_Center);
+                    if ((int)new HTuple(hv_Center.TupleEqual(new HTuple())) != 0)
+                    {
+                        hv_Center.Dispose();
+                        hv_Center = new HTuple();
+                        hv_Center[0] = 0;
+                        hv_Center[1] = 0;
+                        hv_Center[2] = 0;
+                    }
+                    if ((int)new HTuple(new HTuple(hv_PoseIn_COPY_INP_TMP.TupleLength()).TupleEqual(
+                        0)) != 0)
+                    {
+                        //If no pose was specified by the caller, automatically calculate
+                        //a pose that is appropriate for the visualization.
+                        //Set the initial model reference pose. The orientation is parallel
+                        //to the object coordinate system, the position is at the center
+                        //of gravity of all models.
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_PoseIn_COPY_INP_TMP.Dispose();
+                            HOperatorSet.CreatePose(-hv_Center.TupleSelect(0), -hv_Center.TupleSelect(
+                                1), -hv_Center.TupleSelect(2), 0, 0, 0, "Rp+T", "gba", "point",
+                                out hv_PoseIn_COPY_INP_TMP);
+                        }
+                        hv_PoseEstimated.Dispose();
+                        determine_optimum_pose_distance(hv_ObjectModel3D, hv_CamParam_COPY_INP_TMP,
+                            0.9, hv_PoseIn_COPY_INP_TMP, out hv_PoseEstimated);
+                        hv_Poses.Dispose();
+                        hv_Poses = new HTuple();
+                        hv_HomMat3Ds.Dispose();
+                        hv_HomMat3Ds = new HTuple();
+                        hv_Sequence.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Sequence = HTuple.TupleGenSequence(
+                                0, hv_NumModels * 7 - 1, 1);
+                        }
+                        hv_Poses.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Poses = hv_PoseEstimated.TupleSelect(
+                                hv_Sequence % 7);
+                        }
+                        ExpTmpLocalVar_gIsSinglePose = 1;
+                        ExpSetGlobalVar_gIsSinglePose(ExpTmpLocalVar_gIsSinglePose);
+                    }
+                    else if ((int)new HTuple(new HTuple(hv_PoseIn_COPY_INP_TMP.TupleLength()
+                        ).TupleEqual(7)) != 0)
+                    {
+                        hv_Poses.Dispose();
+                        hv_Poses = new HTuple();
+                        hv_HomMat3Ds.Dispose();
+                        hv_HomMat3Ds = new HTuple();
+                        hv_Sequence.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Sequence = HTuple.TupleGenSequence(
+                                0, hv_NumModels * 7 - 1, 1);
+                        }
+                        hv_Poses.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Poses = hv_PoseIn_COPY_INP_TMP.TupleSelect(
+                                hv_Sequence % 7);
+                        }
+                        ExpTmpLocalVar_gIsSinglePose = 1;
+                        ExpSetGlobalVar_gIsSinglePose(ExpTmpLocalVar_gIsSinglePose);
+                    }
+                    else
+                    {
+                        if ((int)new HTuple(new HTuple(hv_PoseIn_COPY_INP_TMP.TupleLength()).TupleNotEqual(
+                            new HTuple(hv_ObjectModel3D.TupleLength()) * 7)) != 0)
+                        {
+                            //Wrong number of values of input control parameter 'PoseIn'
+                            throw new HalconException("Wrong number of values of input control parameter 'PoseIn'.");
+                        }
+                        else
+                        {
+                            hv_Poses.Dispose();
+                            hv_Poses = new HTuple(hv_PoseIn_COPY_INP_TMP);
+                        }
+                        ExpTmpLocalVar_gIsSinglePose = 0;
+                        ExpSetGlobalVar_gIsSinglePose(ExpTmpLocalVar_gIsSinglePose);
+                    }
+                    //
+                    //Open (invisible) buffer window to avoid flickering
+                    hv_WindowHandleBuffer.Dispose();
+                    HOperatorSet.OpenWindow(0, 0, hv_Width, hv_Height, 0, "buffer", "", out hv_WindowHandleBuffer);
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.SetPart(hv_WindowHandleBuffer, 0, 0, hv_Height - 1, hv_Width - 1);
+                    }
+                    hv_Font.Dispose();
+                    HOperatorSet.GetFont(hv_WindowHandle, out hv_Font);
+                    try
+                    {
+                        HOperatorSet.SetFont(hv_WindowHandleBuffer, hv_Font);
+                    }
+                    // catch (Exception) 
+                    catch (HalconException HDevExpDefaultException2)
+                    {
+                        HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                    }
+                    //
+                    // Is OpenGL available and should it be used?
+                    ExpTmpLocalVar_gUsesOpenGL = "true";
+                    ExpSetGlobalVar_gUsesOpenGL(ExpTmpLocalVar_gUsesOpenGL);
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                            "opengl");
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            ExpTmpLocalVar_gUsesOpenGL = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                hv_Indices.TupleSelect(0));
+                        }
+                        ExpSetGlobalVar_gUsesOpenGL(ExpTmpLocalVar_gUsesOpenGL);
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamName = hv_GenParamName_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpLocalVar_GenParamName;
+                            }
+                        }
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            {
+                                HTuple
+                                  ExpTmpLocalVar_GenParamValue = hv_GenParamValue_COPY_INP_TMP.TupleRemove(
+                                    hv_Indices);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpLocalVar_GenParamValue;
+                            }
+                        }
+                        if ((int)new HTuple(ExpGetGlobalVar_gUsesOpenGL().TupleNotEqual("true")).TupleAnd(
+                            new HTuple(ExpGetGlobalVar_gUsesOpenGL().TupleNotEqual("false"))) != 0)
+                        {
+                            //Wrong parameter value: Only 'true' and 'false' are allowed
+                            throw new HalconException("Wrong value for parameter 'opengl' (must be either 'true' or 'false')");
+                        }
+                    }
+                    if ((int)new HTuple(ExpGetGlobalVar_gUsesOpenGL().TupleEqual("true")) != 0)
+                    {
+                        hv_OpenGLInfo.Dispose();
+                        HOperatorSet.GetSystem("opengl_info", out hv_OpenGLInfo);
+                        if ((int)new HTuple(hv_OpenGLInfo.TupleEqual("No OpenGL support included.")) != 0)
+                        {
+                            ExpTmpLocalVar_gUsesOpenGL = "false";
+                            ExpSetGlobalVar_gUsesOpenGL(ExpTmpLocalVar_gUsesOpenGL);
+                        }
+                        else
+                        {
+                            hv_DummyObjectModel3D.Dispose();
+                            HOperatorSet.GenObjectModel3dFromPoints(0, 0, 0, out hv_DummyObjectModel3D);
+                            hv_Scene3DTest.Dispose();
+                            HOperatorSet.CreateScene3d(out hv_Scene3DTest);
+                            hv_CameraIndexTest.Dispose();
+                            HOperatorSet.AddScene3dCamera(hv_Scene3DTest, hv_CamParam_COPY_INP_TMP,
+                                out hv_CameraIndexTest);
+                            hv_PoseTest.Dispose();
+                            determine_optimum_pose_distance(hv_DummyObjectModel3D, hv_CamParam_COPY_INP_TMP,
+                                0.9, new HTuple(0).TupleConcat(0).TupleConcat(0).TupleConcat(
+                                0).TupleConcat(0).TupleConcat(0).TupleConcat(0), out hv_PoseTest);
+                            hv_InstanceIndexTest.Dispose();
+                            HOperatorSet.AddScene3dInstance(hv_Scene3DTest, hv_DummyObjectModel3D,
+                                hv_PoseTest, out hv_InstanceIndexTest);
+                            try
+                            {
+                                HOperatorSet.DisplayScene3d(hv_WindowHandleBuffer, hv_Scene3DTest,
+                                    hv_InstanceIndexTest);
+                            }
+                            // catch (Exception) 
+                            catch (HalconException HDevExpDefaultException2)
+                            {
+                                HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                                ExpTmpLocalVar_gUsesOpenGL = "false";
+                                ExpSetGlobalVar_gUsesOpenGL(ExpTmpLocalVar_gUsesOpenGL);
+                            }
+                            HOperatorSet.ClearScene3d(hv_Scene3DTest);
+                            hv_Scene3DTest.Dispose();
+                            hv_Scene3DTest = new HTuple();
+                            HOperatorSet.ClearObjectModel3d(hv_DummyObjectModel3D);
+                        }
+                    }
+                    //
+                    //Compute the trackball
+                    hv_MinImageSize.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_MinImageSize = hv_Width.TupleConcat(
+                            hv_Height).TupleMin();
+                    }
+                    hv_TrackballRadiusPixel.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TrackballRadiusPixel = hv_TrackballSize * hv_MinImageSize / 2.0;
+                    }
+                    //
+                    //Measure the text extents for the continue button in the
+                    //graphics window
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Ascent.Dispose(); hv_Descent.Dispose(); hv_TextWidth.Dispose(); hv_TextHeight.Dispose();
+                        HOperatorSet.GetStringExtents(hv_WindowHandleBuffer, ExpGetGlobalVar_gTerminationButtonLabel() + "  ",
+                            out hv_Ascent, out hv_Descent, out hv_TextWidth, out hv_TextHeight);
+                    }
+                    //
+                    //Store background image
+                    if ((int)new HTuple(hv_DispBackground.TupleEqual("false")) != 0)
+                    {
+                        HOperatorSet.ClearWindow(hv_WindowHandle);
+                    }
+                    ho_Image.Dispose();
+                    HOperatorSet.DumpWindowImage(out ho_Image, hv_WindowHandle);
+                    //Special treatment for color background images necessary
+                    hv_NumChannels.Dispose();
+                    HOperatorSet.CountChannels(ho_Image, out hv_NumChannels);
+                    hv_ColorImage.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_ColorImage = new HTuple(hv_NumChannels.TupleEqual(
+                            3));
+                    }
+                    //
+                    hv_Scene3D.Dispose();
+                    HOperatorSet.CreateScene3d(out hv_Scene3D);
+                    hv_CameraIndex.Dispose();
+                    HOperatorSet.AddScene3dCamera(hv_Scene3D, hv_CamParam_COPY_INP_TMP, out hv_CameraIndex);
+                    hv_AllInstances.Dispose();
+                    HOperatorSet.AddScene3dInstance(hv_Scene3D, hv_ObjectModel3D, hv_Poses, out hv_AllInstances);
+                    //Always set 'disp_background' to true,  because it is handled explicitly
+                    //in this procedure (see above)
+                    HOperatorSet.SetScene3dParam(hv_Scene3D, "disp_background", "true");
+                    //Check if we have to set light specific parameters
+                    hv_SetLight.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_SetLight = new HTuple(hv_GenParamName_COPY_INP_TMP.TupleRegexpTest(
+                            "light_"));
+                    }
+                    if ((int)hv_SetLight != 0)
+                    {
+                        //set position of light source
+                        hv_Indices.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                                "light_position");
+                        }
+                        if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                            new HTuple()))) != 0)
+                        {
+                            //If multiple light positions are given, use the last one
+                            hv_LightParam.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_LightParam = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                    hv_Indices.TupleSelect(new HTuple(hv_Indices.TupleLength()) - 1)).TupleSplit(
+                                    new HTuple(", ")).TupleNumber();
+                            }
+                            if ((int)new HTuple(new HTuple(hv_LightParam.TupleLength()).TupleNotEqual(
+                                4)) != 0)
+                            {
+                                throw new HalconException("light_position must be given as a string that contains four space separated floating point numbers");
+                            }
+                            hv_LightPosition.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_LightPosition = hv_LightParam.TupleSelectRange(
+                                    0, 2);
+                            }
+                            hv_LightKind.Dispose();
+                            hv_LightKind = "point_light";
+                            if ((int)new HTuple(hv_LightParam.TupleSelect(3).TupleEqual(0)) != 0)
+                            {
+                                hv_LightKind.Dispose();
+                                hv_LightKind = "directional_light";
+                            }
+                            //Currently, only one light source is supported
+                            HOperatorSet.RemoveScene3dLight(hv_Scene3D, 0);
+                            hv_LightIndex.Dispose();
+                            HOperatorSet.AddScene3dLight(hv_Scene3D, hv_LightPosition, hv_LightKind,
+                                out hv_LightIndex);
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamName_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamValue_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                        }
+                        //set ambient part of light source
+                        hv_Indices.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                                "light_ambient");
+                        }
+                        if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                            new HTuple()))) != 0)
+                        {
+                            //If the ambient part is set multiple times, use the last setting
+                            hv_LightParam.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_LightParam = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                    hv_Indices.TupleSelect(new HTuple(hv_Indices.TupleLength()) - 1)).TupleSplit(
+                                    new HTuple(", ")).TupleNumber();
+                            }
+                            if ((int)new HTuple(new HTuple(hv_LightParam.TupleLength()).TupleLess(
+                                3)) != 0)
+                            {
+                                throw new HalconException("light_ambient must be given as a string that contains three space separated floating point numbers");
+                            }
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                HOperatorSet.SetScene3dLightParam(hv_Scene3D, 0, "ambient", hv_LightParam.TupleSelectRange(
+                                    0, 2));
+                            }
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamName_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamValue_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                        }
+                        //Set diffuse part of light source
+                        hv_Indices.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                                "light_diffuse");
+                        }
+                        if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                            new HTuple()))) != 0)
+                        {
+                            //If the diffuse part is set multiple times, use the last setting
+                            hv_LightParam.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_LightParam = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                    hv_Indices.TupleSelect(new HTuple(hv_Indices.TupleLength()) - 1)).TupleSplit(
+                                    new HTuple(", ")).TupleNumber();
+                            }
+                            if ((int)new HTuple(new HTuple(hv_LightParam.TupleLength()).TupleLess(
+                                3)) != 0)
+                            {
+                                throw new HalconException("light_diffuse must be given as a string that contains three space separated floating point numbers");
+                            }
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                HOperatorSet.SetScene3dLightParam(hv_Scene3D, 0, "diffuse", hv_LightParam.TupleSelectRange(
+                                    0, 2));
+                            }
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamName_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamName_COPY_INP_TMP.Dispose();
+                                hv_GenParamName_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                            {
+                                HTuple ExpTmpOutVar_0;
+                                HOperatorSet.TupleRemove(hv_GenParamValue_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                                hv_GenParamValue_COPY_INP_TMP = ExpTmpOutVar_0;
+                            }
+                        }
+                    }
+                    //
+                    //Handle persistence parameters separately because persistence will
+                    //only be activated immediately before leaving the visualization
+                    //procedure
+                    hv_PersistenceParamName.Dispose();
+                    hv_PersistenceParamName = new HTuple();
+                    hv_PersistenceParamValue.Dispose();
+                    hv_PersistenceParamValue = new HTuple();
+                    //Set position of light source
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                            "object_index_persistence");
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(hv_Indices.TupleSelect(
+                            new HTuple(hv_Indices.TupleLength()) - 1)).TupleEqual("true")) != 0)
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                {
+                                    HTuple
+                                      ExpTmpLocalVar_PersistenceParamName = hv_PersistenceParamName.TupleConcat(
+                                        "object_index_persistence");
+                                    hv_PersistenceParamName.Dispose();
+                                    hv_PersistenceParamName = ExpTmpLocalVar_PersistenceParamName;
+                                }
+                            }
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                {
+                                    HTuple
+                                      ExpTmpLocalVar_PersistenceParamValue = hv_PersistenceParamValue.TupleConcat(
+                                        "true");
+                                    hv_PersistenceParamValue.Dispose();
+                                    hv_PersistenceParamValue = ExpTmpLocalVar_PersistenceParamValue;
+                                }
+                            }
+                        }
+                        else if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                            hv_Indices.TupleSelect(new HTuple(hv_Indices.TupleLength()) - 1)).TupleEqual(
+                            "false")) != 0)
+                        {
+                        }
+                        else
+                        {
+                            throw new HalconException("Wrong value for parameter 'object_index_persistence' (must be either 'true' or 'false')");
+                        }
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            HOperatorSet.TupleRemove(hv_GenParamName_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                            hv_GenParamName_COPY_INP_TMP.Dispose();
+                            hv_GenParamName_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            HOperatorSet.TupleRemove(hv_GenParamValue_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                            hv_GenParamValue_COPY_INP_TMP.Dispose();
+                            hv_GenParamValue_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                    }
+                    hv_Indices.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Indices = hv_GenParamName_COPY_INP_TMP.TupleFind(
+                            "depth_persistence");
+                    }
+                    if ((int)new HTuple(hv_Indices.TupleNotEqual(-1)).TupleAnd(new HTuple(hv_Indices.TupleNotEqual(
+                        new HTuple()))) != 0)
+                    {
+                        if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(hv_Indices.TupleSelect(
+                            new HTuple(hv_Indices.TupleLength()) - 1)).TupleEqual("true")) != 0)
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                {
+                                    HTuple
+                                      ExpTmpLocalVar_PersistenceParamName = hv_PersistenceParamName.TupleConcat(
+                                        "depth_persistence");
+                                    hv_PersistenceParamName.Dispose();
+                                    hv_PersistenceParamName = ExpTmpLocalVar_PersistenceParamName;
+                                }
+                            }
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                {
+                                    HTuple
+                                      ExpTmpLocalVar_PersistenceParamValue = hv_PersistenceParamValue.TupleConcat(
+                                        "true");
+                                    hv_PersistenceParamValue.Dispose();
+                                    hv_PersistenceParamValue = ExpTmpLocalVar_PersistenceParamValue;
+                                }
+                            }
+                        }
+                        else if ((int)new HTuple(hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                            hv_Indices.TupleSelect(new HTuple(hv_Indices.TupleLength()) - 1)).TupleEqual(
+                            "false")) != 0)
+                        {
+                        }
+                        else
+                        {
+                            throw new HalconException("Wrong value for parameter 'depth_persistence' (must be either 'true' or 'false')");
+                        }
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            HOperatorSet.TupleRemove(hv_GenParamName_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                            hv_GenParamName_COPY_INP_TMP.Dispose();
+                            hv_GenParamName_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                        {
+                            HTuple ExpTmpOutVar_0;
+                            HOperatorSet.TupleRemove(hv_GenParamValue_COPY_INP_TMP, hv_Indices, out ExpTmpOutVar_0);
+                            hv_GenParamValue_COPY_INP_TMP.Dispose();
+                            hv_GenParamValue_COPY_INP_TMP = ExpTmpOutVar_0;
+                        }
+                    }
+                    //
+                    //Parse the generic parameters
+                    //- First, all parameters that are understood by set_scene_3d_instance_param
+                    hv_AlphaOrig.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_AlphaOrig = HTuple.TupleGenConst(
+                            hv_NumModels, 1);
+                    }
+                    for (hv_I = 0; (int)hv_I <= (int)(new HTuple(hv_GenParamName_COPY_INP_TMP.TupleLength()
+                        ) - 1); hv_I = (int)hv_I + 1)
+                    {
+                        hv_ParamName.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamName = hv_GenParamName_COPY_INP_TMP.TupleSelect(
+                                hv_I);
+                        }
+                        hv_ParamValue.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamValue = hv_GenParamValue_COPY_INP_TMP.TupleSelect(
+                                hv_I);
+                        }
+                        //Check if this parameter is understood by set_scene_3d_param
+                        if ((int)new HTuple(hv_ParamName.TupleEqual("alpha")) != 0)
+                        {
+                            hv_AlphaOrig.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_AlphaOrig = HTuple.TupleGenConst(
+                                    hv_NumModels, hv_ParamValue);
+                            }
+                        }
+                        try
+                        {
+                            HOperatorSet.SetScene3dParam(hv_Scene3D, hv_ParamName, hv_ParamValue);
+                            continue;
+                        }
+                        // catch (Exception) 
+                        catch (HalconException HDevExpDefaultException2)
+                        {
+                            HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                            if ((int)new HTuple(hv_Exception.TupleSelect(0).TupleEqual(1203)).TupleOr(
+                                new HTuple(hv_Exception.TupleSelect(0).TupleEqual(1303))) != 0)
+                            {
+                                if ((int)new HTuple(new HTuple(new HTuple(hv_ParamName.TupleEqual(
+                                    "color_attrib")).TupleOr(new HTuple(hv_ParamName.TupleEqual("red_channel_attrib")))).TupleOr(
+                                    new HTuple(hv_ParamName.TupleEqual("green_channel_attrib")))).TupleOr(
+                                    new HTuple(hv_ParamName.TupleEqual("blue_channel_attrib"))) != 0)
+                                {
+                                    throw new HalconException("Wrong type or value for parameter " + hv_ParamName + ": " + hv_ParamValue + ". " + hv_ParamValue + " may not be attached to the points of the 3D object model. Compare the parameter AttachExtAttribTo of set_object_model_3d_attrib.");
+                                }
+                                else
+                                {
+                                    throw new HalconException("Wrong type or value for parameter " + hv_ParamName + ": " + hv_ParamValue);
+                                }
+                            }
+                        }
+                        //Check if it is a parameter that is valid for only one instance
+                        //and therefore can be set only with set_scene_3d_instance_param
+                        hv_ParamNameTrunk.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_ParamNameTrunk = hv_ParamName.TupleRegexpReplace(
+                                "_\\d+$", "");
+                        }
+                        if ((int)new HTuple(hv_ParamName.TupleEqual(hv_ParamNameTrunk)) != 0)
+                        {
+                            hv_Instance.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Instance = HTuple.TupleGenSequence(
+                                    0, hv_NumModels - 1, 1);
+                            }
+                        }
+                        else
+                        {
+                            hv_Instance.Dispose();
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_Instance = hv_ParamName.TupleRegexpReplace(
+                                    "^" + hv_ParamNameTrunk + "_(\\d+)$", "$1").TupleNumber();
+                            }
+                            if ((int)new HTuple(hv_Instance.TupleLess(0)).TupleOr(new HTuple(hv_Instance.TupleGreater(
+                                hv_NumModels - 1))) != 0)
+                            {
+                                throw new HalconException("Parameter " + hv_ParamName + " refers to a non existing 3D object model");
+                            }
+                        }
+                        try
+                        {
+                            HOperatorSet.SetScene3dInstanceParam(hv_Scene3D, hv_Instance, hv_ParamNameTrunk,
+                                hv_ParamValue);
+                        }
+                        // catch (Exception) 
+                        catch (HalconException HDevExpDefaultException2)
+                        {
+                            HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                            if ((int)new HTuple(hv_Exception.TupleSelect(0).TupleEqual(1204)).TupleOr(
+                                new HTuple(hv_Exception.TupleSelect(0).TupleEqual(1304))) != 0)
+                            {
+                                if ((int)new HTuple(new HTuple(new HTuple(hv_ParamNameTrunk.TupleEqual(
+                                    "color_attrib")).TupleOr(new HTuple(hv_ParamNameTrunk.TupleEqual(
+                                    "red_channel_attrib")))).TupleOr(new HTuple(hv_ParamNameTrunk.TupleEqual(
+                                    "green_channel_attrib")))).TupleOr(new HTuple(hv_ParamNameTrunk.TupleEqual(
+                                    "blue_channel_attrib"))) != 0)
+                                {
+                                    throw new HalconException("Wrong type or value for parameter " + hv_ParamName + ": " + hv_ParamValue + ". " + hv_ParamValue + " may not be attached to the points of the 3D object model. Compare the parameter AttachExtAttribTo of set_object_model_3d_attrib.");
+                                }
+                                else
+                                {
+                                    throw new HalconException("Wrong type or value for parameter " + hv_ParamName + ": " + hv_ParamValue);
+                                }
+                            }
+                            else if ((int)new HTuple(hv_Exception.TupleSelect(0).TupleEqual(
+                                1203)).TupleOr(new HTuple(hv_Exception.TupleSelect(0).TupleEqual(
+                                1303))) != 0)
+                            {
+                                throw new HalconException("Wrong parameter name " + hv_ParamName);
+                            }
+                            else
+                            {
+                                throw new HalconException(hv_Exception);
+                            }
+                        }
+                        if ((int)new HTuple(hv_ParamNameTrunk.TupleEqual("alpha")) != 0)
+                        {
+                            if (hv_AlphaOrig == null)
+                                hv_AlphaOrig = new HTuple();
+                            hv_AlphaOrig[hv_Instance] = hv_ParamValue;
+                        }
+                    }
+                    //
+                    //Start the visualization loop
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_HomMat3D.Dispose();
+                        HOperatorSet.PoseToHomMat3d(hv_Poses.TupleSelectRange(0, 6), out hv_HomMat3D);
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_Qx.Dispose(); hv_Qy.Dispose(); hv_Qz.Dispose();
+                        HOperatorSet.AffineTransPoint3d(hv_HomMat3D, hv_Center.TupleSelect(0), hv_Center.TupleSelect(
+                            1), hv_Center.TupleSelect(2), out hv_Qx, out hv_Qy, out hv_Qz);
+                    }
+                    hv_TBCenter.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TBCenter = new HTuple();
+                        hv_TBCenter = hv_TBCenter.TupleConcat(hv_Qx, hv_Qy, hv_Qz);
+                    }
+                    hv_TBSize.Dispose();
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_TBSize = (0.5 + 0.5 * hv_SelectedObject.TupleSum()
+                             / hv_NumModels) * hv_TrackballRadiusPixel;
+                    }
+                    hv_ButtonHold.Dispose();
+                    hv_ButtonHold = 0;
+                    while (1 != 0)
+                    {
+                        // 璁剧疆鍦ㄦ寰幆涓嶅崱涓荤嚎绋�
+
+                        hv_VisualizeTB.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_VisualizeTB = new HTuple(hv_SelectedObject.TupleMax()
+                                .TupleNotEqual(0));
+                        }
+                        hv_MaxIndex.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_MaxIndex = new HTuple(hv_ObjectModel3D.TupleLength()
+                                ).TupleConcat(hv_MaxNumModels).TupleMin() - 1;
+                        }
+                        //Set trackball fixed in the center of the window
+                        hv_TrackballCenterRow.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_TrackballCenterRow = hv_Height / 2;
+                        }
+                        hv_TrackballCenterCol.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_TrackballCenterCol = hv_Width / 2;
+                        }
+                        if ((int)new HTuple(hv_WindowCenteredRotation.TupleEqual(1)) != 0)
+                        {
+                            try
+                            {
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_TBCenter.Dispose(); hv_TBSize.Dispose();
+                                    get_trackball_center_fixed(hv_SelectedObject.TupleSelectRange(0, hv_MaxIndex),
+                                        hv_TrackballCenterRow, hv_TrackballCenterCol, hv_TrackballRadiusPixel,
+                                        hv_Scene3D, hv_ObjectModel3D.TupleSelectRange(0, hv_MaxIndex), hv_Poses.TupleSelectRange(
+                                        0, (hv_MaxIndex + 1) * 7 - 1), hv_WindowHandleBuffer, hv_CamParam_COPY_INP_TMP,
+                                        hv_GenParamName_COPY_INP_TMP, hv_GenParamValue_COPY_INP_TMP, out hv_TBCenter,
+                                        out hv_TBSize);
+                                }
+                            }
+                            // catch (Exception) 
+                            catch (HalconException HDevExpDefaultException2)
+                            {
+                                HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                                disp_message(hv_WindowHandle, "Surface inspection mode is not available.",
+                                    "image", 5, 20, "red", "true");
+                                hv_WindowCenteredRotation.Dispose();
+                                hv_WindowCenteredRotation = 2;
+                                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                                {
+                                    hv_TBCenter.Dispose(); hv_TBSize.Dispose();
+                                    get_trackball_center(hv_SelectedObject.TupleSelectRange(0, hv_MaxIndex),
+                                        hv_TrackballRadiusPixel, hv_ObjectModel3D.TupleSelectRange(0, hv_MaxIndex),
+                                        hv_Poses.TupleSelectRange(0, (hv_MaxIndex + 1) * 7 - 1), out hv_TBCenter,
+                                        out hv_TBSize);
+                                }
+                                HOperatorSet.WaitSeconds(1);
+                            }
+                        }
+                        else
+                        {
+                            using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                            {
+                                hv_TBCenter.Dispose(); hv_TBSize.Dispose();
+                                get_trackball_center(hv_SelectedObject.TupleSelectRange(0, hv_MaxIndex),
+                                    hv_TrackballRadiusPixel, hv_ObjectModel3D.TupleSelectRange(0, hv_MaxIndex),
+                                    hv_Poses.TupleSelectRange(0, (hv_MaxIndex + 1) * 7 - 1), out hv_TBCenter,
+                                    out hv_TBSize);
+                            }
+                        }
+                        dump_image_output(ho_Image, hv_WindowHandleBuffer, hv_Scene3D, hv_AlphaOrig,
+                            hv_ObjectModel3D, hv_GenParamName_COPY_INP_TMP, hv_GenParamValue_COPY_INP_TMP,
+                            hv_CamParam_COPY_INP_TMP, hv_Poses, hv_ColorImage, hv_Title, hv_Information,
+                            hv_Label_COPY_INP_TMP, hv_VisualizeTB, "true", hv_TrackballCenterRow,
+                            hv_TrackballCenterCol, hv_TBSize, hv_SelectedObject, hv_WindowCenteredRotation,
+                            hv_TBCenter);
+                        ho_ImageDump.Dispose();
+                        HOperatorSet.DumpWindowImage(out ho_ImageDump, hv_WindowHandleBuffer);
+                        HDevWindowStack.SetActive(hv_WindowHandle);
+                        if (HDevWindowStack.IsOpen())
+                        {
+                            HOperatorSet.DispObj(ho_ImageDump, HDevWindowStack.GetActive());
+                        }
+                        //
+                        //Check for mouse events
+                        hv_GraphEvent.Dispose();
+                        hv_GraphEvent = 0;
+                        hv_Exit.Dispose();
+                        hv_Exit = 0;
+                        while (1 != 0)
+                        {
+                            // 璁剧疆鍦ㄦ寰幆涓嶅崱涓荤嚎绋�
+                            //
+                            //Check graphic event
+                            try
+                            {
+                                hv_GraphButtonRow.Dispose(); hv_GraphButtonColumn.Dispose(); hv_GraphButton.Dispose();
+                                HOperatorSet.GetMpositionSubPix(hv_WindowHandle, out hv_GraphButtonRow,
+                                    out hv_GraphButtonColumn, out hv_GraphButton);
+                                if ((int)new HTuple(hv_GraphButton.TupleNotEqual(0)) != 0)
+                                {
+                                    if ((int)new HTuple(new HTuple(new HTuple(hv_GraphButtonRow.TupleGreater(
+                                        hv_Height - hv_TextHeight - 25)).TupleAnd(new HTuple(hv_GraphButtonRow.TupleLess(
+                                        hv_Height)))).TupleAnd(new HTuple(hv_GraphButtonColumn.TupleGreater(
+                                        hv_Width - hv_TextWidth - 15)))).TupleAnd(new HTuple(hv_GraphButtonColumn.TupleLess(
+                                        hv_Width))) != 0)
+                                    {
+                                        //Wait until the continue button has been released
+                                        if ((int)new HTuple(hv_WaitForButtonRelease.TupleEqual("true")) != 0)
+                                        {
+                                            while (1 != 0)
+                                            {
+                                                hv_GraphButtonRow.Dispose(); hv_GraphButtonColumn.Dispose(); hv_GraphButton.Dispose();
+                                                HOperatorSet.GetMpositionSubPix(hv_WindowHandle, out hv_GraphButtonRow,
+                                                    out hv_GraphButtonColumn, out hv_GraphButton);
+                                                if ((int)new HTuple(hv_GraphButton.TupleEqual(0)).TupleOr(
+                                                    new HTuple(hv_GraphButton.TupleEqual(new HTuple()))) != 0)
+                                                {
+                                                    if ((int)new HTuple(new HTuple(new HTuple(hv_GraphButtonRow.TupleGreater(
+                                                        hv_Height - hv_TextHeight - 25)).TupleAnd(new HTuple(hv_GraphButtonRow.TupleLess(
+                                                        hv_Height)))).TupleAnd(new HTuple(hv_GraphButtonColumn.TupleGreater(
+                                                        hv_Width - hv_TextWidth - 15)))).TupleAnd(new HTuple(hv_GraphButtonColumn.TupleLess(
+                                                        hv_Width))) != 0)
+                                                    {
+                                                        hv_ButtonReleased.Dispose();
+                                                        hv_ButtonReleased = 1;
+                                                    }
+                                                    else
+                                                    {
+                                                        hv_ButtonReleased.Dispose();
+                                                        hv_ButtonReleased = 0;
+                                                    }
+                                                    //
+                                                    break;
+                                                }
+                                                //Keep waiting until mouse button is released or moved out of the window
+                                            }
+                                        }
+                                        else
+                                        {
+                                            hv_ButtonReleased.Dispose();
+                                            hv_ButtonReleased = 1;
+                                        }
+                                        //Exit the visualization loop
+                                        if ((int)hv_ButtonReleased != 0)
+                                        {
+                                            hv_Exit.Dispose();
+                                            hv_Exit = 1;
+                                            break;
+                                        }
+                                    }
+                                    hv_GraphEvent.Dispose();
+                                    hv_GraphEvent = 1;
+                                    break;
+                                }
+                                else
+                                {
+                                    hv_ButtonHold.Dispose();
+                                    hv_ButtonHold = 0;
+                                }
+                            }
+                            // catch (Exception) 
+                            catch (HalconException HDevExpDefaultException2)
+                            {
+                                HDevExpDefaultException2.ToHTuple(out hv_Exception);
+                                //Keep waiting
+                            }
+                        }
+                        if ((int)hv_GraphEvent != 0)
+                        {
+                            {
+                                HTuple ExpTmpOutVar_0; HTuple ExpTmpOutVar_1; HTuple ExpTmpOutVar_2; HTuple ExpTmpOutVar_3;
+                                analyze_graph_event(ho_Image, hv_MouseMapping, hv_GraphButton, hv_GraphButtonRow,
+                                    hv_GraphButtonColumn, hv_WindowHandle, hv_WindowHandleBuffer, hv_VirtualTrackball,
+                                    hv_TrackballSize, hv_SelectedObject, hv_Scene3D, hv_AlphaOrig, hv_ObjectModel3D,
+                                    hv_CamParam_COPY_INP_TMP, hv_Label_COPY_INP_TMP, hv_Title, hv_Information,
+                                    hv_GenParamName_COPY_INP_TMP, hv_GenParamValue_COPY_INP_TMP, hv_Poses,
+                                    hv_ButtonHold, hv_TBCenter, hv_TBSize, hv_WindowCenteredRotation,
+                                    hv_MaxNumModels, out ExpTmpOutVar_0, out ExpTmpOutVar_1, out ExpTmpOutVar_2,
+                                    out ExpTmpOutVar_3);
+                                hv_Poses.Dispose();
+                                hv_Poses = ExpTmpOutVar_0;
+                                hv_SelectedObject.Dispose();
+                                hv_SelectedObject = ExpTmpOutVar_1;
+                                hv_ButtonHold.Dispose();
+                                hv_ButtonHold = ExpTmpOutVar_2;
+                                hv_WindowCenteredRotation.Dispose();
+                                hv_WindowCenteredRotation = ExpTmpOutVar_3;
+                            }
+                        }
+                        if ((int)hv_Exit != 0)
+                        {
+                            break;
+                        }
+                    }
+                    //
+                    //Display final state with persistence, if requested
+                    //Note that disp_object_model_3d must be used instead of the 3D scene
+                    if ((int)new HTuple(new HTuple(hv_PersistenceParamName.TupleLength()).TupleGreater(
+                        0)) != 0)
+                    {
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            HOperatorSet.DispObjectModel3d(hv_WindowHandle, hv_ObjectModel3D, hv_CamParam_COPY_INP_TMP,
+                                hv_Poses, new HTuple("disp_background").TupleConcat("alpha").TupleConcat(
+                                hv_PersistenceParamName), new HTuple("true").TupleConcat(0.0).TupleConcat(
+                                hv_PersistenceParamValue));
+                        }
+                    }
+                    //
+                    //Compute the output pose
+                    if ((int)ExpGetGlobalVar_gIsSinglePose() != 0)
+                    {
+                        hv_PoseOut.Dispose();
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            hv_PoseOut = hv_Poses.TupleSelectRange(
+                                0, 6);
+                        }
+                    }
+                    else
+                    {
+                        hv_PoseOut.Dispose();
+                        hv_PoseOut = new HTuple(hv_Poses);
+                    }
+                    //
+                    //Clean up.
+                    HOperatorSet.SetSystem("clip_region", hv_ClipRegion);
+                    // dev_set_preferences(...); only in hdevelop
+                    // dev_set_preferences(...); only in hdevelop
+                    dump_image_output(ho_Image, hv_WindowHandleBuffer, hv_Scene3D, hv_AlphaOrig,
+                        hv_ObjectModel3D, hv_GenParamName_COPY_INP_TMP, hv_GenParamValue_COPY_INP_TMP,
+                        hv_CamParam_COPY_INP_TMP, hv_Poses, hv_ColorImage, hv_Title, new HTuple(),
+                        hv_Label_COPY_INP_TMP, 0, "false", hv_TrackballCenterRow, hv_TrackballCenterCol,
+                        hv_TBSize, hv_SelectedObject, hv_WindowCenteredRotation, hv_TBCenter);
+                    ho_ImageDump.Dispose();
+                    HOperatorSet.DumpWindowImage(out ho_ImageDump, hv_WindowHandleBuffer);
+                    HDevWindowStack.SetActive(hv_WindowHandle);
+                    if (HDevWindowStack.IsOpen())
+                    {
+                        HOperatorSet.DispObj(ho_ImageDump, HDevWindowStack.GetActive());
+                    }
+                    HOperatorSet.CloseWindow(hv_WindowHandleBuffer);
+                    HOperatorSet.SetPart(hv_WindowHandle, hv_WPRow1, hv_WPColumn1, hv_WPRow2,
+                        hv_WPColumn2);
+                    HOperatorSet.ClearScene3d(hv_Scene3D);
+                    hv_Scene3D.Dispose();
+                    hv_Scene3D = new HTuple();
+                }
+                // catch (Exception) 
+                catch (HalconException HDevExpDefaultException1)
+                {
+                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
+                    try
+                    {
+                        //Try to clean up as much as possible.
+                        if ((int)new HTuple(new HTuple(0).TupleLess(new HTuple(hv_Scene3DTest.TupleLength()
+                            ))) != 0)
+                        {
+                            HOperatorSet.ClearScene3d(hv_Scene3DTest);
+                            hv_Scene3DTest.Dispose();
+                            hv_Scene3DTest = new HTuple();
+                        }
+                        if ((int)new HTuple(new HTuple(0).TupleLess(new HTuple(hv_Scene3D.TupleLength()
+                            ))) != 0)
+                        {
+                            HOperatorSet.ClearScene3d(hv_Scene3D);
+                            hv_Scene3D.Dispose();
+                            hv_Scene3D = new HTuple();
+                        }
+                        if ((int)new HTuple(new HTuple(0).TupleLess(new HTuple(hv_WindowHandleBuffer.TupleLength()
+                            ))) != 0)
+                        {
+                            HOperatorSet.CloseWindow(hv_WindowHandleBuffer);
+                            hv_WindowHandleBuffer.Dispose();
+                            hv_WindowHandleBuffer = new HTuple();
+                        }
+                    }
+                    // catch (e) 
+                    catch (HalconException HDevExpDefaultException2)
+                    {
+                        HDevExpDefaultException2.ToHTuple(out hv_e);
+                        //Suppress all further exceptions to return the original exception.
+                    }
+                    try
+                    {
+                        //Restore system settings.
+                        HOperatorSet.SetSystem("clip_region", hv_ClipRegion);
+                        // dev_set_preferences(...); only in hdevelop
+                        // dev_set_preferences(...); only in hdevelop
+                    }
+                    // catch (e) 
+                    catch (HalconException HDevExpDefaultException2)
+                    {
+                        HDevExpDefaultException2.ToHTuple(out hv_e);
+                        //Suppress all further exceptions to return the original exception.
+                    }
+                    //
+                    throw new HalconException(hv_Exception);
+                }
+                ho_Image.Dispose();
+                ho_ImageDump.Dispose();
+
+                hv_CamParam_COPY_INP_TMP.Dispose();
+                hv_GenParamName_COPY_INP_TMP.Dispose();
+                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                hv_Label_COPY_INP_TMP.Dispose();
+                hv_PoseIn_COPY_INP_TMP.Dispose();
+                hv_Scene3DTest.Dispose();
+                hv_Scene3D.Dispose();
+                hv_WindowHandleBuffer.Dispose();
+                hv_TrackballSize.Dispose();
+                hv_VirtualTrackball.Dispose();
+                hv_MouseMapping.Dispose();
+                hv_WaitForButtonRelease.Dispose();
+                hv_MaxNumModels.Dispose();
+                hv_WindowCenteredRotation.Dispose();
+                hv_NumModels.Dispose();
+                hv_SelectedObject.Dispose();
+                hv_ClipRegion.Dispose();
+                hv_CPLength.Dispose();
+                hv_RowNotUsed.Dispose();
+                hv_ColumnNotUsed.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_WPRow1.Dispose();
+                hv_WPColumn1.Dispose();
+                hv_WPRow2.Dispose();
+                hv_WPColumn2.Dispose();
+                hv_CamParamValue.Dispose();
+                hv_CamWidth.Dispose();
+                hv_CamHeight.Dispose();
+                hv_Scale.Dispose();
+                hv_Indices.Dispose();
+                hv_DispBackground.Dispose();
+                hv_Mask.Dispose();
+                hv_Center.Dispose();
+                hv_PoseEstimated.Dispose();
+                hv_Poses.Dispose();
+                hv_HomMat3Ds.Dispose();
+                hv_Sequence.Dispose();
+                hv_Font.Dispose();
+                hv_Exception.Dispose();
+                hv_OpenGLInfo.Dispose();
+                hv_DummyObjectModel3D.Dispose();
+                hv_CameraIndexTest.Dispose();
+                hv_PoseTest.Dispose();
+                hv_InstanceIndexTest.Dispose();
+                hv_MinImageSize.Dispose();
+                hv_TrackballRadiusPixel.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_TextWidth.Dispose();
+                hv_TextHeight.Dispose();
+                hv_NumChannels.Dispose();
+                hv_ColorImage.Dispose();
+                hv_CameraIndex.Dispose();
+                hv_AllInstances.Dispose();
+                hv_SetLight.Dispose();
+                hv_LightParam.Dispose();
+                hv_LightPosition.Dispose();
+                hv_LightKind.Dispose();
+                hv_LightIndex.Dispose();
+                hv_PersistenceParamName.Dispose();
+                hv_PersistenceParamValue.Dispose();
+                hv_AlphaOrig.Dispose();
+                hv_I.Dispose();
+                hv_ParamName.Dispose();
+                hv_ParamValue.Dispose();
+                hv_ParamNameTrunk.Dispose();
+                hv_Instance.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_Qx.Dispose();
+                hv_Qy.Dispose();
+                hv_Qz.Dispose();
+                hv_TBCenter.Dispose();
+                hv_TBSize.Dispose();
+                hv_ButtonHold.Dispose();
+                hv_VisualizeTB.Dispose();
+                hv_MaxIndex.Dispose();
+                hv_TrackballCenterRow.Dispose();
+                hv_TrackballCenterCol.Dispose();
+                hv_GraphEvent.Dispose();
+                hv_Exit.Dispose();
+                hv_GraphButtonRow.Dispose();
+                hv_GraphButtonColumn.Dispose();
+                hv_GraphButton.Dispose();
+                hv_ButtonReleased.Dispose();
+                hv_e.Dispose();
+
+                return;
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_Image.Dispose();
+                ho_ImageDump.Dispose();
+
+                hv_CamParam_COPY_INP_TMP.Dispose();
+                hv_GenParamName_COPY_INP_TMP.Dispose();
+                hv_GenParamValue_COPY_INP_TMP.Dispose();
+                hv_Label_COPY_INP_TMP.Dispose();
+                hv_PoseIn_COPY_INP_TMP.Dispose();
+                hv_Scene3DTest.Dispose();
+                hv_Scene3D.Dispose();
+                hv_WindowHandleBuffer.Dispose();
+                hv_TrackballSize.Dispose();
+                hv_VirtualTrackball.Dispose();
+                hv_MouseMapping.Dispose();
+                hv_WaitForButtonRelease.Dispose();
+                hv_MaxNumModels.Dispose();
+                hv_WindowCenteredRotation.Dispose();
+                hv_NumModels.Dispose();
+                hv_SelectedObject.Dispose();
+                hv_ClipRegion.Dispose();
+                hv_CPLength.Dispose();
+                hv_RowNotUsed.Dispose();
+                hv_ColumnNotUsed.Dispose();
+                hv_Width.Dispose();
+                hv_Height.Dispose();
+                hv_WPRow1.Dispose();
+                hv_WPColumn1.Dispose();
+                hv_WPRow2.Dispose();
+                hv_WPColumn2.Dispose();
+                hv_CamParamValue.Dispose();
+                hv_CamWidth.Dispose();
+                hv_CamHeight.Dispose();
+                hv_Scale.Dispose();
+                hv_Indices.Dispose();
+                hv_DispBackground.Dispose();
+                hv_Mask.Dispose();
+                hv_Center.Dispose();
+                hv_PoseEstimated.Dispose();
+                hv_Poses.Dispose();
+                hv_HomMat3Ds.Dispose();
+                hv_Sequence.Dispose();
+                hv_Font.Dispose();
+                hv_Exception.Dispose();
+                hv_OpenGLInfo.Dispose();
+                hv_DummyObjectModel3D.Dispose();
+                hv_CameraIndexTest.Dispose();
+                hv_PoseTest.Dispose();
+                hv_InstanceIndexTest.Dispose();
+                hv_MinImageSize.Dispose();
+                hv_TrackballRadiusPixel.Dispose();
+                hv_Ascent.Dispose();
+                hv_Descent.Dispose();
+                hv_TextWidth.Dispose();
+                hv_TextHeight.Dispose();
+                hv_NumChannels.Dispose();
+                hv_ColorImage.Dispose();
+                hv_CameraIndex.Dispose();
+                hv_AllInstances.Dispose();
+                hv_SetLight.Dispose();
+                hv_LightParam.Dispose();
+                hv_LightPosition.Dispose();
+                hv_LightKind.Dispose();
+                hv_LightIndex.Dispose();
+                hv_PersistenceParamName.Dispose();
+                hv_PersistenceParamValue.Dispose();
+                hv_AlphaOrig.Dispose();
+                hv_I.Dispose();
+                hv_ParamName.Dispose();
+                hv_ParamValue.Dispose();
+                hv_ParamNameTrunk.Dispose();
+                hv_Instance.Dispose();
+                hv_HomMat3D.Dispose();
+                hv_Qx.Dispose();
+                hv_Qy.Dispose();
+                hv_Qz.Dispose();
+                hv_TBCenter.Dispose();
+                hv_TBSize.Dispose();
+                hv_ButtonHold.Dispose();
+                hv_VisualizeTB.Dispose();
+                hv_MaxIndex.Dispose();
+                hv_TrackballCenterRow.Dispose();
+                hv_TrackballCenterCol.Dispose();
+                hv_GraphEvent.Dispose();
+                hv_Exit.Dispose();
+                hv_GraphButtonRow.Dispose();
+                hv_GraphButtonColumn.Dispose();
+                hv_GraphButton.Dispose();
+                hv_ButtonReleased.Dispose();
+                hv_e.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+        }
+
+#if !NO_EXPORT_MAIN
+        // Main procedure 
+        private void action()
+        {
+
+
+            // Stack for temporary objects 
+            HObject[] OTemp = new HObject[20];
+
+            // Local iconic variables 
+
+            HObject ho_Image, ho_X, ho_Y, ho_Z;
+
+            // Local control variables 
+
+            HTuple hv_ImagePath = new HTuple(), hv_ObjectModel3DID = new HTuple();
+            HTuple hv_Pose = new HTuple(), hv_Instructions = new HTuple();
+            HTuple hv_CamParam = new HTuple(), hv_GenParamName = new HTuple();
+            HTuple hv_GenParamValue = new HTuple(), hv_WindowHandle = new HTuple();
+            HTuple hv_GenParamValue1 = new HTuple(), hv_MinValue = new HTuple();
+            HTuple hv_MaxValue = new HTuple(), hv_ObjectModel3DIDReduced = new HTuple();
+            HTuple hv_ObjectModel3DIDConnections = new HTuple(), hv_Volume = new HTuple();
+            HTuple hv_Diameter = new HTuple(), hv_WindowHandle1 = new HTuple();
+            HTuple hv_Indices = new HTuple(), hv_ResultMessage = new HTuple();
+            HTuple hv_Sequence = new HTuple(), hv_MinVolume = new HTuple();
+            HTuple hv_MaxVolume = new HTuple(), hv_MinDiameter = new HTuple();
+            HTuple hv_MaxDiameter = new HTuple(), hv_HomMat3DIdentity = new HTuple();
+            HTuple hv_HomMat3DTranslation = new HTuple(), hv_HomMat3DInvert = new HTuple();
+            HTuple hv_ObjectModel3DTranslated = new HTuple(), hv_Index = new HTuple();
+            HTuple hv_Volume1 = new HTuple(), hv_ObjectModel3DSelected = new HTuple();
+            HTuple hv_Title = new HTuple(), hv_Label = new HTuple();
+            HTuple hv_FormerIndex = new HTuple(), hv_Message = new HTuple();
+            // Initialize local and output iconic variables 
+            HOperatorSet.GenEmptyObj(out ho_Image);
+            HOperatorSet.GenEmptyObj(out ho_X);
+            HOperatorSet.GenEmptyObj(out ho_Y);
+            HOperatorSet.GenEmptyObj(out ho_Z);
+            try
+            {
+                dev_update_off();
+                if (HDevWindowStack.IsOpen())
+                {
+                    HOperatorSet.CloseWindow(HDevWindowStack.Pop());
+                }
+                //1銆佸姞杞絏,Y, z鏁版嵁锛岀缉鏀惧埌绫筹紝骞剁敓鎴愪竴涓�3D瀵硅薄妯″瀷
+                hv_ImagePath.Dispose();
+                hv_ImagePath = "time_of_flight/";
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    ho_Image.Dispose();
+                    HOperatorSet.ReadImage(out ho_Image, hv_ImagePath + "engine_cover_xyz_01");
+                }
+                //缂╂斁鍥惧儚鐨勭伆搴﹀��
+                //灏嗗浘鍍忔斁澶т竴涓粰瀹氱殑鍊嶆暟
+                {
+                    HObject ExpTmpOutVar_0;
+                    HOperatorSet.ScaleImage(ho_Image, out ExpTmpOutVar_0, .001, .0);
+                    ho_Image.Dispose();
+                    ho_Image = ExpTmpOutVar_0;
+                }
+                {
+                    HObject ExpTmpOutVar_0;
+                    HOperatorSet.ZoomImageFactor(ho_Image, out ExpTmpOutVar_0, 2, 2, "constant");
+                    ho_Image.Dispose();
+                    ho_Image = ExpTmpOutVar_0;
+                }
+                ho_X.Dispose(); ho_Y.Dispose(); ho_Z.Dispose();
+                HOperatorSet.Decompose3(ho_Image, out ho_X, out ho_Y, out ho_Z);
+                hv_ObjectModel3DID.Dispose();
+                HOperatorSet.XyzToObjectModel3d(ho_X, ho_Y, ho_Z, out hv_ObjectModel3DID);
+                //2銆佽绠楁ā鍨嬬殑缃戞牸锛圖elaunay涓夎娴嬮噺锛�
+                //CamParam1 := ['area_scan_division',0.06,0,8.5e-06,8.5e-06,295,180,591,361]
+                //Pose1 := [-0.165397,-0.120794,12.7612,349.085,14.5769,176.361,0]
+                //GenParamName1 := ['colored','color_0']
+                //GenParamValue2 := [12,'light gray']
+                if (HDevWindowStack.IsOpen())
+                {
+                    //dev_get_window (WindowHandle2)
+                }
+                //* disp_object_model_3d (WindowHandle2, ObjectModel3DID, CamParam1, Pose1, GenParamName1, GenParamValue2)
+                //涓�'segmentation'锛屽噯澶囦竴涓�3D瀵硅薄妯″瀷锛堝鏋滆瀵瑰悓涓�鎿嶄綔澶氭浣跨敤3D瀵硅薄妯″瀷锛岃繖鏍峰仛浼氭洿蹇級
+                HOperatorSet.PrepareObjectModel3d(hv_ObjectModel3DID, "segmentation", "true",
+                    new HTuple(), new HTuple());
+                //
+                //3銆佸噯澶囧彲瑙嗗寲骞舵樉绀�3D瀵硅薄妯″瀷
+                hv_Pose.Dispose();
+                HOperatorSet.CreatePose(0.058, -0.165, 0.660, 345.0, 355.0, 356.0, "Rp+T",
+                    "gba", "point", out hv_Pose);
+                //
+                //Instructions for visualize_object_model_3d
+                if (hv_Instructions == null)
+                    hv_Instructions = new HTuple();
+                hv_Instructions[0] = "Rotate: Left button";
+                if (hv_Instructions == null)
+                    hv_Instructions = new HTuple();
+                hv_Instructions[1] = "Zoom:   Shift + left button";
+                if (hv_Instructions == null)
+                    hv_Instructions = new HTuple();
+                hv_Instructions[2] = "Move:   Ctrl  + left button";
+                //Configuration
+                //鐢熸垚闈㈤樀鐩告満鍒濆鍙傛暟锛屽弬鏁板潎涓虹浉鏈哄凡鐭ュ弬鏁�
+                //锛�: : 鐒﹁窛, 鐣稿彉鍥犲瓙, Sx, Sy, Cx, Cy, 鍥惧儚瀹藉害, 鍥惧儚楂樺害 : CameraParam瀛樺偍鍏冪粍锛�
+                //锛圫x, Sy涓轰紶鎰熷櫒鑺墖涓婁袱涓浉閭诲崟鍏冧箣闂寸殑姘村钩绔栫洿璺濈锛屼篃灏辨槸鍍忕礌鐨勫ぇ灏忥紝鍗曚綅涓簃/鍍忕礌锛汣x, Cy涓哄浘鍍忓師鐐圭殑琛屽垪鍧愭爣锛屽崟浣嶄负鍍忕礌锛涳級
+                hv_CamParam.Dispose();
+                gen_cam_par_area_scan_division(0.01, 0, 7e-6, 7e-6, 352, 288, 710, 576, out hv_CamParam);
+                hv_GenParamName.Dispose();
+                hv_GenParamName = new HTuple();
+                hv_GenParamName[0] = "color";
+                hv_GenParamName[1] = "disp_pose";
+                hv_GenParamName[2] = "alpha";
+                hv_GenParamValue.Dispose();
+                hv_GenParamValue = new HTuple();
+                hv_GenParamValue[0] = "green";
+                hv_GenParamValue[1] = "false";
+                hv_GenParamValue[2] = 0.8;
+                //
+                HOperatorSet.SetWindowAttr("background_color", "black");
+                HOperatorSet.OpenWindow(0, 0, 710, 576, 0, "visible", "", out hv_WindowHandle);
+                HDevWindowStack.Push(hv_WindowHandle);
+                set_display_font(hv_WindowHandle, 16, "mono", "true", "false");
+                //鏄剧ず鍒涘缓鐨�3D妯″瀷
+                {
+                    HTuple ExpTmpOutVar_0;
+                    visualize_object_model_3d(hv_WindowHandle, hv_ObjectModel3DID, hv_CamParam,
+                        hv_Pose, hv_GenParamName, hv_GenParamValue, "This scene will be segmented into single objects",
+                        new HTuple(), hv_Instructions, out ExpTmpOutVar_0);
+                    hv_Pose.Dispose();
+                    hv_Pose = ExpTmpOutVar_0;
+                }
+                hv_GenParamValue1.Dispose();
+                HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DID, "point_coord_z", out hv_GenParamValue1);
+                //
+                //4銆侀槇鍊间笁缁村璞℃ā鍨�
+                hv_MinValue.Dispose();
+                hv_MinValue = 0.500;
+                hv_MaxValue.Dispose();
+                hv_MaxValue = 0.670;
+                //瀵�3D瀵硅薄妯″瀷搴旂敤闃堝��
+                hv_ObjectModel3DIDReduced.Dispose();
+                HOperatorSet.SelectPointsObjectModel3d(hv_ObjectModel3DID, "point_coord_z",
+                    hv_MinValue, hv_MaxValue, out hv_ObjectModel3DIDReduced);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    HTuple ExpTmpOutVar_0;
+                    visualize_object_model_3d(hv_WindowHandle, hv_ObjectModel3DIDReduced, hv_CamParam,
+                        hv_Pose, hv_GenParamName, hv_GenParamValue, "Result after thresholding at z=" + (hv_MaxValue * 1e3).TupleString(
+                        ".3") + "mm from the camera", new HTuple(), hv_Instructions, out ExpTmpOutVar_0);
+                    hv_Pose.Dispose();
+                    hv_Pose = ExpTmpOutVar_0;
+                }
+                //
+                //Calculate the connected components and the volume and diameter
+                //of each of the resulting object
+                //5銆佽绠楄繛鎺ュ垎閲忓拰姣忎釜缁撴灉瀵硅薄鐨勪綋绉拰鐩村緞
+                if (hv_GenParamName == null)
+                    hv_GenParamName = new HTuple();
+                hv_GenParamName[0] = "colored";
+                if (hv_GenParamValue == null)
+                    hv_GenParamValue = new HTuple();
+                hv_GenParamValue[0] = 12;
+                //1锛夌‘瀹�3D瀵硅薄妯″瀷鐨勮繛閫氬垎閲� 閫氳繃璋冭妭distance_3d鍙傛暟锛屾妸涓�浜涘櫔鐐瑰垎绂诲嚭鏉�
+                //2锛夎绠椾笁缁寸墿浣撴ā鍨嬬浉瀵逛簬骞抽潰[0,0,MaxValue,0,0,0,0]鐨勪綋绉� Volume
+                //3锛夎绠�3D瀵硅薄妯″瀷鐨勬渶澶х洿寰� Diameter
+                hv_ObjectModel3DIDConnections.Dispose();
+                HOperatorSet.ConnectionObjectModel3d(hv_ObjectModel3DIDReduced, "distance_3d",
+                    0.01, out hv_ObjectModel3DIDConnections);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Volume.Dispose();
+                    HOperatorSet.VolumeObjectModel3dRelativeToPlane(hv_ObjectModel3DIDConnections,
+                        new HTuple(0).TupleConcat(0).TupleConcat(hv_MaxValue).TupleConcat(
+                        new HTuple(0).TupleConcat(0).TupleConcat(0).TupleConcat(0)), "signed",
+                        "true", out hv_Volume);
+                }
+                hv_Diameter.Dispose();
+                HOperatorSet.MaxDiameterObjectModel3d(hv_ObjectModel3DIDConnections, out hv_Diameter);
+                //
+                //6銆佹樉绀虹粨鏋�
+                HOperatorSet.SetWindowAttr("background_color", "black");
+                HOperatorSet.OpenWindow(0, 720, 400, 576, 0, "visible", "", out hv_WindowHandle1);
+                HDevWindowStack.Push(hv_WindowHandle1);
+                set_display_font(hv_WindowHandle1, 14, "mono", "true", "false");
+                hv_Indices.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Indices = HTuple.TupleGenSequence(
+                        0, new HTuple(hv_ObjectModel3DIDConnections.TupleLength()) - 1, 1);
+                }
+                disp_message(hv_WindowHandle1, new HTuple("Features of the connected components:").TupleConcat(
+                    " ").TupleConcat(" "), "window", 12, 12, "white", "false");
+                hv_ResultMessage.Dispose();
+                hv_ResultMessage = "  #  Max. diameter    Volume";
+                hv_Sequence.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Sequence = HTuple.TupleGenSequence(
+                        0, new HTuple(hv_ObjectModel3DIDConnections.TupleLength()) - 1, 1);
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    {
+                        HTuple
+                          ExpTmpLocalVar_ResultMessage = hv_ResultMessage.TupleConcat(
+                            hv_Sequence.TupleString(" 3") + "     " + (hv_Diameter * 1e3).TupleString(
+                            "7.1f") + " mm  " + (hv_Volume * 1e3).TupleString("7.3f") + " dm鲁");
+                        hv_ResultMessage.Dispose();
+                        hv_ResultMessage = ExpTmpLocalVar_ResultMessage;
+                    }
+                }
+                disp_message(hv_WindowHandle1, hv_ResultMessage, "window", 50, 12, "white",
+                    "false");
+                HDevWindowStack.SetActive(hv_WindowHandle);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    HTuple ExpTmpOutVar_0;
+                    visualize_object_model_3d(hv_WindowHandle, hv_ObjectModel3DIDConnections, hv_CamParam,
+                        hv_Pose, hv_GenParamName, hv_GenParamValue, new HTuple(new HTuple("Found ") + new HTuple(hv_ObjectModel3DIDConnections.TupleLength()
+                        )) + " connected components", "#" + hv_Indices, hv_Instructions, out ExpTmpOutVar_0);
+                    hv_Pose.Dispose();
+                    hv_Pose = ExpTmpOutVar_0;
+                }
+                //
+                //7銆佹牴鎹粍浠剁殑浣撶Н鍜屾渶澶х洿寰勯�夋嫨缁勪欢
+                //
+                hv_MinVolume.Dispose();
+                hv_MinVolume = 0.35e-003;
+                hv_MaxVolume.Dispose();
+                hv_MaxVolume = 1.0e-003;
+                hv_MinDiameter.Dispose();
+                hv_MinDiameter = 185.0e-003;
+                hv_MaxDiameter.Dispose();
+                hv_MaxDiameter = 300.0e-003;
+
+                //**** 8銆佹敞鎰忥細
+                //    select_object_model_3d浣跨敤骞抽潰[0,0,0,0,0,0]杩涜浣撶Н璁$畻!
+                //    鍥犳锛屾垜浠繀椤昏浆鎹�3d瀵硅薄妯″瀷锛屼互渚垮弬鑰冨钩闈�(濡傚墠闈㈠volume_object_model_3d_relative_to_plane鐨勮皟鐢ㄤ腑瀹氫箟鐨勯偅鏍�)涓庨粯璁ゅ钩闈㈤噸鍚堛��
+                //
+                //1锛夌敓鎴愪笁缁村彉鎹㈢殑榻愭鍙樻崲鐭╅樀
+                //2锛夊鍔犲钩绉诲彉鎹�
+                //3锛夋眰榻愭涓夌淮鍙樻崲鐭╅樀鐨勯��
+                hv_HomMat3DIdentity.Dispose();
+                HOperatorSet.HomMat3dIdentity(out hv_HomMat3DIdentity);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_HomMat3DTranslation.Dispose();
+                    HOperatorSet.HomMat3dTranslate(hv_HomMat3DIdentity, 0, 0, -hv_MaxValue, out hv_HomMat3DTranslation);
+                }
+                hv_HomMat3DInvert.Dispose();
+                HOperatorSet.HomMat3dInvert(hv_HomMat3DTranslation, out hv_HomMat3DInvert);
+                hv_ObjectModel3DTranslated.Dispose();
+                HOperatorSet.AffineTransObjectModel3d(hv_ObjectModel3DIDConnections, hv_HomMat3DTranslation,
+                    out hv_ObjectModel3DTranslated);
+                //4锛変负姣忎釜閮ㄥ垎璁剧疆鏍囩
+                for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_ObjectModel3DIDConnections.TupleLength()
+                    ) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        HOperatorSet.SetObjectModel3dAttribMod(hv_ObjectModel3DTranslated.TupleSelect(
+                            hv_Index), "&Index", new HTuple(), hv_Index);
+                    }
+                }
+                //5锛夊啀娆¤绠椾笁缁寸墿浣撴ā鍨嬬浉瀵逛簬骞抽潰[0,0,0,0,0,0,0]鐨勪綋绉� Volume1
+                //6锛変粠涓�缁勪笁缁村璞℃ā鍨嬩腑閫夋嫨涓夌淮瀵硅薄妯″瀷锛�'volume'锛�'diameter_object'锛�
+                hv_Volume1.Dispose();
+                HOperatorSet.VolumeObjectModel3dRelativeToPlane(hv_ObjectModel3DTranslated,
+                    new HTuple(0).TupleConcat(0).TupleConcat(0).TupleConcat(0).TupleConcat(
+                    0).TupleConcat(0).TupleConcat(0), "signed", "true", out hv_Volume1);
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_ObjectModel3DSelected.Dispose();
+                    HOperatorSet.SelectObjectModel3d(hv_ObjectModel3DTranslated, new HTuple("volume").TupleConcat(
+                        "diameter_object"), "and", hv_MinVolume.TupleConcat(hv_MinDiameter), hv_MaxVolume.TupleConcat(
+                        hv_MaxDiameter), out hv_ObjectModel3DSelected);
+                }
+                //
+                hv_Title.Dispose();
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    hv_Title = new HTuple();
+                    hv_Title[0] = "Parts selected by using the following features: ";
+                    hv_Title = hv_Title.TupleConcat("       " + (hv_MinVolume * 1e3).TupleString(
+                        "3.1f") + " dm鲁 <= volume <= " + (hv_MaxVolume * 1e3).TupleString("3.1f") + " dm鲁");
+                    hv_Title = hv_Title.TupleConcat("and:   " + (hv_MinDiameter * 1e3).TupleString(
+                        ".1f") + " mm <= max. diameter <= " + (hv_MaxDiameter * 1e3).TupleString(
+                        ".1f") + " mm");
+                }
+                //鍒涘缓涓�涓爣绛�
+                hv_Label.Dispose();
+                hv_Label = new HTuple();
+                for (hv_Index = 0; (int)hv_Index <= (int)(new HTuple(hv_ObjectModel3DSelected.TupleLength()
+                    ) - 1); hv_Index = (int)hv_Index + 1)
+                {
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        hv_FormerIndex.Dispose();
+                        HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3DSelected.TupleSelect(
+                            hv_Index), "&Index", out hv_FormerIndex);
+                    }
+                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                    {
+                        {
+                            HTuple
+                              ExpTmpLocalVar_Label = hv_Label.TupleConcat(
+                                "#" + hv_FormerIndex);
+                            hv_Label.Dispose();
+                            hv_Label = ExpTmpLocalVar_Label;
+                        }
+                    }
+                }
+                //
+                if ((int)new HTuple(new HTuple(hv_ObjectModel3DSelected.TupleLength()).TupleGreater(
+                    1)) != 0)
+                {
+                    hv_Pose.Dispose();
+                    visualize_object_model_3d(hv_WindowHandle, hv_ObjectModel3DSelected, hv_CamParam,
+                        new HTuple(), hv_GenParamName, hv_GenParamValue, hv_Title, hv_Label,
+                        hv_Instructions, out hv_Pose);
+                }
+                else
+                {
+                    hv_Message.Dispose();
+                    hv_Message = "No object left after using the following features: ";
+                    if (hv_Message == null)
+                        hv_Message = new HTuple();
+                    hv_Message[1] = "       " + (hv_MinVolume * 1e3).TupleString("3.1f") + " dm鲁 <= volume <= " + (hv_MaxVolume * 1e3).TupleString(
+                        "3.1f") + " dm鲁";
+                    if (hv_Message == null)
+                        hv_Message = new HTuple();
+                    hv_Message[2] = "and:   " + (hv_MinDiameter * 1e3).TupleString(".1f") + " mm <= max. diameter <= " + (hv_MaxDiameter * 1e3).TupleString(
+                        ".1f") + " mm";
+                    disp_message(hv_WindowHandle, hv_Message, "window", 12, 12, "black", "true");
+                }
+                //
+                //Clear the 3d object models
+                HDevWindowStack.SetActive(hv_WindowHandle1);
+                if (HDevWindowStack.IsOpen())
+                {
+                    HOperatorSet.CloseWindow(HDevWindowStack.Pop());
+                }
+                using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                {
+                    HOperatorSet.ClearObjectModel3d(hv_ObjectModel3DID.TupleConcat(hv_ObjectModel3DIDReduced).TupleConcat(
+                        hv_ObjectModel3DSelected).TupleConcat(hv_ObjectModel3DTranslated).TupleConcat(
+                        hv_ObjectModel3DIDConnections));
+                }
+            }
+            catch (HalconException HDevExpDefaultException)
+            {
+                ho_Image.Dispose();
+                ho_X.Dispose();
+                ho_Y.Dispose();
+                ho_Z.Dispose();
+
+                hv_ImagePath.Dispose();
+                hv_ObjectModel3DID.Dispose();
+                hv_Pose.Dispose();
+                hv_Instructions.Dispose();
+                hv_CamParam.Dispose();
+                hv_GenParamName.Dispose();
+                hv_GenParamValue.Dispose();
+                hv_WindowHandle.Dispose();
+                hv_GenParamValue1.Dispose();
+                hv_MinValue.Dispose();
+                hv_MaxValue.Dispose();
+                hv_ObjectModel3DIDReduced.Dispose();
+                hv_ObjectModel3DIDConnections.Dispose();
+                hv_Volume.Dispose();
+                hv_Diameter.Dispose();
+                hv_WindowHandle1.Dispose();
+                hv_Indices.Dispose();
+                hv_ResultMessage.Dispose();
+                hv_Sequence.Dispose();
+                hv_MinVolume.Dispose();
+                hv_MaxVolume.Dispose();
+                hv_MinDiameter.Dispose();
+                hv_MaxDiameter.Dispose();
+                hv_HomMat3DIdentity.Dispose();
+                hv_HomMat3DTranslation.Dispose();
+                hv_HomMat3DInvert.Dispose();
+                hv_ObjectModel3DTranslated.Dispose();
+                hv_Index.Dispose();
+                hv_Volume1.Dispose();
+                hv_ObjectModel3DSelected.Dispose();
+                hv_Title.Dispose();
+                hv_Label.Dispose();
+                hv_FormerIndex.Dispose();
+                hv_Message.Dispose();
+
+                throw HDevExpDefaultException;
+            }
+            ho_Image.Dispose();
+            ho_X.Dispose();
+            ho_Y.Dispose();
+            ho_Z.Dispose();
+
+            hv_ImagePath.Dispose();
+            hv_ObjectModel3DID.Dispose();
+            hv_Pose.Dispose();
+            hv_Instructions.Dispose();
+            hv_CamParam.Dispose();
+            hv_GenParamName.Dispose();
+            hv_GenParamValue.Dispose();
+            hv_WindowHandle.Dispose();
+            hv_GenParamValue1.Dispose();
+            hv_MinValue.Dispose();
+            hv_MaxValue.Dispose();
+            hv_ObjectModel3DIDReduced.Dispose();
+            hv_ObjectModel3DIDConnections.Dispose();
+            hv_Volume.Dispose();
+            hv_Diameter.Dispose();
+            hv_WindowHandle1.Dispose();
+            hv_Indices.Dispose();
+            hv_ResultMessage.Dispose();
+            hv_Sequence.Dispose();
+            hv_MinVolume.Dispose();
+            hv_MaxVolume.Dispose();
+            hv_MinDiameter.Dispose();
+            hv_MaxDiameter.Dispose();
+            hv_HomMat3DIdentity.Dispose();
+            hv_HomMat3DTranslation.Dispose();
+            hv_HomMat3DInvert.Dispose();
+            hv_ObjectModel3DTranslated.Dispose();
+            hv_Index.Dispose();
+            hv_Volume1.Dispose();
+            hv_ObjectModel3DSelected.Dispose();
+            hv_Title.Dispose();
+            hv_Label.Dispose();
+            hv_FormerIndex.Dispose();
+            hv_Message.Dispose();
+
+        }
+
+        internal void visualize_object_model_3d(object hv_WindowHandle, object hv_ObjectModel3DID, HTuple hv_CamParam, HTuple hv_Pose, HTuple hv_GenParamName, HTuple hv_GenParamValue, string v, HTuple hTuple1, HTuple hTuple2, out object postOut)
+        {
+            throw new NotImplementedException();
+        }
+
+#endif
+
+
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobTool.cs b/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobTool.cs
new file mode 100644
index 0000000..82bed25
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobTool.cs
@@ -0,0 +1,408 @@
+锘縰sing HalconDotNet;
+using OpenCvSharp;
+using Point = OpenCvSharp.Point;
+
+namespace LB_VisionProcesses.Alogrithms.OpenCvSharp
+{
+    [Process("OpenCvSharp_鏂戠偣宸ュ叿", Category = "OpenCvSharp宸ュ叿", Description = "鍒涘缓OpenCvSharp_鏂戠偣宸ュ叿")]
+    public class BlobTool : TAlgorithm
+    {
+        public BlobTool()
+        {
+            strProcessClass = "LB_VisionProcesses.Alogrithms.OpenCvSharp.BlobTool";
+            strProcessName = "OpenCvSharp_鏂戠偣宸ュ叿";
+
+            Params.Inputs.Add("MinThreshold", 127);
+            Params.Inputs.Add("MaxThreshold", 255);
+            Params.Inputs.Add("MinArea", 0);
+            Params.Inputs.Add("MaxArea", double.MaxValue);
+            Params.Inputs.Add("MinRow", 0.0);
+            Params.Inputs.Add("MaxRow", double.MaxValue);
+            Params.Inputs.Add("MinColumn", 0.0);
+            Params.Inputs.Add("MaxColumn", double.MaxValue);
+            Params.Inputs.Add("MinCircularity", 0.0);
+            Params.Inputs.Add("MaxCircularity", 1.0); ;
+            Params.Inputs.Add("MinRectangularity", 0.0);
+            Params.Inputs.Add("MaxRectangularity", 1.0);
+            Params.Inputs.Add("MinCount", 0);
+            Params.Inputs.Add("MaxCount", 9999);
+
+            Params.Outputs.Add("CenterX", new List<double>());
+            Params.Outputs.Add("CenterY", new List<double>());
+            Params.Outputs.Add("Angle", new List<double>());
+            Params.Outputs.Add("Width", new List<double>());
+            Params.Outputs.Add("Height", new List<double>());
+            Params.Outputs.Add("Area", new List<double>());
+            Params.Outputs.Add("Count", 0);
+        }
+
+        /// <summary>
+        /// 绠楀瓙閫昏緫
+        /// </summary>
+        public override void TAlgorithmMain()
+        {
+            #region 鍒濆鍖栧彉閲�
+            HObject ho_Regions, ho_ConnectedRegions, ho_SelectedRegions;
+            HOperatorSet.GenEmptyObj(out ho_Regions);
+            HOperatorSet.GenEmptyObj(out ho_ConnectedRegions);
+            #endregion
+
+            try
+            {
+                if (InputImage == null)
+                {
+                    Msg = "杈撳叆鍥剧墖涓虹┖";
+                    Result = false;
+                    return;
+                }
+                if (!(InputImage is Mat))
+                {
+                    Msg = "杈撳叆鍥剧墖鏍煎紡涓嶄负Mat";
+                    Result = false;
+                    return;
+                }
+
+                #region 瑁佸壀鍖哄煙
+                object DomainImage = null;
+                if (!ReduceDomainImage(InputImage, ref DomainImage))
+                {
+                    Msg = "瑁佸壀鍖哄煙澶辫触";
+                    Result = false;
+                    return;
+                }
+                Mat hoDomainImage = DomainImage as Mat;
+                //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                try
+                {
+                    if (hoDomainImage.Channels() != 1)
+                        Cv2.CvtColor(hoDomainImage, hoDomainImage, ColorConversionCodes.RGB2GRAY);
+
+                    //杞崲鍚庡啀娆℃鏌ユ槸鍚︿负鐏板害鍥�
+                    if (hoDomainImage.Channels() != 1)
+                    {
+                        Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥�";
+                        Result = false;
+                        return;
+                    }
+                }
+                catch
+                {
+                    Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥句笖杞崲澶辫触";
+                    Result = false;
+                    return;
+                }
+                #endregion
+
+                #region 绠楀瓙閫昏緫
+                Record = new ObjectRecord();
+                double MinThreshold = Convert.ToDouble(Params.Inputs["MinThreshold"]);
+                double MaxThreshold = Convert.ToDouble(Params.Inputs["MaxThreshold"]);
+                double MinArea = Convert.ToDouble(Params.Inputs["MinArea"]);
+                double MaxArea = Convert.ToDouble(Params.Inputs["MaxArea"]);
+                double MinRow = Convert.ToDouble(Params.Inputs["MinRow"]);
+                double MaxRow = Convert.ToDouble(Params.Inputs["MaxRow"]);
+                double MinColumn = Convert.ToDouble(Params.Inputs["MinColumn"]);
+                double MaxColumn = Convert.ToDouble(Params.Inputs["MaxColumn"]);
+                double MinCircularity = Convert.ToDouble(Params.Inputs["MinCircularity"]);
+                double MaxCircularity = Convert.ToDouble(Params.Inputs["MaxCircularity"]);
+                double MinRectangularity = Convert.ToDouble(Params.Inputs["MinRectangularity"]);
+                double MaxRectangularity = Convert.ToDouble(Params.Inputs["MaxRectangularity"]);
+                List<Blob> results = AnalyzeBlobs(hoDomainImage, MinArea, MaxArea, MinCircularity, MinRectangularity, MinThreshold, MaxThreshold);
+                #endregion
+
+                #region 缁撴灉澶勭悊
+                //璁℃暟鐢ㄤ簬鍚庣画鍒ゆ柇
+                List<double> CenterX = new List<double>();
+                List<double> CenterY = new List<double>();
+                List<double> Angle = new List<double>();
+                List<double> Width = new List<double>();
+                List<double> Height = new List<double>();
+                List<double> Area = new List<double>();
+                for (int i = 0; i < results.Count; i++)
+                {
+                    // 濉厖涓虹煩褰�
+                    CenterX.Add(Convert.ToDouble(results[i].RotatedBoundingBox.Center.X));
+                    CenterY.Add(Convert.ToDouble(results[i].RotatedBoundingBox.Center.Y));
+                    Angle.Add(Convert.ToDouble(results[i].RotatedBoundingBox.Angle));
+                    Width.Add(Convert.ToDouble(results[i].RotatedBoundingBox.Size.Width));
+                    Height.Add(Convert.ToDouble(results[i].RotatedBoundingBox.Size.Height));
+                    Area.Add(results[i].ContourArea);
+
+                    //HOperatorSet.GenRectangle2(out HObject hRectangle, CenterY[i], CenterX[i], -1 * Angle[i] / 180 * Math.PI
+                    //    , Width[i] / 2, Height[i] / 2);
+                    //((ObjectRecord)Record).AddRecord(hRectangle);
+
+                    var contourArray = results[i].Contour.ToArray();
+                    int count = contourArray.Length;
+
+                    int[] Xpoints = new int[count + 1];
+                    int[] Ypoints = new int[count + 1];
+
+                    Parallel.For(0, count, j =>
+                    {
+                        var point = contourArray[j];
+                        Xpoints[j] = point.X;
+                        Ypoints[j] = point.Y;
+                    });
+
+                    Xpoints[count] = Xpoints[0];
+                    Ypoints[count] = Ypoints[0];
+
+                    HOperatorSet.GenContourPolygonXld(out HObject contour, new HTuple(Ypoints), new HTuple(Xpoints));
+                    ((ObjectRecord)Record).AddXld(contour);
+                }
+
+
+
+
+
+                Params.Outputs["CenterX"] = CenterX;
+                Params.Outputs["CenterY"] = CenterY;
+                Params.Outputs["Angle"] = Angle;
+                Params.Outputs["Width"] = Width;
+                Params.Outputs["Height"] = Height;
+                Params.Outputs["Area"] = Area;
+                Params.Outputs["Count"] = CenterX.Count;
+                #endregion
+
+                #region 鐢熸垚OutputImage缁欏悗缁鐞�
+                try
+                {
+                    OutputImage = DomainImage;
+                }
+                catch (Exception ex)
+                {
+                    Msg = "鐢熸垚OutputImage澶辫触,鍘熷洜鏄�:" + ex.ToString();
+                    Result = false;
+                    return;
+                }
+                #endregion
+
+                if (Msg == "杩愯瓒呮椂")
+                {
+                    Result = false;
+                    return;
+                }
+
+                int MinCount = ProcessParams.ConvertToInt32(Params.Inputs["MinCount"]);
+                int MaxCount = ProcessParams.ConvertToInt32(Params.Inputs["MaxCount"]);
+
+                if (CenterX.Count < MinCount || CenterX.Count > MaxCount)
+                {
+                    Msg = string.Format("缁撴灉涓暟瓒呭嚭鑼冨洿({0},{1})", MinCount, MaxCount);
+                    Record.ChangeAll2False();
+                    Result = false;
+                    return;
+                }
+
+                Msg = "杩愯鎴愬姛";
+                Result = true;
+                return;
+            }
+            catch (Exception ex)
+            {
+                Msg = "杩愯澶辫触,鍘熷洜鏄�:" + ex.ToString().TrimEnd();
+                OutputImage = null;
+                Result = false;
+                return;
+            }
+            finally
+            {
+                bCompleted = true;
+
+                #region 鍐呭瓨閲婃斁
+                ho_Regions.Dispose();
+                ho_ConnectedRegions.Dispose();
+                #endregion
+            }
+        }
+
+        public class BlobRotatedRect
+        {
+            public Point2f Center { get; set; }
+            public Size2f Size { get; set; }
+            public float Angle { get; set; }
+            public Point2f[] Points { get; set; }
+
+            public BlobRotatedRect() { }
+
+            public BlobRotatedRect(RotatedRect rect)
+            {
+                Center = rect.Center;
+                Size = rect.Size;
+                Angle = rect.Angle;
+                Points = Cv2.BoxPoints(rect);
+            }
+        }
+
+        public class Blob
+        {
+            public int Id { get; set; }
+            //public Rect BoundingBox { get; set; }
+            public BlobRotatedRect RotatedBoundingBox { get; set; }
+            //public Point2f Centroid { get; set; }
+            //public double Area { get; set; }
+            public double Perimeter { get; set; }
+            public double Circularity { get; set; }
+            public double Rectangularity { get; set; }
+            public double AspectRatio { get; set; }
+            public List<Point> Contour { get; set; }
+            public double ContourArea { get; set; }
+            //public double RotatedRectArea { get; set; }
+        }
+
+        public static List<Blob> AnalyzeBlobs(Mat image,
+            double minArea = 50,
+            double maxArea = 10000,
+            double minCircularity = 0.1,
+            double minRectangularity = 0.5,
+            double minThreshold = 0,
+            double maxThreshold = 255,
+            ThresholdTypes thresholdType = ThresholdTypes.Binary)
+        {
+            var blobs = new List<Blob>();
+
+            // 杞崲涓虹伆搴﹀浘
+            Mat gray = new Mat();
+            if (image.Channels() == 3)
+                Cv2.CvtColor(image, gray, ColorConversionCodes.BGR2GRAY);
+            else
+                image.CopyTo(gray);
+
+            // 闃堝�煎垎鍓�
+            Mat binary = new Mat();
+            Cv2.Threshold(gray, binary, minThreshold, maxThreshold, thresholdType);
+
+            // 鏌ユ壘杞粨
+            Point[][] contours;
+            HierarchyIndex[] hierarchy;
+            Cv2.FindContours(binary, out contours, out hierarchy,
+                RetrievalModes.External, ContourApproximationModes.ApproxSimple);
+
+            // 澶勭悊姣忎釜杞粨
+            for (int i = 0; i < contours.Length; i++)
+            {
+                var contour = contours[i];
+                if (contour.Length < 5) continue; // 鑷冲皯闇�瑕�5涓偣鎵嶈兘鎷熷悎鏃嬭浆鐭╁舰
+
+                double area = Cv2.ContourArea(contour);
+
+                // 闈㈢Н杩囨护
+                if (area < minArea || area > maxArea)
+                    continue;
+
+                // 璁$畻鍛ㄩ暱
+                double perimeter = Cv2.ArcLength(contour, true);
+
+                // 璁$畻鍦嗗舰搴�
+                double circularity = (4 * Math.PI * area) / (perimeter * perimeter);
+
+                // 鍦嗗舰搴﹁繃婊�
+                if (circularity < minCircularity)
+                    continue;
+
+                // 璁$畻澶栨帴鐭╁舰
+                Rect boundingBox = Cv2.BoundingRect(contour);
+
+                // 璁$畻鏈�灏忓鎺ョ煩褰紙甯﹁搴︼級
+                RotatedRect rotatedRect = Cv2.MinAreaRect(contour);
+                BlobRotatedRect rotatedBoundingBox = new BlobRotatedRect(rotatedRect);
+
+                // 璁$畻璐ㄥ績
+                Moments moments = Cv2.Moments(contour);
+                Point2f centroid = new Point2f(
+                    (float)(moments.M10 / moments.M00),
+                    (float)(moments.M01 / moments.M00)
+                );
+
+                // 璁$畻鐭╁舰搴�
+                double rectangularity = CalculateRectangularity(contour, rotatedRect);
+
+                // 鐭╁舰搴﹁繃婊�
+                if (rectangularity < minRectangularity)
+                    continue;
+
+                // 璁$畻瀹介珮姣�
+                double aspectRatio = CalculateAspectRatio(rotatedRect);
+
+                blobs.Add(new Blob
+                {
+                    Id = i,
+                    //Area = area,
+                    Perimeter = perimeter,
+                    Circularity = circularity,
+                    Rectangularity = rectangularity,
+                    AspectRatio = aspectRatio,
+                    //BoundingBox = boundingBox,
+                    RotatedBoundingBox = rotatedBoundingBox,
+                    //Centroid = centroid,
+                    Contour = new List<Point>(contour),
+                    ContourArea = area
+                    //RotatedRectArea = rotatedRect.Size.Width * rotatedRect.Size.Height
+                });
+            }
+
+            gray.Dispose();
+            binary.Dispose();
+
+            return blobs;
+        }
+
+        /// <summary>
+        /// 璁$畻鐭╁舰搴︼紙杞粨闈㈢Н涓庢渶灏忓鎺ョ煩褰㈤潰绉殑姣斿�硷級
+        /// </summary>
+        private static double CalculateRectangularity(Point[] contour, RotatedRect rotatedRect)
+        {
+            double contourArea = Cv2.ContourArea(contour);
+            double rotatedRectArea = rotatedRect.Size.Width * rotatedRect.Size.Height;
+
+            if (rotatedRectArea == 0) return 0;
+
+            return contourArea / rotatedRectArea;
+        }
+
+        /// <summary>
+        /// 璁$畻瀹介珮姣�
+        /// </summary>
+        private static double CalculateAspectRatio(RotatedRect rotatedRect)
+        {
+            double width = rotatedRect.Size.Width;
+            double height = rotatedRect.Size.Height;
+
+            if (height == 0) return double.MaxValue;
+
+            // 纭繚瀹介珮姣斿缁� >= 1
+            return width >= height ? width / height : height / width;
+        }
+
+        /// <summary>
+        /// 鏍规嵁鐭╁舰搴﹁繃婊lob
+        /// </summary>
+        public static List<Blob> FilterByRectangularity(List<Blob> blobs, double minRectangularity, double maxRectangularity = 1.0)
+        {
+            return blobs.Where(b => b.Rectangularity >= minRectangularity && b.Rectangularity <= maxRectangularity).ToList();
+        }
+
+        /// <summary>
+        /// 鏍规嵁瀹介珮姣旇繃婊lob
+        /// </summary>
+        public static List<Blob> FilterByAspectRatio(List<Blob> blobs, double minAspectRatio, double maxAspectRatio)
+        {
+            return blobs.Where(b => b.AspectRatio >= minAspectRatio && b.AspectRatio <= maxAspectRatio).ToList();
+        }
+
+        /// <summary>
+        /// 鏍规嵁鏂瑰悜瑙掑害杩囨护Blob
+        /// </summary>
+        public static List<Blob> FilterByAngle(List<Blob> blobs, double minAngle, double maxAngle)
+        {
+            return blobs.Where(b =>
+            {
+                double angle = Math.Abs(b.RotatedBoundingBox.Angle);
+                // 澶勭悊瑙掑害鍛ㄦ湡鎬�
+                if (angle > 90) angle = 180 - angle;
+                return angle >= minAngle && angle <= maxAngle;
+            }).ToList();
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.Designer.cs b/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.Designer.cs
new file mode 100644
index 0000000..7031258
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.Designer.cs
@@ -0,0 +1,1026 @@
+锘縰sing LB_VisionProcesses.Alogrithms;
+
+namespace LB_VisionProcesses.Alogrithms.OpenCvSharp
+{
+    partial class BlobToolEdit
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tablePanelParas = new TableLayoutPanel();
+            label1 = new Label();
+            dtxtMinThreshold = new TextBox();
+            label2 = new Label();
+            dtxtMaxThreshold = new TextBox();
+            label3 = new Label();
+            dtxtMinArea = new TextBox();
+            label4 = new Label();
+            dtxtMaxArea = new TextBox();
+            label10 = new Label();
+            dtxtMinRow = new TextBox();
+            label11 = new Label();
+            dtxtMaxRow = new TextBox();
+            label12 = new Label();
+            dtxtMinColumn = new TextBox();
+            label13 = new Label();
+            dtxtMaxColumn = new TextBox();
+            label14 = new Label();
+            dtxtMinCircularity = new TextBox();
+            label15 = new Label();
+            dtxtMaxCircularity = new TextBox();
+            label16 = new Label();
+            dtxtMinRectangularity = new TextBox();
+            label17 = new Label();
+            dtxtMaxRectangularity = new TextBox();
+            dtxtMinCount = new TextBox();
+            dtxtMaxCount = new TextBox();
+            label19 = new Label();
+            label20 = new Label();
+            pnlInputImage = new Panel();
+            TopToolStrip = new ToolStrip();
+            btnRun = new ToolStripButton();
+            btnLoadImage = new ToolStripButton();
+            btnSaveParas = new ToolStripButton();
+            btnLoadParas = new ToolStripButton();
+            BtmStatusStrip = new StatusStrip();
+            lblResult = new ToolStripStatusLabel();
+            lblMsg = new ToolStripStatusLabel();
+            lblRunTime = new ToolStripStatusLabel();
+            MainTableLayoutPanel = new TableLayoutPanel();
+            parasTabControl = new TabControl();
+            tabPage1 = new TabPage();
+            tabPage5 = new TabPage();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            cmbTypeRoi = new ComboBox();
+            label21 = new Label();
+            label22 = new Label();
+            cmbFixture = new ComboBox();
+            ckbDrawRoi = new CheckBox();
+            tabPage2 = new TabPage();
+            tableLayoutResults = new TableLayoutPanel();
+            dtxtHeight = new TextBox();
+            label9 = new Label();
+            label5 = new Label();
+            label6 = new Label();
+            label7 = new Label();
+            label8 = new Label();
+            dtxtCenterX = new TextBox();
+            dtxtCenterY = new TextBox();
+            dtxtAngle = new TextBox();
+            dtxtWidth = new TextBox();
+            label18 = new Label();
+            dtxtCount = new TextBox();
+            label23 = new Label();
+            dtxtArea = new TextBox();
+            imgTabControl = new TabControl();
+            tabPageInputImage = new TabPage();
+            tabPageRecordImage = new TabPage();
+            pnlRecordImage = new Panel();
+            tablePanelParas.SuspendLayout();
+            TopToolStrip.SuspendLayout();
+            BtmStatusStrip.SuspendLayout();
+            MainTableLayoutPanel.SuspendLayout();
+            parasTabControl.SuspendLayout();
+            tabPage1.SuspendLayout();
+            tabPage5.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tabPage2.SuspendLayout();
+            tableLayoutResults.SuspendLayout();
+            imgTabControl.SuspendLayout();
+            tabPageInputImage.SuspendLayout();
+            tabPageRecordImage.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tablePanelParas
+            // 
+            tablePanelParas.ColumnCount = 4;
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.Controls.Add(label1, 0, 0);
+            tablePanelParas.Controls.Add(dtxtMinThreshold, 1, 0);
+            tablePanelParas.Controls.Add(label2, 2, 0);
+            tablePanelParas.Controls.Add(dtxtMaxThreshold, 3, 0);
+            tablePanelParas.Controls.Add(label3, 0, 1);
+            tablePanelParas.Controls.Add(dtxtMinArea, 1, 1);
+            tablePanelParas.Controls.Add(label4, 2, 1);
+            tablePanelParas.Controls.Add(dtxtMaxArea, 3, 1);
+            tablePanelParas.Controls.Add(label10, 0, 2);
+            tablePanelParas.Controls.Add(dtxtMinRow, 1, 2);
+            tablePanelParas.Controls.Add(label11, 2, 2);
+            tablePanelParas.Controls.Add(dtxtMaxRow, 3, 2);
+            tablePanelParas.Controls.Add(label12, 0, 3);
+            tablePanelParas.Controls.Add(dtxtMinColumn, 1, 3);
+            tablePanelParas.Controls.Add(label13, 2, 3);
+            tablePanelParas.Controls.Add(dtxtMaxColumn, 3, 3);
+            tablePanelParas.Controls.Add(label14, 0, 4);
+            tablePanelParas.Controls.Add(dtxtMinCircularity, 1, 4);
+            tablePanelParas.Controls.Add(label15, 2, 4);
+            tablePanelParas.Controls.Add(dtxtMaxCircularity, 3, 4);
+            tablePanelParas.Controls.Add(label16, 0, 5);
+            tablePanelParas.Controls.Add(dtxtMinRectangularity, 1, 5);
+            tablePanelParas.Controls.Add(label17, 2, 5);
+            tablePanelParas.Controls.Add(dtxtMaxRectangularity, 3, 5);
+            tablePanelParas.Controls.Add(dtxtMinCount, 1, 6);
+            tablePanelParas.Controls.Add(dtxtMaxCount, 3, 6);
+            tablePanelParas.Controls.Add(label19, 0, 6);
+            tablePanelParas.Controls.Add(label20, 2, 6);
+            tablePanelParas.Dock = DockStyle.Fill;
+            tablePanelParas.Location = new Point(3, 3);
+            tablePanelParas.Margin = new Padding(2, 3, 2, 3);
+            tablePanelParas.Name = "tablePanelParas";
+            tablePanelParas.RowCount = 10;
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.Size = new Size(397, 510);
+            tablePanelParas.TabIndex = 0;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Location = new Point(2, 0);
+            label1.Margin = new Padding(2, 0, 2, 0);
+            label1.MaximumSize = new Size(0, 28);
+            label1.MinimumSize = new Size(0, 28);
+            label1.Name = "label1";
+            label1.Size = new Size(68, 28);
+            label1.TabIndex = 0;
+            label1.Text = "鏈�灏忕伆搴﹀��";
+            label1.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinThreshold
+            // 
+            dtxtMinThreshold.Location = new Point(92, 3);
+            dtxtMinThreshold.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinThreshold.Name = "dtxtMinThreshold";
+            dtxtMinThreshold.Size = new Size(98, 23);
+            dtxtMinThreshold.TabIndex = 5;
+            dtxtMinThreshold.Text = "0";
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.Location = new Point(200, 0);
+            label2.Margin = new Padding(2, 0, 2, 0);
+            label2.MaximumSize = new Size(0, 28);
+            label2.MinimumSize = new Size(0, 28);
+            label2.Name = "label2";
+            label2.Size = new Size(68, 28);
+            label2.TabIndex = 1;
+            label2.Text = "鏈�澶х伆搴﹀��";
+            label2.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxThreshold
+            // 
+            dtxtMaxThreshold.Location = new Point(290, 3);
+            dtxtMaxThreshold.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxThreshold.Name = "dtxtMaxThreshold";
+            dtxtMaxThreshold.Size = new Size(98, 23);
+            dtxtMaxThreshold.TabIndex = 6;
+            dtxtMaxThreshold.Text = "255";
+            // 
+            // label3
+            // 
+            label3.AutoSize = true;
+            label3.Location = new Point(2, 51);
+            label3.Margin = new Padding(2, 0, 2, 0);
+            label3.MaximumSize = new Size(0, 28);
+            label3.MinimumSize = new Size(0, 28);
+            label3.Name = "label3";
+            label3.Size = new Size(56, 28);
+            label3.TabIndex = 2;
+            label3.Text = "鏈�灏忛潰绉�";
+            label3.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinArea
+            // 
+            dtxtMinArea.Location = new Point(92, 54);
+            dtxtMinArea.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinArea.Name = "dtxtMinArea";
+            dtxtMinArea.Size = new Size(98, 23);
+            dtxtMinArea.TabIndex = 7;
+            dtxtMinArea.Text = "0";
+            // 
+            // label4
+            // 
+            label4.AutoSize = true;
+            label4.Location = new Point(200, 51);
+            label4.Margin = new Padding(2, 0, 2, 0);
+            label4.MaximumSize = new Size(0, 28);
+            label4.MinimumSize = new Size(0, 28);
+            label4.Name = "label4";
+            label4.Size = new Size(56, 28);
+            label4.TabIndex = 3;
+            label4.Text = "鏈�澶ч潰绉�";
+            label4.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxArea
+            // 
+            dtxtMaxArea.Location = new Point(290, 54);
+            dtxtMaxArea.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxArea.Name = "dtxtMaxArea";
+            dtxtMaxArea.Size = new Size(98, 23);
+            dtxtMaxArea.TabIndex = 8;
+            dtxtMaxArea.Text = "0";
+            // 
+            // label10
+            // 
+            label10.AutoSize = true;
+            label10.Location = new Point(2, 102);
+            label10.Margin = new Padding(2, 0, 2, 0);
+            label10.MaximumSize = new Size(0, 28);
+            label10.MinimumSize = new Size(0, 28);
+            label10.Name = "label10";
+            label10.Size = new Size(75, 28);
+            label10.TabIndex = 9;
+            label10.Text = "鏈�灏忕旱鍧愭爣Y";
+            label10.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinRow
+            // 
+            dtxtMinRow.Location = new Point(92, 105);
+            dtxtMinRow.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinRow.Name = "dtxtMinRow";
+            dtxtMinRow.Size = new Size(98, 23);
+            dtxtMinRow.TabIndex = 9;
+            dtxtMinRow.Text = "0";
+            // 
+            // label11
+            // 
+            label11.AutoSize = true;
+            label11.Location = new Point(200, 102);
+            label11.Margin = new Padding(2, 0, 2, 0);
+            label11.MaximumSize = new Size(0, 28);
+            label11.MinimumSize = new Size(0, 28);
+            label11.Name = "label11";
+            label11.Size = new Size(75, 28);
+            label11.TabIndex = 10;
+            label11.Text = "鏈�澶х旱鍧愭爣Y";
+            label11.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxRow
+            // 
+            dtxtMaxRow.Location = new Point(290, 105);
+            dtxtMaxRow.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxRow.Name = "dtxtMaxRow";
+            dtxtMaxRow.Size = new Size(98, 23);
+            dtxtMaxRow.TabIndex = 9;
+            dtxtMaxRow.Text = "0";
+            // 
+            // label12
+            // 
+            label12.AutoSize = true;
+            label12.Location = new Point(2, 153);
+            label12.Margin = new Padding(2, 0, 2, 0);
+            label12.MaximumSize = new Size(0, 28);
+            label12.MinimumSize = new Size(0, 28);
+            label12.Name = "label12";
+            label12.Size = new Size(76, 28);
+            label12.TabIndex = 11;
+            label12.Text = "鏈�灏忔í鍧愭爣X";
+            label12.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinColumn
+            // 
+            dtxtMinColumn.Location = new Point(92, 156);
+            dtxtMinColumn.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinColumn.Name = "dtxtMinColumn";
+            dtxtMinColumn.Size = new Size(98, 23);
+            dtxtMinColumn.TabIndex = 9;
+            dtxtMinColumn.Text = "0";
+            // 
+            // label13
+            // 
+            label13.AutoSize = true;
+            label13.Location = new Point(200, 153);
+            label13.Margin = new Padding(2, 0, 2, 0);
+            label13.MaximumSize = new Size(0, 28);
+            label13.MinimumSize = new Size(0, 28);
+            label13.Name = "label13";
+            label13.Size = new Size(76, 28);
+            label13.TabIndex = 12;
+            label13.Text = "鏈�澶фí鍧愭爣X";
+            label13.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxColumn
+            // 
+            dtxtMaxColumn.Location = new Point(290, 156);
+            dtxtMaxColumn.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxColumn.Name = "dtxtMaxColumn";
+            dtxtMaxColumn.Size = new Size(98, 23);
+            dtxtMaxColumn.TabIndex = 9;
+            dtxtMaxColumn.Text = "0";
+            // 
+            // label14
+            // 
+            label14.AutoSize = true;
+            label14.Location = new Point(2, 204);
+            label14.Margin = new Padding(2, 0, 2, 0);
+            label14.MaximumSize = new Size(0, 28);
+            label14.MinimumSize = new Size(0, 28);
+            label14.Name = "label14";
+            label14.Size = new Size(56, 28);
+            label14.TabIndex = 13;
+            label14.Text = "鏈�灏忓渾搴�";
+            label14.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinCircularity
+            // 
+            dtxtMinCircularity.Location = new Point(92, 207);
+            dtxtMinCircularity.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinCircularity.Name = "dtxtMinCircularity";
+            dtxtMinCircularity.Size = new Size(98, 23);
+            dtxtMinCircularity.TabIndex = 9;
+            dtxtMinCircularity.Text = "0";
+            // 
+            // label15
+            // 
+            label15.AutoSize = true;
+            label15.Location = new Point(200, 204);
+            label15.Margin = new Padding(2, 0, 2, 0);
+            label15.MaximumSize = new Size(0, 28);
+            label15.MinimumSize = new Size(0, 28);
+            label15.Name = "label15";
+            label15.Size = new Size(56, 28);
+            label15.TabIndex = 14;
+            label15.Text = "鏈�澶у渾搴�";
+            label15.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxCircularity
+            // 
+            dtxtMaxCircularity.Location = new Point(290, 207);
+            dtxtMaxCircularity.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxCircularity.Name = "dtxtMaxCircularity";
+            dtxtMaxCircularity.Size = new Size(98, 23);
+            dtxtMaxCircularity.TabIndex = 9;
+            dtxtMaxCircularity.Text = "1";
+            // 
+            // label16
+            // 
+            label16.AutoSize = true;
+            label16.Location = new Point(2, 255);
+            label16.Margin = new Padding(2, 0, 2, 0);
+            label16.MaximumSize = new Size(0, 28);
+            label16.MinimumSize = new Size(0, 28);
+            label16.Name = "label16";
+            label16.Size = new Size(68, 28);
+            label16.TabIndex = 15;
+            label16.Text = "鏈�灏忕煩褰㈠害";
+            label16.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMinRectangularity
+            // 
+            dtxtMinRectangularity.Location = new Point(92, 258);
+            dtxtMinRectangularity.Margin = new Padding(2, 3, 2, 3);
+            dtxtMinRectangularity.Name = "dtxtMinRectangularity";
+            dtxtMinRectangularity.Size = new Size(98, 23);
+            dtxtMinRectangularity.TabIndex = 9;
+            dtxtMinRectangularity.Text = "0";
+            // 
+            // label17
+            // 
+            label17.AutoSize = true;
+            label17.Location = new Point(200, 255);
+            label17.Margin = new Padding(2, 0, 2, 0);
+            label17.MaximumSize = new Size(0, 28);
+            label17.MinimumSize = new Size(0, 28);
+            label17.Name = "label17";
+            label17.Size = new Size(68, 28);
+            label17.TabIndex = 16;
+            label17.Text = "鏈�澶х煩褰㈠害";
+            label17.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtMaxRectangularity
+            // 
+            dtxtMaxRectangularity.Location = new Point(290, 258);
+            dtxtMaxRectangularity.Margin = new Padding(2, 3, 2, 3);
+            dtxtMaxRectangularity.Name = "dtxtMaxRectangularity";
+            dtxtMaxRectangularity.Size = new Size(98, 23);
+            dtxtMaxRectangularity.TabIndex = 10;
+            dtxtMaxRectangularity.Text = "1";
+            // 
+            // dtxtMinCount
+            // 
+            dtxtMinCount.Location = new Point(93, 309);
+            dtxtMinCount.Name = "dtxtMinCount";
+            dtxtMinCount.Size = new Size(97, 23);
+            dtxtMinCount.TabIndex = 17;
+            dtxtMinCount.Text = "0";
+            // 
+            // dtxtMaxCount
+            // 
+            dtxtMaxCount.Location = new Point(291, 309);
+            dtxtMaxCount.Name = "dtxtMaxCount";
+            dtxtMaxCount.Size = new Size(97, 23);
+            dtxtMaxCount.TabIndex = 18;
+            dtxtMaxCount.Text = "9999";
+            // 
+            // label19
+            // 
+            label19.AutoSize = true;
+            label19.Location = new Point(3, 306);
+            label19.Name = "label19";
+            label19.Size = new Size(56, 17);
+            label19.TabIndex = 19;
+            label19.Text = "鏈�灏忔暟閲�";
+            // 
+            // label20
+            // 
+            label20.AutoSize = true;
+            label20.Location = new Point(201, 306);
+            label20.Name = "label20";
+            label20.Size = new Size(56, 17);
+            label20.TabIndex = 20;
+            label20.Text = "鏈�澶ф暟閲�";
+            // 
+            // pnlInputImage
+            // 
+            pnlInputImage.Dock = DockStyle.Fill;
+            pnlInputImage.Location = new Point(3, 3);
+            pnlInputImage.Margin = new Padding(4);
+            pnlInputImage.Name = "pnlInputImage";
+            pnlInputImage.Size = new Size(607, 510);
+            pnlInputImage.TabIndex = 44;
+            // 
+            // TopToolStrip
+            // 
+            TopToolStrip.Items.AddRange(new ToolStripItem[] { btnRun, btnLoadImage, btnSaveParas, btnLoadParas });
+            TopToolStrip.Location = new Point(0, 0);
+            TopToolStrip.Name = "TopToolStrip";
+            TopToolStrip.Size = new Size(1044, 25);
+            TopToolStrip.TabIndex = 45;
+            TopToolStrip.Text = "toolStrip1";
+            // 
+            // btnRun
+            // 
+            btnRun.BackgroundImageLayout = ImageLayout.Zoom;
+            btnRun.ImageTransparentColor = Color.Magenta;
+            btnRun.Name = "btnRun";
+            btnRun.Size = new Size(36, 22);
+            btnRun.Text = "杩愯";
+            btnRun.Click += btnRun_Click;
+            // 
+            // btnLoadImage
+            // 
+            btnLoadImage.ImageTransparentColor = Color.Magenta;
+            btnLoadImage.Name = "btnLoadImage";
+            btnLoadImage.Size = new Size(36, 22);
+            btnLoadImage.Text = "瀵煎浘";
+            btnLoadImage.Click += btnLoadImage_Click;
+            // 
+            // btnSaveParas
+            // 
+            btnSaveParas.ImageTransparentColor = Color.Magenta;
+            btnSaveParas.Name = "btnSaveParas";
+            btnSaveParas.Size = new Size(36, 22);
+            btnSaveParas.Text = "淇濆瓨";
+            btnSaveParas.Click += btnSaveParas_Click;
+            // 
+            // btnLoadParas
+            // 
+            btnLoadParas.ImageTransparentColor = Color.Magenta;
+            btnLoadParas.Name = "btnLoadParas";
+            btnLoadParas.Size = new Size(36, 22);
+            btnLoadParas.Text = "鍔犺浇";
+            btnLoadParas.Click += btnLoadParas_Click;
+            // 
+            // BtmStatusStrip
+            // 
+            BtmStatusStrip.Items.AddRange(new ToolStripItem[] { lblResult, lblMsg, lblRunTime });
+            BtmStatusStrip.Location = new Point(0, 577);
+            BtmStatusStrip.Name = "BtmStatusStrip";
+            BtmStatusStrip.Size = new Size(1044, 22);
+            BtmStatusStrip.TabIndex = 46;
+            BtmStatusStrip.Text = "statusStrip1";
+            // 
+            // lblResult
+            // 
+            lblResult.Name = "lblResult";
+            lblResult.Size = new Size(34, 17);
+            lblResult.Text = "True";
+            // 
+            // lblMsg
+            // 
+            lblMsg.Name = "lblMsg";
+            lblMsg.Size = new Size(56, 17);
+            lblMsg.Text = "杩愯鎴愬姛";
+            // 
+            // lblRunTime
+            // 
+            lblRunTime.Name = "lblRunTime";
+            lblRunTime.Size = new Size(32, 17);
+            lblRunTime.Text = "0ms";
+            // 
+            // MainTableLayoutPanel
+            // 
+            MainTableLayoutPanel.ColumnCount = 2;
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F));
+            MainTableLayoutPanel.Controls.Add(parasTabControl, 0, 0);
+            MainTableLayoutPanel.Controls.Add(imgTabControl, 1, 0);
+            MainTableLayoutPanel.Dock = DockStyle.Fill;
+            MainTableLayoutPanel.Location = new Point(0, 25);
+            MainTableLayoutPanel.Name = "MainTableLayoutPanel";
+            MainTableLayoutPanel.RowCount = 1;
+            MainTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            MainTableLayoutPanel.Size = new Size(1044, 552);
+            MainTableLayoutPanel.TabIndex = 47;
+            // 
+            // parasTabControl
+            // 
+            parasTabControl.Controls.Add(tabPage1);
+            parasTabControl.Controls.Add(tabPage5);
+            parasTabControl.Controls.Add(tabPage2);
+            parasTabControl.Dock = DockStyle.Fill;
+            parasTabControl.Location = new Point(3, 3);
+            parasTabControl.Name = "parasTabControl";
+            parasTabControl.SelectedIndex = 0;
+            parasTabControl.Size = new Size(411, 546);
+            parasTabControl.TabIndex = 48;
+            // 
+            // tabPage1
+            // 
+            tabPage1.Controls.Add(tablePanelParas);
+            tabPage1.Location = new Point(4, 26);
+            tabPage1.Name = "tabPage1";
+            tabPage1.Padding = new Padding(3);
+            tabPage1.Size = new Size(403, 516);
+            tabPage1.TabIndex = 0;
+            tabPage1.Text = "杈撳叆鍙傛暟";
+            tabPage1.UseVisualStyleBackColor = true;
+            // 
+            // tabPage5
+            // 
+            tabPage5.Controls.Add(tableLayoutPanel2);
+            tabPage5.Location = new Point(4, 26);
+            tabPage5.Name = "tabPage5";
+            tabPage5.Size = new Size(403, 516);
+            tabPage5.TabIndex = 2;
+            tabPage5.Text = "杩愯鍙傛暟";
+            tabPage5.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 4;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 60F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 150F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(cmbTypeRoi, 1, 0);
+            tableLayoutPanel2.Controls.Add(label21, 0, 0);
+            tableLayoutPanel2.Controls.Add(label22, 0, 1);
+            tableLayoutPanel2.Controls.Add(cmbFixture, 1, 1);
+            tableLayoutPanel2.Controls.Add(ckbDrawRoi, 2, 0);
+            tableLayoutPanel2.Location = new Point(3, 3);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 3;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(323, 196);
+            tableLayoutPanel2.TabIndex = 4;
+            // 
+            // cmbTypeRoi
+            // 
+            cmbTypeRoi.FormattingEnabled = true;
+            cmbTypeRoi.Location = new Point(63, 3);
+            cmbTypeRoi.Name = "cmbTypeRoi";
+            cmbTypeRoi.Size = new Size(121, 25);
+            cmbTypeRoi.TabIndex = 1;
+            cmbTypeRoi.SelectedIndexChanged += cmbTypeRoi_SelectedIndexChanged;
+            // 
+            // label21
+            // 
+            label21.AutoSize = true;
+            label21.Dock = DockStyle.Fill;
+            label21.Location = new Point(3, 0);
+            label21.Name = "label21";
+            label21.Size = new Size(54, 30);
+            label21.TabIndex = 3;
+            label21.Text = "ROI";
+            label21.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label22
+            // 
+            label22.AutoSize = true;
+            label22.Dock = DockStyle.Fill;
+            label22.Location = new Point(3, 30);
+            label22.Name = "label22";
+            label22.Size = new Size(54, 30);
+            label22.TabIndex = 4;
+            label22.Text = "Fixture";
+            label22.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbFixture
+            // 
+            cmbFixture.FormattingEnabled = true;
+            cmbFixture.Location = new Point(63, 33);
+            cmbFixture.Name = "cmbFixture";
+            cmbFixture.Size = new Size(121, 25);
+            cmbFixture.TabIndex = 5;
+            cmbFixture.SelectedIndexChanged += cmbFixture_SelectedIndexChanged;
+            // 
+            // ckbDrawRoi
+            // 
+            ckbDrawRoi.AutoSize = true;
+            ckbDrawRoi.CheckAlign = ContentAlignment.MiddleCenter;
+            ckbDrawRoi.Location = new Point(213, 3);
+            ckbDrawRoi.Name = "ckbDrawRoi";
+            ckbDrawRoi.Size = new Size(14, 14);
+            ckbDrawRoi.TabIndex = 2;
+            ckbDrawRoi.UseVisualStyleBackColor = true;
+            ckbDrawRoi.CheckedChanged += ckbDrawRoi_CheckedChanged;
+            // 
+            // tabPage2
+            // 
+            tabPage2.Controls.Add(tableLayoutResults);
+            tabPage2.Location = new Point(4, 26);
+            tabPage2.Name = "tabPage2";
+            tabPage2.Padding = new Padding(3);
+            tabPage2.Size = new Size(403, 516);
+            tabPage2.TabIndex = 1;
+            tabPage2.Text = "杈撳嚭缁撴灉";
+            tabPage2.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutResults
+            // 
+            tableLayoutResults.ColumnCount = 2;
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutResults.Controls.Add(dtxtHeight, 1, 4);
+            tableLayoutResults.Controls.Add(label9, 0, 4);
+            tableLayoutResults.Controls.Add(label5, 0, 0);
+            tableLayoutResults.Controls.Add(label6, 0, 1);
+            tableLayoutResults.Controls.Add(label7, 0, 2);
+            tableLayoutResults.Controls.Add(label8, 0, 3);
+            tableLayoutResults.Controls.Add(dtxtCenterX, 1, 0);
+            tableLayoutResults.Controls.Add(dtxtCenterY, 1, 1);
+            tableLayoutResults.Controls.Add(dtxtAngle, 1, 2);
+            tableLayoutResults.Controls.Add(dtxtWidth, 1, 3);
+            tableLayoutResults.Controls.Add(label18, 0, 6);
+            tableLayoutResults.Controls.Add(dtxtCount, 1, 6);
+            tableLayoutResults.Controls.Add(label23, 0, 5);
+            tableLayoutResults.Controls.Add(dtxtArea, 1, 5);
+            tableLayoutResults.Dock = DockStyle.Fill;
+            tableLayoutResults.Location = new Point(3, 3);
+            tableLayoutResults.Margin = new Padding(2, 3, 2, 3);
+            tableLayoutResults.Name = "tableLayoutResults";
+            tableLayoutResults.RowCount = 10;
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.Size = new Size(397, 510);
+            tableLayoutResults.TabIndex = 1;
+            // 
+            // dtxtHeight
+            // 
+            dtxtHeight.Dock = DockStyle.Fill;
+            dtxtHeight.Location = new Point(102, 207);
+            dtxtHeight.Margin = new Padding(2, 3, 2, 3);
+            dtxtHeight.Name = "dtxtHeight";
+            dtxtHeight.ReadOnly = true;
+            dtxtHeight.Size = new Size(293, 23);
+            dtxtHeight.TabIndex = 9;
+            // 
+            // label9
+            // 
+            label9.AutoSize = true;
+            label9.Dock = DockStyle.Fill;
+            label9.Location = new Point(2, 204);
+            label9.Margin = new Padding(2, 0, 2, 0);
+            label9.MaximumSize = new Size(0, 28);
+            label9.MinimumSize = new Size(0, 28);
+            label9.Name = "label9";
+            label9.Size = new Size(96, 28);
+            label9.TabIndex = 3;
+            label9.Text = "楂樺害";
+            label9.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Dock = DockStyle.Fill;
+            label5.Location = new Point(2, 0);
+            label5.Margin = new Padding(2, 0, 2, 0);
+            label5.MaximumSize = new Size(0, 28);
+            label5.MinimumSize = new Size(0, 28);
+            label5.Name = "label5";
+            label5.Size = new Size(96, 28);
+            label5.TabIndex = 0;
+            label5.Text = "X";
+            label5.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label6
+            // 
+            label6.AutoSize = true;
+            label6.Dock = DockStyle.Fill;
+            label6.Location = new Point(2, 51);
+            label6.Margin = new Padding(2, 0, 2, 0);
+            label6.MaximumSize = new Size(0, 28);
+            label6.MinimumSize = new Size(0, 28);
+            label6.Name = "label6";
+            label6.Size = new Size(96, 28);
+            label6.TabIndex = 1;
+            label6.Text = "Y";
+            label6.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label7
+            // 
+            label7.AutoSize = true;
+            label7.Dock = DockStyle.Fill;
+            label7.Location = new Point(2, 102);
+            label7.Margin = new Padding(2, 0, 2, 0);
+            label7.MaximumSize = new Size(0, 28);
+            label7.MinimumSize = new Size(0, 28);
+            label7.Name = "label7";
+            label7.Size = new Size(96, 28);
+            label7.TabIndex = 2;
+            label7.Text = "瑙掑害(掳)";
+            label7.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label8
+            // 
+            label8.AutoSize = true;
+            label8.Dock = DockStyle.Fill;
+            label8.Location = new Point(2, 153);
+            label8.Margin = new Padding(2, 0, 2, 0);
+            label8.MaximumSize = new Size(0, 28);
+            label8.MinimumSize = new Size(0, 28);
+            label8.Name = "label8";
+            label8.Size = new Size(96, 28);
+            label8.TabIndex = 3;
+            label8.Text = "瀹藉害";
+            label8.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCenterX
+            // 
+            dtxtCenterX.Dock = DockStyle.Fill;
+            dtxtCenterX.Location = new Point(102, 3);
+            dtxtCenterX.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterX.Name = "dtxtCenterX";
+            dtxtCenterX.ReadOnly = true;
+            dtxtCenterX.Size = new Size(293, 23);
+            dtxtCenterX.TabIndex = 5;
+            // 
+            // dtxtCenterY
+            // 
+            dtxtCenterY.Dock = DockStyle.Fill;
+            dtxtCenterY.Location = new Point(102, 54);
+            dtxtCenterY.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterY.Name = "dtxtCenterY";
+            dtxtCenterY.ReadOnly = true;
+            dtxtCenterY.Size = new Size(293, 23);
+            dtxtCenterY.TabIndex = 6;
+            // 
+            // dtxtAngle
+            // 
+            dtxtAngle.Dock = DockStyle.Fill;
+            dtxtAngle.Location = new Point(102, 105);
+            dtxtAngle.Margin = new Padding(2, 3, 2, 3);
+            dtxtAngle.Name = "dtxtAngle";
+            dtxtAngle.ReadOnly = true;
+            dtxtAngle.Size = new Size(293, 23);
+            dtxtAngle.TabIndex = 7;
+            // 
+            // dtxtWidth
+            // 
+            dtxtWidth.Dock = DockStyle.Fill;
+            dtxtWidth.Location = new Point(102, 156);
+            dtxtWidth.Margin = new Padding(2, 3, 2, 3);
+            dtxtWidth.Name = "dtxtWidth";
+            dtxtWidth.ReadOnly = true;
+            dtxtWidth.Size = new Size(293, 23);
+            dtxtWidth.TabIndex = 8;
+            // 
+            // label18
+            // 
+            label18.AutoSize = true;
+            label18.Dock = DockStyle.Fill;
+            label18.Location = new Point(3, 306);
+            label18.Name = "label18";
+            label18.Size = new Size(94, 51);
+            label18.TabIndex = 10;
+            label18.Text = "鏁伴噺";
+            label18.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCount
+            // 
+            dtxtCount.Dock = DockStyle.Fill;
+            dtxtCount.Location = new Point(103, 309);
+            dtxtCount.Name = "dtxtCount";
+            dtxtCount.ReadOnly = true;
+            dtxtCount.Size = new Size(291, 23);
+            dtxtCount.TabIndex = 11;
+            // 
+            // label23
+            // 
+            label23.AutoSize = true;
+            label23.Dock = DockStyle.Fill;
+            label23.Location = new Point(3, 255);
+            label23.Name = "label23";
+            label23.Size = new Size(94, 51);
+            label23.TabIndex = 12;
+            label23.Text = "闈㈢Н";
+            label23.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtArea
+            // 
+            dtxtArea.Dock = DockStyle.Fill;
+            dtxtArea.Location = new Point(103, 258);
+            dtxtArea.Name = "dtxtArea";
+            dtxtArea.ReadOnly = true;
+            dtxtArea.Size = new Size(291, 23);
+            dtxtArea.TabIndex = 13;
+            // 
+            // imgTabControl
+            // 
+            imgTabControl.Controls.Add(tabPageInputImage);
+            imgTabControl.Controls.Add(tabPageRecordImage);
+            imgTabControl.Dock = DockStyle.Fill;
+            imgTabControl.Location = new Point(420, 3);
+            imgTabControl.Name = "imgTabControl";
+            imgTabControl.SelectedIndex = 0;
+            imgTabControl.Size = new Size(621, 546);
+            imgTabControl.TabIndex = 49;
+            // 
+            // tabPageInputImage
+            // 
+            tabPageInputImage.Controls.Add(pnlInputImage);
+            tabPageInputImage.Location = new Point(4, 26);
+            tabPageInputImage.Name = "tabPageInputImage";
+            tabPageInputImage.Padding = new Padding(3);
+            tabPageInputImage.Size = new Size(613, 516);
+            tabPageInputImage.TabIndex = 0;
+            tabPageInputImage.Text = "杈撳叆鍥惧儚";
+            tabPageInputImage.UseVisualStyleBackColor = true;
+            // 
+            // tabPageRecordImage
+            // 
+            tabPageRecordImage.Controls.Add(pnlRecordImage);
+            tabPageRecordImage.Location = new Point(4, 26);
+            tabPageRecordImage.Name = "tabPageRecordImage";
+            tabPageRecordImage.Padding = new Padding(3);
+            tabPageRecordImage.Size = new Size(613, 516);
+            tabPageRecordImage.TabIndex = 1;
+            tabPageRecordImage.Text = "缁撴灉鍥惧儚";
+            tabPageRecordImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlRecordImage
+            // 
+            pnlRecordImage.Dock = DockStyle.Fill;
+            pnlRecordImage.Location = new Point(3, 3);
+            pnlRecordImage.Margin = new Padding(4);
+            pnlRecordImage.Name = "pnlRecordImage";
+            pnlRecordImage.Size = new Size(607, 510);
+            pnlRecordImage.TabIndex = 45;
+            // 
+            // HBlobToolEdit
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(MainTableLayoutPanel);
+            Controls.Add(BtmStatusStrip);
+            Controls.Add(TopToolStrip);
+            Margin = new Padding(2, 3, 2, 3);
+            Name = "BlobToolEdit";
+            Size = new Size(1044, 599);
+            Load += BlobToolEdit_Load;
+            tablePanelParas.ResumeLayout(false);
+            tablePanelParas.PerformLayout();
+            TopToolStrip.ResumeLayout(false);
+            TopToolStrip.PerformLayout();
+            BtmStatusStrip.ResumeLayout(false);
+            BtmStatusStrip.PerformLayout();
+            MainTableLayoutPanel.ResumeLayout(false);
+            parasTabControl.ResumeLayout(false);
+            tabPage1.ResumeLayout(false);
+            tabPage5.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel2.PerformLayout();
+            tabPage2.ResumeLayout(false);
+            tableLayoutResults.ResumeLayout(false);
+            tableLayoutResults.PerformLayout();
+            imgTabControl.ResumeLayout(false);
+            tabPageInputImage.ResumeLayout(false);
+            tabPageRecordImage.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TableLayoutPanel tablePanelParas;
+        private System.Windows.Forms.Panel pnlInputImage;
+        private ToolStrip TopToolStrip;
+        private ToolStripButton btnRun;
+        private StatusStrip BtmStatusStrip;
+        private ToolStripStatusLabel lblResult;
+        private ToolStripStatusLabel lblMsg;
+        private TableLayoutPanel MainTableLayoutPanel;
+        private ToolStripButton btnLoadImage;
+        private TabControl parasTabControl;
+        private TabPage tabPage1;
+        private TabPage tabPage2;
+        private TableLayoutPanel tableLayoutResults;
+        private Label label5;
+        private Label label6;
+        private Label label7;
+        private Label label8;
+        private TextBox dtxtCenterX;
+        private TextBox dtxtCenterY;
+        private TextBox dtxtAngle;
+        private TextBox dtxtWidth;
+        private TextBox dtxtHeight;
+        private Label label9;
+        private TabPage tabPage5;
+        private TabControl imgTabControl;
+        private TabPage tabPageInputImage;
+        private TabPage tabPageRecordImage;
+        private ToolStripButton btnSaveParas;
+        private ToolStripButton btnLoadParas;
+        private Panel pnlRecordImage;
+        private Label label1;
+        private TextBox dtxtMinThreshold;
+        private Label label2;
+        private TextBox dtxtMaxThreshold;
+        private Label label3;
+        private TextBox dtxtMinArea;
+        private Label label4;
+        private TextBox dtxtMaxArea;
+        private Label label10;
+        private TextBox dtxtMinRow;
+        private Label label11;
+        private TextBox dtxtMaxRow;
+        private Label label12;
+        private TextBox dtxtMinColumn;
+        private Label label13;
+        private TextBox dtxtMaxColumn;
+        private Label label14;
+        private TextBox dtxtMinCircularity;
+        private Label label15;
+        private TextBox dtxtMaxCircularity;
+        private Label label16;
+        private TextBox dtxtMinRectangularity;
+        private Label label17;
+        private TextBox dtxtMaxRectangularity;
+        private Label label18;
+        private TextBox dtxtCount;
+        private TextBox dtxtMinCount;
+        private TextBox dtxtMaxCount;
+        private Label label19;
+        private Label label20;
+        private ToolStripStatusLabel lblRunTime;
+        private TableLayoutPanel tableLayoutPanel2;
+        public ComboBox cmbTypeRoi;
+        private Label label21;
+        private Label label22;
+        private ComboBox cmbFixture;
+        private CheckBox ckbDrawRoi;
+        private Label label23;
+        private TextBox dtxtArea;
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.cs b/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.cs
new file mode 100644
index 0000000..5395562
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.cs
@@ -0,0 +1,349 @@
+锘縰sing HalconDotNet;
+using LB_VisionControl;
+using OpenCvSharp;
+
+namespace LB_VisionProcesses.Alogrithms.OpenCvSharp
+{
+    public partial class BlobToolEdit : TAlgorithmEdit
+    {
+        public BlobToolEdit(BlobTool subject = null)
+        {
+            if (subject != null && subject is BlobTool)
+                Subject = subject;
+            else
+                Subject = new BlobTool();
+
+            this.Dock = DockStyle.Fill;
+            InitializeComponent();
+        }
+
+        /// <summary>
+        /// 鎺т欢鍔犺浇浜嬩欢
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void BlobToolEdit_Load(object sender, EventArgs e)
+        {
+            pnlInputImage.Controls.Add(inputImageHSmartWindowControl);
+            inputImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            pnlRecordImage.Controls.Add(recordImageHSmartWindowControl);
+            recordImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            //閬嶅巻鍙互閫夋嫨鐨凴oi绫诲瀷鏋氫妇
+            foreach (var value in Enum.GetValues(typeof(RoiType)))
+                cmbTypeRoi.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨凢ixture鏋氫妇
+            cmbFixture.Items.Add("");
+            foreach (string value in IProcess.dicFixtures.Keys)
+                cmbFixture.Items.Add(value.ToString());
+
+            cmbTypeRoi.Text = RoiType.None.ToString();
+            LoadParas();
+
+            if (Subject.Result)
+            {
+                lblResult.BackColor = Color.Green;
+                lblResult.Text = "True";
+            }
+            else
+            {
+                lblResult.BackColor = Color.Red;
+                lblResult.Text = "False";
+            }
+
+            lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+            lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+            lblRunTime.Text = $"{Subject.RunTime}ms";
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯鍙傛暟
+        /// </summary>
+        public override void UpdataInputs()
+        {
+            //璁剧疆杩愯鍙傛暟
+            double dResult = 0;
+            int iResult = 0;
+
+            Subject.Params.Inputs["MinThreshold"] = int.TryParse(dtxtMinThreshold.Text, out iResult) ? iResult : Subject.Params.Inputs["MinThreshold"];
+            Subject.Params.Inputs["MaxThreshold"] = int.TryParse(dtxtMaxThreshold.Text, out iResult) ? iResult : Subject.Params.Inputs["MaxThreshold"];
+
+            Subject.Params.Inputs["MinArea"] = double.TryParse(dtxtMinArea.Text, out dResult) ? dResult : Subject.Params.Inputs["MinArea"];
+            Subject.Params.Inputs["MaxArea"] = double.TryParse(dtxtMaxArea.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxArea"];
+
+            Subject.Params.Inputs["MinRow"] = double.TryParse(dtxtMinRow.Text, out dResult) ? dResult : Subject.Params.Inputs["MinRow"];
+            Subject.Params.Inputs["MaxRow"] = double.TryParse(dtxtMaxRow.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxRow"];
+
+            Subject.Params.Inputs["MinColumn"] = double.TryParse(dtxtMinColumn.Text, out dResult) ? dResult : Subject.Params.Inputs["MinColumn"];
+            Subject.Params.Inputs["MaxColumn"] = double.TryParse(dtxtMaxColumn.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxColumn"];
+
+            Subject.Params.Inputs["MinCircularity"] = double.TryParse(dtxtMinCircularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MinCircularity"];
+            Subject.Params.Inputs["MaxCircularity"] = double.TryParse(dtxtMaxCircularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxCircularity"];
+
+            Subject.Params.Inputs["MinRectangularity"] = double.TryParse(dtxtMinRectangularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MinRectangularity"];
+            Subject.Params.Inputs["MaxRectangularity"] = double.TryParse(dtxtMaxRectangularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxRectangularity"];
+
+            Subject.Params.Inputs["MinCount"] = int.TryParse(dtxtMinCount.Text, out iResult) ? iResult : Subject.Params.Inputs["MinCount"];
+            Subject.Params.Inputs["MaxCount"] = int.TryParse(dtxtMaxCount.Text, out iResult) ? iResult : Subject.Params.Inputs["MaxCount"];
+
+            if (cmbFixture.Text == "")
+                Subject.Params.Fixture = new Fixture();
+            else if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+
+            base.UpdataInputs();
+        }
+
+        /// <summary>
+        /// 鍔犺浇杩愯鍙傛暟
+        /// </summary>
+        public override void LoadParas()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                dtxtMinThreshold.Text = Subject.Params.Inputs["MinThreshold"].ToString();
+                dtxtMaxThreshold.Text = Subject.Params.Inputs["MaxThreshold"].ToString();
+                dtxtMinArea.Text = Subject.Params.Inputs["MinArea"].ToString();
+                dtxtMaxArea.Text = Subject.Params.Inputs["MaxArea"].ToString();
+                dtxtMinRow.Text = Subject.Params.Inputs["MinRow"].ToString();
+                dtxtMaxRow.Text = Subject.Params.Inputs["MaxRow"].ToString();
+                dtxtMinColumn.Text = Subject.Params.Inputs["MinColumn"].ToString();
+                dtxtMaxColumn.Text = Subject.Params.Inputs["MaxColumn"].ToString();
+                dtxtMinCircularity.Text = Subject.Params.Inputs["MinCircularity"].ToString();
+                dtxtMaxCircularity.Text = Subject.Params.Inputs["MaxCircularity"].ToString();
+                dtxtMinRectangularity.Text = Subject.Params.Inputs["MinRectangularity"].ToString();
+                dtxtMaxRectangularity.Text = Subject.Params.Inputs["MaxRectangularity"].ToString();
+                dtxtMinCount.Text = Subject.Params.Inputs["MinCount"].ToString();
+                dtxtMaxCount.Text = Subject.Params.Inputs["MaxCount"].ToString();
+
+                if (Subject.InputImage != null && Subject.InputImage is Mat)
+                {
+                    TAlgorithm.Mat2HObject((Mat)Subject.InputImage, out HObject image);
+                    inputImageHSmartWindowControl.ShowHoImage(image);
+                }
+
+                Type type = Subject.Params.ROI?.GetType();
+                if (Subject.Params.ROI != null)
+                {
+                    switch (type)
+                    {
+                        case Type t when t == typeof(HRectangle2):
+                            cmbTypeRoi.Text = RoiType.Rectangle2.ToString();
+                            break;
+                        case Type t when t == typeof(HCircle):
+                            cmbTypeRoi.Text = RoiType.Circle.ToString();
+                            break;
+                        case Type t when t == typeof(HSegment):
+                            cmbTypeRoi.Text = RoiType.Segment.ToString();
+                            break;
+                        default:
+                            cmbTypeRoi.Text = RoiType.None.ToString();
+                            break;
+                    }
+                    if (cmbTypeRoi.Text.ToString() != "None")
+                        ckbDrawRoi.Checked = true;
+                    else
+                        ckbDrawRoi.Checked = false;
+
+                    inputImageHSmartWindowControl.oRoi = Subject.Params.ROI;
+                }
+
+                if (Subject.Params.Fixture != null)
+                    cmbFixture.Text = Subject.Params.Fixture.strName;
+                else
+                    cmbFixture.Text = "";
+
+                base.LoadParas();
+            }));
+        }
+
+        /// <summary>
+        /// 鏇存柊杈撳嚭缁撴灉
+        /// </summary>
+        public override void UpdataOutputs()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                //瀛樺湪鍙嶅簭鍒楀寲閿欎贡鐨勬儏鍐甸渶瑕佷娇鐢ㄨ嚜瀹氫箟鐨勮浆鎹㈠櫒
+                dtxtCenterX.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterX"]);
+                dtxtCenterY.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterY"]);
+                dtxtAngle.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Angle"]);
+                dtxtWidth.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Width"]);
+                dtxtHeight.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Height"]);
+                dtxtArea.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Area"]);
+                dtxtCount.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Count"]);
+            }));
+        }
+
+        /// <summary>
+        /// 鐐瑰嚮杩愯
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        public override void btnRun_Click(object sender, EventArgs e)
+        {
+            if (Subject.InputImage != null)
+                InputImage = Subject.InputImage;
+
+            DateTime StartTime = DateTime.Now;
+            Run();
+
+            //鏇存柊鏃ュ織涓庣粨鏋�
+            this.BeginInvoke(new Action(() =>
+            {
+                if (Subject.Result)
+                {
+                    lblResult.BackColor = Color.Green;
+                    lblResult.Text = "True";
+                    recordImageHSmartWindowControl.SetColor("green");
+                }
+                else
+                {
+                    lblResult.BackColor = Color.Red;
+                    lblResult.Text = "False";
+                    recordImageHSmartWindowControl.SetColor("red");
+                }
+
+                lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+                lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+                lblRunTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
+
+                UpdataOutputs();
+                imgTabControl.SelectedTab = tabPageRecordImage;
+
+                if (Subject.InputImage != null && Subject.InputImage is Mat)
+                {
+                    TAlgorithm.Mat2HObject((Mat)Subject.InputImage, out HObject image);
+                    HOperatorSet.GetImageSize(image, out HTuple ho_ImageWidth, out HTuple ho_ImageHeight);
+                    recordImageHSmartWindowControl.ShowHoImage(image);
+                }
+
+                //鍏堝垽鏂瓙绫诲啀鍒ゆ柇鐖剁被
+                if (Subject.Record != null && Subject.Record is MsgRecord msgRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_NG, false);
+
+                    for (int i = 0; i < msgRecord.Msg.Length; i++)
+                        recordImageHSmartWindowControl.ShowMsg(msgRecord.Msg[i]
+                            , 1 == msgRecord.Result[i] ? true : false, msgRecord.Column[i], msgRecord.Row[i]);
+                }
+                else if (Subject.Record != null && Subject.Record is ObjectRecord objRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_NG, false);
+                }
+
+                GC.Collect();
+            }));
+        }
+
+        public override void btnLoadImage_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    Mat mat = Cv2.ImRead(selectedFiles[0]);
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    if (mat.Channels() != 1)
+                    {
+                        Cv2.CvtColor(mat, mat, ColorConversionCodes.RGB2GRAY);
+                        //鏇存柊鏃ュ織涓庣粨鏋�
+                        this.BeginInvoke(new Action(() =>
+                        {
+                            lblMsg.Text = "瀵煎叆鍥剧墖闈炵伆搴﹀浘,鑷姩杞崲涓虹伆搴﹀浘";
+                        }));
+                    }
+                    InputImage = mat;
+                    imgTabControl.SelectedTab = tabPageInputImage;
+                    inputImageHSmartWindowControl.oRoi = inputImageHSmartWindowControl.oRoi;
+                }
+            }
+        }
+
+        public override void btnSaveParas_Click(object sender, EventArgs e) { base.btnSaveParas_Click(sender, e); }
+
+        public override void ckbDrawRoi_CheckedChanged(object sender, EventArgs e)
+        {
+            if (ckbDrawRoi.Checked)
+            {
+                inputImageHSmartWindowControl.bAollowDraw = true;
+                imgTabControl.SelectedTab = tabPageInputImage;
+            }
+            else
+            {
+                inputImageHSmartWindowControl.bAollowDraw = false;
+                Subject.Params.ROI = new ROI();
+            }
+        }
+
+        public override void cmbTypeRoi_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (Enum.TryParse(cmbTypeRoi.Text.ToString(), out RoiType type))
+                {
+                    HTuple hv_imageWidth = 0;
+                    HTuple hv_imageHeight = 0;
+                    if (InputImage != null && InputImage is Mat)
+                    {
+                        TAlgorithm.Mat2HObject((Mat)InputImage, out HObject image);
+                        HOperatorSet.GetImageSize(image, out hv_imageWidth, out hv_imageHeight);
+                    }
+                    switch (type)
+                    {
+                        case RoiType.Rectangle2:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, 0
+                                , hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.Circle:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HCircle(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, hv_imageWidth.TupleReal() / 4);
+                            break;
+                        //case RoiType.Ellipse:
+                        //    inputImageHSmartWindowControl.oRoi
+                        //        = new HEllipse(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2,0, hv_imageHeight.TupleReal() / 4, hv_imageWidth.TupleReal() / 4);
+                        //    break;
+                        //case RoiType.Segment:
+                        //    inputImageHSmartWindowControl.oRoi
+                        //        = new HSegment(0, 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                        //    break;
+                        case RoiType.None:
+                        default:
+                            inputImageHSmartWindowControl.oRoi = null;
+                            break;
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public override void cmbFixture_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+                else
+                    Subject.Params.Fixture = new Fixture();
+            }
+            catch { }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.resx b/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.resx
new file mode 100644
index 0000000..1526ea6
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/BlobTool/BlobToolEdit.resx
@@ -0,0 +1,129 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema 
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="lblMsgToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="TopToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>156, 17</value>
+  </metadata>
+  <metadata name="BtmStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>287, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineTool.cs b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineTool.cs
new file mode 100644
index 0000000..142d8f0
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineTool.cs
@@ -0,0 +1,817 @@
+锘縰sing HalconDotNet;
+using LB_VisionProcesses.Alogrithms.Halcon;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using OpenCvSharp;
+using Size = OpenCvSharp.Size;
+using Point = OpenCvSharp.Point;
+using static LB_VisionProcesses.Alogrithms.OpenCvSharp.FindLineTool;
+using System.Diagnostics;
+using LB_VisionControl;
+
+namespace LB_VisionProcesses.Alogrithms.OpenCvSharp
+{
+    public enum Transition { Positive, Negative, Ignore }
+
+    public enum Selector { First, Last, Best }
+    [Process("OpenCvSharp_鎵剧嚎宸ュ叿", Category = "OpenCvSharp宸ュ叿", Description = "鍒涘缓OpenCvSharp_鎵剧嚎宸ュ叿")]
+    public class FindLineTool : TAlgorithm
+    {
+        public FindLineTool()
+        {
+            strProcessClass = "LB_VisionProcesses.Alogrithms.OpenCvSharp.FindLineTool";
+            strProcessName = "OpenCvSharp_鎵剧嚎宸ュ叿";
+
+            Params.Inputs.Add("鍗″昂鏁伴噺", 6);
+            Params.Inputs.Add("鍗″昂闀垮害", 30);
+            Params.Inputs.Add("鍗″昂瀹藉害", 10);
+            Params.Inputs.Add("杩囨护涓�鍗婂儚绱�", 2);
+            Params.Inputs.Add("瀵规瘮搴﹂槇鍊�", 5);
+            Params.Inputs.Add("鏋佹��", "Ignore");
+            Params.Inputs.Add("杈圭紭浣嶇疆", "Best");
+            Params.Inputs.Add("蹇界暐鐐规暟", 0);
+
+            Params.Outputs.Add("X", new List<double>());
+            Params.Outputs.Add("Y", new List<double>());
+            Params.Outputs.Add("CenterX", 0.0);
+            Params.Outputs.Add("CenterY", 0.0);
+            Params.Outputs.Add("Phi", 0.0);
+            Params.Outputs.Add("Angle", 0.0);
+            Params.Outputs.Add("Count", 0);
+            Params.Outputs.Add("Segment", new HSegment());
+
+            Params.ROI = new HSegment(0, 0, 250, 250);
+        }
+
+        /// <summary>
+        /// 绠楀瓙閫昏緫
+        /// </summary>
+        public override void TAlgorithmMain()
+        {
+            #region 鍒濆鍖栧彉閲�
+            HObject ho_Regions, ho_LineXld;
+            HOperatorSet.GenEmptyObj(out ho_Regions);
+            HOperatorSet.GenEmptyObj(out ho_LineXld);
+            #endregion
+
+            try
+            {
+                if (InputImage == null)
+                {
+                    Msg = "杈撳叆鍥剧墖涓虹┖";
+                    Result = false;
+                    return;
+                }
+
+                #region 瑁佸壀鍖哄煙
+                object DomainImage = null;
+                if (!ReduceDomainImage(InputImage, ref DomainImage))
+                {
+                    Msg = "瑁佸壀鍖哄煙澶辫触";
+                    Result = false;
+                    return;
+                }
+
+                Mat hoDomainImage = DomainImage as Mat;
+                //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                try
+                {
+                    if (hoDomainImage.Channels() != 1)
+                        Cv2.CvtColor(hoDomainImage, hoDomainImage, ColorConversionCodes.RGB2GRAY);
+
+                    //杞崲鍚庡啀娆℃鏌ユ槸鍚︿负鐏板害鍥�
+                    if (hoDomainImage.Channels() != 1)
+                    {
+                        Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥�";
+                        Result = false;
+                        return;
+                    }
+                }
+                catch
+                {
+                    Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥句笖杞崲澶辫触";
+                    Result = false;
+                    return;
+                }
+                #endregion
+
+
+                #region 绠楀瓙閫昏緫
+                Record = new ObjectRecord();
+
+                int hv_Elements = Convert.ToInt16(Params.Inputs["鍗″昂鏁伴噺"]);
+                double hv_DetectHeight = Convert.ToDouble(Params.Inputs["鍗″昂闀垮害"]);
+                double hv_DetectWidth = Convert.ToDouble(Params.Inputs["鍗″昂瀹藉害"]);
+                int hv_Sigma = Convert.ToInt16(Params.Inputs["杩囨护涓�鍗婂儚绱�"]);
+                int hv_Threshold = Convert.ToInt16(Params.Inputs["瀵规瘮搴﹂槇鍊�"]);
+                int hv_IgnoreNum = Convert.ToInt16(Params.Inputs["蹇界暐鐐规暟"]);
+
+                Enum.TryParse(Params.Inputs["鏋佹��"]?.ToString(), out Transition transition);
+                string hv_Transition = "ignore";
+                switch (transition)
+                {
+                    case Transition.Positive:
+                        hv_Transition = "positive";
+                        break;
+                    case Transition.Negative:
+                        hv_Transition = "negative";
+                        break;
+                    case Transition.Ignore:
+                    default:
+                        hv_Transition = "ignore";
+                        break;
+                }
+                double hv_Row1 = Convert.ToDouble(((HSegment)Params.ROI).BeginRow + Params.Fixture.Row);
+                double hv_Column1 = Convert.ToDouble(((HSegment)Params.ROI).BeginColumn + Params.Fixture.Column);
+                double hv_Row2 = Convert.ToDouble(((HSegment)Params.ROI).EndRow + Params.Fixture.Row);
+                double hv_Column2 = Convert.ToDouble(((HSegment)Params.ROI).EndColumn + Params.Fixture.Column);
+
+                // 鎵ц妫�娴�
+                var lines = DetectEdgePoints(hoDomainImage, new Point(hv_Column1, hv_Row1), new Point(hv_Column2, hv_Row2));
+
+                if (lines.Count <= 0)
+                {
+                    Msg = "鎵剧嚎澶辫触";
+                    Result = false;
+                    return;
+                }
+                #endregion
+
+                #region 缁撴灉澶勭悊
+                List<double> X = new List<double>();
+                List<double> Y = new List<double>();
+                double CenterX = 0;
+                double CenterY = 0;
+                double Phi = 0;
+                HSegment HSegment = new HSegment();
+
+                var contourArray = lines.ToArray();
+                int count = contourArray.Length;
+
+                double[] Xpoints = new double[count];
+                double[] Ypoints = new double[count];
+
+                Parallel.For(0, count, j =>
+                {
+                    var point = contourArray[j];
+                    Xpoints[j] = Convert.ToDouble(point.X);
+                    Ypoints[j] = Convert.ToDouble(point.Y);
+                });
+
+                X.AddRange(Xpoints);
+                Y.AddRange(Ypoints);
+
+                var resultSegment = FitLineToPoints(lines);
+
+                pts_to_best_line(out ho_LineXld, new HTuple(Ypoints), new HTuple(Xpoints), hv_IgnoreNum
+                        , out HTuple hv_Row11, out HTuple hv_Column11, out HTuple hv_Row21, out HTuple hv_Column21);
+                ((ObjectRecord)Record).AddXld(ho_LineXld);
+                CenterX = (hv_Column11.D + hv_Column21.D) / 2;
+                CenterY = (hv_Row11.D + hv_Row21.D) / 2;
+                //璁$畻鐩寸嚎涓巟杞寸殑澶硅锛岄�嗘椂閽堟柟鍚戜负姝e悜
+                HOperatorSet.AngleLx(hv_Row11, hv_Column11, hv_Row21, hv_Column21, out HTuple hv_ATan);
+                Phi = hv_ATan;
+
+                if (X.Count >= 2)
+                    HSegment = new HSegment(hv_Column11.D, hv_Row11.D, hv_Column21.D, hv_Row21.D);
+
+                //HOperatorSet.GenRegionLine(out ho_LineXld, resultSegment.StartPoint.Y, resultSegment.StartPoint.X
+                //    , resultSegment.EndPoint.Y, resultSegment.EndPoint.X);
+                //((ObjectRecord)Record).AddXld(ho_LineXld);
+
+                //CenterX = (resultSegment.StartPoint.X + resultSegment.EndPoint.X) / 2;
+                //CenterY = (resultSegment.StartPoint.Y + resultSegment.EndPoint.Y) / 2;
+
+                //Phi = resultSegment.Angle / 180 * Math.PI;
+
+                //if (X.Count >= 2)
+                //    HSegment = new HSegment(resultSegment.StartPoint.X, resultSegment.StartPoint.Y
+                //        , resultSegment.EndPoint.X, resultSegment.EndPoint.Y);
+
+                Params.Outputs["X"] = X;
+                Params.Outputs["Y"] = Y;
+                Params.Outputs["CenterX"] = CenterX;
+                Params.Outputs["CenterY"] = CenterY;
+                Params.Outputs["Phi"] = Phi;
+                Params.Outputs["Angle"] = Phi * 180.0 / Math.PI;
+                Params.Outputs["Count"] = X.Count;
+                Params.Outputs["Segment"] = HSegment;
+                #endregion
+
+                #region 鐢熸垚OutputImage缁欏悗缁鐞�
+                try
+                {
+                    OutputImage = hoDomainImage;
+                }
+                catch (Exception ex)
+                {
+                    Msg = "鐢熸垚OutputImage澶辫触,鍘熷洜鏄�:" + ex.ToString();
+                    Result = false;
+                    return;
+                }
+                #endregion
+
+                if (Msg == "杩愯瓒呮椂")
+                {
+                    Result = false;
+                    return;
+                }
+
+                Msg = "杩愯鎴愬姛";
+                Result = true;
+                return;
+            }
+            catch (Exception ex)
+            {
+                Msg = "杩愯澶辫触,鍘熷洜鏄�:" + ex.ToString().TrimEnd();
+                OutputImage = null;
+                Result = false;
+                return;
+            }
+            finally
+            {
+                if (!Result)
+                {
+                    Params.Outputs.Add("X", new List<double>());
+                    Params.Outputs.Add("Y", new List<double>());
+                    Params.Outputs.Add("CenterX", 0.0);
+                    Params.Outputs.Add("CenterY", 0.0);
+                    Params.Outputs.Add("Phi", 0.0);
+                    Params.Outputs.Add("Angle", 0.0);
+                    Params.Outputs.Add("Count", 0);
+                    Params.Outputs.Add("Segment", new HSegment());
+                }
+
+                bCompleted = true;
+                #region 鍐呭瓨閲婃斁
+                ho_Regions.Dispose();
+                #endregion
+            }
+        }
+
+        /// <summary>
+        /// 鐩寸嚎娈垫暟鎹�
+        /// </summary>
+        public class LineSegment
+        {
+            public Point2f StartPoint { get; set; }
+            public Point2f EndPoint { get; set; }
+
+            public List<Point2f> EdgePoints { get; set; }
+
+            public float Vx { get; set; }  // 鏂瑰悜鍚戦噺X
+            public float Vy { get; set; }  // 鏂瑰悜鍚戦噺Y
+            public float Score { get; set; } // 鎷熷悎鍒嗘暟 0-100
+            public int RegionIndex { get; set; } // 鍖哄煙绱㈠紩
+
+            public double Length => Math.Sqrt(
+                Math.Pow(EndPoint.X - StartPoint.X, 2) +
+                Math.Pow(EndPoint.Y - StartPoint.Y, 2));
+
+            public double Angle => Math.Atan2(Vy, Vx) * 180 / Math.PI;
+
+            public LineSegment() { }
+
+            public LineSegment(Point2f start, Point2f end, float vx, float vy, List<Point2f> edgePoints)
+            {
+                StartPoint = start;
+                EndPoint = end;
+                Vx = vx;
+                Vy = vy;
+                EdgePoints = edgePoints;
+            }
+        }
+
+        /// <summary>
+        /// 杩囨护鏃犳晥鐐�
+        /// </summary>
+        private List<Point2f> FilterValidPoints(List<Point2f> points)
+        {
+            if (points == null) return new List<Point2f>();
+
+            return points.Where(p =>
+                !float.IsNaN(p.X) && !float.IsNaN(p.Y) &&
+                !float.IsInfinity(p.X) && !float.IsInfinity(p.Y) &&
+                p.X >= 0 && p.Y >= 0).ToList();
+        }
+
+        /// <summary>
+        /// 妫�娴嬭竟缂樼偣锛堜娇鐢ㄥ崱灏烘娴嬫柟寮忥級
+        /// </summary>
+        private List<Point2f> DetectEdgePoints(Mat regionImage, Point startPoint, Point endPoint)
+        {
+            var edgePoints = new List<Point2f>();
+
+            try
+            {
+                // 杞崲涓虹伆搴�
+                var gray = new Mat();
+                if (regionImage.Channels() != 1)
+                    Cv2.CvtColor(regionImage, gray, ColorConversionCodes.RGB2GRAY);
+                else
+                    gray = regionImage.Clone();
+
+                // 鑾峰彇鍙傛暟
+                int caliperCount = Params.Inputs.ContainsKey("鍗″昂鏁伴噺") ?
+                    Convert.ToInt32(Params.Inputs["鍗″昂鏁伴噺"]) : 6;
+                int caliperLength = Params.Inputs.ContainsKey("鍗″昂闀垮害") ?
+                    Convert.ToInt32(Params.Inputs["鍗″昂闀垮害"]) : 30;
+                int caliperWidth = Params.Inputs.ContainsKey("鍗″昂瀹藉害") ?
+                    Convert.ToInt32(Params.Inputs["鍗″昂瀹藉害"]) : 10;
+                int filterHalfPixels = Params.Inputs.ContainsKey("杩囨护涓�鍗婂儚绱�") ?
+                    Convert.ToInt32(Params.Inputs["杩囨护涓�鍗婂儚绱�"]) : 2;
+                int contrastThreshold = Params.Inputs.ContainsKey("瀵规瘮搴﹂槇鍊�") ?
+                    Convert.ToInt32(Params.Inputs["瀵规瘮搴﹂槇鍊�"]) : 5;
+                string polarity = Params.Inputs.ContainsKey("鏋佹��") ?
+                    Params.Inputs["鏋佹��"]?.ToString() : "Ignore";
+                string edgePosition = Params.Inputs.ContainsKey("杈圭紭浣嶇疆") ?
+                    Params.Inputs["杈圭紭浣嶇疆"]?.ToString() : "Best";
+
+                // 浣跨敤鍗″昂鏂瑰紡妫�娴嬭竟缂樼偣锛屼紶鍏ヨ捣濮嬬偣鍜岀粓鐐�
+                edgePoints = DetectEdgesAlongLineWithCaliper(
+                    gray,
+                    startPoint,
+                    endPoint,
+                    caliperCount,
+                    caliperLength,
+                    caliperWidth,
+                    contrastThreshold,
+                    polarity,
+                    edgePosition);
+
+                // 杩囨护鎺夋棤鏁堢殑鐐�
+                edgePoints = FilterValidPoints(edgePoints);
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"杈圭紭鐐规娴嬮敊璇�: {ex.Message}");
+            }
+
+            return edgePoints ?? new List<Point2f>();
+        }
+
+        /// <summary>
+        /// 娌挎寚瀹氱嚎娈典娇鐢ㄥ涓崱灏烘娴嬭竟缂樼偣
+        /// </summary>
+        private List<Point2f> DetectEdgesAlongLineWithCaliper(
+            Mat grayImage,
+            Point startPoint,
+            Point endPoint,
+            int caliperCount,
+            int caliperLength,
+            int caliperWidth,
+            int contrastThreshold,
+            string polarity,
+            string edgePosition)
+        {
+            var edgePoints = new List<Point2f>();
+
+            // 璁$畻涓荤嚎娈垫柟鍚�
+            double dx = endPoint.X - startPoint.X;
+            double dy = endPoint.Y - startPoint.Y;
+            double mainLength = Math.Sqrt(dx * dx + dy * dy);
+
+            if (mainLength < 1) return edgePoints;
+
+            // 涓荤嚎娈靛崟浣嶆柟鍚戝悜閲�
+            double mainUx = dx / mainLength;
+            double mainUy = dy / mainLength;
+
+            // 涓荤嚎娈靛瀭鐩存柟鍚戝悜閲忥紙鍗″昂鏂瑰悜锛�
+            double caliperUx = -mainUy;
+            double caliperUy = mainUx;
+
+            // 鍦ㄤ富绾挎涓婂潎鍖�鍒嗗竷鍗″昂
+            for (int i = 0; i < caliperCount; i++)
+            {
+                double t = (i + 1.0) / (caliperCount + 1); // 鍦�0-1涔嬮棿鍧囧寑鍒嗗竷
+                double centerX = startPoint.X + t * mainLength * mainUx;
+                double centerY = startPoint.Y + t * mainLength * mainUy;
+
+                // 璁$畻鍗″昂鐨勮捣鐐瑰拰缁堢偣锛堝瀭鐩翠簬涓荤嚎娈垫柟鍚戯級
+                Point caliperStart = new Point(
+                    (int)Math.Round(centerX - caliperLength / 2.0 * caliperUx),
+                    (int)Math.Round(centerY - caliperLength / 2.0 * caliperUy));
+
+                Point caliperEnd = new Point(
+                    (int)Math.Round(centerX + caliperLength / 2.0 * caliperUx),
+                    (int)Math.Round(centerY + caliperLength / 2.0 * caliperUy));
+
+                // 妫�娴嬪崟涓崱灏轰笂鐨勮竟缂樼偣
+                var edges = DetectEdgesAlongLine(
+                    grayImage,
+                    caliperStart.X, caliperStart.Y,
+                    caliperEnd.X, caliperEnd.Y,
+                    caliperWidth,
+                    contrastThreshold,
+                    polarity,
+                    edgePosition);
+                edgePoints.AddRange(edges);
+            }
+
+            return edgePoints;
+        }
+
+        /// <summary>
+        /// 娌跨洿绾挎娴嬭竟缂樼偣
+        /// </summary>
+        private List<Point2f> DetectEdgesAlongLine(
+            Mat grayImage,
+            int startX, int startY,
+            int endX, int endY,
+            int lineWidth,
+            int contrastThreshold,
+            string polarity, string edgePosition)
+        {
+            var edgePoints = new List<Point2f>();
+
+            // 璁$畻鐩寸嚎鏂瑰悜
+            double dx = endX - startX;
+            double dy = endY - startY;
+            double length = Math.Sqrt(dx * dx + dy * dy);
+
+            if (length == 0) return edgePoints;
+
+            // 鍗曚綅鏂瑰悜鍚戦噺
+            double ux = dx / length;
+            double uy = dy / length;
+
+            // 鍨傜洿鏂瑰悜鍚戦噺
+            double vx = -uy;
+            double vy = ux;
+
+            // 娌跨嚎閲囨牱
+            for (double t = 0; t <= length; t += 1.0)
+            {
+                double centerX = startX + t * ux;
+                double centerY = startY + t * uy;
+
+                // 鍦ㄥ瀭鐩存柟鍚戜笂杩涜閲囨牱
+                List<double> profile = new List<double>();
+                List<Point> profilePoints = new List<Point>();
+
+                for (int w = -lineWidth / 2; w <= lineWidth / 2; w++)
+                {
+                    int sampleX = (int)Math.Round(centerX + w * vx);
+                    int sampleY = (int)Math.Round(centerY + w * vy);
+
+                    if (sampleX >= 0 && sampleX < grayImage.Width &&
+                        sampleY >= 0 && sampleY < grayImage.Height)
+                    {
+                        byte pixelValue = grayImage.At<byte>(sampleY, sampleX);
+                        profile.Add(pixelValue);
+                        profilePoints.Add(new Point(sampleX, sampleY));
+                    }
+                }
+
+                if (profile.Count > 0)
+                {
+                    // 鍒嗘瀽鐏板害鍓栭潰锛屾娴嬭竟缂�
+                    if (Enum.TryParse(polarity, out Transition transition))
+                    {
+                        var edgeCandidates = FindEdgesInProfile(profile, profilePoints, contrastThreshold, transition, edgePosition);
+                        edgePoints.AddRange(edgeCandidates);
+                    }
+                    else
+                    {
+                        var edgeCandidates = FindEdgesInProfile(profile, profilePoints, contrastThreshold, Transition.Ignore, edgePosition);
+                        edgePoints.AddRange(edgeCandidates);
+                    }
+                }
+            }
+
+            return edgePoints;
+        }
+
+        /// <summary>
+        /// 鍦ㄧ伆搴﹀墫闈腑鏌ユ壘杈圭紭鐐�
+        /// </summary>
+        private List<Point2f> FindEdgesInProfile(
+            List<double> profile,
+            List<Point> profilePoints,
+            int contrastThreshold,
+            Transition polarity, string edgePosition)
+        {
+            var edges = new List<Point2f>();
+
+            if (profile.Count < 3) return edges;
+
+            // 璁$畻姊害
+            List<double> gradients = new List<double>();
+            for (int i = 1; i < profile.Count - 1; i++)
+            {
+                double gradient = (profile[i + 1] - profile[i - 1]) / 2.0;
+                gradients.Add(gradient);
+            }
+
+            // 鏍规嵁鏋佹�ц繃婊よ竟缂�
+            var edgeCandidates = new List<(int index, double strength)>();
+
+            for (int i = 0; i < gradients.Count; i++)
+            {
+                double gradient = gradients[i];
+                bool isEdge = false;
+
+                if (polarity == Transition.Positive && gradient > contrastThreshold)
+                {
+                    isEdge = true; // 浠庢殫鍒颁寒鐨勮竟缂�
+                }
+                else if (polarity == Transition.Negative && gradient < -contrastThreshold)
+                {
+                    isEdge = true; // 浠庝寒鍒版殫鐨勮竟缂�
+                }
+                else if (polarity == Transition.Ignore && Math.Abs(gradient) > contrastThreshold)
+                {
+                    isEdge = true; // 蹇界暐鏋佹�э紝鍙叧娉ㄥ姣斿害
+                }
+
+                if (isEdge)
+                {
+                    edgeCandidates.Add((i + 1, Math.Abs(gradient)));
+                }
+            }
+
+            // 鏍规嵁杈圭紭浣嶇疆鍙傛暟閫夋嫨杈圭紭鐐�
+            if (edgeCandidates.Count > 0)
+            {
+                if (Enum.TryParse(edgePosition, out Selector selector))
+                {
+                    var selectedEdge = SelectEdgeByPosition(edgeCandidates, profile, selector);
+                    if (selectedEdge.index >= 0)
+                    {
+                        Point2f edgePoint = RefineEdgePosition(profile, profilePoints, selectedEdge.index);
+                        edges.Add(edgePoint);
+                    }
+                }
+                else
+                {
+                    var selectedEdge = SelectEdgeByPosition(edgeCandidates, profile, Selector.Best);
+                    if (selectedEdge.index >= 0)
+                    {
+                        Point2f edgePoint = RefineEdgePosition(profile, profilePoints, selectedEdge.index);
+                        edges.Add(edgePoint);
+                    }
+                }
+            }
+
+            return edges;
+        }
+
+        /// <summary>
+        /// 鏍规嵁杈圭紭浣嶇疆鍙傛暟閫夋嫨杈圭紭鐐�
+        /// </summary>
+        private (int index, double strength) SelectEdgeByPosition(
+            List<(int index, double strength)> edgeCandidates,
+            List<double> profile,
+            Selector edgePosition)
+        {
+            if (edgeCandidates.Count == 0) return (-1, 0);
+
+            switch (edgePosition)
+            {
+                case Selector.Best: // 鏈�寮鸿竟缂�
+                    return edgeCandidates.OrderByDescending(e => e.strength).First();
+
+                case Selector.First: // 绗竴涓竟缂�
+                    return edgeCandidates.OrderBy(e => e.index).First();
+
+                case Selector.Last: // 鏈�鍚庝竴涓竟缂�
+                    return edgeCandidates.OrderByDescending(e => e.index).First();
+
+                default: // 榛樿浣跨敤鏈�寮鸿竟缂�
+                    return edgeCandidates.OrderByDescending(e => e.strength).First();
+            }
+        }
+
+        /// <summary>
+        /// 浜氬儚绱犵簿搴﹁竟缂樺畾浣�
+        /// </summary>
+        private Point2f RefineEdgePosition(List<double> profile, List<Point> profilePoints, int edgeIndex)
+        {
+            if (edgeIndex <= 0 || edgeIndex >= profile.Count - 1)
+                return new Point2f(profilePoints[edgeIndex].X, profilePoints[edgeIndex].Y);
+
+            // 绠�鍗曠殑浜屾鎻掑��
+            double y0 = profile[edgeIndex - 1];
+            double y1 = profile[edgeIndex];
+            double y2 = profile[edgeIndex + 1];
+
+            // 璁$畻浜氬儚绱犲亸绉�
+            double offset = (y0 - y2) / (2 * (y0 - 2 * y1 + y2));
+
+            // 绾挎�ф彃鍊艰绠椾簹鍍忕礌浣嶇疆
+            Point p0 = profilePoints[edgeIndex - 1];
+            Point p1 = profilePoints[edgeIndex];
+            Point p2 = profilePoints[edgeIndex + 1];
+
+            double subPixelX = p1.X + offset * (p2.X - p0.X) / 2.0;
+            double subPixelY = p1.Y + offset * (p2.Y - p0.Y) / 2.0;
+
+            return new Point2f((float)subPixelX, (float)subPixelY);
+        }
+
+
+        /// <summary>
+        /// 鎷熷悎鐩寸嚎
+        /// </summary>
+        private LineSegment FitLineToPoints(List<Point2f> points, float LineExtension = 5.0f)
+        {
+            if (points.Count < 2) return null;
+
+            try
+            {
+                // 浣跨敤OpenCV鐨凢itLine
+                var lineOutput = new Mat();
+                using (var pointsArray = InputArray.Create(points))
+                {
+                    Cv2.FitLine(pointsArray, lineOutput, DistanceTypes.L2, 0, 0.01, 0.01);
+                }
+
+                // 瑙f瀽鎷熷悎缁撴灉: [vx, vy, x0, y0]
+                float vx = lineOutput.At<float>(0);
+                float vy = lineOutput.At<float>(1);
+                float x0 = lineOutput.At<float>(2);
+                float y0 = lineOutput.At<float>(3);
+
+                // 妫�鏌ユ嫙鍚堢粨鏋滄槸鍚︽湁鏁�
+                if (float.IsNaN(vx) || float.IsNaN(vy) || float.IsNaN(x0) || float.IsNaN(y0) ||
+                    float.IsInfinity(vx) || float.IsInfinity(vy) || float.IsInfinity(x0) || float.IsInfinity(y0))
+                {
+                    Debug.WriteLine("鐩寸嚎鎷熷悎缁撴灉鍖呭惈NaN鎴朓nfinity鍊�");
+                    return FitLineFallback(points, LineExtension);
+                }
+
+                // 妫�鏌ユ柟鍚戝悜閲忔槸鍚︿负闆跺悜閲�
+                float dirLength = (float)Math.Sqrt(vx * vx + vy * vy);
+                if (dirLength < 1e-6f)
+                {
+                    Debug.WriteLine("鏂瑰悜鍚戦噺闀垮害鎺ヨ繎闆讹紝浣跨敤澶囩敤鏂规硶");
+                    return FitLineFallback(points, LineExtension);
+                }
+
+                // 褰掍竴鍖栨柟鍚戝悜閲�
+                vx /= dirLength;
+                vy /= dirLength;
+
+                // 璁$畻鐩寸嚎鐨勮捣鐐瑰拰缁堢偣锛堝熀浜庣偣闆嗙殑鑼冨洿锛�
+                float minT = float.MaxValue;
+                float maxT = float.MinValue;
+
+                foreach (var point in points)
+                {
+                    float t = (point.X - x0) * vx + (point.Y - y0) * vy;
+                    if (float.IsNaN(t) || float.IsInfinity(t))
+                        continue;
+
+                    minT = Math.Min(minT, t);
+                    maxT = Math.Max(maxT, t);
+                }
+
+                // 妫�鏌ュ弬鏁拌寖鍥存槸鍚︽湁鏁�
+                if (minT > maxT || float.IsNaN(minT) || float.IsNaN(maxT) ||
+                    float.IsInfinity(minT) || float.IsInfinity(maxT))
+                {
+                    Debug.WriteLine("鍙傛暟鑼冨洿鏃犳晥锛屼娇鐢ㄥ鐢ㄦ柟娉�");
+                    return FitLineFallback(points, LineExtension);
+                }
+
+                // 鎵╁睍绾挎
+                minT -= LineExtension;
+                maxT += LineExtension;
+
+                var startPoint = new Point2f(x0 + minT * vx, y0 + minT * vy);
+                var endPoint = new Point2f(x0 + maxT * vx, y0 + maxT * vy);
+
+                // 妫�鏌ユ渶缁堝潗鏍囨槸鍚︽湁鏁�
+                if (float.IsNaN(startPoint.X) || float.IsNaN(startPoint.Y) ||
+                    float.IsNaN(endPoint.X) || float.IsNaN(endPoint.Y))
+                {
+                    Debug.WriteLine("鏈�缁堝潗鏍囧寘鍚玁aN锛屼娇鐢ㄥ鐢ㄦ柟娉�");
+                    return FitLineFallback(points, LineExtension);
+                }
+
+                return new LineSegment(startPoint, endPoint, vx, vy, points);
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"鐩寸嚎鎷熷悎閿欒: {ex.Message}锛屼娇鐢ㄥ鐢ㄦ柟娉�");
+                return FitLineFallback(points, LineExtension);
+            }
+        }
+
+        /// <summary>
+        /// 澶囩敤鐩寸嚎鎷熷悎鏂规硶锛堟渶灏忎簩涔樻硶锛�
+        /// </summary>
+        private LineSegment FitLineFallback(List<Point2f> points, float LineExtension = 5.0f)
+        {
+            if (points.Count < 2) return null;
+
+            try
+            {
+                // 璁$畻鐐圭殑鍧囧��
+                float meanX = points.Average(p => p.X);
+                float meanY = points.Average(p => p.Y);
+
+                // 璁$畻鏂瑰樊鍜屽崗鏂瑰樊
+                float varX = 0, varY = 0, covXY = 0;
+                foreach (var point in points)
+                {
+                    float dx = point.X - meanX;
+                    float dy = point.Y - meanY;
+                    varX += dx * dx;
+                    varY += dy * dy;
+                    covXY += dx * dy;
+                }
+
+                // 妫�鏌ユ暟鎹槸鍚︽湁鏁�
+                if (varX < 1e-6f && varY < 1e-6f)
+                {
+                    // 鎵�鏈夌偣鍑犱箮閲嶅悎锛屽垱寤烘按骞崇嚎
+                    float minX = points.Min(p => p.X);
+                    float maxX = points.Max(p => p.X);
+                    float centerY = points.Average(p => p.Y);
+
+                    return new LineSegment(new Point2f(minX - LineExtension, centerY)
+                        , new Point2f(maxX + LineExtension, centerY), 1, 0, points);
+                }
+
+                // 璁$畻涓绘柟鍚�
+                float angle;
+                if (varX > varY)
+                {
+                    // 涓昏娌縓杞存柟鍚�
+                    angle = 0;
+                }
+                else
+                {
+                    // 涓昏娌縔杞存柟鍚�
+                    angle = (float)(Math.PI / 2);
+                }
+
+                // 璁$畻鏂瑰悜鍚戦噺
+                float vx = (float)Math.Cos(angle);
+                float vy = (float)Math.Sin(angle);
+
+                // 璁$畻鐐瑰湪涓绘柟鍚戜笂鐨勬姇褰辫寖鍥�
+                float minT = float.MaxValue;
+                float maxT = float.MinValue;
+
+                foreach (var point in points)
+                {
+                    float t = (point.X - meanX) * vx + (point.Y - meanY) * vy;
+                    minT = Math.Min(minT, t);
+                    maxT = Math.Max(maxT, t);
+                }
+
+                // 鎵╁睍绾挎
+                minT -= LineExtension;
+                maxT += LineExtension;
+
+                var startPoint = new Point2f(meanX + minT * vx, meanY + minT * vy);
+                var endPoint = new Point2f(meanX + maxT * vx, meanY + maxT * vy);
+
+                return new LineSegment(startPoint, endPoint, vx, vy, points);
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"澶囩敤鐩寸嚎鎷熷悎涔熷け璐�: {ex.Message}");
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 鏁版嵁棰勫鐞嗭紝绉婚櫎寮傚父鐐�
+        /// </summary>
+        private List<Point2f> PreprocessPoints(List<Point2f> points)
+        {
+            if (points.Count < 3) return points;
+
+            // 璁$畻鐐圭殑涓績
+            float meanX = points.Average(p => p.X);
+            float meanY = points.Average(p => p.Y);
+
+            // 璁$畻璺濈涓績鐨勫钩鍧囪窛绂诲拰鏍囧噯宸�
+            var distances = points.Select(p =>
+                Math.Sqrt(Math.Pow(p.X - meanX, 2) + Math.Pow(p.Y - meanY, 2))).ToList();
+
+            double meanDistance = distances.Average();
+            double stdDistance = Math.Sqrt(distances.Average(d => Math.Pow(d - meanDistance, 2)));
+
+            // 绉婚櫎璺濈涓績杩囪繙鐨勫紓甯哥偣锛堣秴杩�3鍊嶆爣鍑嗗樊锛�
+            var filteredPoints = points.Where((p, i) =>
+                distances[i] <= meanDistance + 3 * stdDistance).ToList();
+
+            if (filteredPoints.Count < 2)
+            {
+                // 濡傛灉杩囨护鍚庣偣鏁板お灏戯紝杩斿洖鍘熷鐐归泦
+                return points;
+            }
+
+            Debug.WriteLine($"杩囨护浜� {points.Count - filteredPoints.Count} 涓紓甯哥偣");
+            return filteredPoints;
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.Designer.cs b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.Designer.cs
new file mode 100644
index 0000000..e8f6cad
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.Designer.cs
@@ -0,0 +1,860 @@
+锘縰sing LB_VisionProcesses.Alogrithms;
+
+namespace LB_VisionProcesses.Alogrithms.OpenCvSharp
+{
+    partial class FindLineToolEdit
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tablePanelParas = new TableLayoutPanel();
+            label1 = new Label();
+            itxtCaliperCount = new TextBox();
+            label2 = new Label();
+            dtxtCaliperHeight = new TextBox();
+            label3 = new Label();
+            dtxtCaliperWidth = new TextBox();
+            label4 = new Label();
+            itxtSigma = new TextBox();
+            label10 = new Label();
+            itxtThreshold = new TextBox();
+            label11 = new Label();
+            itxtIgnoreCount = new TextBox();
+            label12 = new Label();
+            label13 = new Label();
+            cmbTransition = new ComboBox();
+            cmbSelect = new ComboBox();
+            pnlInputImage = new Panel();
+            TopToolStrip = new ToolStrip();
+            btnRun = new ToolStripButton();
+            btnLoadImage = new ToolStripButton();
+            btnSaveParas = new ToolStripButton();
+            btnLoadParas = new ToolStripButton();
+            BtmStatusStrip = new StatusStrip();
+            lblResult = new ToolStripStatusLabel();
+            lblMsg = new ToolStripStatusLabel();
+            lblRunTime = new ToolStripStatusLabel();
+            MainTableLayoutPanel = new TableLayoutPanel();
+            parasTabControl = new TabControl();
+            tabPage1 = new TabPage();
+            tabPage5 = new TabPage();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            cmbTypeRoi = new ComboBox();
+            label21 = new Label();
+            label22 = new Label();
+            cmbFixture = new ComboBox();
+            ckbDrawRoi = new CheckBox();
+            tabPage2 = new TabPage();
+            tableLayoutResults = new TableLayoutPanel();
+            dtxtHeight = new TextBox();
+            label9 = new Label();
+            label5 = new Label();
+            label6 = new Label();
+            label7 = new Label();
+            label8 = new Label();
+            dtxtCenterX = new TextBox();
+            dtxtCenterY = new TextBox();
+            dtxtAngle = new TextBox();
+            dtxtWidth = new TextBox();
+            label18 = new Label();
+            dtxtCount = new TextBox();
+            imgTabControl = new TabControl();
+            tabPageInputImage = new TabPage();
+            tabPageRecordImage = new TabPage();
+            pnlRecordImage = new Panel();
+            btnShowROI = new Button();
+            tablePanelParas.SuspendLayout();
+            TopToolStrip.SuspendLayout();
+            BtmStatusStrip.SuspendLayout();
+            MainTableLayoutPanel.SuspendLayout();
+            parasTabControl.SuspendLayout();
+            tabPage1.SuspendLayout();
+            tabPage5.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tabPage2.SuspendLayout();
+            tableLayoutResults.SuspendLayout();
+            imgTabControl.SuspendLayout();
+            tabPageInputImage.SuspendLayout();
+            tabPageRecordImage.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tablePanelParas
+            // 
+            tablePanelParas.ColumnCount = 4;
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 90F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.Controls.Add(label1, 0, 0);
+            tablePanelParas.Controls.Add(itxtCaliperCount, 1, 0);
+            tablePanelParas.Controls.Add(label2, 2, 0);
+            tablePanelParas.Controls.Add(dtxtCaliperHeight, 3, 0);
+            tablePanelParas.Controls.Add(label3, 0, 1);
+            tablePanelParas.Controls.Add(dtxtCaliperWidth, 1, 1);
+            tablePanelParas.Controls.Add(label4, 2, 1);
+            tablePanelParas.Controls.Add(itxtSigma, 3, 1);
+            tablePanelParas.Controls.Add(label10, 0, 2);
+            tablePanelParas.Controls.Add(itxtThreshold, 1, 2);
+            tablePanelParas.Controls.Add(label11, 2, 2);
+            tablePanelParas.Controls.Add(itxtIgnoreCount, 3, 2);
+            tablePanelParas.Controls.Add(label12, 0, 3);
+            tablePanelParas.Controls.Add(label13, 2, 3);
+            tablePanelParas.Controls.Add(cmbTransition, 1, 3);
+            tablePanelParas.Controls.Add(cmbSelect, 3, 3);
+            tablePanelParas.Controls.Add(btnShowROI, 0, 4);
+            tablePanelParas.Dock = DockStyle.Fill;
+            tablePanelParas.Location = new Point(3, 3);
+            tablePanelParas.Margin = new Padding(2, 3, 2, 3);
+            tablePanelParas.Name = "tablePanelParas";
+            tablePanelParas.RowCount = 10;
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10.000001F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tablePanelParas.Size = new Size(397, 510);
+            tablePanelParas.TabIndex = 0;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Location = new Point(2, 0);
+            label1.Margin = new Padding(2, 0, 2, 0);
+            label1.MaximumSize = new Size(0, 28);
+            label1.MinimumSize = new Size(0, 28);
+            label1.Name = "label1";
+            label1.Size = new Size(56, 28);
+            label1.TabIndex = 0;
+            label1.Text = "鍗″昂鏁伴噺";
+            label1.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // itxtCaliperCount
+            // 
+            itxtCaliperCount.Location = new Point(92, 3);
+            itxtCaliperCount.Margin = new Padding(2, 3, 2, 3);
+            itxtCaliperCount.Name = "itxtCaliperCount";
+            itxtCaliperCount.Size = new Size(98, 23);
+            itxtCaliperCount.TabIndex = 5;
+            itxtCaliperCount.Text = "6";
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.Location = new Point(200, 0);
+            label2.Margin = new Padding(2, 0, 2, 0);
+            label2.MaximumSize = new Size(0, 28);
+            label2.MinimumSize = new Size(0, 28);
+            label2.Name = "label2";
+            label2.Size = new Size(56, 28);
+            label2.TabIndex = 1;
+            label2.Text = "鍗″昂闀垮害";
+            label2.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtCaliperHeight
+            // 
+            dtxtCaliperHeight.Location = new Point(290, 3);
+            dtxtCaliperHeight.Margin = new Padding(2, 3, 2, 3);
+            dtxtCaliperHeight.Name = "dtxtCaliperHeight";
+            dtxtCaliperHeight.Size = new Size(98, 23);
+            dtxtCaliperHeight.TabIndex = 6;
+            dtxtCaliperHeight.Text = "30";
+            // 
+            // label3
+            // 
+            label3.AutoSize = true;
+            label3.Location = new Point(2, 51);
+            label3.Margin = new Padding(2, 0, 2, 0);
+            label3.MaximumSize = new Size(0, 28);
+            label3.MinimumSize = new Size(0, 28);
+            label3.Name = "label3";
+            label3.Size = new Size(56, 28);
+            label3.TabIndex = 2;
+            label3.Text = "鍗″昂瀹藉害";
+            label3.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // dtxtCaliperWidth
+            // 
+            dtxtCaliperWidth.Location = new Point(92, 54);
+            dtxtCaliperWidth.Margin = new Padding(2, 3, 2, 3);
+            dtxtCaliperWidth.Name = "dtxtCaliperWidth";
+            dtxtCaliperWidth.Size = new Size(98, 23);
+            dtxtCaliperWidth.TabIndex = 7;
+            dtxtCaliperWidth.Text = "10";
+            // 
+            // label4
+            // 
+            label4.AutoSize = true;
+            label4.Location = new Point(200, 51);
+            label4.Margin = new Padding(2, 0, 2, 0);
+            label4.MaximumSize = new Size(0, 28);
+            label4.MinimumSize = new Size(0, 28);
+            label4.Name = "label4";
+            label4.Size = new Size(80, 28);
+            label4.TabIndex = 3;
+            label4.Text = "杩囨护涓�鍗婂儚绱�";
+            label4.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // itxtSigma
+            // 
+            itxtSigma.Location = new Point(290, 54);
+            itxtSigma.Margin = new Padding(2, 3, 2, 3);
+            itxtSigma.Name = "itxtSigma";
+            itxtSigma.Size = new Size(98, 23);
+            itxtSigma.TabIndex = 8;
+            itxtSigma.Text = "0";
+            // 
+            // label10
+            // 
+            label10.AutoSize = true;
+            label10.Location = new Point(2, 102);
+            label10.Margin = new Padding(2, 0, 2, 0);
+            label10.MaximumSize = new Size(0, 28);
+            label10.MinimumSize = new Size(0, 28);
+            label10.Name = "label10";
+            label10.Size = new Size(68, 28);
+            label10.TabIndex = 9;
+            label10.Text = "瀵规瘮搴﹂槇鍊�";
+            label10.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // itxtThreshold
+            // 
+            itxtThreshold.Location = new Point(92, 105);
+            itxtThreshold.Margin = new Padding(2, 3, 2, 3);
+            itxtThreshold.Name = "itxtThreshold";
+            itxtThreshold.Size = new Size(98, 23);
+            itxtThreshold.TabIndex = 9;
+            itxtThreshold.Text = "0";
+            // 
+            // label11
+            // 
+            label11.AutoSize = true;
+            label11.Location = new Point(200, 102);
+            label11.Margin = new Padding(2, 0, 2, 0);
+            label11.MaximumSize = new Size(0, 28);
+            label11.MinimumSize = new Size(0, 28);
+            label11.Name = "label11";
+            label11.Size = new Size(56, 28);
+            label11.TabIndex = 10;
+            label11.Text = "蹇界暐鐐规暟";
+            label11.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // itxtIgnoreCount
+            // 
+            itxtIgnoreCount.Location = new Point(290, 105);
+            itxtIgnoreCount.Margin = new Padding(2, 3, 2, 3);
+            itxtIgnoreCount.Name = "itxtIgnoreCount";
+            itxtIgnoreCount.Size = new Size(98, 23);
+            itxtIgnoreCount.TabIndex = 9;
+            itxtIgnoreCount.Text = "0";
+            // 
+            // label12
+            // 
+            label12.AutoSize = true;
+            label12.Location = new Point(2, 153);
+            label12.Margin = new Padding(2, 0, 2, 0);
+            label12.MaximumSize = new Size(0, 28);
+            label12.MinimumSize = new Size(0, 28);
+            label12.Name = "label12";
+            label12.Size = new Size(32, 28);
+            label12.TabIndex = 11;
+            label12.Text = "鏋佹��";
+            label12.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label13
+            // 
+            label13.AutoSize = true;
+            label13.Location = new Point(200, 153);
+            label13.Margin = new Padding(2, 0, 2, 0);
+            label13.MaximumSize = new Size(0, 28);
+            label13.MinimumSize = new Size(0, 28);
+            label13.Name = "label13";
+            label13.Size = new Size(56, 28);
+            label13.TabIndex = 12;
+            label13.Text = "杈圭紭浣嶇疆";
+            label13.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbTransition
+            // 
+            cmbTransition.FormattingEnabled = true;
+            cmbTransition.Location = new Point(93, 156);
+            cmbTransition.Name = "cmbTransition";
+            cmbTransition.Size = new Size(102, 25);
+            cmbTransition.TabIndex = 13;
+            // 
+            // cmbSelect
+            // 
+            cmbSelect.FormattingEnabled = true;
+            cmbSelect.Location = new Point(291, 156);
+            cmbSelect.Name = "cmbSelect";
+            cmbSelect.Size = new Size(103, 25);
+            cmbSelect.TabIndex = 14;
+            // 
+            // pnlInputImage
+            // 
+            pnlInputImage.Dock = DockStyle.Fill;
+            pnlInputImage.Location = new Point(3, 3);
+            pnlInputImage.Margin = new Padding(4);
+            pnlInputImage.Name = "pnlInputImage";
+            pnlInputImage.Size = new Size(607, 510);
+            pnlInputImage.TabIndex = 44;
+            // 
+            // TopToolStrip
+            // 
+            TopToolStrip.Items.AddRange(new ToolStripItem[] { btnRun, btnLoadImage, btnSaveParas, btnLoadParas });
+            TopToolStrip.Location = new Point(0, 0);
+            TopToolStrip.Name = "TopToolStrip";
+            TopToolStrip.Size = new Size(1044, 25);
+            TopToolStrip.TabIndex = 45;
+            TopToolStrip.Text = "toolStrip1";
+            // 
+            // btnRun
+            // 
+            btnRun.BackgroundImageLayout = ImageLayout.Zoom;
+            btnRun.ImageTransparentColor = Color.Magenta;
+            btnRun.Name = "btnRun";
+            btnRun.Size = new Size(36, 22);
+            btnRun.Text = "杩愯";
+            btnRun.Click += btnRun_Click;
+            // 
+            // btnLoadImage
+            // 
+            btnLoadImage.ImageTransparentColor = Color.Magenta;
+            btnLoadImage.Name = "btnLoadImage";
+            btnLoadImage.Size = new Size(36, 22);
+            btnLoadImage.Text = "瀵煎浘";
+            btnLoadImage.Click += btnLoadImage_Click;
+            // 
+            // btnSaveParas
+            // 
+            btnSaveParas.ImageTransparentColor = Color.Magenta;
+            btnSaveParas.Name = "btnSaveParas";
+            btnSaveParas.Size = new Size(36, 22);
+            btnSaveParas.Text = "淇濆瓨";
+            btnSaveParas.Click += btnSaveParas_Click;
+            // 
+            // btnLoadParas
+            // 
+            btnLoadParas.ImageTransparentColor = Color.Magenta;
+            btnLoadParas.Name = "btnLoadParas";
+            btnLoadParas.Size = new Size(36, 22);
+            btnLoadParas.Text = "鍔犺浇";
+            btnLoadParas.Click += btnLoadParas_Click;
+            // 
+            // BtmStatusStrip
+            // 
+            BtmStatusStrip.Items.AddRange(new ToolStripItem[] { lblResult, lblMsg, lblRunTime });
+            BtmStatusStrip.Location = new Point(0, 577);
+            BtmStatusStrip.Name = "BtmStatusStrip";
+            BtmStatusStrip.Size = new Size(1044, 22);
+            BtmStatusStrip.TabIndex = 46;
+            BtmStatusStrip.Text = "statusStrip1";
+            // 
+            // lblResult
+            // 
+            lblResult.Name = "lblResult";
+            lblResult.Size = new Size(34, 17);
+            lblResult.Text = "True";
+            // 
+            // lblMsg
+            // 
+            lblMsg.Name = "lblMsg";
+            lblMsg.Size = new Size(56, 17);
+            lblMsg.Text = "杩愯鎴愬姛";
+            // 
+            // lblRunTime
+            // 
+            lblRunTime.Name = "lblRunTime";
+            lblRunTime.Size = new Size(32, 17);
+            lblRunTime.Text = "0ms";
+            // 
+            // MainTableLayoutPanel
+            // 
+            MainTableLayoutPanel.ColumnCount = 2;
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F));
+            MainTableLayoutPanel.Controls.Add(parasTabControl, 0, 0);
+            MainTableLayoutPanel.Controls.Add(imgTabControl, 1, 0);
+            MainTableLayoutPanel.Dock = DockStyle.Fill;
+            MainTableLayoutPanel.Location = new Point(0, 25);
+            MainTableLayoutPanel.Name = "MainTableLayoutPanel";
+            MainTableLayoutPanel.RowCount = 1;
+            MainTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            MainTableLayoutPanel.Size = new Size(1044, 552);
+            MainTableLayoutPanel.TabIndex = 47;
+            // 
+            // parasTabControl
+            // 
+            parasTabControl.Controls.Add(tabPage1);
+            parasTabControl.Controls.Add(tabPage5);
+            parasTabControl.Controls.Add(tabPage2);
+            parasTabControl.Dock = DockStyle.Fill;
+            parasTabControl.Location = new Point(3, 3);
+            parasTabControl.Name = "parasTabControl";
+            parasTabControl.SelectedIndex = 0;
+            parasTabControl.Size = new Size(411, 546);
+            parasTabControl.TabIndex = 48;
+            // 
+            // tabPage1
+            // 
+            tabPage1.Controls.Add(tablePanelParas);
+            tabPage1.Location = new Point(4, 26);
+            tabPage1.Name = "tabPage1";
+            tabPage1.Padding = new Padding(3);
+            tabPage1.Size = new Size(403, 516);
+            tabPage1.TabIndex = 0;
+            tabPage1.Text = "杈撳叆鍙傛暟";
+            tabPage1.UseVisualStyleBackColor = true;
+            // 
+            // tabPage5
+            // 
+            tabPage5.Controls.Add(tableLayoutPanel2);
+            tabPage5.Location = new Point(4, 26);
+            tabPage5.Name = "tabPage5";
+            tabPage5.Size = new Size(403, 516);
+            tabPage5.TabIndex = 2;
+            tabPage5.Text = "杩愯鍙傛暟";
+            tabPage5.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 4;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 60F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 150F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(cmbTypeRoi, 1, 0);
+            tableLayoutPanel2.Controls.Add(label21, 0, 0);
+            tableLayoutPanel2.Controls.Add(label22, 0, 1);
+            tableLayoutPanel2.Controls.Add(cmbFixture, 1, 1);
+            tableLayoutPanel2.Controls.Add(ckbDrawRoi, 2, 0);
+            tableLayoutPanel2.Location = new Point(3, 3);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 8;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(323, 309);
+            tableLayoutPanel2.TabIndex = 4;
+            // 
+            // cmbTypeRoi
+            // 
+            cmbTypeRoi.Enabled = false;
+            cmbTypeRoi.FormattingEnabled = true;
+            cmbTypeRoi.Location = new Point(63, 3);
+            cmbTypeRoi.Name = "cmbTypeRoi";
+            cmbTypeRoi.Size = new Size(121, 25);
+            cmbTypeRoi.TabIndex = 1;
+            cmbTypeRoi.SelectedIndexChanged += cmbTypeRoi_SelectedIndexChanged;
+            // 
+            // label21
+            // 
+            label21.AutoSize = true;
+            label21.Dock = DockStyle.Fill;
+            label21.Location = new Point(3, 0);
+            label21.Name = "label21";
+            label21.Size = new Size(54, 30);
+            label21.TabIndex = 3;
+            label21.Text = "ROI";
+            label21.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label22
+            // 
+            label22.AutoSize = true;
+            label22.Dock = DockStyle.Fill;
+            label22.Location = new Point(3, 30);
+            label22.Name = "label22";
+            label22.Size = new Size(54, 30);
+            label22.TabIndex = 4;
+            label22.Text = "Fixture";
+            label22.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbFixture
+            // 
+            cmbFixture.FormattingEnabled = true;
+            cmbFixture.Location = new Point(63, 33);
+            cmbFixture.Name = "cmbFixture";
+            cmbFixture.Size = new Size(121, 25);
+            cmbFixture.TabIndex = 5;
+            cmbFixture.SelectedIndexChanged += cmbFixture_SelectedIndexChanged;
+            // 
+            // ckbDrawRoi
+            // 
+            ckbDrawRoi.AutoSize = true;
+            ckbDrawRoi.CheckAlign = ContentAlignment.MiddleCenter;
+            ckbDrawRoi.Location = new Point(213, 3);
+            ckbDrawRoi.Name = "ckbDrawRoi";
+            ckbDrawRoi.Size = new Size(14, 14);
+            ckbDrawRoi.TabIndex = 2;
+            ckbDrawRoi.UseVisualStyleBackColor = true;
+            ckbDrawRoi.CheckedChanged += ckbDrawRoi_CheckedChanged;
+            // 
+            // tabPage2
+            // 
+            tabPage2.Controls.Add(tableLayoutResults);
+            tabPage2.Location = new Point(4, 26);
+            tabPage2.Name = "tabPage2";
+            tabPage2.Padding = new Padding(3);
+            tabPage2.Size = new Size(403, 516);
+            tabPage2.TabIndex = 1;
+            tabPage2.Text = "杈撳嚭缁撴灉";
+            tabPage2.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutResults
+            // 
+            tableLayoutResults.ColumnCount = 2;
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutResults.Controls.Add(dtxtHeight, 1, 4);
+            tableLayoutResults.Controls.Add(label9, 0, 4);
+            tableLayoutResults.Controls.Add(label5, 0, 0);
+            tableLayoutResults.Controls.Add(label6, 0, 1);
+            tableLayoutResults.Controls.Add(label7, 0, 2);
+            tableLayoutResults.Controls.Add(label8, 0, 3);
+            tableLayoutResults.Controls.Add(dtxtCenterX, 1, 0);
+            tableLayoutResults.Controls.Add(dtxtCenterY, 1, 1);
+            tableLayoutResults.Controls.Add(dtxtAngle, 1, 2);
+            tableLayoutResults.Controls.Add(dtxtWidth, 1, 3);
+            tableLayoutResults.Controls.Add(label18, 0, 5);
+            tableLayoutResults.Controls.Add(dtxtCount, 1, 5);
+            tableLayoutResults.Dock = DockStyle.Fill;
+            tableLayoutResults.Location = new Point(3, 3);
+            tableLayoutResults.Margin = new Padding(2, 3, 2, 3);
+            tableLayoutResults.Name = "tableLayoutResults";
+            tableLayoutResults.RowCount = 10;
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.Size = new Size(397, 510);
+            tableLayoutResults.TabIndex = 1;
+            // 
+            // dtxtHeight
+            // 
+            dtxtHeight.Dock = DockStyle.Fill;
+            dtxtHeight.Location = new Point(102, 207);
+            dtxtHeight.Margin = new Padding(2, 3, 2, 3);
+            dtxtHeight.Name = "dtxtHeight";
+            dtxtHeight.ReadOnly = true;
+            dtxtHeight.Size = new Size(293, 23);
+            dtxtHeight.TabIndex = 9;
+            // 
+            // label9
+            // 
+            label9.AutoSize = true;
+            label9.Dock = DockStyle.Fill;
+            label9.Location = new Point(2, 204);
+            label9.Margin = new Padding(2, 0, 2, 0);
+            label9.MaximumSize = new Size(0, 28);
+            label9.MinimumSize = new Size(0, 28);
+            label9.Name = "label9";
+            label9.Size = new Size(96, 28);
+            label9.TabIndex = 3;
+            label9.Text = "楂樺害";
+            label9.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Dock = DockStyle.Fill;
+            label5.Location = new Point(2, 0);
+            label5.Margin = new Padding(2, 0, 2, 0);
+            label5.MaximumSize = new Size(0, 28);
+            label5.MinimumSize = new Size(0, 28);
+            label5.Name = "label5";
+            label5.Size = new Size(96, 28);
+            label5.TabIndex = 0;
+            label5.Text = "X";
+            label5.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label6
+            // 
+            label6.AutoSize = true;
+            label6.Dock = DockStyle.Fill;
+            label6.Location = new Point(2, 51);
+            label6.Margin = new Padding(2, 0, 2, 0);
+            label6.MaximumSize = new Size(0, 28);
+            label6.MinimumSize = new Size(0, 28);
+            label6.Name = "label6";
+            label6.Size = new Size(96, 28);
+            label6.TabIndex = 1;
+            label6.Text = "Y";
+            label6.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label7
+            // 
+            label7.AutoSize = true;
+            label7.Dock = DockStyle.Fill;
+            label7.Location = new Point(2, 102);
+            label7.Margin = new Padding(2, 0, 2, 0);
+            label7.MaximumSize = new Size(0, 28);
+            label7.MinimumSize = new Size(0, 28);
+            label7.Name = "label7";
+            label7.Size = new Size(96, 28);
+            label7.TabIndex = 2;
+            label7.Text = "瑙掑害(掳)";
+            label7.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label8
+            // 
+            label8.AutoSize = true;
+            label8.Dock = DockStyle.Fill;
+            label8.Location = new Point(2, 153);
+            label8.Margin = new Padding(2, 0, 2, 0);
+            label8.MaximumSize = new Size(0, 28);
+            label8.MinimumSize = new Size(0, 28);
+            label8.Name = "label8";
+            label8.Size = new Size(96, 28);
+            label8.TabIndex = 3;
+            label8.Text = "瀹藉害";
+            label8.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCenterX
+            // 
+            dtxtCenterX.Dock = DockStyle.Fill;
+            dtxtCenterX.Location = new Point(102, 3);
+            dtxtCenterX.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterX.Name = "dtxtCenterX";
+            dtxtCenterX.ReadOnly = true;
+            dtxtCenterX.Size = new Size(293, 23);
+            dtxtCenterX.TabIndex = 5;
+            // 
+            // dtxtCenterY
+            // 
+            dtxtCenterY.Dock = DockStyle.Fill;
+            dtxtCenterY.Location = new Point(102, 54);
+            dtxtCenterY.Margin = new Padding(2, 3, 2, 3);
+            dtxtCenterY.Name = "dtxtCenterY";
+            dtxtCenterY.ReadOnly = true;
+            dtxtCenterY.Size = new Size(293, 23);
+            dtxtCenterY.TabIndex = 6;
+            // 
+            // dtxtAngle
+            // 
+            dtxtAngle.Dock = DockStyle.Fill;
+            dtxtAngle.Location = new Point(102, 105);
+            dtxtAngle.Margin = new Padding(2, 3, 2, 3);
+            dtxtAngle.Name = "dtxtAngle";
+            dtxtAngle.ReadOnly = true;
+            dtxtAngle.Size = new Size(293, 23);
+            dtxtAngle.TabIndex = 7;
+            // 
+            // dtxtWidth
+            // 
+            dtxtWidth.Dock = DockStyle.Fill;
+            dtxtWidth.Location = new Point(102, 156);
+            dtxtWidth.Margin = new Padding(2, 3, 2, 3);
+            dtxtWidth.Name = "dtxtWidth";
+            dtxtWidth.ReadOnly = true;
+            dtxtWidth.Size = new Size(293, 23);
+            dtxtWidth.TabIndex = 8;
+            // 
+            // label18
+            // 
+            label18.AutoSize = true;
+            label18.Dock = DockStyle.Fill;
+            label18.Location = new Point(3, 255);
+            label18.Name = "label18";
+            label18.Size = new Size(94, 51);
+            label18.TabIndex = 10;
+            label18.Text = "鏁伴噺";
+            label18.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCount
+            // 
+            dtxtCount.Dock = DockStyle.Fill;
+            dtxtCount.Location = new Point(103, 258);
+            dtxtCount.Name = "dtxtCount";
+            dtxtCount.ReadOnly = true;
+            dtxtCount.Size = new Size(291, 23);
+            dtxtCount.TabIndex = 11;
+            // 
+            // imgTabControl
+            // 
+            imgTabControl.Controls.Add(tabPageInputImage);
+            imgTabControl.Controls.Add(tabPageRecordImage);
+            imgTabControl.Dock = DockStyle.Fill;
+            imgTabControl.Location = new Point(420, 3);
+            imgTabControl.Name = "imgTabControl";
+            imgTabControl.SelectedIndex = 0;
+            imgTabControl.Size = new Size(621, 546);
+            imgTabControl.TabIndex = 49;
+            // 
+            // tabPageInputImage
+            // 
+            tabPageInputImage.Controls.Add(pnlInputImage);
+            tabPageInputImage.Location = new Point(4, 26);
+            tabPageInputImage.Name = "tabPageInputImage";
+            tabPageInputImage.Padding = new Padding(3);
+            tabPageInputImage.Size = new Size(613, 516);
+            tabPageInputImage.TabIndex = 0;
+            tabPageInputImage.Text = "杈撳叆鍥惧儚";
+            tabPageInputImage.UseVisualStyleBackColor = true;
+            // 
+            // tabPageRecordImage
+            // 
+            tabPageRecordImage.Controls.Add(pnlRecordImage);
+            tabPageRecordImage.Location = new Point(4, 26);
+            tabPageRecordImage.Name = "tabPageRecordImage";
+            tabPageRecordImage.Padding = new Padding(3);
+            tabPageRecordImage.Size = new Size(613, 516);
+            tabPageRecordImage.TabIndex = 1;
+            tabPageRecordImage.Text = "缁撴灉鍥惧儚";
+            tabPageRecordImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlRecordImage
+            // 
+            pnlRecordImage.Dock = DockStyle.Fill;
+            pnlRecordImage.Location = new Point(3, 3);
+            pnlRecordImage.Margin = new Padding(4);
+            pnlRecordImage.Name = "pnlRecordImage";
+            pnlRecordImage.Size = new Size(607, 510);
+            pnlRecordImage.TabIndex = 45;
+            // 
+            // btnShowROI
+            // 
+            btnShowROI.Dock = DockStyle.Fill;
+            btnShowROI.Location = new Point(3, 207);
+            btnShowROI.Name = "btnShowROI";
+            btnShowROI.Size = new Size(84, 45);
+            btnShowROI.TabIndex = 15;
+            btnShowROI.Text = "鏄剧ず鎵剧嚎鍖哄煙";
+            btnShowROI.UseVisualStyleBackColor = true;
+            btnShowROI.Click += btnShowROI_Click;
+            // 
+            // HFindLineToolEdit
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(MainTableLayoutPanel);
+            Controls.Add(BtmStatusStrip);
+            Controls.Add(TopToolStrip);
+            Margin = new Padding(2, 3, 2, 3);
+            Name = "HFindLineToolEdit";
+            Size = new Size(1044, 599);
+            Load += HFindLineToolEdit_Load;
+            tablePanelParas.ResumeLayout(false);
+            tablePanelParas.PerformLayout();
+            TopToolStrip.ResumeLayout(false);
+            TopToolStrip.PerformLayout();
+            BtmStatusStrip.ResumeLayout(false);
+            BtmStatusStrip.PerformLayout();
+            MainTableLayoutPanel.ResumeLayout(false);
+            parasTabControl.ResumeLayout(false);
+            tabPage1.ResumeLayout(false);
+            tabPage5.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel2.PerformLayout();
+            tabPage2.ResumeLayout(false);
+            tableLayoutResults.ResumeLayout(false);
+            tableLayoutResults.PerformLayout();
+            imgTabControl.ResumeLayout(false);
+            tabPageInputImage.ResumeLayout(false);
+            tabPageRecordImage.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TableLayoutPanel tablePanelParas;
+        private System.Windows.Forms.Panel pnlInputImage;
+        private ToolStrip TopToolStrip;
+        private ToolStripButton btnRun;
+        private StatusStrip BtmStatusStrip;
+        private ToolStripStatusLabel lblResult;
+        private ToolStripStatusLabel lblMsg;
+        private TableLayoutPanel MainTableLayoutPanel;
+        private ToolStripButton btnLoadImage;
+        private TabControl parasTabControl;
+        private TabPage tabPage1;
+        private TabPage tabPage2;
+        private TableLayoutPanel tableLayoutResults;
+        private Label label5;
+        private Label label6;
+        private Label label7;
+        private Label label8;
+        private TextBox dtxtCenterX;
+        private TextBox dtxtCenterY;
+        private TextBox dtxtAngle;
+        private TextBox dtxtWidth;
+        private TextBox dtxtHeight;
+        private Label label9;
+        private TabPage tabPage5;
+        private TabControl imgTabControl;
+        private TabPage tabPageInputImage;
+        private TabPage tabPageRecordImage;
+        private ToolStripButton btnSaveParas;
+        private ToolStripButton btnLoadParas;
+        private Panel pnlRecordImage;
+        private Label label1;
+        private TextBox itxtCaliperCount;
+        private Label label2;
+        private TextBox dtxtCaliperHeight;
+        private Label label3;
+        private TextBox dtxtCaliperWidth;
+        private Label label4;
+        private TextBox itxtSigma;
+        private Label label10;
+        private TextBox itxtThreshold;
+        private Label label11;
+        private TextBox itxtIgnoreCount;
+        private Label label12;
+        private Label label13;
+        private Label label18;
+        private TextBox dtxtCount;
+        private ToolStripStatusLabel lblRunTime;
+        private TableLayoutPanel tableLayoutPanel2;
+        public ComboBox cmbTypeRoi;
+        private Label label21;
+        private Label label22;
+        private ComboBox cmbFixture;
+        private CheckBox ckbDrawRoi;
+        private ComboBox cmbTransition;
+        private ComboBox cmbSelect;
+        private Button btnShowROI;
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.cs b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.cs
new file mode 100644
index 0000000..bcfa800
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.cs
@@ -0,0 +1,424 @@
+锘縰sing HalconDotNet;
+using System.Data.Common;
+using LB_VisionProcesses.Alogrithms;
+using System.Windows.Forms;
+using OpenCvSharp;
+using LB_VisionControl;
+
+namespace LB_VisionProcesses.Alogrithms.OpenCvSharp
+{
+    public partial class FindLineToolEdit : TAlgorithmEdit
+    {
+        public FindLineToolEdit(FindLineTool subject = null)
+        {
+            if (subject != null && subject is FindLineTool)
+                Subject = subject;
+            else
+                Subject = new FindLineTool();
+
+            if (!(Subject.Params.ROI is HSegment))
+                Subject.Params.ROI = new HSegment(0, 0, 250, 250);
+
+            this.Dock = DockStyle.Fill;
+            InitializeComponent();
+        }
+
+        /// <summary>
+        /// 鎺т欢鍔犺浇浜嬩欢
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void HFindLineToolEdit_Load(object sender, EventArgs e)
+        {
+            pnlInputImage.Controls.Add(inputImageHSmartWindowControl);
+            inputImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            pnlRecordImage.Controls.Add(recordImageHSmartWindowControl);
+            recordImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            //閬嶅巻鍙互閫夋嫨鐨凴oi绫诲瀷鏋氫妇
+            foreach (var value in Enum.GetValues(typeof(RoiType)))
+                cmbTypeRoi.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨勬瀬鎬х被鍨嬫灇涓�
+            foreach (var value in Enum.GetValues(typeof(Transition)))
+                cmbTransition.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨勮竟缂樼被鍨嬫灇涓�
+            foreach (var value in Enum.GetValues(typeof(Selector)))
+                cmbSelect.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨凢ixture鏋氫妇
+            cmbFixture.Items.Add("");
+            foreach (string value in IProcess.dicFixtures.Keys)
+                cmbFixture.Items.Add(value.ToString());
+
+            ckbDrawRoi.Checked = true;
+            cmbTypeRoi.Text = RoiType.Segment.ToString();
+            cmbTransition.Text = Transition.Ignore.ToString();
+            cmbSelect.Text = Selector.Best.ToString();
+            LoadParas();
+
+            if (Subject.Result)
+            {
+                lblResult.BackColor = Color.Green;
+                lblResult.Text = "True";
+            }
+            else
+            {
+                lblResult.BackColor = Color.Red;
+                lblResult.Text = "False";
+            }
+
+            lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+            lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+            lblRunTime.Text = $"{Subject.RunTime}ms";
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯鍙傛暟
+        /// </summary>
+        public override void UpdataInputs()
+        {
+            //璁剧疆杩愯鍙傛暟
+            double dResult = 0;
+            int iResult = 0;
+
+            Subject.Params.Inputs["鍗″昂鏁伴噺"] = int.TryParse(itxtCaliperCount.Text, out iResult) ? iResult : Subject.Params.Inputs["鍗″昂鏁伴噺"];
+            Subject.Params.Inputs["鍗″昂闀垮害"] = double.TryParse(dtxtCaliperHeight.Text, out dResult) ? dResult : Subject.Params.Inputs["鍗″昂闀垮害"];
+            Subject.Params.Inputs["鍗″昂瀹藉害"] = double.TryParse(dtxtCaliperWidth.Text, out dResult) ? dResult : Subject.Params.Inputs["鍗″昂瀹藉害"];
+
+            Subject.Params.Inputs["杩囨护涓�鍗婂儚绱�"] = int.TryParse(itxtSigma.Text, out iResult) ? iResult : Subject.Params.Inputs["杩囨护涓�鍗婂儚绱�"];
+            Subject.Params.Inputs["瀵规瘮搴﹂槇鍊�"] = int.TryParse(itxtThreshold.Text, out iResult) ? iResult : Subject.Params.Inputs["瀵规瘮搴﹂槇鍊�"];
+
+            Subject.Params.Inputs["鏋佹��"] = cmbTransition.SelectedItem.ToString();
+            Subject.Params.Inputs["杈圭紭浣嶇疆"] = cmbSelect.SelectedItem.ToString();
+
+            if (cmbFixture.Text == "")
+                Subject.Params.Fixture = new Fixture();
+            else if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+
+            Type type = inputImageHSmartWindowControl.oRoi?.GetType();
+            switch (type)
+            {
+                case Type t when t == typeof(HRectangle2):
+                    HRectangle2 hRectangle2 = (HRectangle2)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HRectangle2(hRectangle2.X - Subject.Params.Fixture.X, hRectangle2.Y - Subject.Params.Fixture.Y
+                        , hRectangle2.Phi - Subject.Params.Fixture.Phi, hRectangle2.Width, hRectangle2.Height);
+                    break;
+                case Type t when t == typeof(HCircle):
+                    HCircle hCircle = (HCircle)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HCircle(hCircle.X - Subject.Params.Fixture.X, hCircle.Y - Subject.Params.Fixture.Y, hCircle.Radius);
+                    break;
+                case Type t when t == typeof(HSegment):
+                    HSegment hSegment = (HSegment)inputImageHSmartWindowControl.oRoi;
+                    Subject.Params.ROI
+                        = new HSegment(hSegment.StartX - Subject.Params.Fixture.X, hSegment.StartY - Subject.Params.Fixture.Y
+                        , hSegment.EndX - Subject.Params.Fixture.X, hSegment.EndY - Subject.Params.Fixture.Y);
+                    break;
+                default:
+                    Subject.Params.ROI = new ROI();
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// 鍔犺浇杩愯鍙傛暟
+        /// </summary>
+        public override void LoadParas()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                itxtCaliperCount.Text = Subject.Params.Inputs["鍗″昂鏁伴噺"].ToString();
+                dtxtCaliperHeight.Text = Subject.Params.Inputs["鍗″昂闀垮害"].ToString();
+                dtxtCaliperWidth.Text = Subject.Params.Inputs["鍗″昂瀹藉害"].ToString();
+                itxtSigma.Text = Subject.Params.Inputs["杩囨护涓�鍗婂儚绱�"].ToString();
+                itxtThreshold.Text = Subject.Params.Inputs["瀵规瘮搴﹂槇鍊�"].ToString();
+                itxtIgnoreCount.Text = Subject.Params.Inputs["蹇界暐鐐规暟"].ToString();
+
+                cmbTransition.Text = Subject.Params.Inputs["鏋佹��"].ToString();
+                cmbSelect.Text = Subject.Params.Inputs["杈圭紭浣嶇疆"].ToString();
+
+                if (Subject.InputImage != null && Subject.InputImage is Mat)
+                {
+                    TAlgorithm.Mat2HObject((Mat)Subject.InputImage, out HObject image);
+                    inputImageHSmartWindowControl.ShowHoImage(image);
+                }
+
+                Type type = Subject.Params.ROI?.GetType();
+                if (Subject.Params.ROI != null)
+                {
+                    switch (type)
+                    {
+                        case Type t when t == typeof(HRectangle2):
+                            cmbTypeRoi.Text = RoiType.Rectangle2.ToString();
+                            break;
+                        case Type t when t == typeof(HCircle):
+                            cmbTypeRoi.Text = RoiType.Circle.ToString();
+                            break;
+                        case Type t when t == typeof(HSegment):
+                            cmbTypeRoi.Text = RoiType.Segment.ToString();
+                            break;
+                        default:
+                            cmbTypeRoi.Text = RoiType.None.ToString();
+                            break;
+                    }
+                    if (cmbTypeRoi.Text.ToString() != "None")
+                        ckbDrawRoi.Checked = true;
+                    else
+                        ckbDrawRoi.Checked = false;
+
+                    inputImageHSmartWindowControl.oRoi = Subject.Params.ROI;
+                }
+
+                if (Subject.Params.Fixture != null)
+                    cmbFixture.Text = Subject.Params.Fixture.strName;
+                else
+                    cmbFixture.Text = "";
+
+                switch (type)
+                {
+                    case Type t when t == typeof(HRectangle2):
+                        inputImageHSmartWindowControl.oRoi
+                             = new HRectangle2(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                             , Subject.Params.ROI.Phi + Subject.Params.Fixture.Phi, ((HRectangle2)Subject.Params.ROI).Width, ((HRectangle2)Subject.Params.ROI).Height);
+                        break;
+                    case Type t when t == typeof(HCircle):
+                        inputImageHSmartWindowControl.oRoi
+                        = new HCircle(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                        , ((HCircle)Subject.Params.ROI).Radius);
+                        break;
+                    case Type t when t == typeof(HSegment):
+                        inputImageHSmartWindowControl.oRoi
+                        = new HSegment(((HSegment)Subject.Params.ROI).StartX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).StartY + Subject.Params.Fixture.Y
+                        , ((HSegment)Subject.Params.ROI).EndX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).EndY + Subject.Params.Fixture.Y);
+                        break;
+                    default:
+                        inputImageHSmartWindowControl.oRoi = null;
+                        break;
+                }
+            }));
+        }
+
+        /// <summary>
+        /// 鏇存柊杈撳嚭缁撴灉
+        /// </summary>
+        public override void UpdataOutputs()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                //瀛樺湪鍙嶅簭鍒楀寲閿欎贡鐨勬儏鍐甸渶瑕佷娇鐢ㄨ嚜瀹氫箟鐨勮浆鎹㈠櫒
+                dtxtCenterX.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterX"]);
+                dtxtCenterY.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterY"]);
+                dtxtAngle.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Angle"]);
+                dtxtWidth.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Width"]);
+                dtxtHeight.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Height"]);
+                dtxtCount.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Count"]);
+            }));
+        }
+
+        /// <summary>
+        /// 鐐瑰嚮杩愯
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        public override void btnRun_Click(object sender, EventArgs e)
+        {
+            if (Subject.InputImage != null)
+                InputImage = Subject.InputImage;
+
+            DateTime StartTime = DateTime.Now;
+            Run();
+
+            //鏇存柊鏃ュ織涓庣粨鏋�
+            this.BeginInvoke(new Action(() =>
+            {
+                if (Subject.Result)
+                {
+                    lblResult.BackColor = Color.Green;
+                    lblResult.Text = "True";
+                    recordImageHSmartWindowControl.SetColor("green");
+                }
+                else
+                {
+                    lblResult.BackColor = Color.Red;
+                    lblResult.Text = "False";
+                    recordImageHSmartWindowControl.SetColor("red");
+                }
+
+                lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+                lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+                lblRunTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
+
+                UpdataOutputs();
+                imgTabControl.SelectedTab = tabPageRecordImage;
+
+                if (Subject.InputImage != null && Subject.InputImage is Mat)
+                {
+                    TAlgorithm.Mat2HObject((Mat)Subject.InputImage, out HObject image);
+                    HOperatorSet.GetImageSize(image, out HTuple ho_ImageWidth, out HTuple ho_ImageHeight);
+                    recordImageHSmartWindowControl.ShowHoImage(image);
+                }
+
+                //鍏堝垽鏂瓙绫诲啀鍒ゆ柇鐖剁被
+                if (Subject.Record != null && Subject.Record is MsgRecord msgRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_NG, false);
+
+                    for (int i = 0; i < msgRecord.Msg.Length; i++)
+                        recordImageHSmartWindowControl.ShowMsg(msgRecord.Msg[i]
+                            , 1 == msgRecord.Result[i] ? true : false, msgRecord.Column[i], msgRecord.Row[i]);
+                }
+                else if (Subject.Record != null && Subject.Record is ObjectRecord objRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_NG, false);
+                }
+
+                GC.Collect();
+            }));
+        }
+
+        public override void btnLoadImage_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    Mat mat = Cv2.ImRead(selectedFiles[0]);
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    if (mat.Channels() != 1)
+                    {
+                        Cv2.CvtColor(mat, mat, ColorConversionCodes.RGB2GRAY);
+                        //鏇存柊鏃ュ織涓庣粨鏋�
+                        this.BeginInvoke(new Action(() =>
+                        {
+                            lblMsg.Text = "瀵煎叆鍥剧墖闈炵伆搴﹀浘,鑷姩杞崲涓虹伆搴﹀浘";
+                        }));
+                    }
+                    InputImage = mat;
+                    imgTabControl.SelectedTab = tabPageInputImage;
+                    inputImageHSmartWindowControl.oRoi = inputImageHSmartWindowControl.oRoi;
+                }
+            }
+        }
+
+        public override void btnSaveParas_Click(object sender, EventArgs e) { base.btnSaveParas_Click(sender, e); }
+
+        public override void ckbDrawRoi_CheckedChanged(object sender, EventArgs e)
+        {
+            if (ckbDrawRoi.Checked)
+            {
+                inputImageHSmartWindowControl.bAollowDraw = true;
+                imgTabControl.SelectedTab = tabPageInputImage;
+            }
+            else
+            {
+                inputImageHSmartWindowControl.bAollowDraw = false;
+                Subject.Params.ROI = new ROI();
+            }
+        }
+
+        public override void cmbTypeRoi_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (Enum.TryParse(cmbTypeRoi.Text.ToString(), out RoiType type))
+                {
+                    HTuple hv_imageWidth = 0;
+                    HTuple hv_imageHeight = 0;
+                    if (InputImage != null && InputImage is Mat)
+                    {
+                        TAlgorithm.Mat2HObject((Mat)InputImage, out HObject image);
+                        HOperatorSet.GetImageSize(image, out hv_imageWidth, out hv_imageHeight);
+                    }
+                    switch (type)
+                    {
+                        case RoiType.Rectangle2:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, 0
+                                , hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.Circle:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HCircle(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, hv_imageWidth.TupleReal() / 4);
+                            break;
+                        case RoiType.Segment:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HSegment(0, 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.None:
+                        default:
+                            inputImageHSmartWindowControl.oRoi = null;
+                            break;
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public override void cmbFixture_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+                else
+                    Subject.Params.Fixture = new Fixture();
+            }
+            catch { }
+        }
+
+        private void btnShowROI_Click(object sender, EventArgs e)
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                try
+                {
+                    imgTabControl.SelectedTab = tabPageInputImage;
+
+                    inputImageHSmartWindowControl.ClearObj();
+
+                    if (InputImage != null && InputImage is Mat)
+                    {
+                        TAlgorithm.Mat2HObject((Mat)InputImage, out HObject image);
+                        inputImageHSmartWindowControl.ShowHoImage(image);
+                    }
+
+                    int hv_Elements = Convert.ToInt16(itxtCaliperCount.Text);
+                    double hv_DetectHeight = Convert.ToDouble(dtxtCaliperHeight.Text);
+                    double hv_DetectWidth = Convert.ToDouble(dtxtCaliperWidth.Text);
+
+                    double hv_Row1 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).BeginRow + Subject.Params.Fixture.Row);
+                    double hv_Column1 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).BeginColumn + Subject.Params.Fixture.Column);
+                    double hv_Row2 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).EndRow + Subject.Params.Fixture.Row);
+                    double hv_Column2 = Convert.ToDouble(((HSegment)inputImageHSmartWindowControl.oRoi).EndColumn + Subject.Params.Fixture.Column);
+
+                    TAlgorithm.GetRakeRegions(null, out HObject ho_Regions, hv_Elements, hv_DetectHeight, hv_DetectWidth
+                        , new HTuple(), new HTuple(), new HTuple(), new HTuple()
+                        , hv_Row1, hv_Column1, hv_Row2, hv_Column2
+                        , out HTuple hv_ResultRow, out HTuple hv_ResultColumn);
+
+                    inputImageHSmartWindowControl.DispObj(ho_Regions);
+                }
+                catch { }
+            }));
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.resx b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.resx
new file mode 100644
index 0000000..551e0b0
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindLineTool/FindLineToolEdit.resx
@@ -0,0 +1,126 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema 
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="TopToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="BtmStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>129, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelTool.cs b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelTool.cs
new file mode 100644
index 0000000..67caa01
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelTool.cs
@@ -0,0 +1,921 @@
+锘縰sing HalconDotNet;
+using Newtonsoft.Json;
+using OpenCvSharp;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+using System.Text;
+using static LB_VisionProcesses.Alogrithms.OpenCvSharp.FindModelTool;
+using Point = OpenCvSharp.Point;
+using Size = OpenCvSharp.Size;
+
+namespace LB_VisionProcesses.Alogrithms.OpenCvSharp
+{
+    [Process("OpenCvSharp_妯℃澘鍖归厤宸ュ叿", Category = "OpenCvSharp宸ュ叿", Description = "鍒涘缓OpenCvSharp_妯℃澘鍖归厤宸ュ叿")]
+    public class FindModelTool : TAlgorithm
+    {
+        public enum ModelType { 鐏板害鍖归厤 };
+
+        public OModel ModelID = new OModel();
+
+        public FindModelTool()
+        {
+            strProcessClass = "LB_VisionProcesses.Alogrithms.OpenCvSharp.FindModelTool";
+            strProcessName = "OpenCvSharp_妯℃澘鍖归厤宸ュ叿";
+
+            Params.Inputs.Add("ModelType", ModelType.鐏板害鍖归厤);
+
+            //AngleStart锛氭悳绱㈡椂鐨勮捣濮嬭搴闇�瑕佽浆鎹负寮у害]
+            Params.Inputs.Add("AngleStart", -5.0);
+            //AngleExtent锛氭悳绱㈡椂鐨勮搴﹁寖鍥�,0琛ㄧず鏃犺搴︽悳绱闇�瑕佽浆鎹负寮у害]
+            Params.Inputs.Add("AngleExtent", 10.0);
+            //AngleStep锛氳搴︽闀�--寮у害[瑙掑害姝ラ暱 >= 0鍜岃搴︽闀� <= pi / 16]
+            Params.Inputs.Add("AngleStep", "auto");
+            Params.Inputs.Add("ScaleRMin", 0.9);
+            Params.Inputs.Add("ScaleRMax", 1.1);
+            Params.Inputs.Add("ScaleCMin", 0.9);
+            Params.Inputs.Add("ScaleCMax", 1.1);
+            //MinScore锛氳鎵惧埌鐨勬ā鏉挎渶灏忓垎鏁�
+            Params.Inputs.Add("MinScore", 0.5);
+            //NumMatches锛氳鎵惧埌鐨勬ā鏉挎渶澶氱殑瀹炰緥鏁�,0鍒欐壘鍒版墍鏈夊彲鑳界殑鍖归厤
+            Params.Inputs.Add("NumMatches", 0);
+            //MaxOverlap锛氬厑璁告壘鍒扮殑妯″瀷瀹炰緥鐨勬渶澶ч噸鍙犳瘮渚�, 寤鸿鍊硷細0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
+            Params.Inputs.Add("MaxOverlap", 0.2);
+            //SubPixel锛氳绠楃簿搴︾殑璁剧疆
+            //'none'    涓嶉�傜敤浜氬儚绱�,鏈�澶ц宸负鍗婁釜鍍忕礌
+            //'interpolation'   宸�煎緱鍒颁簹鍍忕礌绮惧害
+            //'least_squares', 'least_squares_high', 'least_squares_very_high'
+            //'max_deformation 1', 'max_deformation 2', 'max_deformation 3', 'max_deformation 4'
+            Params.Inputs.Add("SubPixel", "none");
+            //NumLevels锛氭悳绱㈡椂閲戝瓧濉旂殑灞傜骇,0琛ㄧず涓嶄娇鐢ㄩ噾瀛楀
+            Params.Inputs.Add("NumLevels", 0);
+            //Greediness锛氳椽濠害,鎼滅储鍚彂寮�,涓�鑸兘璁句负2,瓒婂皬閫熷害瓒婂揩,瀹规槗鍑虹幇鎵句笉鍒扮殑鎯呭喌
+            Params.Inputs.Add("Greediness", 2);
+            Params.Inputs.Add("ResultType", "");
+
+            Params.Inputs.Add("MinCount", 0);
+            Params.Inputs.Add("MaxCount", 9999);
+
+            Params.Outputs.Add("CenterX", new List<double>());
+            Params.Outputs.Add("CenterY", new List<double>());
+            Params.Outputs.Add("Phi", new List<double>());
+            Params.Outputs.Add("Score", new List<double>());
+            Params.Outputs.Add("Count", 0);
+        }
+
+        private static readonly object lockObj = new object();
+        /// <summary>
+        /// 杩愯绠楀瓙
+        /// </summary>
+        public override void TAlgorithmMain()
+        {
+            lock (lockObj)
+            {
+                try
+                {
+                    if (InputImage == null)
+                    {
+                        Msg = "杈撳叆鍥剧墖涓虹┖";
+                        Result = false;
+                        return;
+                    }
+                    if (!(InputImage is Mat))
+                    {
+                        Msg = "杈撳叆鍥剧墖鏍煎紡涓嶄负Mat";
+                        Result = false;
+                        return;
+                    }
+
+                    #region 瑁佸壀鍖哄煙
+                    object DomainImage = null;
+
+                    if (!ReduceDomainImage(InputImage, ref DomainImage))
+                    {
+                        Msg = "瑁佸壀鍖哄煙澶辫触";
+                        Result = false;
+                        return;
+                    }
+
+                    Mat hoDomainImage = DomainImage as Mat;
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    try
+                    {
+                        if (hoDomainImage.Channels() != 1)
+                            Cv2.CvtColor(hoDomainImage, hoDomainImage, ColorConversionCodes.RGB2GRAY);
+
+                        //杞崲鍚庡啀娆℃鏌ユ槸鍚︿负鐏板害鍥�
+                        if (hoDomainImage.Channels() != 1)
+                        {
+                            Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥�";
+                            Result = false;
+                            return;
+                        }
+                    }
+                    catch
+                    {
+                        Msg = "杈撳叆鍥剧墖涓嶄负鐏板害鍥句笖杞崲澶辫触";
+                        Result = false;
+                        return;
+                    }
+                    #endregion
+
+                    //鍒ゆ柇鏄惁鏈夋ā鏉�
+                    if (ModelID.hoImage == null || ModelID.hoImage.Empty())
+                    {
+                        Msg = "鏈垱寤烘ā鏉�";
+                        Result = false;
+                        return;
+                    }
+
+                    #region 绠楀瓙閫昏緫
+                    Record = new ObjectRecord();
+                    ModelType type = ModelID.Type;
+                    int ho_ModelWidth = ModelID.Width;
+                    int ho_ModelHeight = ModelID.Height;
+
+                    double AngleStart = Convert.ToDouble(Params.Inputs["AngleStart"]);
+                    double AngleExtent = Convert.ToDouble(Params.Inputs["AngleExtent"]);
+                    double MinScore = Convert.ToDouble(Params.Inputs["MinScore"]);
+                    int NumMatches = ProcessParams.ConvertToInt32(Params.Inputs["NumMatches"]);
+                    double MaxOverlap = Convert.ToDouble(Params.Inputs["MaxOverlap"]);
+                    string SubPixel = ProcessParams.ConvertToString(Params.Inputs["SubPixel"]);
+                    string NumLevels = ProcessParams.ConvertToString(Params.Inputs["NumLevels"]);
+                    double Greediness = Convert.ToDouble(Params.Inputs["Greediness"]);
+
+                    double ScaleRMin = Convert.ToDouble(Params.Inputs["ScaleRMin"]);
+                    double ScaleRMax = Convert.ToDouble(Params.Inputs["ScaleRMax"]);
+                    double ScaleCMin = Convert.ToDouble(Params.Inputs["ScaleCMin"]);
+                    double ScaleCMax = Convert.ToDouble(Params.Inputs["ScaleCMax"]);
+
+                    double ScaleMin = ScaleCMin > ScaleRMin ? ScaleRMin : ScaleCMin;
+                    double ScaleMax = ScaleCMax > ScaleRMax ? ScaleRMax : ScaleCMax;
+                    double ScaleStep = (ScaleMax - ScaleMin) / Greediness;
+
+                    List<RotatedRect> results = new List<RotatedRect>();
+                    switch (type)
+                    {
+                        case ModelType.鐏板害鍖归厤:
+                            // 鎵ц鐏板害鍖归厤
+                            results = MultiAngleTemplateMatch(hoDomainImage, ModelID.hoImage, AngleStart, AngleStart + AngleExtent, AngleExtent / Greediness
+                                , ScaleMin, ScaleMax, ScaleStep, MinScore, MaxOverlap);
+
+                            break;
+                        default:
+                            Msg = "涓嶆敮鎸佺殑妯℃澘";
+                            Result = false;
+                            return;
+                    }
+                    #endregion
+
+                    #region 缁撴灉澶勭悊
+                    List<double> CenterX = new List<double>();
+                    List<double> CenterY = new List<double>();
+                    List<double> Phi = new List<double>();
+                    List<double> Score = new List<double>();
+                    for (int i = 0; i < results.Count; i++)
+                    {
+                        CenterX.Add(results[i].Center.X);
+                        CenterY.Add(results[i].Center.Y);
+                        Phi.Add(results[i].Angle / 180 * Math.PI);
+
+                        HOperatorSet.GenRectangle2(out HObject hRectangle, CenterY[i], CenterX[i], Phi[i], ho_ModelWidth / 2, ho_ModelHeight / 2);
+                        ((ObjectRecord)Record).AddRecord(hRectangle);
+                    }
+
+                    Params.Outputs["CenterX"] = CenterX;
+                    Params.Outputs["CenterY"] = CenterY;
+                    Params.Outputs["Phi"] = Phi;
+                    Params.Outputs["Score"] = Score;
+                    Params.Outputs["Count"] = Score.Count;
+                    #endregion
+
+                    #region 鐢熸垚OutputImage缁欏悗缁鐞�
+                    try
+                    {
+                        OutputImage = hoDomainImage;
+                    }
+                    catch (Exception ex)
+                    {
+                        Msg = "鐢熸垚OutputImage澶辫触,鍘熷洜鏄�:" + ex.ToString();
+                        Result = false;
+                        return;
+                    }
+                    #endregion
+
+                    if (Msg == "杩愯瓒呮椂")
+                    {
+                        Result = false;
+                        Record.ChangeAll2False();
+                        return;
+                    }
+
+                    int MinCount = ProcessParams.ConvertToInt32(Params.Inputs["MinCount"]);
+                    int MaxCount = ProcessParams.ConvertToInt32(Params.Inputs["MaxCount"]);
+
+                    if (CenterX.Count < MinCount || CenterX.Count > MaxCount)
+                    {
+                        Msg = string.Format("缁撴灉涓暟瓒呭嚭鑼冨洿({0},{1})", MinCount, MaxCount);
+                        Record.ChangeAll2False();
+                        Result = false;
+                        return;
+                    }
+
+                    Msg = "杩愯鎴愬姛";
+                    Result = true;
+                    return;
+                }
+                catch (Exception ex)
+                {
+                    Msg = "杩愯澶辫触,鍘熷洜鏄�:" + ex.ToString().TrimEnd();
+                    OutputImage = null;
+                    Result = false;
+                    return;
+                }
+                finally
+                {
+                    if (!Result)
+                    {
+                        Params.Outputs["CenterX"] = 0;
+                        Params.Outputs["CenterY"] = 0;
+                        Params.Outputs["Phi"] = 0;
+                        Params.Outputs["Score"] = 0;
+                        Params.Outputs["Count"] = 0;
+                    }
+                    bCompleted = true;
+                    #region 鍐呭瓨閲婃斁
+
+                    #endregion
+                }
+            }
+        }
+
+        /// <summary>
+        /// 甯﹁搴︾殑鐏板害鍖归厤
+        /// </summary>
+        /// <param name="source"></param>
+        /// <param name="template"></param>
+        /// <param name="startAngle"></param>
+        /// <param name="endAngle"></param>
+        /// <param name="angleStep"></param>
+        /// <param name="scaleStart"></param>
+        /// <param name="scaleEnd"></param>
+        /// <param name="scaleStep"></param>
+        /// <param name="threshold"></param>
+        /// <param name="NMS"></param>
+        /// <returns></returns>
+        public static List<RotatedRect> MultiAngleTemplateMatch(
+               Mat source,
+               Mat template,
+               double startAngle = 0,
+               double endAngle = 360,
+               double angleStep = 10,
+               double scaleStart = 0.5,
+               double scaleEnd = 2.0,
+               double scaleStep = 0.1,
+               double threshold = 0.8,
+               double NMS = 0.3)
+        {
+            var allMatches = new List<MatchResult>();
+
+            // 鐢熸垚瑙掑害搴忓垪
+            var angles = GenerateAngleSequence(startAngle, endAngle, angleStep);
+
+            // 鐢熸垚缂╂斁搴忓垪
+            var scales = GenerateScaleSequence(scaleStart, scaleEnd, scaleStep);
+
+            // 澶氱嚎绋嬪姞閫熸柟娉昜瀛樺湪鍖归厤缁撴灉涓嶄竴鑷寸殑鎯呭喌]
+            //allMatches = MultiScaleAngleTemplateMatchFullParallel(source, template, scales, angles, threshold);
+
+            foreach (double scale in scales)
+            {
+                // 缂╂斁妯℃澘
+                Mat scaledTemplate = new Mat();
+                if (scale != 1.0)
+                {
+                    Cv2.Resize(template, scaledTemplate,
+                        new Size(template.Width * scale, template.Height * scale));
+                }
+                else
+                    scaledTemplate = template.Clone();
+
+                if (scaledTemplate.Width > source.Width || scaledTemplate.Height > source.Height)
+                    continue;
+
+                foreach (double angle in angles)
+                {
+                    // 鏃嬭浆妯℃澘
+                    using (Mat rotatedTemplate = RotateImageForTemplateMatching(scaledTemplate, angle))
+                    {
+                        if (rotatedTemplate.Empty()) continue;
+
+                        using (Mat resultMatrix = new Mat())
+                        {
+                            Cv2.MatchTemplate(source, rotatedTemplate, resultMatrix,
+                                TemplateMatchModes.CCoeffNormed);
+
+                            // 鏌ユ壘鏈�浣冲尮閰嶄綅缃�
+                            double minVal, maxVal;
+                            Point minLoc, maxLoc;
+                            Cv2.MinMaxLoc(resultMatrix, out minVal, out maxVal, out minLoc, out maxLoc);
+
+                            if (maxVal >= threshold)
+                            {
+                                var rotatedRect = new RotatedRect(
+                                    new Point2f(maxLoc.X + rotatedTemplate.Width / 2.0f,
+                                              maxLoc.Y + rotatedTemplate.Height / 2.0f),
+                                    new Size2f(rotatedTemplate.Width, rotatedTemplate.Height),
+                                    (float)angle);
+
+                                allMatches.Add(new MatchResult
+                                {
+                                    RotatedRect = rotatedRect,
+                                    Score = maxVal,
+                                    Scale = scale
+                                });
+                            }
+                        }
+                    }
+                }
+            }
+
+            // 搴旂敤鏃嬭浆鐭╁舰鐨勯潪鏋佸ぇ鍊兼姂鍒�
+            return ApplyRotatedNMS(allMatches, NMS);
+        }
+
+        public static List<MatchResult> MultiScaleAngleTemplateMatchFullParallel(
+            Mat source,
+            Mat template,
+            double[] scales,
+            double[] angles,
+            double threshold = 0.8)
+        {
+            var allMatches = new ConcurrentBag<MatchResult>();
+
+            // 棰勫鐞嗘簮鍥惧儚
+            // 鍒涘缓鎵�鏈夊昂搴�-瑙掑害缁勫悎
+            var combinations = from scale in scales
+                               from angle in angles
+                               select new { Scale = scale, Angle = angle };
+
+            Parallel.ForEach(combinations, combination =>
+            {
+                try
+                {
+                    ProcessScaleAngleCombination(source, template,
+                        combination.Scale, combination.Angle, threshold, allMatches);
+                }
+                catch (Exception ex)
+                {
+                    Debug.WriteLine($"澶勭悊灏哄害 {combination.Scale}, 瑙掑害 {combination.Angle} 鏃跺嚭閿�: {ex.Message}");
+                }
+            });
+
+            return allMatches.ToList();
+        }
+
+        private static void ProcessScaleAngleCombination(Mat source, Mat template,
+            double scale, double angle, double threshold, ConcurrentBag<MatchResult> allMatches)
+        {
+            Mat scaledTemplate = new Mat();
+            // 缂╂斁
+            if (scale != 1.0)
+            {
+                Cv2.Resize(template, scaledTemplate,
+                    new Size(template.Width * scale, template.Height * scale));
+            }
+            else
+            {
+                scaledTemplate = template.Clone();
+            }
+
+            if (scaledTemplate.Width > source.Width || scaledTemplate.Height > source.Height)
+                return;
+
+            // 鏃嬭浆
+            using (Mat rotatedTemplate = RotateImageForTemplateMatching(scaledTemplate, angle))
+            {
+                if (rotatedTemplate.Empty()) return;
+
+                using (Mat resultMatrix = new Mat())
+                {
+                    Cv2.MatchTemplate(source, rotatedTemplate, resultMatrix,
+                        TemplateMatchModes.CCoeffNormed);
+
+                    double minVal, maxVal;
+                    Point minLoc, maxLoc;
+                    Cv2.MinMaxLoc(resultMatrix, out minVal, out maxVal, out minLoc, out maxLoc);
+
+                    if (maxVal >= threshold)
+                    {
+                        var rotatedRect = new RotatedRect(
+                            new Point2f(maxLoc.X + rotatedTemplate.Width / 2.0f,
+                                      maxLoc.Y + rotatedTemplate.Height / 2.0f),
+                            new Size2f(rotatedTemplate.Width, rotatedTemplate.Height),
+                            (float)angle);
+
+                        allMatches.Add(new MatchResult
+                        {
+                            RotatedRect = rotatedRect,
+                            Score = maxVal,
+                            Scale = scale
+                        });
+                    }
+                }
+            }
+        }
+
+        public static Mat RotateImageForTemplateMatching(Mat template, double angle, double scale = 1.0)
+        {
+            if (template.Empty())
+                return new Mat();
+
+            try
+            {
+                double radians = angle * Math.PI / 180.0;
+                double sin = Math.Abs(Math.Sin(radians));
+                double cos = Math.Abs(Math.Cos(radians));
+
+                int newWidth = (int)Math.Ceiling((template.Width * cos + template.Height * sin) * scale);
+                int newHeight = (int)Math.Ceiling((template.Width * sin + template.Height * cos) * scale);
+
+                // 纭繚浣跨敤鐩稿悓鐨勭被鍨嬪垱寤虹敾甯�
+                Mat canvas = new Mat(newHeight, newWidth, template.Type(), Scalar.Black);
+
+                int xOffset = (newWidth - template.Width) / 2;
+                int yOffset = (newHeight - template.Height) / 2;
+
+                Rect roi = new Rect(xOffset, yOffset, template.Width, template.Height);
+                using (Mat canvasRoi = new Mat(canvas, roi))
+                {
+                    template.CopyTo(canvasRoi);
+                }
+
+                Point2f center = new Point2f(newWidth / 2.0f, newHeight / 2.0f);
+
+                using (Mat rotationMatrix = Cv2.GetRotationMatrix2D(center, angle, scale))
+                {
+                    Mat rotated = new Mat();
+                    Cv2.WarpAffine(canvas, rotated, rotationMatrix, new Size(newWidth, newHeight),
+                                  InterpolationFlags.Linear, BorderTypes.Constant, Scalar.Black);
+
+                    // 纭繚杈撳嚭绫诲瀷涓庤緭鍏ヤ竴鑷�
+                    if (rotated.Type() != template.Type())
+                    {
+                        Mat converted = new Mat();
+                        rotated.ConvertTo(converted, template.Type());
+                        rotated.Dispose();
+                        canvas.Dispose();
+                        return converted;
+                    }
+
+                    canvas.Dispose();
+                    return rotated;
+                }
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"鏃嬭浆鍥惧儚鏃跺嚭閿�: {ex.Message}");
+                return new Mat();
+            }
+        }
+
+        private static List<RotatedRect> ApplyRotatedNMS(List<MatchResult> matches, double overlapThreshold)
+        {
+            var results = new List<RotatedRect>();
+            var remainingMatches = new List<MatchResult>(matches);
+
+            while (remainingMatches.Count > 0)
+            {
+                // 鍙栧垎鏁版渶楂樼殑鍖归厤
+                var bestMatch = remainingMatches[0];
+                results.Add(bestMatch.RotatedRect);
+                remainingMatches.RemoveAt(0);
+
+                // 绉婚櫎涓庢渶浣冲尮閰嶉噸鍙犲害楂樼殑鍏朵粬鍖归厤
+                for (int i = remainingMatches.Count - 1; i >= 0; i--)
+                {
+                    double overlap = CalculateRotatedOverlap(bestMatch.RotatedRect,
+                        remainingMatches[i].RotatedRect);
+
+                    if (overlap > overlapThreshold)
+                    {
+                        remainingMatches.RemoveAt(i);
+                    }
+                }
+            }
+
+            return results;
+        }
+
+        public class MatchResult
+        {
+            public RotatedRect RotatedRect { get; set; }
+            public double Score { get; set; }
+            public double Scale { get; set; }
+        }
+
+        private static double CalculateRotatedOverlap(RotatedRect rect1, RotatedRect rect2)
+        {
+            // 璁$畻涓や釜鏃嬭浆鐭╁舰鐨勪氦骞舵瘮
+            Point2f[] vertices1 = rect1.Points();
+            Point2f[] vertices2 = rect2.Points();
+
+            // 浣跨敤杞粨闈㈢Н璁$畻閲嶅彔搴�
+            using (Mat img1 = new Mat(1000, 1000, MatType.CV_8UC1, Scalar.Black))
+            using (Mat img2 = new Mat(1000, 1000, MatType.CV_8UC1, Scalar.Black))
+            {
+                // 缁樺埗绗竴涓煩褰�
+                Point[] points1 = vertices1.Select(p => new Point(p.X + 500, p.Y + 500)).ToArray();
+                Cv2.FillConvexPoly(img1, points1, Scalar.White);
+
+                // 缁樺埗绗簩涓煩褰�
+                Point[] points2 = vertices2.Select(p => new Point(p.X + 500, p.Y + 500)).ToArray();
+                Cv2.FillConvexPoly(img2, points2, Scalar.White);
+
+                // 璁$畻浜ら泦
+                using (Mat intersection = new Mat())
+                {
+                    Cv2.BitwiseAnd(img1, img2, intersection);
+
+                    double intersectionArea = Cv2.CountNonZero(intersection);
+                    double unionArea = Cv2.CountNonZero(img1) + Cv2.CountNonZero(img2) - intersectionArea;
+
+                    return intersectionArea / unionArea;
+                }
+            }
+        }
+
+        private static double[] GenerateAngleSequence(double start, double end, double step)
+        {
+            var angles = new List<double>();
+            for (double angle = start; angle < end; angle += step)
+            {
+                angles.Add(angle);
+            }
+            return angles.ToArray();
+        }
+
+        private static double[] GenerateScaleSequence(double start, double end, double step)
+        {
+            var scales = new List<double>();
+            for (double scale = start; scale <= end; scale += step)
+            {
+                scales.Add(scale);
+            }
+            return scales.ToArray();
+        }
+
+        public bool CreateModel(Mat Template, ModelType modelType = ModelType.鐏板害鍖归厤, string NumLevels = "auto"
+            , double AngleStart = -5, double AngleExtent = 10, string AngleStep = "auto"
+            , double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto"
+            , double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto"
+            , string Optimization = "none", string Metric = "ignore_local_polarity"
+            , string Contrast = "auto", int MinContrast = 10)
+        {
+            try
+            {
+                if (Template == null || Template.Empty())
+                    Template = new Mat();
+
+                #region 鍙傛暟浠嬬粛
+                //Template: : //reduce_domain鍚庣殑妯℃澘鍥惧儚
+                //NumLevels ,//閲戝瓧濉旂殑灞傛暟锛屽彲璁句负鈥渁uto鈥濇垨0鈥�10鐨勬暣鏁�
+                //AngleStart ,//妯℃澘鏃嬭浆鐨勮捣濮嬭搴�
+                //AngleExtent ,//妯℃澘鏃嬭浆瑙掑害鑼冨洿, >=0
+                //AngleStep ,//鏃嬭浆瑙掑害鐨勬闀匡紝 >=0 and <=pi/16
+                //Optimization ,//璁剧疆妯℃澘浼樺寲鍜屾ā鏉垮垱寤烘柟娉�
+                //Metric , //鍖归厤鏂规硶璁剧疆
+                //Contrast ,//璁剧疆瀵规瘮搴�
+                //MinContrast // 璁剧疆鏈�灏忓姣斿害
+                #endregion
+                switch (modelType)
+                {
+                    case ModelType.鐏板害鍖归厤:
+                        //HOperatorSet.CreateLocalDeformableModel(Template, NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
+                        //    , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
+                        //    , ScaleRMin, ScaleRMax, ScaleRStep == "auto" ? ScaleRStep : Convert.ToDouble(ScaleRStep)
+                        //    , ScaleCMin, ScaleCMax, ScaleCStep == "auto" ? ScaleCStep : Convert.ToDouble(ScaleCStep)
+                        //    , Optimization, Metric
+                        //    , Contrast, MinContrast
+                        //    , new HTuple(), new HTuple()
+                        //    , out ModelID.hvModel);
+                        ModelID.hoImage = Template.Clone();
+                        ModelID.Type = ModelType.鐏板害鍖归厤;
+                        return true;
+                    default:
+                        //HOperatorSet.CreateAnisoShapeModel(Template, NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
+                        //    , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
+                        //    , ScaleRMin, ScaleRMax, ScaleRStep == "auto" ? ScaleRStep : Convert.ToDouble(ScaleRStep)
+                        //    , ScaleCMin, ScaleCMax, ScaleCStep == "auto" ? ScaleCStep : Convert.ToDouble(ScaleCStep)
+                        //    , Optimization, Metric
+                        //    , Contrast, MinContrast, out ModelID.hvModel);
+                        ModelID.hoImage = Template.Clone();
+                        ModelID.Type = ModelType.鐏板害鍖归厤;
+                        return true;
+                }
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 鍔犺浇绠楁硶
+        /// </summary>
+        /// <param name="fullPath">瀹屾暣璺緞甯�.json</param>
+        /// <returns></returns>
+        public override bool Load(string fullPath)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                if (!fullPath.Contains(".json"))
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                if (fullPath.StartsWith(".\\"))
+                {
+                    // 鍒ゆ柇鍘熷瓧绗︿覆闀垮害鏄惁澶т簬绛変簬2锛岄伩鍏嶈秺鐣�
+                    if (fullPath.Length >= 2)
+                    {
+                        // 鏇挎崲寮�澶翠袱涓瓧绗�
+                        fullPath = Application.StartupPath + fullPath.Substring(2);
+                        Debug.WriteLine($"淇敼鍚庣殑瀛楃涓�: {fullPath}");
+                    }
+                }
+
+                // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                string directoryPath = Path.GetDirectoryName(fullPath);
+                strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+                // 淇鐪熷疄璺緞,妯℃澘鍖归厤宸ュ叿鍏惰矾寰勪负涓�涓枃浠跺す,鑰屼笉鏄竴涓枃浠�
+                fullPath = directoryPath + "\\" + strProcessName + "\\" + strProcessName + ".json";
+
+                if (!File.Exists(fullPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    ModelID = new OModel(fullPath, ModelType.鐏板害鍖归厤, strProcessName);
+                    Save(directoryPath);
+                    ModelID.Save(fullPath, ModelID.Type);
+                    return true;
+                }
+
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+                Params = JsonConvert.DeserializeObject<ProcessParams>(strJson);
+                if (Params == null)
+                    return false;
+
+                // 鍙嶅簭鍒楀寲鍚庝慨澶嶆暟鎹�
+                Params.FixDeserializedData();
+                strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+
+                if (!Enum.TryParse(Params.Inputs["ModelType"].ToString(), out ModelType modelType))
+                    return false;
+
+                if (!ModelID.Load(fullPath, modelType))
+                    return false;
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨绠楁硶
+        /// </summary>
+        /// <param name="filePath">涓嶅甫.json</param>
+        /// <returns></returns>
+        public override bool Save(string filePath)
+        {
+            try
+            {
+                // 淇鐪熷疄璺緞,妯℃澘鍖归厤宸ュ叿鍏惰矾寰勪负涓�涓枃浠跺す,鑰屼笉鏄竴涓枃浠�
+                filePath += ("\\" + strProcessName);
+                Params.Inputs.Add("ModelType", ModelID.Type.ToString());
+                if (!base.Save(filePath)
+                    || !ModelID.Save(filePath + "\\" + strProcessName + ".json", ModelID.Type))
+                    return false;
+
+                return true;
+            }
+            catch { return false; }
+        }
+    }
+
+    public class OModel
+    {
+        public OModel(string modelName = "") { ModelName = modelName; }
+
+        public OModel(string modelFullPath, ModelType modelType, string modelName)
+        {
+            ModelFullPath = modelFullPath;
+            ModelName = modelName;
+            Type = modelType;
+            switch (modelType)
+            {
+                case ModelType.鐏板害鍖归厤:
+                    Load(ModelFullPath, modelType);
+                    break;
+                default:
+                    Load(ModelFullPath, modelType);
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// 妯℃澘璺緞
+        /// </summary>
+        public string ModelFullPath = "C:\\MyVisionModel\\ModelName.temp";
+
+        /// <summary>
+        /// 妯℃澘鍚嶇О
+        /// </summary>
+        public string ModelName
+        {
+            get { return Path.GetFileNameWithoutExtension(ModelFullPath); }
+            set
+            {
+                // 鑾峰彇鏂囦欢鐨勬墿灞曞悕锛堝寘鎷偣锛�
+                string fileExtension = Path.GetExtension(ModelFullPath);
+
+                // 鑾峰彇鏂囦欢鎵�鍦ㄧ殑鏂囦欢澶硅矾寰�
+                string directoryPath = Path.GetDirectoryName(ModelFullPath);
+
+                ModelFullPath = directoryPath + "\\" + value + fileExtension;
+            }
+        }
+
+        /// <summary>
+        /// 妯℃澘鍥剧墖
+        /// </summary>
+        public Mat hoImage;
+
+        public int Width
+        {
+            get
+            {
+                if (hoImage == null || hoImage.Empty())
+                    return 0;
+                return hoImage.Width;
+            }
+        }
+
+        public int Height
+        {
+            get
+            {
+                if (hoImage == null || hoImage.Empty())
+                    return 0;
+                return hoImage.Height;
+            }
+        }
+
+        /// <summary>
+        /// 妯℃澘绫诲瀷
+        /// </summary>
+        public ModelType Type = ModelType.鐏板害鍖归厤;
+
+        /// <summary>
+        /// 鍔犺浇妯℃澘(甯�.json)
+        /// </summary>
+        /// <param name="fullPath">瀹屾暣璺緞甯�.json</param>
+        /// <returns></returns>
+        public bool Load(string fullPath, ModelType modelType)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                string filePath = Path.GetDirectoryName(fullPath);
+                ModelName = Path.GetFileNameWithoutExtension(fullPath);
+                ModelFullPath = filePath + "\\" + ModelName;
+                ModelFullPath += ".model";
+                Type = modelType;
+                //switch (modelType)
+                //{
+                //    case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                //        ModelFullPath += ".dfm";
+                //        if (File.Exists(ModelFullPath))
+                //            HOperatorSet.ReadDeformableModel(ModelFullPath, out hvModel);
+                //        break;
+                //    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                //    default:
+                //        if (File.Exists(ModelFullPath))
+                //            HOperatorSet.ReadShapeModel(ModelFullPath, out hvModel);
+                //        break;
+                //}
+
+                string ImageFileName = Path.GetFileNameWithoutExtension(fullPath);
+                string ImageFullPath = filePath + "\\" + ImageFileName + ".bmp";
+                if (File.Exists(ImageFullPath))
+                    hoImage = Cv2.ImRead(ImageFullPath);
+
+                if (hoImage == null || hoImage.Empty())
+                    return false;
+
+                if (hoImage.Channels() != 1)
+                    Cv2.CvtColor(hoImage, hoImage, ColorConversionCodes.RGB2GRAY);
+
+                return true;
+            }
+            catch { Type = ModelType.鐏板害鍖归厤; return false; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨妯℃澘(璺緞甯�.model)
+        /// </summary>
+        /// <param name="fullPath">甯�.model</param>
+        /// <returns></returns>
+        public bool Save(string fullPath)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                string filePath = Path.GetDirectoryName(fullPath);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦�
+                if (!Directory.Exists(filePath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(filePath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+
+                ModelName = Path.GetFileNameWithoutExtension(fullPath);
+                // 浣跨敤 Path.GetExtension 鎻愬彇鎵╁睍鍚�
+                //switch (Type)
+                //{
+                //    case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                //        HOperatorSet.WriteDeformableModel(hvModel, fullPath);
+                //        break;
+                //    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                //    default:
+                //        HOperatorSet.WriteShapeModel(hvModel, fullPath);
+                //        break;
+                //}
+
+                string ImageFileName = Path.GetFileNameWithoutExtension(fullPath);
+                string ImageFullPath = filePath + "\\" + ImageFileName + ".bmp";
+                Cv2.ImWrite(ImageFullPath, hoImage);
+                //HOperatorSet.WriteImage(hoImage, "bmp", 0, ImageFullPath);
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨妯℃澘(璺緞甯�.json)
+        /// </summary>
+        /// <param name="fullPath">甯�.json</param>
+        /// <returns></returns>
+        public bool Save(string fullPath, ModelType modelType)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                string filePath = Path.GetDirectoryName(fullPath);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦�
+                if (!Directory.Exists(filePath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(filePath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+
+                ModelName = Path.GetFileNameWithoutExtension(fullPath);
+                ModelFullPath = filePath + "\\" + ModelName + ".model";
+                Type = modelType;
+                //switch (modelType)
+                //{
+                //    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                //        HOperatorSet.WriteDeformableModel(hvModel, ModelFullPath);
+                //        break;
+                //    default:
+                //        HOperatorSet.WriteShapeModel(hvModel, ModelFullPath);
+                //        break;
+                //}
+
+                string ImageFileName = Path.GetFileNameWithoutExtension(fullPath);
+                string ImageFullPath = filePath + "\\" + ImageFileName + ".bmp";
+                Cv2.ImWrite(ImageFullPath, hoImage);
+                return true;
+            }
+            catch { return false; }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.Designer.cs b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.Designer.cs
new file mode 100644
index 0000000..c34238c
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.Designer.cs
@@ -0,0 +1,1807 @@
+锘縩amespace LB_VisionProcesses.Alogrithms.OpenCvSharp
+{
+    partial class FindModelToolEdit
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tablePanelParas = new TableLayoutPanel();
+            lblInputParam1 = new Label();
+            dtxtInputParam1 = new TextBox();
+            lblInputParam2 = new Label();
+            dtxtInputParam2 = new TextBox();
+            lblInputParam3 = new Label();
+            dtxtInputParam3 = new TextBox();
+            lblInputParam4 = new Label();
+            dtxtInputParam4 = new TextBox();
+            lblInputParam5 = new Label();
+            dtxtInputParam5 = new TextBox();
+            lblInputParam6 = new Label();
+            dtxtInputParam6 = new TextBox();
+            lblInputParam7 = new Label();
+            lblInputParam9 = new Label();
+            lblInputParam11 = new Label();
+            lblInputParam13 = new Label();
+            lblInputParam15 = new Label();
+            lblInputParam17 = new Label();
+            dtxtInputParam7 = new TextBox();
+            dtxtInputParam9 = new TextBox();
+            dtxtInputParam11 = new TextBox();
+            dtxtInputParam13 = new TextBox();
+            dtxtInputParam15 = new TextBox();
+            dtxtInputParam17 = new TextBox();
+            lblInputParam8 = new Label();
+            dtxtInputParam8 = new TextBox();
+            lblInputParam10 = new Label();
+            dtxtInputParam10 = new TextBox();
+            lblInputParam12 = new Label();
+            dtxtInputParam12 = new TextBox();
+            lblInputParam14 = new Label();
+            dtxtInputParam14 = new TextBox();
+            lblInputParam16 = new Label();
+            dtxtInputParam16 = new TextBox();
+            lblInputParam18 = new Label();
+            dtxtInputParam18 = new TextBox();
+            TopToolStrip = new ToolStrip();
+            btnRun = new ToolStripButton();
+            btnLoadImage = new ToolStripButton();
+            btnSaveParas = new ToolStripButton();
+            btnLoadParas = new ToolStripButton();
+            BtmStatusStrip = new StatusStrip();
+            lblResult = new ToolStripStatusLabel();
+            lblMsg = new ToolStripStatusLabel();
+            lblRunTime = new ToolStripStatusLabel();
+            MainTableLayoutPanel = new TableLayoutPanel();
+            parasTabControl = new TabControl();
+            tabPage1 = new TabPage();
+            tabPageRunParas = new TabPage();
+            tableLayoutPanel3 = new TableLayoutPanel();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            cmbTypeRoi = new ComboBox();
+            label21 = new Label();
+            label22 = new Label();
+            cmbFixture = new ComboBox();
+            ckbDrawRoi = new CheckBox();
+            grpModel = new GroupBox();
+            tabPage7 = new TabPage();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            dtxtModelParam13 = new TextBox();
+            lblModelParam13 = new Label();
+            lblModelParam11 = new Label();
+            dtxtModelParam11 = new TextBox();
+            lblModelParam9 = new Label();
+            dtxtModelParam9 = new TextBox();
+            lblModelParam7 = new Label();
+            dtxtModelParam7 = new TextBox();
+            lblModelParam5 = new Label();
+            dtxtModelParam5 = new TextBox();
+            lblModelParam3 = new Label();
+            dtxtModelParam3 = new TextBox();
+            lblModelParam1 = new Label();
+            dtxtModelParam1 = new TextBox();
+            dtxtModelParam2 = new TextBox();
+            btnSaveModel = new Button();
+            lblModelParam2 = new Label();
+            lblModelParam4 = new Label();
+            dtxtModelParam4 = new TextBox();
+            lblModelParam6 = new Label();
+            dtxtModelParam6 = new TextBox();
+            lblModelParam8 = new Label();
+            dtxtModelParam8 = new TextBox();
+            lblModelParam10 = new Label();
+            dtxtModelParam10 = new TextBox();
+            lblModelParam12 = new Label();
+            dtxtModelParam12 = new TextBox();
+            lblModelParam14 = new Label();
+            dtxtModelParam14 = new TextBox();
+            lblModelParam15 = new Label();
+            lblModelParam17 = new Label();
+            dtxtModelParam15 = new TextBox();
+            dtxtModelParam17 = new TextBox();
+            lblModelParam16 = new Label();
+            lblModelParam18 = new Label();
+            dtxtModelParam16 = new TextBox();
+            dtxtModelParam18 = new TextBox();
+            btnCreateModel = new Button();
+            lblModelType = new Label();
+            cmbModelType = new ComboBox();
+            tabPage2 = new TabPage();
+            tableLayoutResults = new TableLayoutPanel();
+            dtxtCount = new TextBox();
+            label5 = new Label();
+            label6 = new Label();
+            label7 = new Label();
+            dtxtCenterX = new TextBox();
+            dtxtCenterY = new TextBox();
+            dtxtPhi = new TextBox();
+            label8 = new Label();
+            dtxtScore = new TextBox();
+            label9 = new Label();
+            imgTabControl = new TabControl();
+            tabPageInputImage = new TabPage();
+            pnlInputImage = new Panel();
+            tabPageModelImage = new TabPage();
+            pnlCreateModelImage = new Panel();
+            tabPageRecordImage = new TabPage();
+            pnlRecordImage = new Panel();
+            tablePanelParas.SuspendLayout();
+            TopToolStrip.SuspendLayout();
+            BtmStatusStrip.SuspendLayout();
+            MainTableLayoutPanel.SuspendLayout();
+            parasTabControl.SuspendLayout();
+            tabPage1.SuspendLayout();
+            tabPageRunParas.SuspendLayout();
+            tableLayoutPanel3.SuspendLayout();
+            tableLayoutPanel1.SuspendLayout();
+            tabPage7.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tabPage2.SuspendLayout();
+            tableLayoutResults.SuspendLayout();
+            imgTabControl.SuspendLayout();
+            tabPageInputImage.SuspendLayout();
+            tabPageModelImage.SuspendLayout();
+            tabPageRecordImage.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tablePanelParas
+            // 
+            tablePanelParas.ColumnCount = 4;
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 129F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 129F));
+            tablePanelParas.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tablePanelParas.Controls.Add(lblInputParam1, 0, 0);
+            tablePanelParas.Controls.Add(dtxtInputParam1, 1, 0);
+            tablePanelParas.Controls.Add(lblInputParam2, 2, 0);
+            tablePanelParas.Controls.Add(dtxtInputParam2, 3, 0);
+            tablePanelParas.Controls.Add(lblInputParam3, 0, 1);
+            tablePanelParas.Controls.Add(dtxtInputParam3, 1, 1);
+            tablePanelParas.Controls.Add(lblInputParam4, 2, 1);
+            tablePanelParas.Controls.Add(dtxtInputParam4, 3, 1);
+            tablePanelParas.Controls.Add(lblInputParam5, 0, 2);
+            tablePanelParas.Controls.Add(dtxtInputParam5, 1, 2);
+            tablePanelParas.Controls.Add(lblInputParam6, 2, 2);
+            tablePanelParas.Controls.Add(dtxtInputParam6, 3, 2);
+            tablePanelParas.Controls.Add(lblInputParam7, 0, 3);
+            tablePanelParas.Controls.Add(lblInputParam9, 0, 4);
+            tablePanelParas.Controls.Add(lblInputParam11, 0, 5);
+            tablePanelParas.Controls.Add(lblInputParam13, 0, 6);
+            tablePanelParas.Controls.Add(lblInputParam15, 0, 7);
+            tablePanelParas.Controls.Add(lblInputParam17, 0, 8);
+            tablePanelParas.Controls.Add(dtxtInputParam7, 1, 3);
+            tablePanelParas.Controls.Add(dtxtInputParam9, 1, 4);
+            tablePanelParas.Controls.Add(dtxtInputParam11, 1, 5);
+            tablePanelParas.Controls.Add(dtxtInputParam13, 1, 6);
+            tablePanelParas.Controls.Add(dtxtInputParam15, 1, 7);
+            tablePanelParas.Controls.Add(dtxtInputParam17, 1, 8);
+            tablePanelParas.Controls.Add(lblInputParam8, 2, 3);
+            tablePanelParas.Controls.Add(dtxtInputParam8, 3, 3);
+            tablePanelParas.Controls.Add(lblInputParam10, 2, 4);
+            tablePanelParas.Controls.Add(dtxtInputParam10, 3, 4);
+            tablePanelParas.Controls.Add(lblInputParam12, 2, 5);
+            tablePanelParas.Controls.Add(dtxtInputParam12, 3, 5);
+            tablePanelParas.Controls.Add(lblInputParam14, 2, 6);
+            tablePanelParas.Controls.Add(dtxtInputParam14, 3, 6);
+            tablePanelParas.Controls.Add(lblInputParam16, 2, 7);
+            tablePanelParas.Controls.Add(dtxtInputParam16, 3, 7);
+            tablePanelParas.Controls.Add(lblInputParam18, 2, 8);
+            tablePanelParas.Controls.Add(dtxtInputParam18, 3, 8);
+            tablePanelParas.Dock = DockStyle.Fill;
+            tablePanelParas.Location = new Point(4, 4);
+            tablePanelParas.Margin = new Padding(3, 4, 3, 4);
+            tablePanelParas.Name = "tablePanelParas";
+            tablePanelParas.RowCount = 12;
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tablePanelParas.Size = new Size(572, 636);
+            tablePanelParas.TabIndex = 0;
+            // 
+            // lblInputParam1
+            // 
+            lblInputParam1.AutoSize = true;
+            lblInputParam1.Location = new Point(3, 0);
+            lblInputParam1.MaximumSize = new Size(0, 35);
+            lblInputParam1.MinimumSize = new Size(0, 35);
+            lblInputParam1.Name = "lblInputParam1";
+            lblInputParam1.Size = new Size(51, 35);
+            lblInputParam1.TabIndex = 0;
+            lblInputParam1.Text = "鍙傛暟1";
+            lblInputParam1.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam1.Visible = false;
+            // 
+            // dtxtInputParam1
+            // 
+            dtxtInputParam1.Location = new Point(132, 4);
+            dtxtInputParam1.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam1.Name = "dtxtInputParam1";
+            dtxtInputParam1.Size = new Size(138, 28);
+            dtxtInputParam1.TabIndex = 5;
+            dtxtInputParam1.Text = "0";
+            dtxtInputParam1.Visible = false;
+            // 
+            // lblInputParam2
+            // 
+            lblInputParam2.AutoSize = true;
+            lblInputParam2.Location = new Point(289, 0);
+            lblInputParam2.MaximumSize = new Size(0, 35);
+            lblInputParam2.MinimumSize = new Size(0, 35);
+            lblInputParam2.Name = "lblInputParam2";
+            lblInputParam2.Size = new Size(51, 35);
+            lblInputParam2.TabIndex = 1;
+            lblInputParam2.Text = "鍙傛暟2";
+            lblInputParam2.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam2.Visible = false;
+            // 
+            // dtxtInputParam2
+            // 
+            dtxtInputParam2.Location = new Point(418, 4);
+            dtxtInputParam2.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam2.Name = "dtxtInputParam2";
+            dtxtInputParam2.Size = new Size(138, 28);
+            dtxtInputParam2.TabIndex = 6;
+            dtxtInputParam2.Text = "0";
+            dtxtInputParam2.Visible = false;
+            // 
+            // lblInputParam3
+            // 
+            lblInputParam3.AutoSize = true;
+            lblInputParam3.Location = new Point(3, 52);
+            lblInputParam3.MaximumSize = new Size(0, 35);
+            lblInputParam3.MinimumSize = new Size(0, 35);
+            lblInputParam3.Name = "lblInputParam3";
+            lblInputParam3.Size = new Size(51, 35);
+            lblInputParam3.TabIndex = 2;
+            lblInputParam3.Text = "鍙傛暟3";
+            lblInputParam3.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam3.Visible = false;
+            // 
+            // dtxtInputParam3
+            // 
+            dtxtInputParam3.Location = new Point(132, 56);
+            dtxtInputParam3.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam3.Name = "dtxtInputParam3";
+            dtxtInputParam3.Size = new Size(138, 28);
+            dtxtInputParam3.TabIndex = 7;
+            dtxtInputParam3.Text = "0";
+            dtxtInputParam3.Visible = false;
+            // 
+            // lblInputParam4
+            // 
+            lblInputParam4.AutoSize = true;
+            lblInputParam4.Location = new Point(289, 52);
+            lblInputParam4.MaximumSize = new Size(0, 35);
+            lblInputParam4.MinimumSize = new Size(0, 35);
+            lblInputParam4.Name = "lblInputParam4";
+            lblInputParam4.Size = new Size(51, 35);
+            lblInputParam4.TabIndex = 3;
+            lblInputParam4.Text = "鍙傛暟4";
+            lblInputParam4.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam4.Visible = false;
+            // 
+            // dtxtInputParam4
+            // 
+            dtxtInputParam4.Location = new Point(418, 56);
+            dtxtInputParam4.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam4.Name = "dtxtInputParam4";
+            dtxtInputParam4.Size = new Size(138, 28);
+            dtxtInputParam4.TabIndex = 8;
+            dtxtInputParam4.Text = "0";
+            dtxtInputParam4.Visible = false;
+            // 
+            // lblInputParam5
+            // 
+            lblInputParam5.AutoSize = true;
+            lblInputParam5.Location = new Point(3, 104);
+            lblInputParam5.MaximumSize = new Size(0, 35);
+            lblInputParam5.MinimumSize = new Size(0, 35);
+            lblInputParam5.Name = "lblInputParam5";
+            lblInputParam5.Size = new Size(51, 35);
+            lblInputParam5.TabIndex = 9;
+            lblInputParam5.Text = "鍙傛暟5";
+            lblInputParam5.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam5.Visible = false;
+            // 
+            // dtxtInputParam5
+            // 
+            dtxtInputParam5.Location = new Point(132, 108);
+            dtxtInputParam5.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam5.Name = "dtxtInputParam5";
+            dtxtInputParam5.Size = new Size(138, 28);
+            dtxtInputParam5.TabIndex = 9;
+            dtxtInputParam5.Text = "0";
+            dtxtInputParam5.Visible = false;
+            // 
+            // lblInputParam6
+            // 
+            lblInputParam6.AutoSize = true;
+            lblInputParam6.Location = new Point(289, 104);
+            lblInputParam6.MaximumSize = new Size(0, 35);
+            lblInputParam6.MinimumSize = new Size(0, 35);
+            lblInputParam6.Name = "lblInputParam6";
+            lblInputParam6.Size = new Size(51, 35);
+            lblInputParam6.TabIndex = 10;
+            lblInputParam6.Text = "鍙傛暟6";
+            lblInputParam6.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam6.Visible = false;
+            // 
+            // dtxtInputParam6
+            // 
+            dtxtInputParam6.Location = new Point(418, 108);
+            dtxtInputParam6.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam6.Name = "dtxtInputParam6";
+            dtxtInputParam6.Size = new Size(138, 28);
+            dtxtInputParam6.TabIndex = 9;
+            dtxtInputParam6.Text = "0";
+            dtxtInputParam6.Visible = false;
+            // 
+            // lblInputParam7
+            // 
+            lblInputParam7.AutoSize = true;
+            lblInputParam7.Location = new Point(3, 156);
+            lblInputParam7.MaximumSize = new Size(0, 35);
+            lblInputParam7.MinimumSize = new Size(0, 35);
+            lblInputParam7.Name = "lblInputParam7";
+            lblInputParam7.Size = new Size(51, 35);
+            lblInputParam7.TabIndex = 11;
+            lblInputParam7.Text = "鍙傛暟7";
+            lblInputParam7.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam7.Visible = false;
+            // 
+            // lblInputParam9
+            // 
+            lblInputParam9.AutoSize = true;
+            lblInputParam9.Location = new Point(3, 208);
+            lblInputParam9.MaximumSize = new Size(0, 35);
+            lblInputParam9.MinimumSize = new Size(0, 35);
+            lblInputParam9.Name = "lblInputParam9";
+            lblInputParam9.Size = new Size(51, 35);
+            lblInputParam9.TabIndex = 13;
+            lblInputParam9.Text = "鍙傛暟9";
+            lblInputParam9.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam9.Visible = false;
+            // 
+            // lblInputParam11
+            // 
+            lblInputParam11.AutoSize = true;
+            lblInputParam11.Location = new Point(3, 260);
+            lblInputParam11.MaximumSize = new Size(0, 35);
+            lblInputParam11.MinimumSize = new Size(0, 35);
+            lblInputParam11.Name = "lblInputParam11";
+            lblInputParam11.Size = new Size(60, 35);
+            lblInputParam11.TabIndex = 15;
+            lblInputParam11.Text = "鍙傛暟11";
+            lblInputParam11.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam11.Visible = false;
+            // 
+            // lblInputParam13
+            // 
+            lblInputParam13.AutoSize = true;
+            lblInputParam13.Location = new Point(3, 312);
+            lblInputParam13.MaximumSize = new Size(0, 35);
+            lblInputParam13.MinimumSize = new Size(0, 35);
+            lblInputParam13.Name = "lblInputParam13";
+            lblInputParam13.Size = new Size(60, 35);
+            lblInputParam13.TabIndex = 17;
+            lblInputParam13.Text = "鍙傛暟13";
+            lblInputParam13.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam13.Visible = false;
+            // 
+            // lblInputParam15
+            // 
+            lblInputParam15.AutoSize = true;
+            lblInputParam15.Location = new Point(3, 364);
+            lblInputParam15.MaximumSize = new Size(0, 35);
+            lblInputParam15.MinimumSize = new Size(0, 35);
+            lblInputParam15.Name = "lblInputParam15";
+            lblInputParam15.Size = new Size(60, 35);
+            lblInputParam15.TabIndex = 19;
+            lblInputParam15.Text = "鍙傛暟15";
+            lblInputParam15.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam15.Visible = false;
+            // 
+            // lblInputParam17
+            // 
+            lblInputParam17.AutoSize = true;
+            lblInputParam17.Location = new Point(3, 416);
+            lblInputParam17.MaximumSize = new Size(0, 35);
+            lblInputParam17.MinimumSize = new Size(0, 35);
+            lblInputParam17.Name = "lblInputParam17";
+            lblInputParam17.Size = new Size(60, 35);
+            lblInputParam17.TabIndex = 21;
+            lblInputParam17.Text = "鍙傛暟17";
+            lblInputParam17.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam17.Visible = false;
+            // 
+            // dtxtInputParam7
+            // 
+            dtxtInputParam7.Location = new Point(132, 160);
+            dtxtInputParam7.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam7.Name = "dtxtInputParam7";
+            dtxtInputParam7.Size = new Size(138, 28);
+            dtxtInputParam7.TabIndex = 9;
+            dtxtInputParam7.Text = "0";
+            dtxtInputParam7.Visible = false;
+            // 
+            // dtxtInputParam9
+            // 
+            dtxtInputParam9.Location = new Point(132, 212);
+            dtxtInputParam9.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam9.Name = "dtxtInputParam9";
+            dtxtInputParam9.Size = new Size(138, 28);
+            dtxtInputParam9.TabIndex = 9;
+            dtxtInputParam9.Text = "0";
+            dtxtInputParam9.Visible = false;
+            // 
+            // dtxtInputParam11
+            // 
+            dtxtInputParam11.Location = new Point(132, 264);
+            dtxtInputParam11.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam11.Name = "dtxtInputParam11";
+            dtxtInputParam11.Size = new Size(138, 28);
+            dtxtInputParam11.TabIndex = 9;
+            dtxtInputParam11.Text = "0";
+            dtxtInputParam11.Visible = false;
+            // 
+            // dtxtInputParam13
+            // 
+            dtxtInputParam13.Location = new Point(132, 316);
+            dtxtInputParam13.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam13.Name = "dtxtInputParam13";
+            dtxtInputParam13.Size = new Size(138, 28);
+            dtxtInputParam13.TabIndex = 23;
+            dtxtInputParam13.Text = "0";
+            dtxtInputParam13.Visible = false;
+            // 
+            // dtxtInputParam15
+            // 
+            dtxtInputParam15.Location = new Point(132, 368);
+            dtxtInputParam15.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam15.Name = "dtxtInputParam15";
+            dtxtInputParam15.Size = new Size(138, 28);
+            dtxtInputParam15.TabIndex = 25;
+            dtxtInputParam15.Text = "0";
+            dtxtInputParam15.Visible = false;
+            // 
+            // dtxtInputParam17
+            // 
+            dtxtInputParam17.Location = new Point(132, 420);
+            dtxtInputParam17.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam17.Name = "dtxtInputParam17";
+            dtxtInputParam17.Size = new Size(138, 28);
+            dtxtInputParam17.TabIndex = 27;
+            dtxtInputParam17.Text = "0";
+            dtxtInputParam17.Visible = false;
+            // 
+            // lblInputParam8
+            // 
+            lblInputParam8.AutoSize = true;
+            lblInputParam8.Location = new Point(289, 156);
+            lblInputParam8.MaximumSize = new Size(0, 35);
+            lblInputParam8.MinimumSize = new Size(0, 35);
+            lblInputParam8.Name = "lblInputParam8";
+            lblInputParam8.Size = new Size(51, 35);
+            lblInputParam8.TabIndex = 12;
+            lblInputParam8.Text = "鍙傛暟8";
+            lblInputParam8.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam8.Visible = false;
+            // 
+            // dtxtInputParam8
+            // 
+            dtxtInputParam8.Location = new Point(418, 160);
+            dtxtInputParam8.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam8.Name = "dtxtInputParam8";
+            dtxtInputParam8.Size = new Size(138, 28);
+            dtxtInputParam8.TabIndex = 9;
+            dtxtInputParam8.Text = "0";
+            dtxtInputParam8.Visible = false;
+            // 
+            // lblInputParam10
+            // 
+            lblInputParam10.AutoSize = true;
+            lblInputParam10.Location = new Point(289, 208);
+            lblInputParam10.MaximumSize = new Size(0, 35);
+            lblInputParam10.MinimumSize = new Size(0, 35);
+            lblInputParam10.Name = "lblInputParam10";
+            lblInputParam10.Size = new Size(60, 35);
+            lblInputParam10.TabIndex = 14;
+            lblInputParam10.Text = "鍙傛暟10";
+            lblInputParam10.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam10.Visible = false;
+            // 
+            // dtxtInputParam10
+            // 
+            dtxtInputParam10.Location = new Point(418, 212);
+            dtxtInputParam10.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam10.Name = "dtxtInputParam10";
+            dtxtInputParam10.Size = new Size(138, 28);
+            dtxtInputParam10.TabIndex = 9;
+            dtxtInputParam10.Text = "0";
+            dtxtInputParam10.Visible = false;
+            // 
+            // lblInputParam12
+            // 
+            lblInputParam12.AutoSize = true;
+            lblInputParam12.Location = new Point(289, 260);
+            lblInputParam12.MaximumSize = new Size(0, 35);
+            lblInputParam12.MinimumSize = new Size(0, 35);
+            lblInputParam12.Name = "lblInputParam12";
+            lblInputParam12.Size = new Size(60, 35);
+            lblInputParam12.TabIndex = 16;
+            lblInputParam12.Text = "鍙傛暟12";
+            lblInputParam12.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam12.Visible = false;
+            // 
+            // dtxtInputParam12
+            // 
+            dtxtInputParam12.Location = new Point(418, 264);
+            dtxtInputParam12.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam12.Name = "dtxtInputParam12";
+            dtxtInputParam12.Size = new Size(138, 28);
+            dtxtInputParam12.TabIndex = 10;
+            dtxtInputParam12.Text = "0";
+            dtxtInputParam12.Visible = false;
+            // 
+            // lblInputParam14
+            // 
+            lblInputParam14.AutoSize = true;
+            lblInputParam14.Location = new Point(289, 312);
+            lblInputParam14.MaximumSize = new Size(0, 35);
+            lblInputParam14.MinimumSize = new Size(0, 35);
+            lblInputParam14.Name = "lblInputParam14";
+            lblInputParam14.Size = new Size(60, 35);
+            lblInputParam14.TabIndex = 18;
+            lblInputParam14.Text = "鍙傛暟14";
+            lblInputParam14.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam14.Visible = false;
+            // 
+            // dtxtInputParam14
+            // 
+            dtxtInputParam14.Location = new Point(418, 316);
+            dtxtInputParam14.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam14.Name = "dtxtInputParam14";
+            dtxtInputParam14.Size = new Size(138, 28);
+            dtxtInputParam14.TabIndex = 24;
+            dtxtInputParam14.Text = "0";
+            dtxtInputParam14.Visible = false;
+            // 
+            // lblInputParam16
+            // 
+            lblInputParam16.AutoSize = true;
+            lblInputParam16.Location = new Point(289, 364);
+            lblInputParam16.MaximumSize = new Size(0, 35);
+            lblInputParam16.MinimumSize = new Size(0, 35);
+            lblInputParam16.Name = "lblInputParam16";
+            lblInputParam16.Size = new Size(60, 35);
+            lblInputParam16.TabIndex = 20;
+            lblInputParam16.Text = "鍙傛暟16";
+            lblInputParam16.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam16.Visible = false;
+            // 
+            // dtxtInputParam16
+            // 
+            dtxtInputParam16.Location = new Point(418, 368);
+            dtxtInputParam16.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam16.Name = "dtxtInputParam16";
+            dtxtInputParam16.Size = new Size(138, 28);
+            dtxtInputParam16.TabIndex = 26;
+            dtxtInputParam16.Text = "0";
+            dtxtInputParam16.Visible = false;
+            // 
+            // lblInputParam18
+            // 
+            lblInputParam18.AutoSize = true;
+            lblInputParam18.Location = new Point(289, 416);
+            lblInputParam18.MaximumSize = new Size(0, 35);
+            lblInputParam18.MinimumSize = new Size(0, 35);
+            lblInputParam18.Name = "lblInputParam18";
+            lblInputParam18.Size = new Size(60, 35);
+            lblInputParam18.TabIndex = 22;
+            lblInputParam18.Text = "鍙傛暟18";
+            lblInputParam18.TextAlign = ContentAlignment.MiddleCenter;
+            lblInputParam18.Visible = false;
+            // 
+            // dtxtInputParam18
+            // 
+            dtxtInputParam18.Location = new Point(418, 420);
+            dtxtInputParam18.Margin = new Padding(3, 4, 3, 4);
+            dtxtInputParam18.Name = "dtxtInputParam18";
+            dtxtInputParam18.Size = new Size(138, 28);
+            dtxtInputParam18.TabIndex = 28;
+            dtxtInputParam18.Text = "0";
+            dtxtInputParam18.Visible = false;
+            // 
+            // TopToolStrip
+            // 
+            TopToolStrip.Items.AddRange(new ToolStripItem[] { btnRun, btnLoadImage, btnSaveParas, btnLoadParas });
+            TopToolStrip.Location = new Point(0, 0);
+            TopToolStrip.Name = "TopToolStrip";
+            TopToolStrip.Size = new Size(1491, 28);
+            TopToolStrip.TabIndex = 45;
+            TopToolStrip.Text = "toolStrip1";
+            // 
+            // btnRun
+            // 
+            btnRun.BackgroundImageLayout = ImageLayout.Zoom;
+            btnRun.ImageTransparentColor = Color.Magenta;
+            btnRun.Name = "btnRun";
+            btnRun.Size = new Size(46, 25);
+            btnRun.Text = "杩愯";
+            btnRun.Click += btnRun_Click;
+            // 
+            // btnLoadImage
+            // 
+            btnLoadImage.ImageTransparentColor = Color.Magenta;
+            btnLoadImage.Name = "btnLoadImage";
+            btnLoadImage.Size = new Size(46, 25);
+            btnLoadImage.Text = "瀵煎浘";
+            btnLoadImage.Click += btnLoadImage_Click;
+            // 
+            // btnSaveParas
+            // 
+            btnSaveParas.ImageTransparentColor = Color.Magenta;
+            btnSaveParas.Name = "btnSaveParas";
+            btnSaveParas.Size = new Size(46, 25);
+            btnSaveParas.Text = "淇濆瓨";
+            btnSaveParas.Click += btnSaveParas_Click;
+            // 
+            // btnLoadParas
+            // 
+            btnLoadParas.ImageTransparentColor = Color.Magenta;
+            btnLoadParas.Name = "btnLoadParas";
+            btnLoadParas.Size = new Size(46, 25);
+            btnLoadParas.Text = "鍔犺浇";
+            btnLoadParas.Click += btnLoadParas_Click;
+            // 
+            // BtmStatusStrip
+            // 
+            BtmStatusStrip.Items.AddRange(new ToolStripItem[] { lblResult, lblMsg, lblRunTime });
+            BtmStatusStrip.Location = new Point(0, 714);
+            BtmStatusStrip.Name = "BtmStatusStrip";
+            BtmStatusStrip.Padding = new Padding(1, 0, 20, 0);
+            BtmStatusStrip.Size = new Size(1491, 26);
+            BtmStatusStrip.TabIndex = 46;
+            BtmStatusStrip.Text = "statusStrip1";
+            // 
+            // lblResult
+            // 
+            lblResult.Name = "lblResult";
+            lblResult.Size = new Size(44, 21);
+            lblResult.Text = "True";
+            // 
+            // lblMsg
+            // 
+            lblMsg.Name = "lblMsg";
+            lblMsg.Size = new Size(74, 21);
+            lblMsg.Text = "杩愯鎴愬姛";
+            lblMsg.TextAlign = ContentAlignment.MiddleLeft;
+            // 
+            // lblRunTime
+            // 
+            lblRunTime.Name = "lblRunTime";
+            lblRunTime.Size = new Size(41, 21);
+            lblRunTime.Text = "0ms";
+            // 
+            // MainTableLayoutPanel
+            // 
+            MainTableLayoutPanel.ColumnCount = 2;
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
+            MainTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F));
+            MainTableLayoutPanel.Controls.Add(parasTabControl, 0, 0);
+            MainTableLayoutPanel.Controls.Add(imgTabControl, 1, 0);
+            MainTableLayoutPanel.Dock = DockStyle.Fill;
+            MainTableLayoutPanel.Location = new Point(0, 28);
+            MainTableLayoutPanel.Margin = new Padding(4, 4, 4, 4);
+            MainTableLayoutPanel.Name = "MainTableLayoutPanel";
+            MainTableLayoutPanel.RowCount = 1;
+            MainTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            MainTableLayoutPanel.Size = new Size(1491, 686);
+            MainTableLayoutPanel.TabIndex = 47;
+            // 
+            // parasTabControl
+            // 
+            parasTabControl.Controls.Add(tabPage1);
+            parasTabControl.Controls.Add(tabPageRunParas);
+            parasTabControl.Controls.Add(tabPage7);
+            parasTabControl.Controls.Add(tabPage2);
+            parasTabControl.Dock = DockStyle.Fill;
+            parasTabControl.Location = new Point(4, 4);
+            parasTabControl.Margin = new Padding(4, 4, 4, 4);
+            parasTabControl.Name = "parasTabControl";
+            parasTabControl.SelectedIndex = 0;
+            parasTabControl.Size = new Size(588, 678);
+            parasTabControl.TabIndex = 48;
+            // 
+            // tabPage1
+            // 
+            tabPage1.Controls.Add(tablePanelParas);
+            tabPage1.Location = new Point(4, 30);
+            tabPage1.Margin = new Padding(4, 4, 4, 4);
+            tabPage1.Name = "tabPage1";
+            tabPage1.Padding = new Padding(4, 4, 4, 4);
+            tabPage1.Size = new Size(580, 644);
+            tabPage1.TabIndex = 0;
+            tabPage1.Text = "杈撳叆鍙傛暟";
+            tabPage1.UseVisualStyleBackColor = true;
+            // 
+            // tabPageRunParas
+            // 
+            tabPageRunParas.Controls.Add(tableLayoutPanel3);
+            tabPageRunParas.Location = new Point(4, 30);
+            tabPageRunParas.Margin = new Padding(4, 4, 4, 4);
+            tabPageRunParas.Name = "tabPageRunParas";
+            tabPageRunParas.Size = new Size(579, 640);
+            tabPageRunParas.TabIndex = 2;
+            tabPageRunParas.Text = "杩愯鍙傛暟";
+            tabPageRunParas.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel3
+            // 
+            tableLayoutPanel3.ColumnCount = 1;
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Controls.Add(tableLayoutPanel1, 0, 0);
+            tableLayoutPanel3.Controls.Add(grpModel, 0, 1);
+            tableLayoutPanel3.Dock = DockStyle.Fill;
+            tableLayoutPanel3.Location = new Point(0, 0);
+            tableLayoutPanel3.Margin = new Padding(4, 4, 4, 4);
+            tableLayoutPanel3.Name = "tableLayoutPanel3";
+            tableLayoutPanel3.RowCount = 2;
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 124F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 25F));
+            tableLayoutPanel3.Size = new Size(579, 640);
+            tableLayoutPanel3.TabIndex = 2;
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 4;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 86F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 214F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 29F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(cmbTypeRoi, 1, 0);
+            tableLayoutPanel1.Controls.Add(label21, 0, 0);
+            tableLayoutPanel1.Controls.Add(label22, 0, 1);
+            tableLayoutPanel1.Controls.Add(cmbFixture, 1, 1);
+            tableLayoutPanel1.Controls.Add(ckbDrawRoi, 2, 0);
+            tableLayoutPanel1.Location = new Point(4, 4);
+            tableLayoutPanel1.Margin = new Padding(4, 4, 4, 4);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 3;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 37F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 37F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Size = new Size(461, 116);
+            tableLayoutPanel1.TabIndex = 6;
+            // 
+            // cmbTypeRoi
+            // 
+            cmbTypeRoi.FormattingEnabled = true;
+            cmbTypeRoi.Location = new Point(90, 4);
+            cmbTypeRoi.Margin = new Padding(4, 4, 4, 4);
+            cmbTypeRoi.Name = "cmbTypeRoi";
+            cmbTypeRoi.Size = new Size(171, 29);
+            cmbTypeRoi.TabIndex = 1;
+            cmbTypeRoi.SelectedIndexChanged += cmbTypeRoi_SelectedIndexChanged;
+            // 
+            // label21
+            // 
+            label21.AutoSize = true;
+            label21.Dock = DockStyle.Fill;
+            label21.Location = new Point(4, 0);
+            label21.Margin = new Padding(4, 0, 4, 0);
+            label21.Name = "label21";
+            label21.Size = new Size(78, 37);
+            label21.TabIndex = 3;
+            label21.Text = "ROI";
+            label21.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label22
+            // 
+            label22.AutoSize = true;
+            label22.Dock = DockStyle.Fill;
+            label22.Location = new Point(4, 37);
+            label22.Margin = new Padding(4, 0, 4, 0);
+            label22.Name = "label22";
+            label22.Size = new Size(78, 37);
+            label22.TabIndex = 4;
+            label22.Text = "Fixture";
+            label22.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbFixture
+            // 
+            cmbFixture.FormattingEnabled = true;
+            cmbFixture.Location = new Point(90, 41);
+            cmbFixture.Margin = new Padding(4, 4, 4, 4);
+            cmbFixture.Name = "cmbFixture";
+            cmbFixture.Size = new Size(171, 29);
+            cmbFixture.TabIndex = 5;
+            cmbFixture.SelectedIndexChanged += cmbFixture_SelectedIndexChanged;
+            // 
+            // ckbDrawRoi
+            // 
+            ckbDrawRoi.AutoSize = true;
+            ckbDrawRoi.CheckAlign = ContentAlignment.MiddleCenter;
+            ckbDrawRoi.Location = new Point(304, 4);
+            ckbDrawRoi.Margin = new Padding(4, 4, 4, 4);
+            ckbDrawRoi.Name = "ckbDrawRoi";
+            ckbDrawRoi.Size = new Size(15, 14);
+            ckbDrawRoi.TabIndex = 2;
+            ckbDrawRoi.UseVisualStyleBackColor = true;
+            ckbDrawRoi.CheckedChanged += ckbDrawRoi_CheckedChanged;
+            // 
+            // grpModel
+            // 
+            grpModel.Dock = DockStyle.Fill;
+            grpModel.Location = new Point(4, 128);
+            grpModel.Margin = new Padding(4, 4, 4, 4);
+            grpModel.Name = "grpModel";
+            grpModel.Padding = new Padding(4, 4, 4, 4);
+            grpModel.Size = new Size(571, 508);
+            grpModel.TabIndex = 3;
+            grpModel.TabStop = false;
+            grpModel.Text = "杩愯妯℃澘";
+            // 
+            // tabPage7
+            // 
+            tabPage7.Controls.Add(tableLayoutPanel2);
+            tabPage7.Location = new Point(4, 30);
+            tabPage7.Margin = new Padding(4, 4, 4, 4);
+            tabPage7.Name = "tabPage7";
+            tabPage7.Padding = new Padding(4, 4, 4, 4);
+            tabPage7.Size = new Size(580, 644);
+            tabPage7.TabIndex = 3;
+            tabPage7.Text = "妯℃澘鍙傛暟";
+            tabPage7.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 4;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 129F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 129F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
+            tableLayoutPanel2.Controls.Add(dtxtModelParam13, 1, 7);
+            tableLayoutPanel2.Controls.Add(lblModelParam13, 0, 7);
+            tableLayoutPanel2.Controls.Add(lblModelParam11, 0, 6);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam11, 1, 6);
+            tableLayoutPanel2.Controls.Add(lblModelParam9, 0, 5);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam9, 1, 5);
+            tableLayoutPanel2.Controls.Add(lblModelParam7, 0, 4);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam7, 1, 4);
+            tableLayoutPanel2.Controls.Add(lblModelParam5, 0, 3);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam5, 1, 3);
+            tableLayoutPanel2.Controls.Add(lblModelParam3, 0, 2);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam3, 1, 2);
+            tableLayoutPanel2.Controls.Add(lblModelParam1, 0, 1);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam1, 1, 1);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam2, 3, 1);
+            tableLayoutPanel2.Controls.Add(btnSaveModel, 3, 0);
+            tableLayoutPanel2.Controls.Add(lblModelParam2, 2, 1);
+            tableLayoutPanel2.Controls.Add(lblModelParam4, 2, 2);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam4, 3, 2);
+            tableLayoutPanel2.Controls.Add(lblModelParam6, 2, 3);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam6, 3, 3);
+            tableLayoutPanel2.Controls.Add(lblModelParam8, 2, 4);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam8, 3, 4);
+            tableLayoutPanel2.Controls.Add(lblModelParam10, 2, 5);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam10, 3, 5);
+            tableLayoutPanel2.Controls.Add(lblModelParam12, 2, 6);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam12, 3, 6);
+            tableLayoutPanel2.Controls.Add(lblModelParam14, 2, 7);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam14, 3, 7);
+            tableLayoutPanel2.Controls.Add(lblModelParam15, 0, 8);
+            tableLayoutPanel2.Controls.Add(lblModelParam17, 0, 9);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam15, 1, 8);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam17, 1, 9);
+            tableLayoutPanel2.Controls.Add(lblModelParam16, 2, 8);
+            tableLayoutPanel2.Controls.Add(lblModelParam18, 2, 9);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam16, 3, 8);
+            tableLayoutPanel2.Controls.Add(dtxtModelParam18, 3, 9);
+            tableLayoutPanel2.Controls.Add(btnCreateModel, 2, 0);
+            tableLayoutPanel2.Controls.Add(lblModelType, 0, 0);
+            tableLayoutPanel2.Controls.Add(cmbModelType, 1, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(4, 4);
+            tableLayoutPanel2.Margin = new Padding(3, 4, 3, 4);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 12;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 8.333333F));
+            tableLayoutPanel2.Size = new Size(572, 636);
+            tableLayoutPanel2.TabIndex = 1;
+            // 
+            // dtxtModelParam13
+            // 
+            dtxtModelParam13.Location = new Point(132, 368);
+            dtxtModelParam13.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam13.Name = "dtxtModelParam13";
+            dtxtModelParam13.Size = new Size(138, 28);
+            dtxtModelParam13.TabIndex = 23;
+            dtxtModelParam13.Text = "0";
+            dtxtModelParam13.Visible = false;
+            // 
+            // lblModelParam13
+            // 
+            lblModelParam13.AutoSize = true;
+            lblModelParam13.Location = new Point(3, 364);
+            lblModelParam13.MaximumSize = new Size(0, 35);
+            lblModelParam13.MinimumSize = new Size(0, 35);
+            lblModelParam13.Name = "lblModelParam13";
+            lblModelParam13.Size = new Size(60, 35);
+            lblModelParam13.TabIndex = 17;
+            lblModelParam13.Text = "鍙傛暟13";
+            lblModelParam13.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam13.Visible = false;
+            // 
+            // lblModelParam11
+            // 
+            lblModelParam11.AutoSize = true;
+            lblModelParam11.Location = new Point(3, 312);
+            lblModelParam11.MaximumSize = new Size(0, 35);
+            lblModelParam11.MinimumSize = new Size(0, 35);
+            lblModelParam11.Name = "lblModelParam11";
+            lblModelParam11.Size = new Size(60, 35);
+            lblModelParam11.TabIndex = 15;
+            lblModelParam11.Text = "鍙傛暟11";
+            lblModelParam11.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam11.Visible = false;
+            // 
+            // dtxtModelParam11
+            // 
+            dtxtModelParam11.Location = new Point(132, 316);
+            dtxtModelParam11.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam11.Name = "dtxtModelParam11";
+            dtxtModelParam11.Size = new Size(138, 28);
+            dtxtModelParam11.TabIndex = 9;
+            dtxtModelParam11.Text = "0";
+            dtxtModelParam11.Visible = false;
+            // 
+            // lblModelParam9
+            // 
+            lblModelParam9.AutoSize = true;
+            lblModelParam9.Location = new Point(3, 260);
+            lblModelParam9.MaximumSize = new Size(0, 35);
+            lblModelParam9.MinimumSize = new Size(0, 35);
+            lblModelParam9.Name = "lblModelParam9";
+            lblModelParam9.Size = new Size(51, 35);
+            lblModelParam9.TabIndex = 13;
+            lblModelParam9.Text = "鍙傛暟9";
+            lblModelParam9.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam9.Visible = false;
+            // 
+            // dtxtModelParam9
+            // 
+            dtxtModelParam9.Location = new Point(132, 264);
+            dtxtModelParam9.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam9.Name = "dtxtModelParam9";
+            dtxtModelParam9.Size = new Size(138, 28);
+            dtxtModelParam9.TabIndex = 9;
+            dtxtModelParam9.Text = "0";
+            dtxtModelParam9.Visible = false;
+            // 
+            // lblModelParam7
+            // 
+            lblModelParam7.AutoSize = true;
+            lblModelParam7.Location = new Point(3, 208);
+            lblModelParam7.MaximumSize = new Size(0, 35);
+            lblModelParam7.MinimumSize = new Size(0, 35);
+            lblModelParam7.Name = "lblModelParam7";
+            lblModelParam7.Size = new Size(51, 35);
+            lblModelParam7.TabIndex = 11;
+            lblModelParam7.Text = "鍙傛暟7";
+            lblModelParam7.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam7.Visible = false;
+            // 
+            // dtxtModelParam7
+            // 
+            dtxtModelParam7.Location = new Point(132, 212);
+            dtxtModelParam7.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam7.Name = "dtxtModelParam7";
+            dtxtModelParam7.Size = new Size(138, 28);
+            dtxtModelParam7.TabIndex = 9;
+            dtxtModelParam7.Text = "0";
+            dtxtModelParam7.Visible = false;
+            // 
+            // lblModelParam5
+            // 
+            lblModelParam5.AutoSize = true;
+            lblModelParam5.Location = new Point(3, 156);
+            lblModelParam5.MaximumSize = new Size(0, 35);
+            lblModelParam5.MinimumSize = new Size(0, 35);
+            lblModelParam5.Name = "lblModelParam5";
+            lblModelParam5.Size = new Size(51, 35);
+            lblModelParam5.TabIndex = 9;
+            lblModelParam5.Text = "鍙傛暟5";
+            lblModelParam5.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam5.Visible = false;
+            // 
+            // dtxtModelParam5
+            // 
+            dtxtModelParam5.Location = new Point(132, 160);
+            dtxtModelParam5.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam5.Name = "dtxtModelParam5";
+            dtxtModelParam5.Size = new Size(138, 28);
+            dtxtModelParam5.TabIndex = 9;
+            dtxtModelParam5.Text = "0";
+            dtxtModelParam5.Visible = false;
+            // 
+            // lblModelParam3
+            // 
+            lblModelParam3.AutoSize = true;
+            lblModelParam3.Location = new Point(3, 104);
+            lblModelParam3.MaximumSize = new Size(0, 35);
+            lblModelParam3.MinimumSize = new Size(0, 35);
+            lblModelParam3.Name = "lblModelParam3";
+            lblModelParam3.Size = new Size(51, 35);
+            lblModelParam3.TabIndex = 2;
+            lblModelParam3.Text = "鍙傛暟3";
+            lblModelParam3.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam3.Visible = false;
+            // 
+            // dtxtModelParam3
+            // 
+            dtxtModelParam3.Location = new Point(132, 108);
+            dtxtModelParam3.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam3.Name = "dtxtModelParam3";
+            dtxtModelParam3.Size = new Size(138, 28);
+            dtxtModelParam3.TabIndex = 7;
+            dtxtModelParam3.Text = "0";
+            dtxtModelParam3.Visible = false;
+            // 
+            // lblModelParam1
+            // 
+            lblModelParam1.AutoSize = true;
+            lblModelParam1.Location = new Point(3, 52);
+            lblModelParam1.MaximumSize = new Size(0, 35);
+            lblModelParam1.MinimumSize = new Size(0, 35);
+            lblModelParam1.Name = "lblModelParam1";
+            lblModelParam1.Size = new Size(51, 35);
+            lblModelParam1.TabIndex = 0;
+            lblModelParam1.Text = "鍙傛暟1";
+            lblModelParam1.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam1.Visible = false;
+            // 
+            // dtxtModelParam1
+            // 
+            dtxtModelParam1.Location = new Point(132, 56);
+            dtxtModelParam1.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam1.Name = "dtxtModelParam1";
+            dtxtModelParam1.Size = new Size(138, 28);
+            dtxtModelParam1.TabIndex = 5;
+            dtxtModelParam1.Text = "0";
+            dtxtModelParam1.Visible = false;
+            // 
+            // dtxtModelParam2
+            // 
+            dtxtModelParam2.Location = new Point(418, 56);
+            dtxtModelParam2.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam2.Name = "dtxtModelParam2";
+            dtxtModelParam2.Size = new Size(138, 28);
+            dtxtModelParam2.TabIndex = 6;
+            dtxtModelParam2.Text = "0";
+            dtxtModelParam2.Visible = false;
+            // 
+            // btnSaveModel
+            // 
+            btnSaveModel.Location = new Point(419, 4);
+            btnSaveModel.Margin = new Padding(4, 4, 4, 4);
+            btnSaveModel.Name = "btnSaveModel";
+            btnSaveModel.Size = new Size(107, 28);
+            btnSaveModel.TabIndex = 30;
+            btnSaveModel.Text = "淇濆瓨妯℃澘";
+            btnSaveModel.UseVisualStyleBackColor = true;
+            btnSaveModel.Click += btnSaveModel_Click;
+            // 
+            // lblModelParam2
+            // 
+            lblModelParam2.AutoSize = true;
+            lblModelParam2.Location = new Point(289, 52);
+            lblModelParam2.MaximumSize = new Size(0, 35);
+            lblModelParam2.MinimumSize = new Size(0, 35);
+            lblModelParam2.Name = "lblModelParam2";
+            lblModelParam2.Size = new Size(51, 35);
+            lblModelParam2.TabIndex = 1;
+            lblModelParam2.Text = "鍙傛暟2";
+            lblModelParam2.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam2.Visible = false;
+            // 
+            // lblModelParam4
+            // 
+            lblModelParam4.AutoSize = true;
+            lblModelParam4.Location = new Point(289, 104);
+            lblModelParam4.MaximumSize = new Size(0, 35);
+            lblModelParam4.MinimumSize = new Size(0, 35);
+            lblModelParam4.Name = "lblModelParam4";
+            lblModelParam4.Size = new Size(51, 35);
+            lblModelParam4.TabIndex = 3;
+            lblModelParam4.Text = "鍙傛暟4";
+            lblModelParam4.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam4.Visible = false;
+            // 
+            // dtxtModelParam4
+            // 
+            dtxtModelParam4.Location = new Point(418, 108);
+            dtxtModelParam4.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam4.Name = "dtxtModelParam4";
+            dtxtModelParam4.Size = new Size(138, 28);
+            dtxtModelParam4.TabIndex = 8;
+            dtxtModelParam4.Text = "0";
+            dtxtModelParam4.Visible = false;
+            // 
+            // lblModelParam6
+            // 
+            lblModelParam6.AutoSize = true;
+            lblModelParam6.Location = new Point(289, 156);
+            lblModelParam6.MaximumSize = new Size(0, 35);
+            lblModelParam6.MinimumSize = new Size(0, 35);
+            lblModelParam6.Name = "lblModelParam6";
+            lblModelParam6.Size = new Size(51, 35);
+            lblModelParam6.TabIndex = 10;
+            lblModelParam6.Text = "鍙傛暟6";
+            lblModelParam6.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam6.Visible = false;
+            // 
+            // dtxtModelParam6
+            // 
+            dtxtModelParam6.Location = new Point(418, 160);
+            dtxtModelParam6.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam6.Name = "dtxtModelParam6";
+            dtxtModelParam6.Size = new Size(138, 28);
+            dtxtModelParam6.TabIndex = 9;
+            dtxtModelParam6.Text = "0";
+            dtxtModelParam6.Visible = false;
+            // 
+            // lblModelParam8
+            // 
+            lblModelParam8.AutoSize = true;
+            lblModelParam8.Location = new Point(289, 208);
+            lblModelParam8.MaximumSize = new Size(0, 35);
+            lblModelParam8.MinimumSize = new Size(0, 35);
+            lblModelParam8.Name = "lblModelParam8";
+            lblModelParam8.Size = new Size(51, 35);
+            lblModelParam8.TabIndex = 12;
+            lblModelParam8.Text = "鍙傛暟8";
+            lblModelParam8.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam8.Visible = false;
+            // 
+            // dtxtModelParam8
+            // 
+            dtxtModelParam8.Location = new Point(418, 212);
+            dtxtModelParam8.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam8.Name = "dtxtModelParam8";
+            dtxtModelParam8.Size = new Size(138, 28);
+            dtxtModelParam8.TabIndex = 9;
+            dtxtModelParam8.Text = "0";
+            dtxtModelParam8.Visible = false;
+            // 
+            // lblModelParam10
+            // 
+            lblModelParam10.AutoSize = true;
+            lblModelParam10.Location = new Point(289, 260);
+            lblModelParam10.MaximumSize = new Size(0, 35);
+            lblModelParam10.MinimumSize = new Size(0, 35);
+            lblModelParam10.Name = "lblModelParam10";
+            lblModelParam10.Size = new Size(60, 35);
+            lblModelParam10.TabIndex = 14;
+            lblModelParam10.Text = "鍙傛暟10";
+            lblModelParam10.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam10.Visible = false;
+            // 
+            // dtxtModelParam10
+            // 
+            dtxtModelParam10.Location = new Point(418, 264);
+            dtxtModelParam10.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam10.Name = "dtxtModelParam10";
+            dtxtModelParam10.Size = new Size(138, 28);
+            dtxtModelParam10.TabIndex = 9;
+            dtxtModelParam10.Text = "1";
+            dtxtModelParam10.Visible = false;
+            // 
+            // lblModelParam12
+            // 
+            lblModelParam12.AutoSize = true;
+            lblModelParam12.Location = new Point(289, 312);
+            lblModelParam12.MaximumSize = new Size(0, 35);
+            lblModelParam12.MinimumSize = new Size(0, 35);
+            lblModelParam12.Name = "lblModelParam12";
+            lblModelParam12.Size = new Size(60, 35);
+            lblModelParam12.TabIndex = 16;
+            lblModelParam12.Text = "鍙傛暟12";
+            lblModelParam12.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam12.Visible = false;
+            // 
+            // dtxtModelParam12
+            // 
+            dtxtModelParam12.Location = new Point(418, 316);
+            dtxtModelParam12.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam12.Name = "dtxtModelParam12";
+            dtxtModelParam12.Size = new Size(138, 28);
+            dtxtModelParam12.TabIndex = 10;
+            dtxtModelParam12.Text = "1";
+            dtxtModelParam12.Visible = false;
+            // 
+            // lblModelParam14
+            // 
+            lblModelParam14.AutoSize = true;
+            lblModelParam14.Location = new Point(289, 364);
+            lblModelParam14.MaximumSize = new Size(0, 35);
+            lblModelParam14.MinimumSize = new Size(0, 35);
+            lblModelParam14.Name = "lblModelParam14";
+            lblModelParam14.Size = new Size(60, 35);
+            lblModelParam14.TabIndex = 18;
+            lblModelParam14.Text = "鍙傛暟14";
+            lblModelParam14.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam14.Visible = false;
+            // 
+            // dtxtModelParam14
+            // 
+            dtxtModelParam14.Location = new Point(418, 368);
+            dtxtModelParam14.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam14.Name = "dtxtModelParam14";
+            dtxtModelParam14.Size = new Size(138, 28);
+            dtxtModelParam14.TabIndex = 24;
+            dtxtModelParam14.Text = "0";
+            dtxtModelParam14.Visible = false;
+            // 
+            // lblModelParam15
+            // 
+            lblModelParam15.AutoSize = true;
+            lblModelParam15.Location = new Point(3, 416);
+            lblModelParam15.MaximumSize = new Size(0, 35);
+            lblModelParam15.MinimumSize = new Size(0, 35);
+            lblModelParam15.Name = "lblModelParam15";
+            lblModelParam15.Size = new Size(60, 35);
+            lblModelParam15.TabIndex = 19;
+            lblModelParam15.Text = "鍙傛暟15";
+            lblModelParam15.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam15.Visible = false;
+            // 
+            // lblModelParam17
+            // 
+            lblModelParam17.AutoSize = true;
+            lblModelParam17.Location = new Point(3, 468);
+            lblModelParam17.MaximumSize = new Size(0, 35);
+            lblModelParam17.MinimumSize = new Size(0, 35);
+            lblModelParam17.Name = "lblModelParam17";
+            lblModelParam17.Size = new Size(60, 35);
+            lblModelParam17.TabIndex = 21;
+            lblModelParam17.Text = "鍙傛暟17";
+            lblModelParam17.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam17.Visible = false;
+            // 
+            // dtxtModelParam15
+            // 
+            dtxtModelParam15.Location = new Point(132, 420);
+            dtxtModelParam15.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam15.Name = "dtxtModelParam15";
+            dtxtModelParam15.Size = new Size(138, 28);
+            dtxtModelParam15.TabIndex = 25;
+            dtxtModelParam15.Text = "0";
+            dtxtModelParam15.Visible = false;
+            // 
+            // dtxtModelParam17
+            // 
+            dtxtModelParam17.Location = new Point(132, 472);
+            dtxtModelParam17.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam17.Name = "dtxtModelParam17";
+            dtxtModelParam17.Size = new Size(138, 28);
+            dtxtModelParam17.TabIndex = 27;
+            dtxtModelParam17.Text = "0";
+            dtxtModelParam17.Visible = false;
+            // 
+            // lblModelParam16
+            // 
+            lblModelParam16.AutoSize = true;
+            lblModelParam16.Location = new Point(289, 416);
+            lblModelParam16.MaximumSize = new Size(0, 35);
+            lblModelParam16.MinimumSize = new Size(0, 35);
+            lblModelParam16.Name = "lblModelParam16";
+            lblModelParam16.Size = new Size(60, 35);
+            lblModelParam16.TabIndex = 20;
+            lblModelParam16.Text = "鍙傛暟16";
+            lblModelParam16.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam16.Visible = false;
+            // 
+            // lblModelParam18
+            // 
+            lblModelParam18.AutoSize = true;
+            lblModelParam18.Location = new Point(289, 468);
+            lblModelParam18.MaximumSize = new Size(0, 35);
+            lblModelParam18.MinimumSize = new Size(0, 35);
+            lblModelParam18.Name = "lblModelParam18";
+            lblModelParam18.Size = new Size(60, 35);
+            lblModelParam18.TabIndex = 22;
+            lblModelParam18.Text = "鍙傛暟18";
+            lblModelParam18.TextAlign = ContentAlignment.MiddleCenter;
+            lblModelParam18.Visible = false;
+            // 
+            // dtxtModelParam16
+            // 
+            dtxtModelParam16.Location = new Point(418, 420);
+            dtxtModelParam16.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam16.Name = "dtxtModelParam16";
+            dtxtModelParam16.Size = new Size(138, 28);
+            dtxtModelParam16.TabIndex = 26;
+            dtxtModelParam16.Text = "0";
+            dtxtModelParam16.Visible = false;
+            // 
+            // dtxtModelParam18
+            // 
+            dtxtModelParam18.Location = new Point(418, 472);
+            dtxtModelParam18.Margin = new Padding(3, 4, 3, 4);
+            dtxtModelParam18.Name = "dtxtModelParam18";
+            dtxtModelParam18.Size = new Size(138, 28);
+            dtxtModelParam18.TabIndex = 28;
+            dtxtModelParam18.Text = "0";
+            dtxtModelParam18.Visible = false;
+            // 
+            // btnCreateModel
+            // 
+            btnCreateModel.Location = new Point(290, 4);
+            btnCreateModel.Margin = new Padding(4, 4, 4, 4);
+            btnCreateModel.Name = "btnCreateModel";
+            btnCreateModel.Size = new Size(107, 28);
+            btnCreateModel.TabIndex = 29;
+            btnCreateModel.Text = "鍒涘缓妯℃澘";
+            btnCreateModel.UseVisualStyleBackColor = true;
+            btnCreateModel.Click += btnCreateModel_Click;
+            // 
+            // lblModelType
+            // 
+            lblModelType.AutoSize = true;
+            lblModelType.Location = new Point(3, 0);
+            lblModelType.MaximumSize = new Size(0, 35);
+            lblModelType.MinimumSize = new Size(0, 35);
+            lblModelType.Name = "lblModelType";
+            lblModelType.Size = new Size(74, 35);
+            lblModelType.TabIndex = 31;
+            lblModelType.Text = "鍖归厤绠楁硶";
+            lblModelType.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // cmbModelType
+            // 
+            cmbModelType.Font = new Font("Microsoft YaHei UI", 9F);
+            cmbModelType.FormattingEnabled = true;
+            cmbModelType.Location = new Point(133, 4);
+            cmbModelType.Margin = new Padding(4, 4, 4, 4);
+            cmbModelType.Name = "cmbModelType";
+            cmbModelType.Size = new Size(137, 25);
+            cmbModelType.TabIndex = 32;
+            cmbModelType.SelectedIndexChanged += cmbModelType_SelectedIndexChanged;
+            // 
+            // tabPage2
+            // 
+            tabPage2.Controls.Add(tableLayoutResults);
+            tabPage2.Location = new Point(4, 30);
+            tabPage2.Margin = new Padding(4, 4, 4, 4);
+            tabPage2.Name = "tabPage2";
+            tabPage2.Padding = new Padding(4, 4, 4, 4);
+            tabPage2.Size = new Size(579, 640);
+            tabPage2.TabIndex = 1;
+            tabPage2.Text = "杈撳嚭缁撴灉";
+            tabPage2.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutResults
+            // 
+            tableLayoutResults.ColumnCount = 2;
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 143F));
+            tableLayoutResults.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutResults.Controls.Add(dtxtCount, 1, 4);
+            tableLayoutResults.Controls.Add(label5, 0, 0);
+            tableLayoutResults.Controls.Add(label6, 0, 1);
+            tableLayoutResults.Controls.Add(label7, 0, 2);
+            tableLayoutResults.Controls.Add(dtxtCenterX, 1, 0);
+            tableLayoutResults.Controls.Add(dtxtCenterY, 1, 1);
+            tableLayoutResults.Controls.Add(dtxtPhi, 1, 2);
+            tableLayoutResults.Controls.Add(label8, 0, 3);
+            tableLayoutResults.Controls.Add(dtxtScore, 1, 3);
+            tableLayoutResults.Controls.Add(label9, 0, 4);
+            tableLayoutResults.Dock = DockStyle.Fill;
+            tableLayoutResults.Location = new Point(4, 4);
+            tableLayoutResults.Margin = new Padding(3, 4, 3, 4);
+            tableLayoutResults.Name = "tableLayoutResults";
+            tableLayoutResults.RowCount = 10;
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.RowStyles.Add(new RowStyle(SizeType.Percent, 10F));
+            tableLayoutResults.Size = new Size(571, 632);
+            tableLayoutResults.TabIndex = 1;
+            // 
+            // dtxtCount
+            // 
+            dtxtCount.Location = new Point(147, 256);
+            dtxtCount.Margin = new Padding(4, 4, 4, 4);
+            dtxtCount.Name = "dtxtCount";
+            dtxtCount.ReadOnly = true;
+            dtxtCount.Size = new Size(414, 28);
+            dtxtCount.TabIndex = 11;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Dock = DockStyle.Fill;
+            label5.Location = new Point(3, 0);
+            label5.MaximumSize = new Size(0, 35);
+            label5.MinimumSize = new Size(0, 35);
+            label5.Name = "label5";
+            label5.Size = new Size(137, 35);
+            label5.TabIndex = 0;
+            label5.Text = "X";
+            label5.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label6
+            // 
+            label6.AutoSize = true;
+            label6.Dock = DockStyle.Fill;
+            label6.Location = new Point(3, 63);
+            label6.MaximumSize = new Size(0, 35);
+            label6.MinimumSize = new Size(0, 35);
+            label6.Name = "label6";
+            label6.Size = new Size(137, 35);
+            label6.TabIndex = 1;
+            label6.Text = "Y";
+            label6.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // label7
+            // 
+            label7.AutoSize = true;
+            label7.Dock = DockStyle.Fill;
+            label7.Location = new Point(3, 126);
+            label7.MaximumSize = new Size(0, 35);
+            label7.MinimumSize = new Size(0, 35);
+            label7.Name = "label7";
+            label7.Size = new Size(137, 35);
+            label7.TabIndex = 2;
+            label7.Text = "寮у害(rad)";
+            label7.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtCenterX
+            // 
+            dtxtCenterX.Dock = DockStyle.Fill;
+            dtxtCenterX.Location = new Point(146, 4);
+            dtxtCenterX.Margin = new Padding(3, 4, 3, 4);
+            dtxtCenterX.Name = "dtxtCenterX";
+            dtxtCenterX.ReadOnly = true;
+            dtxtCenterX.Size = new Size(422, 28);
+            dtxtCenterX.TabIndex = 5;
+            // 
+            // dtxtCenterY
+            // 
+            dtxtCenterY.Dock = DockStyle.Fill;
+            dtxtCenterY.Location = new Point(146, 67);
+            dtxtCenterY.Margin = new Padding(3, 4, 3, 4);
+            dtxtCenterY.Name = "dtxtCenterY";
+            dtxtCenterY.ReadOnly = true;
+            dtxtCenterY.Size = new Size(422, 28);
+            dtxtCenterY.TabIndex = 6;
+            // 
+            // dtxtPhi
+            // 
+            dtxtPhi.Dock = DockStyle.Fill;
+            dtxtPhi.Location = new Point(146, 130);
+            dtxtPhi.Margin = new Padding(3, 4, 3, 4);
+            dtxtPhi.Name = "dtxtPhi";
+            dtxtPhi.ReadOnly = true;
+            dtxtPhi.Size = new Size(422, 28);
+            dtxtPhi.TabIndex = 7;
+            // 
+            // label8
+            // 
+            label8.AutoSize = true;
+            label8.Dock = DockStyle.Fill;
+            label8.Location = new Point(4, 189);
+            label8.Margin = new Padding(4, 0, 4, 0);
+            label8.Name = "label8";
+            label8.Size = new Size(135, 63);
+            label8.TabIndex = 8;
+            label8.Text = "鍒嗘暟";
+            label8.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // dtxtScore
+            // 
+            dtxtScore.Location = new Point(147, 193);
+            dtxtScore.Margin = new Padding(4, 4, 4, 4);
+            dtxtScore.Name = "dtxtScore";
+            dtxtScore.ReadOnly = true;
+            dtxtScore.Size = new Size(414, 28);
+            dtxtScore.TabIndex = 9;
+            // 
+            // label9
+            // 
+            label9.AutoSize = true;
+            label9.Dock = DockStyle.Fill;
+            label9.Location = new Point(4, 252);
+            label9.Margin = new Padding(4, 0, 4, 0);
+            label9.Name = "label9";
+            label9.Size = new Size(135, 63);
+            label9.TabIndex = 10;
+            label9.Text = "鏁伴噺";
+            label9.TextAlign = ContentAlignment.TopCenter;
+            // 
+            // imgTabControl
+            // 
+            imgTabControl.Controls.Add(tabPageInputImage);
+            imgTabControl.Controls.Add(tabPageModelImage);
+            imgTabControl.Controls.Add(tabPageRecordImage);
+            imgTabControl.Dock = DockStyle.Fill;
+            imgTabControl.Location = new Point(600, 4);
+            imgTabControl.Margin = new Padding(4, 4, 4, 4);
+            imgTabControl.Name = "imgTabControl";
+            imgTabControl.SelectedIndex = 0;
+            imgTabControl.Size = new Size(887, 678);
+            imgTabControl.TabIndex = 49;
+            // 
+            // tabPageInputImage
+            // 
+            tabPageInputImage.Controls.Add(pnlInputImage);
+            tabPageInputImage.Location = new Point(4, 30);
+            tabPageInputImage.Margin = new Padding(4, 4, 4, 4);
+            tabPageInputImage.Name = "tabPageInputImage";
+            tabPageInputImage.Padding = new Padding(4, 4, 4, 4);
+            tabPageInputImage.Size = new Size(879, 644);
+            tabPageInputImage.TabIndex = 0;
+            tabPageInputImage.Text = "杈撳叆鍥惧儚";
+            tabPageInputImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlInputImage
+            // 
+            pnlInputImage.Dock = DockStyle.Fill;
+            pnlInputImage.Location = new Point(4, 4);
+            pnlInputImage.Margin = new Padding(6, 5, 6, 5);
+            pnlInputImage.Name = "pnlInputImage";
+            pnlInputImage.Size = new Size(871, 636);
+            pnlInputImage.TabIndex = 44;
+            // 
+            // tabPageModelImage
+            // 
+            tabPageModelImage.Controls.Add(pnlCreateModelImage);
+            tabPageModelImage.Location = new Point(4, 30);
+            tabPageModelImage.Margin = new Padding(4, 4, 4, 4);
+            tabPageModelImage.Name = "tabPageModelImage";
+            tabPageModelImage.Size = new Size(879, 640);
+            tabPageModelImage.TabIndex = 2;
+            tabPageModelImage.Text = "妯℃澘鍥惧儚";
+            tabPageModelImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlCreateModelImage
+            // 
+            pnlCreateModelImage.Dock = DockStyle.Fill;
+            pnlCreateModelImage.Location = new Point(0, 0);
+            pnlCreateModelImage.Margin = new Padding(4, 4, 4, 4);
+            pnlCreateModelImage.Name = "pnlCreateModelImage";
+            pnlCreateModelImage.Size = new Size(879, 640);
+            pnlCreateModelImage.TabIndex = 0;
+            // 
+            // tabPageRecordImage
+            // 
+            tabPageRecordImage.Controls.Add(pnlRecordImage);
+            tabPageRecordImage.Location = new Point(4, 30);
+            tabPageRecordImage.Margin = new Padding(4, 4, 4, 4);
+            tabPageRecordImage.Name = "tabPageRecordImage";
+            tabPageRecordImage.Padding = new Padding(4, 4, 4, 4);
+            tabPageRecordImage.Size = new Size(879, 640);
+            tabPageRecordImage.TabIndex = 1;
+            tabPageRecordImage.Text = "缁撴灉鍥惧儚";
+            tabPageRecordImage.UseVisualStyleBackColor = true;
+            // 
+            // pnlRecordImage
+            // 
+            pnlRecordImage.Dock = DockStyle.Fill;
+            pnlRecordImage.Location = new Point(4, 4);
+            pnlRecordImage.Margin = new Padding(6, 5, 6, 5);
+            pnlRecordImage.Name = "pnlRecordImage";
+            pnlRecordImage.Size = new Size(871, 632);
+            pnlRecordImage.TabIndex = 45;
+            // 
+            // FindModelToolEdit
+            // 
+            AutoScaleDimensions = new SizeF(10F, 21F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(MainTableLayoutPanel);
+            Controls.Add(BtmStatusStrip);
+            Controls.Add(TopToolStrip);
+            Margin = new Padding(3, 4, 3, 4);
+            Name = "FindModelToolEdit";
+            Size = new Size(1491, 740);
+            Load += HFindModelToolEdit_Load;
+            SizeChanged += HFindModelToolEdit_SizeChanged;
+            tablePanelParas.ResumeLayout(false);
+            tablePanelParas.PerformLayout();
+            TopToolStrip.ResumeLayout(false);
+            TopToolStrip.PerformLayout();
+            BtmStatusStrip.ResumeLayout(false);
+            BtmStatusStrip.PerformLayout();
+            MainTableLayoutPanel.ResumeLayout(false);
+            parasTabControl.ResumeLayout(false);
+            tabPage1.ResumeLayout(false);
+            tabPageRunParas.ResumeLayout(false);
+            tableLayoutPanel3.ResumeLayout(false);
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel1.PerformLayout();
+            tabPage7.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel2.PerformLayout();
+            tabPage2.ResumeLayout(false);
+            tableLayoutResults.ResumeLayout(false);
+            tableLayoutResults.PerformLayout();
+            imgTabControl.ResumeLayout(false);
+            tabPageInputImage.ResumeLayout(false);
+            tabPageModelImage.ResumeLayout(false);
+            tabPageRecordImage.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TableLayoutPanel tablePanelParas;
+        private System.Windows.Forms.Label lblInputParam1;
+        private System.Windows.Forms.Label lblInputParam2;
+        private System.Windows.Forms.Label lblInputParam3;
+        private System.Windows.Forms.Label lblInputParam4;
+        private System.Windows.Forms.TextBox dtxtInputParam1;
+        private System.Windows.Forms.TextBox dtxtInputParam2;
+        private System.Windows.Forms.TextBox dtxtInputParam3;
+        private System.Windows.Forms.TextBox dtxtInputParam4;
+        private ToolStrip TopToolStrip;
+        private ToolStripButton btnRun;
+        private StatusStrip BtmStatusStrip;
+        private ToolStripStatusLabel lblResult;
+        private ToolStripStatusLabel lblMsg;
+        private TableLayoutPanel MainTableLayoutPanel;
+        private ToolStripButton btnLoadImage;
+        private TabControl parasTabControl;
+        private TabPage tabPage1;
+        private TabPage tabPage2;
+        private TabPage tabPageRunParas;
+        private TabControl imgTabControl;
+        private TabPage tabPageRecordImage;
+        private ToolStripButton btnSaveParas;
+        private ToolStripButton btnLoadParas;
+        private Panel pnlRecordImage;
+        private Label lblInputParam5;
+        private Label lblInputParam6;
+        private Label lblInputParam7;
+        private Label lblInputParam8;
+        private Label lblInputParam9;
+        private Label lblInputParam10;
+        private Label lblInputParam11;
+        private Label lblInputParam12;
+        private TextBox dtxtInputParam12;
+        private TextBox dtxtInputParam11;
+        private TextBox dtxtInputParam10;
+        private TextBox dtxtInputParam9;
+        private TextBox dtxtInputParam8;
+        private TextBox dtxtInputParam7;
+        private TextBox dtxtInputParam6;
+        private TextBox dtxtInputParam5;
+        private TabPage tabPageModelImage;
+        private TabPage tabPage7;
+        private TableLayoutPanel tableLayoutResults;
+        private Label label5;
+        private Label label6;
+        private Label label7;
+        private TextBox dtxtCenterX;
+        private TextBox dtxtCenterY;
+        private TextBox dtxtPhi;
+        private Label lblInputParam13;
+        private Label lblInputParam14;
+        private Label lblInputParam15;
+        private Label lblInputParam16;
+        private Label lblInputParam17;
+        private Label lblInputParam18;
+        private TextBox dtxtInputParam13;
+        private TextBox dtxtInputParam14;
+        private TextBox dtxtInputParam15;
+        private TextBox dtxtInputParam16;
+        private TextBox dtxtInputParam17;
+        private TextBox dtxtInputParam18;
+        private TableLayoutPanel tableLayoutPanel2;
+        private Label lblModelParam1;
+        private TextBox dtxtModelParam1;
+        private Label lblModelParam2;
+        private TextBox dtxtModelParam2;
+        private Label lblModelParam3;
+        private TextBox dtxtModelParam3;
+        private Label lblModelParam4;
+        private TextBox dtxtModelParam4;
+        private Label lblModelParam5;
+        private TextBox dtxtModelParam5;
+        private Label lblModelParam6;
+        private TextBox dtxtModelParam6;
+        private Label lblModelParam7;
+        private TextBox dtxtModelParam7;
+        private Label lblModelParam8;
+        private TextBox dtxtModelParam8;
+        private Label lblModelParam9;
+        private TextBox dtxtModelParam9;
+        private Label lblModelParam10;
+        private TextBox dtxtModelParam10;
+        private Label lblModelParam11;
+        private TextBox dtxtModelParam11;
+        private Label lblModelParam12;
+        private TextBox dtxtModelParam12;
+        private Label lblModelParam13;
+        private Label lblModelParam14;
+        private Label lblModelParam15;
+        private Label lblModelParam16;
+        private Label lblModelParam17;
+        private Label lblModelParam18;
+        private TextBox dtxtModelParam13;
+        private TextBox dtxtModelParam14;
+        private TextBox dtxtModelParam15;
+        private TextBox dtxtModelParam16;
+        private TextBox dtxtModelParam17;
+        private TextBox dtxtModelParam18;
+        private Button btnCreateModel;
+        private Button btnSaveModel;
+        private GroupBox grpModel;
+        private TableLayoutPanel tableLayoutPanel3;
+        private TabPage tabPageInputImage;
+        private Panel pnlInputImage;
+        private Panel pnlCreateModelImage;
+        private Label label8;
+        private TextBox dtxtScore;
+        private TextBox dtxtCount;
+        private Label label9;
+        private ToolStripStatusLabel lblRunTime;
+        private Label lblModelType;
+        private ComboBox cmbModelType;
+        private TableLayoutPanel tableLayoutPanel1;
+        public ComboBox cmbTypeRoi;
+        private Label label21;
+        private Label label22;
+        private ComboBox cmbFixture;
+        private CheckBox ckbDrawRoi;
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.cs b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.cs
new file mode 100644
index 0000000..392ee61
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.cs
@@ -0,0 +1,1249 @@
+锘縰sing HalconDotNet;
+using LB_VisionControl;
+using OpenCvSharp;
+using System.Diagnostics;
+using System.Reflection;
+using static LB_VisionProcesses.Alogrithms.OpenCvSharp.FindModelTool;
+
+namespace LB_VisionProcesses.Alogrithms.OpenCvSharp
+{
+    public partial class FindModelToolEdit : TAlgorithmEdit
+    {
+        public FindModelToolEdit(FindModelTool subject = null)
+        {
+            if (subject != null && subject is FindModelTool)
+                Subject = subject;
+            else
+                Subject = new FindModelTool();
+
+            this.Dock = DockStyle.Fill;
+            InitializeComponent();
+        }
+
+        public UserHSmartWindowControl modelImageHSmartWindowControl = new UserHSmartWindowControl();
+        public UserHSmartWindowControl createModelImageHSmartWindowControl = new UserHSmartWindowControl();
+
+        /// <summary>
+        /// 鎺т欢鍔犺浇浜嬩欢
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void HFindModelToolEdit_Load(object sender, EventArgs e)
+        {
+            pnlInputImage.Controls.Add(inputImageHSmartWindowControl);
+            inputImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            pnlRecordImage.Controls.Add(recordImageHSmartWindowControl);
+            recordImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            pnlCreateModelImage.Controls.Add(createModelImageHSmartWindowControl);
+            createModelImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            grpModel.Controls.Add(modelImageHSmartWindowControl);
+            modelImageHSmartWindowControl.Dock = DockStyle.Fill;
+
+            //cmbModelType.SelectedIndex = cmbModelType.FindString("褰㈢姸");
+            UpdataInputsUI();
+
+            // 璁剧疆鏄剧ず鏍峰紡
+            toolTip.AutoPopDelay = 5000;//鎻愮ず淇℃伅鐨勫彲瑙佹椂闂�
+            toolTip.InitialDelay = 500;//浜嬩欢瑙﹀彂澶氫箙鍚庡嚭鐜版彁绀�
+            toolTip.ReshowDelay = 500;//鎸囬拡浠庝竴涓帶浠剁Щ鍚戝彟涓�涓帶浠舵椂锛岀粡杩囧涔呮墠浼氭樉绀轰笅涓�涓彁绀烘
+            toolTip.ShowAlways = true;//鏄惁鏄剧ず鎻愮ず妗�
+
+            //閬嶅巻鍙互閫夋嫨鐨凴oi绫诲瀷鏋氫妇
+            foreach (var value in Enum.GetValues(typeof(RoiType)))
+            {
+                cmbTypeRoi.Items.Add(value.ToString());
+            }
+
+            //閬嶅巻鍙互閫夋嫨鐨凢ixture鏋氫妇
+            cmbFixture.Items.Add("");
+            foreach (string value in IProcess.dicFixtures.Keys)
+                cmbFixture.Items.Add(value.ToString());
+
+            //閬嶅巻鍙互閫夋嫨鐨凪odel绫诲瀷鏋氫妇
+            foreach (var value in Enum.GetValues(typeof(ModelType)))
+                cmbModelType.Items.Add(value.ToString());
+
+            cmbTypeRoi.Text = RoiType.None.ToString();
+            LoadParas();
+
+            if (Subject.Result)
+            {
+                lblResult.BackColor = Color.Green;
+                lblResult.Text = "True";
+            }
+            else
+            {
+                lblResult.BackColor = Color.Red;
+                lblResult.Text = "False";
+            }
+
+            lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+            lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+            lblRunTime.Text = $"{Subject.RunTime}ms";
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯鍙傛暟
+        /// </summary>
+        public override void UpdataInputs()
+        {
+            //璁剧疆杩愯鍙傛暟
+            double dResult = 0;
+            int iResult = 0;
+            cmbModelType.Text = ((FindModelTool)Subject).ModelID.Type.ToString();
+            if (Enum.TryParse(cmbModelType.SelectedItem.ToString(), out ModelType modelType))
+            {
+                switch (modelType)
+                {
+                    case ModelType.鐏板害鍖归厤:
+                        //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                        //, ScaleRMin, ScaleRMax
+                        //, ScaleCMin, ScaleCMax
+                        //, MinScore, NumMatches, MaxOverlap
+                        //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                        //, Greediness, ResultType, new HTuple(), new HTuple()
+                        //, out hv_Score, out hv_CenterRow, out hv_CenterColumn);
+                        #region 杈撳叆鍙傛暟
+                        Subject.Params.Inputs["AngleStart"] = dtxtInputParam1.Text;
+                        Subject.Params.Inputs["AngleExtent"] = dtxtInputParam2.Text;
+                        Subject.Params.Inputs["ScaleRMin"] = dtxtInputParam3.Text;
+                        Subject.Params.Inputs["ScaleRMax"] = dtxtInputParam4.Text;
+                        Subject.Params.Inputs["ScaleCMin"] = dtxtInputParam5.Text;
+                        Subject.Params.Inputs["ScaleCMax"] = dtxtInputParam6.Text;
+                        Subject.Params.Inputs["MinScore"] = dtxtInputParam7.Text;
+                        Subject.Params.Inputs["NumMatches"] = dtxtInputParam8.Text;
+                        Subject.Params.Inputs["MaxOverlap"] = dtxtInputParam9.Text;
+                        Subject.Params.Inputs["ResultType"] = dtxtInputParam10.Text;
+                        Subject.Params.Inputs["NumLevels"] = dtxtInputParam11.Text;
+                        Subject.Params.Inputs["Greediness"] = dtxtInputParam12.Text;
+                        Subject.Params.Inputs["MinCount"] = dtxtInputParam13.Text;
+                        Subject.Params.Inputs["MaxCount"] = dtxtInputParam14.Text;
+                        #endregion
+                        break;
+                    default:
+                        //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                        //, ScaleRMin, ScaleRMax
+                        //, ScaleCMin, ScaleCMax
+                        //, MinScore, NumMatches, MaxOverlap, SubPixel
+                        //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                        //, Greediness
+                        #region 杈撳叆鍙傛暟
+                        Subject.Params.Inputs["AngleStart"] = dtxtInputParam1.Text;
+                        Subject.Params.Inputs["AngleExtent"] = dtxtInputParam2.Text;
+                        Subject.Params.Inputs["ScaleRMin"] = dtxtInputParam3.Text;
+                        Subject.Params.Inputs["ScaleRMax"] = dtxtInputParam4.Text;
+                        Subject.Params.Inputs["ScaleCMin"] = dtxtInputParam5.Text;
+                        Subject.Params.Inputs["ScaleCMax"] = dtxtInputParam6.Text;
+                        Subject.Params.Inputs["MinScore"] = dtxtInputParam7.Text;
+                        Subject.Params.Inputs["NumMatches"] = dtxtInputParam8.Text;
+                        Subject.Params.Inputs["MaxOverlap"] = dtxtInputParam9.Text;
+                        Subject.Params.Inputs["SubPixel"] = dtxtInputParam10.Text;
+                        Subject.Params.Inputs["NumLevels"] = dtxtInputParam11.Text;
+                        Subject.Params.Inputs["Greediness"] = dtxtInputParam12.Text;
+                        Subject.Params.Inputs["MinCount"] = dtxtInputParam13.Text;
+                        Subject.Params.Inputs["MaxCount"] = dtxtInputParam14.Text;
+                        #endregion
+                        break;
+                }
+
+                //if (cmbFixture.Text == "")
+                //    Subject.Params.Fixture = new Fixture();
+                //else if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                //    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+
+                Type type = inputImageHSmartWindowControl.oRoi?.GetType();
+                switch (type)
+                {
+                    case Type t when t == typeof(HRectangle2):
+                        HRectangle2 hRectangle2 = (HRectangle2)inputImageHSmartWindowControl.oRoi;
+                        Subject.Params.ROI
+                            = new HRectangle2(hRectangle2.X - Subject.Params.Fixture.X, hRectangle2.Y - Subject.Params.Fixture.Y
+                            , hRectangle2.Phi - Subject.Params.Fixture.Phi, hRectangle2.Width, hRectangle2.Height);
+                        break;
+                    case Type t when t == typeof(HCircle):
+                        HCircle hCircle = (HCircle)inputImageHSmartWindowControl.oRoi;
+                        Subject.Params.ROI
+                            = new HCircle(hCircle.X - Subject.Params.Fixture.X, hCircle.Y - Subject.Params.Fixture.Y, hCircle.Radius);
+                        break;
+                    case Type t when t == typeof(HSegment):
+                        HSegment hSegment = (HSegment)inputImageHSmartWindowControl.oRoi;
+                        Subject.Params.ROI
+                            = new HSegment(hSegment.StartX - Subject.Params.Fixture.X, hSegment.StartY - Subject.Params.Fixture.Y
+                            , hSegment.EndX - Subject.Params.Fixture.X, hSegment.EndY - Subject.Params.Fixture.Y);
+                        break;
+                    default:
+                        Subject.Params.ROI = new ROI();
+                        break;
+                }
+
+            }
+        }
+
+        /// <summary>
+        /// 鍔犺浇杩愯鍙傛暟
+        /// </summary>
+        public override void LoadParas()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                cmbModelType.Text = ((FindModelTool)Subject).ModelID.Type.ToString();
+                if (Enum.TryParse(cmbModelType.Text, out ModelType modelType))
+                {
+                    switch (modelType)
+                    {
+                        case ModelType.鐏板害鍖归厤:
+                            //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                            //, ScaleRMin, ScaleRMax
+                            //, ScaleCMin, ScaleCMax
+                            //, MinScore, NumMatches, MaxOverlap
+                            //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                            //, Greediness, ResultType, new HTuple(), new HTuple()
+                            #region 杈撳叆鍙傛暟
+                            dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"].ToString();
+                            dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"].ToString();
+                            dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"].ToString();
+                            dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"].ToString();
+                            dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"].ToString();
+                            dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"].ToString();
+                            dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"].ToString();
+                            dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"].ToString();
+                            dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"].ToString();
+                            dtxtInputParam10.Text = Subject.Params.Inputs["ResultType"].ToString();
+                            dtxtInputParam11.Text = Subject.Params.Inputs["NumLevels"].ToString();
+                            dtxtInputParam12.Text = Subject.Params.Inputs["Greediness"].ToString();
+                            dtxtInputParam13.Text = Subject.Params.Inputs["MinCount"].ToString();
+                            dtxtInputParam14.Text = Subject.Params.Inputs["MaxCount"].ToString();
+                            #endregion
+                            break;
+                        default:
+                            #region 杈撳叆鍙傛暟
+                            dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"].ToString();
+                            dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"].ToString();
+                            dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"].ToString();
+                            dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"].ToString();
+                            dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"].ToString();
+                            dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"].ToString();
+                            dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"].ToString();
+                            dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"].ToString();
+                            dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"].ToString();
+                            dtxtInputParam10.Text = Subject.Params.Inputs["ResultType"].ToString();
+                            dtxtInputParam11.Text = Subject.Params.Inputs["NumLevels"].ToString();
+                            dtxtInputParam12.Text = Subject.Params.Inputs["Greediness"].ToString();
+                            dtxtInputParam13.Text = Subject.Params.Inputs["MinCount"].ToString();
+                            dtxtInputParam14.Text = Subject.Params.Inputs["MaxCount"].ToString();
+                            #endregion
+                            break;
+                    }
+                }
+
+                if (Subject.InputImage != null && Subject.InputImage is Mat)
+                {
+                    TAlgorithm.Mat2HObject((Mat)Subject.InputImage, out HObject image);
+                    inputImageHSmartWindowControl.ShowHoImage(image);
+                }
+
+                Type type = Subject.Params.ROI?.GetType();
+                if (Subject.Params.ROI != null)
+                {
+                    switch (type)
+                    {
+                        case Type t when t == typeof(HRectangle2):
+                            cmbTypeRoi.Text = RoiType.Rectangle2.ToString();
+                            break;
+                        case Type t when t == typeof(HCircle):
+                            cmbTypeRoi.Text = RoiType.Circle.ToString();
+                            break;
+                        case Type t when t == typeof(HSegment):
+                            cmbTypeRoi.Text = RoiType.Segment.ToString();
+                            break;
+                        default:
+                            cmbTypeRoi.Text = RoiType.None.ToString();
+                            break;
+                    }
+                    if (cmbTypeRoi.Text.ToString() != "None")
+                        ckbDrawRoi.Checked = true;
+                    else
+                        ckbDrawRoi.Checked = false;
+
+                    inputImageHSmartWindowControl.oRoi = Subject.Params.ROI;
+                }
+
+                if (Subject.Params.Fixture != null)
+                    cmbFixture.Text = Subject.Params.Fixture.strName;
+                else
+                    cmbFixture.Text = "";
+
+                switch (type)
+                {
+                    case Type t when t == typeof(HRectangle2):
+                        inputImageHSmartWindowControl.oRoi
+                             = new HRectangle2(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                             , Subject.Params.ROI.Phi + Subject.Params.Fixture.Phi, ((HRectangle2)Subject.Params.ROI).Width, ((HRectangle2)Subject.Params.ROI).Height);
+                        break;
+                    case Type t when t == typeof(HCircle):
+                        inputImageHSmartWindowControl.oRoi
+                        = new HCircle(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
+                        , ((HCircle)Subject.Params.ROI).Radius);
+                        break;
+                    case Type t when t == typeof(HSegment):
+                        inputImageHSmartWindowControl.oRoi
+                        = new HSegment(((HSegment)Subject.Params.ROI).StartX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).StartY + Subject.Params.Fixture.Y
+                        , ((HSegment)Subject.Params.ROI).EndX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).EndY + Subject.Params.Fixture.Y);
+                        break;
+                    default:
+                        inputImageHSmartWindowControl.oRoi = null;
+                        break;
+                }
+
+                ShowModel(((FindModelTool)Subject).ModelID);
+            }));
+        }
+
+        /// <summary>
+        /// 鏇存柊杈撳嚭缁撴灉
+        /// </summary>
+        public override void UpdataOutputs()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                //瀛樺湪鍙嶅簭鍒楀寲閿欎贡鐨勬儏鍐甸渶瑕佷娇鐢ㄨ嚜瀹氫箟鐨勮浆鎹㈠櫒
+                dtxtCenterX.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterX"]);
+                dtxtCenterY.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterY"]);
+                dtxtPhi.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Phi"]);
+                dtxtScore.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Score"]);
+                dtxtCount.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Count"]);
+            }));
+        }
+
+        /// <summary>
+        /// 鐐瑰嚮杩愯
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        public override void btnRun_Click(object sender, EventArgs e)
+        {
+
+            if (Subject.InputImage != null)
+                InputImage = Subject.InputImage;
+
+            DateTime StartTime = DateTime.Now;
+            Run();
+
+            //鏇存柊鏃ュ織涓庣粨鏋�
+            this.BeginInvoke(new Action(() =>
+            {
+                if (Subject.Result)
+                {
+                    lblResult.BackColor = Color.Green;
+                    lblResult.Text = "True";
+                    recordImageHSmartWindowControl.SetColor("green");
+                }
+                else
+                {
+                    lblResult.BackColor = Color.Red;
+                    lblResult.Text = "False";
+                    recordImageHSmartWindowControl.SetColor("red");
+                }
+
+                lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
+                lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
+                lblRunTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
+
+                UpdataOutputs();
+                imgTabControl.SelectedTab = tabPageRecordImage;
+
+                if (Subject.InputImage != null && Subject.InputImage is Mat)
+                {
+                    TAlgorithm.Mat2HObject((Mat)Subject.InputImage, out HObject image);
+                    HOperatorSet.GetImageSize(image, out HTuple ho_ImageWidth, out HTuple ho_ImageHeight);
+                    recordImageHSmartWindowControl.ShowHoImage(image);
+                }
+
+                //鍏堝垽鏂瓙绫诲啀鍒ゆ柇鐖剁被
+                if (Subject.Record != null && Subject.Record is MsgRecord msgRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_NG, false);
+
+                    for (int i = 0; i < msgRecord.Msg.Length; i++)
+                        recordImageHSmartWindowControl.ShowMsg(msgRecord.Msg[i]
+                            , 1 == msgRecord.Result[i] ? true : false, msgRecord.Column[i], msgRecord.Row[i]);
+                }
+                else if (Subject.Record != null && Subject.Record is ObjectRecord objRecord)
+                {
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_OK, true);
+                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_NG, false);
+                }
+
+                GC.Collect();
+            }));
+        }
+
+        public override void btnLoadImage_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    Mat mat = Cv2.ImRead(selectedFiles[0]);
+                    //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                    if (mat.Channels() != 1)
+                    {
+                        Cv2.CvtColor(mat, mat, ColorConversionCodes.RGB2GRAY);
+                        //鏇存柊鏃ュ織涓庣粨鏋�
+                        this.BeginInvoke(new Action(() =>
+                        {
+                            lblMsg.Text = "瀵煎叆鍥剧墖闈炵伆搴﹀浘,鑷姩杞崲涓虹伆搴﹀浘";
+                        }));
+                    }
+                    InputImage = mat;
+                    imgTabControl.SelectedTab = tabPageInputImage;
+                    inputImageHSmartWindowControl.oRoi = inputImageHSmartWindowControl.oRoi;
+                }
+            }
+        }
+
+        public override void btnSaveParas_Click(object sender, EventArgs e)
+        {
+            //淇濆瓨鍓嶉渶瑕佹洿鏂拌緭鍏ュ弬鏁癐nputs
+            UpdataInputs();
+
+            // 鍒涘缓 SaveFileDialog 瀹炰緥
+            using (SaveFileDialog saveFileDialog = new SaveFileDialog())
+            {
+                // 璁剧疆瀵硅瘽妗嗘爣棰�
+                saveFileDialog.Title = "淇濆瓨鏂囦欢";
+
+                // 璁剧疆榛樿璺緞
+                saveFileDialog.InitialDirectory = System.Windows.Forms.Application.StartupPath;
+
+                // 璁剧疆鏂囦欢绫诲瀷杩囨护鍣�
+                saveFileDialog.Filter = "鏂囨湰鏂囦欢 (*.json)|*.json|鎵�鏈夋枃浠� (*.*)|*.*";
+
+                // 璁剧疆榛樿鏂囦欢鍚�
+                saveFileDialog.FileName = Subject.strProcessName + ".json";
+
+                // 鏄剧ず瀵硅瘽妗嗗苟妫�鏌ョ敤鎴锋槸鍚︾偣鍑讳簡淇濆瓨鎸夐挳
+                if (saveFileDialog.ShowDialog() == DialogResult.OK)
+                {
+                    // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠惰矾寰�
+                    string fullPath = saveFileDialog.FileName;
+                    Debug.WriteLine("閫夋嫨鐨勬枃浠惰矾寰勬槸: " + fullPath);
+                    Subject.strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+                    ((FindModelTool)Subject).Save(Path.GetDirectoryName(fullPath));
+                }
+            }
+        }
+
+        public override void btnLoadParas_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = false; // 涓嶅厑璁稿閫�
+            // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Ini Files (*.json)|*.json|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                if (selectedFiles.Length > 0)
+                {
+                    ((FindModelTool)Subject).Load(selectedFiles[0]);
+                    LoadParas();
+                }
+            }
+        }
+
+        public override void ckbDrawRoi_CheckedChanged(object sender, EventArgs e)
+        {
+            if (ckbDrawRoi.Checked)
+            {
+                inputImageHSmartWindowControl.bAollowDraw = true;
+                imgTabControl.SelectedTab = tabPageInputImage;
+            }
+            else
+            {
+                inputImageHSmartWindowControl.bAollowDraw = false;
+                Subject.Params.ROI = new ROI();
+            }
+        }
+
+        public override void cmbTypeRoi_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (Enum.TryParse(cmbTypeRoi.Text.ToString(), out RoiType type))
+                {
+                    HTuple hv_imageWidth = 0;
+                    HTuple hv_imageHeight = 0;
+                    if (InputImage != null && InputImage is Mat)
+                    {
+                        TAlgorithm.Mat2HObject((Mat)InputImage, out HObject image);
+                        HOperatorSet.GetImageSize(image, out hv_imageWidth, out hv_imageHeight);
+                    }
+                    switch (type)
+                    {
+                        case RoiType.Rectangle2:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, 0
+                                , hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.Circle:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HCircle(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, hv_imageWidth.TupleReal() / 4);
+                            break;
+                        case RoiType.Segment:
+                            inputImageHSmartWindowControl.oRoi
+                                = new HSegment(0, 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+                            break;
+                        case RoiType.None:
+                        default:
+                            inputImageHSmartWindowControl.oRoi = null;
+                            break;
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public override void cmbFixture_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
+                    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
+                else
+                    Subject.Params.Fixture = new Fixture();
+            }
+            catch { }
+        }
+
+        private System.Windows.Forms.ToolTip toolTip = new System.Windows.Forms.ToolTip();
+        private void ShowToolTip(Control control, string message)
+        {
+            toolTip.SetToolTip(control, message);
+        }
+
+        // 閫氳繃鍙嶅皠娓呴櫎鎵�鏈変簨浠跺鐞嗙▼搴�
+        public void ClearAllEventHandlers()
+        {
+            // 鑾峰彇浜嬩欢瀛楁
+            FieldInfo field = typeof(Label).GetField("MouseHover", BindingFlags.NonPublic | BindingFlags.Instance);
+
+            if (field != null)
+            {
+                // 灏嗕簨浠跺瓧娈佃涓� null锛岀Щ闄ゆ墍鏈変簨浠跺鐞嗙▼搴�
+                field.SetValue(this, null);
+            }
+        }
+
+        private void cmbModelType_TextUpdate(object sender, EventArgs e)
+        {
+            cmbModelType_SelectedIndexChanged(sender, e);
+        }
+
+        private void cmbModelType_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            UpdataInputsUI();
+        }
+
+        void UpdataInputsUI()
+        {
+            this.BeginInvoke(() =>
+            {
+                #region 娓呯┖杈撳叆
+                this.lblInputParam1.Visible = false;
+                this.lblInputParam2.Visible = false;
+                this.lblInputParam3.Visible = false;
+                this.lblInputParam4.Visible = false;
+                this.lblInputParam5.Visible = false;
+                this.lblInputParam6.Visible = false;
+                this.lblInputParam7.Visible = false;
+                this.lblInputParam8.Visible = false;
+                this.lblInputParam9.Visible = false;
+                this.lblInputParam10.Visible = false;
+                this.lblInputParam11.Visible = false;
+                this.lblInputParam12.Visible = false;
+                this.lblInputParam13.Visible = false;
+                this.lblInputParam14.Visible = false;
+                this.lblInputParam15.Visible = false;
+                this.lblInputParam16.Visible = false;
+                this.lblInputParam17.Visible = false;
+                this.lblInputParam18.Visible = false;
+
+                this.dtxtInputParam1.Visible = false;
+                this.dtxtInputParam2.Visible = false;
+                this.dtxtInputParam3.Visible = false;
+                this.dtxtInputParam4.Visible = false;
+                this.dtxtInputParam5.Visible = false;
+                this.dtxtInputParam6.Visible = false;
+                this.dtxtInputParam7.Visible = false;
+                this.dtxtInputParam8.Visible = false;
+                this.dtxtInputParam9.Visible = false;
+                this.dtxtInputParam10.Visible = false;
+                this.dtxtInputParam11.Visible = false;
+                this.dtxtInputParam12.Visible = false;
+                this.dtxtInputParam13.Visible = false;
+                this.dtxtInputParam14.Visible = false;
+                this.dtxtInputParam15.Visible = false;
+                this.dtxtInputParam16.Visible = false;
+                this.dtxtInputParam17.Visible = false;
+                this.dtxtInputParam18.Visible = false;
+                #endregion
+
+                #region 娓呯┖妯℃澘
+                this.lblModelParam1.Visible = false;
+                this.lblModelParam2.Visible = false;
+                this.lblModelParam3.Visible = false;
+                this.lblModelParam4.Visible = false;
+                this.lblModelParam5.Visible = false;
+                this.lblModelParam6.Visible = false;
+                this.lblModelParam7.Visible = false;
+                this.lblModelParam8.Visible = false;
+                this.lblModelParam9.Visible = false;
+                this.lblModelParam10.Visible = false;
+                this.lblModelParam11.Visible = false;
+                this.lblModelParam12.Visible = false;
+                this.lblModelParam13.Visible = false;
+                this.lblModelParam14.Visible = false;
+                this.lblModelParam15.Visible = false;
+                this.lblModelParam16.Visible = false;
+                this.lblModelParam17.Visible = false;
+                this.lblModelParam18.Visible = false;
+
+                this.dtxtModelParam1.Visible = false;
+                this.dtxtModelParam2.Visible = false;
+                this.dtxtModelParam3.Visible = false;
+                this.dtxtModelParam4.Visible = false;
+                this.dtxtModelParam5.Visible = false;
+                this.dtxtModelParam6.Visible = false;
+                this.dtxtModelParam7.Visible = false;
+                this.dtxtModelParam8.Visible = false;
+                this.dtxtModelParam9.Visible = false;
+                this.dtxtModelParam10.Visible = false;
+                this.dtxtModelParam11.Visible = false;
+                this.dtxtModelParam12.Visible = false;
+                this.dtxtModelParam13.Visible = false;
+                this.dtxtModelParam14.Visible = false;
+                this.dtxtModelParam15.Visible = false;
+                this.dtxtModelParam16.Visible = false;
+                this.dtxtModelParam17.Visible = false;
+                this.dtxtModelParam18.Visible = false;
+                #endregion
+
+                ClearAllEventHandlers();
+
+                if (Enum.TryParse(cmbModelType.Text, out ModelType modelType))
+                {
+                    switch (modelType)
+                    {
+                        case ModelType.鐏板害鍖归厤:
+                            //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                            //, ScaleRMin, ScaleRMax
+                            //, ScaleCMin, ScaleCMax
+                            //, MinScore, NumMatches, MaxOverlap
+                            //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                            //, Greediness, ResultType, new HTuple(), new HTuple()
+
+                            #region 杈撳叆鍙傛暟
+                            //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                            this.lblInputParam1.Text = "璧峰瑙掑害";
+                            this.dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"].ToString();
+                            this.lblInputParam1.Visible = true;
+                            this.dtxtInputParam1.Visible = true;
+                            this.dtxtInputParam1.Enabled = true;
+                            lblInputParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑璧峰瑙掑害AngleStart");
+
+                            this.lblInputParam2.Text = "瑙掑害鑼冨洿";
+                            this.dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"].ToString();
+                            this.lblInputParam2.Visible = true;
+                            this.dtxtInputParam2.Visible = true;
+                            this.dtxtInputParam2.Enabled = true;
+                            lblInputParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑瑙掑害鑼冨洿AngleExtent,'0'琛ㄧず鏃犺搴︽悳绱�");
+
+                            //, ScaleRMin, ScaleRMax
+                            this.lblInputParam3.Text = "绾靛悜缂╂斁鏈�灏忓��";
+                            this.dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"].ToString();
+                            this.lblInputParam3.Visible = true;
+                            this.dtxtInputParam3.Visible = true;
+                            this.dtxtInputParam3.Enabled = true;
+                            lblInputParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�灏忓�糞caleRMin");
+
+                            this.lblInputParam4.Text = "绾靛悜缂╂斁鏈�澶у��";
+                            this.dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"].ToString();
+                            this.lblInputParam4.Visible = true;
+                            this.dtxtInputParam4.Visible = true;
+                            this.dtxtInputParam4.Enabled = true;
+                            lblInputParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�澶у�糞caleRMax");
+
+                            //, ScaleCMin, ScaleCMax
+                            this.lblInputParam5.Text = "妯悜缂╂斁鏈�灏忓��";
+                            this.dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"].ToString();
+                            this.lblInputParam5.Visible = true;
+                            this.dtxtInputParam5.Visible = true;
+                            this.dtxtInputParam5.Enabled = true;
+                            lblInputParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�灏忓�糞caleCMin");
+
+                            this.lblInputParam6.Text = "妯悜缂╂斁鏈�澶у��";
+                            this.dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"].ToString();
+                            this.lblInputParam6.Visible = true;
+                            this.dtxtInputParam6.Visible = true;
+                            this.dtxtInputParam6.Enabled = true;
+                            lblInputParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�澶у�糞caleCMax");
+
+                            //, MinScore, NumMatches, MaxOverlap, ResultType
+                            this.lblInputParam7.Text = "鏈�灏忓垎鏁�";
+                            this.dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"].ToString();
+                            this.lblInputParam7.Visible = true;
+                            this.dtxtInputParam7.Visible = true;
+                            this.dtxtInputParam7.Enabled = true;
+                            lblInputParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "琚壘鍒扮殑妯℃澘鏈�灏忓垎鏁癕inScore");
+
+                            this.lblInputParam8.Text = "鏈熸湜涓暟";
+                            this.dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"].ToString();
+                            this.lblInputParam8.Visible = true;
+                            this.dtxtInputParam8.Visible = true;
+                            this.dtxtInputParam8.Enabled = true;
+                            lblInputParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "瑕佹壘鍒扮殑妯℃澘鏈�澶氱殑瀹炰緥鏁癗umMatches,'0'鍒欐壘鍒版墍鏈夊彲鑳界殑鍖归厤");
+
+                            this.lblInputParam9.Text = "鏈�澶ч噸鍙犳瘮渚�";
+                            this.dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"].ToString();
+                            this.lblInputParam9.Visible = true;
+                            this.dtxtInputParam9.Visible = true;
+                            this.dtxtInputParam9.Enabled = true;
+                            lblInputParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "鍏佽鎵惧埌鐨勬ā鍨嬪疄渚嬬殑鏈�澶ч噸鍙犳瘮渚婱axOverlap[杈冨皬鐨勫�间細閬垮厤鎵惧埌澶氫釜鐩镐技鐨勫尮閰峕");
+
+                            this.lblInputParam10.Text = "ResultType";
+                            this.dtxtInputParam10.Text = Subject.Params.Inputs["ResultType"].ToString();
+                            this.lblInputParam10.Visible = true;
+                            this.dtxtInputParam10.Visible = true;
+                            this.dtxtInputParam10.Enabled = false;
+                            lblInputParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "璁$畻绮惧害鐨勮缃甊esultType['1'寰楀埌浜氬儚绱犵簿搴");
+
+                            //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                            //, Greediness, , new HTuple(), new HTuple()
+                            this.lblInputParam11.Text = "鎼滅储鏃堕噾瀛楀鐨勫眰绾�";
+                            this.dtxtInputParam11.Text = "0";
+                            this.lblInputParam11.Visible = true;
+                            this.dtxtInputParam11.Visible = true;
+                            this.dtxtInputParam11.Enabled = false;
+                            lblInputParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃堕噾瀛楀鐨勫眰绾�");
+
+                            this.lblInputParam12.Text = "璐┆搴�";
+                            this.dtxtInputParam12.Text = "2";
+                            this.lblInputParam12.Visible = true;
+                            this.dtxtInputParam12.Visible = true;
+                            this.dtxtInputParam12.Enabled = true;
+                            lblInputParam12.MouseHover += (s, e) => ShowToolTip((Control)s, "璐┆搴�,瓒婂皬閫熷害瓒婂揩[涓�鑸兘璁句负2,澶皬瀹规槗鍑虹幇鎵句笉鍒扮殑鎯呭喌]");
+
+                            this.lblInputParam13.Text = "鏈�灏忔暟閲�";
+                            this.dtxtInputParam13.Text = "0";
+                            this.lblInputParam13.Visible = true;
+                            this.dtxtInputParam13.Visible = true;
+                            this.dtxtInputParam13.Enabled = true;
+                            lblInputParam13.MouseHover += (s, e) => ShowToolTip((Control)s, "鍖归厤缁撴灉瑕佹眰鐨勬渶灏忔暟閲�");
+
+                            this.lblInputParam14.Text = "鏈�澶ф暟閲�";
+                            this.dtxtInputParam14.Text = "9999";
+                            this.lblInputParam14.Visible = true;
+                            this.dtxtInputParam14.Visible = true;
+                            this.dtxtInputParam14.Enabled = true;
+                            lblInputParam14.MouseHover += (s, e) => ShowToolTip((Control)s, "鍖归厤缁撴灉瑕佹眰鐨勬渶澶ф暟閲�");
+                            #endregion
+                            //UpdataInputs();
+
+                            //NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
+                            //   , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
+                            //   , ScaleRMin, ScaleRMax, ScaleRStep == "auto" ? ScaleRStep : Convert.ToDouble(ScaleRStep)
+                            //   , ScaleCMin, ScaleCMax, ScaleCStep == "auto" ? ScaleCStep : Convert.ToDouble(ScaleCStep)
+                            //   , Optimization, Metric
+                            //   , Contrast, MinContrast
+
+                            #region 妯℃澘鍙傛暟
+                            //NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
+                            this.lblModelParam1.Text = "閲戝瓧濉旂殑灞傜骇";
+                            this.dtxtModelParam1.Text = "auto";
+                            this.lblModelParam1.Visible = true;
+                            this.dtxtModelParam1.Visible = true;
+                            this.dtxtModelParam1.Enabled = false;
+                            lblModelParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃堕噾瀛楀鐨勫眰绾umLevels,'0'琛ㄧず涓嶄娇鐢ㄩ噾瀛楀");
+
+                            //   , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
+                            this.lblModelParam2.Text = "瑙掑害姝ラ暱";
+                            this.dtxtModelParam2.Text = "auto";
+                            this.lblModelParam2.Visible = true;
+                            this.dtxtModelParam2.Visible = true;
+                            this.dtxtModelParam2.Enabled = false;
+                            lblModelParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "瑙掑害鑼冨洿鍐呰繘琛屾棆杞殑姝ラ暱AngleStep,'auto'琛ㄧず鐢辩郴缁熻嚜鍔ㄩ�夋嫨鍚堥�傜殑姝ラ暱");
+
+                            this.lblModelParam3.Text = "璧峰瑙掑害";
+                            this.dtxtModelParam3.Text = "-5";
+                            this.lblModelParam3.Visible = true;
+                            this.dtxtModelParam3.Visible = true;
+                            this.dtxtModelParam3.Enabled = true;
+                            lblModelParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑璧峰瑙掑害AngleStart");
+
+                            this.lblModelParam4.Text = "瑙掑害鑼冨洿";
+                            this.dtxtModelParam4.Text = "10";
+                            this.lblModelParam4.Visible = true;
+                            this.dtxtModelParam4.Visible = true;
+                            this.dtxtModelParam4.Enabled = true;
+                            lblModelParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑瑙掑害鑼冨洿AngleExtent,'0'琛ㄧず鏃犺搴︽悳绱�");
+
+                            //, double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto"
+                            this.lblModelParam5.Text = "绾靛悜缂╂斁鏈�灏忓��";
+                            this.dtxtModelParam5.Text = "0.9";
+                            this.lblModelParam5.Visible = true;
+                            this.dtxtModelParam5.Visible = true;
+                            this.dtxtModelParam5.Enabled = true;
+                            lblModelParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�灏忓�糞caleRMin");
+
+                            this.lblModelParam6.Text = "绾靛悜缂╂斁鏈�澶у��";
+                            this.dtxtModelParam6.Text = "1.1";
+                            this.lblModelParam6.Visible = true;
+                            this.dtxtModelParam6.Visible = true;
+                            this.dtxtModelParam6.Enabled = true;
+                            lblModelParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�澶у�糞caleRMax");
+
+                            //, double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto"
+                            this.lblModelParam7.Text = "妯悜缂╂斁鏈�灏忓��";
+                            this.dtxtModelParam7.Text = "0.9";
+                            this.lblModelParam7.Visible = true;
+                            this.dtxtModelParam7.Visible = true;
+                            this.dtxtModelParam7.Enabled = true;
+                            lblModelParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�灏忓�糞caleCMin");
+
+                            this.lblModelParam8.Text = "妯悜缂╂斁鏈�澶у��";
+                            this.dtxtModelParam8.Text = "1.1";
+                            this.lblModelParam8.Visible = true;
+                            this.dtxtModelParam8.Visible = true;
+                            this.dtxtModelParam8.Enabled = true;
+                            lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�澶у�糞caleCMax");
+
+                            //, string Optimization = "auto", string Metric = "ignore_local_polarity"
+                            this.lblModelParam9.Text = "浼樺寲";
+                            this.dtxtModelParam9.Text = "none";
+                            this.lblModelParam9.Visible = true;
+                            this.dtxtModelParam9.Visible = true;
+                            this.dtxtModelParam9.Enabled = false;
+                            lblModelParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "褰卞搷褰㈢姸妯″瀷鍒涘缓鏃剁殑閫熷害鍜岀簿搴︾殑浼樺寲閫夐」Optimization");
+
+                            this.lblModelParam10.Text = "鏋佹��";
+                            this.dtxtModelParam10.Text = "ignore_local_polarity";
+                            this.lblModelParam10.Visible = true;
+                            this.dtxtModelParam10.Visible = true;
+                            this.dtxtModelParam10.Enabled = false;
+                            lblModelParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "鏋佹�т俊鎭殑搴﹂噺鏂规硶Metric");
+
+                            //, string Contrast = "auto", int MinContrast = 10
+                            this.lblModelParam11.Text = "瀵规瘮搴﹀弬鏁�";
+                            this.dtxtModelParam11.Text = "auto";
+                            this.lblModelParam11.Visible = true;
+                            this.dtxtModelParam11.Visible = true;
+                            this.dtxtModelParam11.Enabled = false;
+                            lblModelParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "鍒涘缓妯℃澘鏃剁殑瀵规瘮搴ontrast");
+
+                            this.lblModelParam12.Text = "鏈�灏忓姣斿害鍙傛暟";
+                            this.dtxtModelParam12.Text = "10";
+                            this.lblModelParam12.Visible = true;
+                            this.dtxtModelParam12.Visible = true;
+                            this.dtxtModelParam12.Enabled = true;
+                            lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "妯″瀷鍖归厤杩囩▼涓�冭檻鐨勬渶灏忓姣斿害MinContrast");
+                            #endregion
+                            break;
+                        default:
+                            //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                            //, ScaleRMin, ScaleRMax
+                            //, ScaleCMin, ScaleCMax
+                            //, MinScore, NumMatches, MaxOverlap, SubPixel
+                            //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                            //, Greediness
+                            #region 杈撳叆鍙傛暟
+                            //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
+                            this.lblInputParam1.Text = "璧峰瑙掑害";
+                            this.dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"].ToString();
+                            this.lblInputParam1.Visible = true;
+                            this.dtxtInputParam1.Visible = true;
+                            this.dtxtInputParam1.Enabled = true;
+                            lblInputParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑璧峰瑙掑害AngleStart");
+
+                            this.lblInputParam2.Text = "瑙掑害鑼冨洿";
+                            this.dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"].ToString();
+                            this.lblInputParam2.Visible = true;
+                            this.dtxtInputParam2.Visible = true;
+                            this.dtxtInputParam2.Enabled = true;
+                            lblInputParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑瑙掑害鑼冨洿AngleExtent,'0'琛ㄧず鏃犺搴︽悳绱�");
+
+                            //, ScaleRMin, ScaleRMax
+                            this.lblInputParam3.Text = "绾靛悜缂╂斁鏈�灏忓��";
+                            this.dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"].ToString();
+                            this.lblInputParam3.Visible = true;
+                            this.dtxtInputParam3.Visible = true;
+                            this.dtxtInputParam3.Enabled = true;
+                            lblInputParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�灏忓�糞caleRMin");
+
+                            this.lblInputParam4.Text = "绾靛悜缂╂斁鏈�澶у��";
+                            this.dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"].ToString();
+                            this.lblInputParam4.Visible = true;
+                            this.dtxtInputParam4.Visible = true;
+                            this.dtxtInputParam4.Enabled = true;
+                            lblInputParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�澶у�糞caleRMax");
+
+                            //, ScaleCMin, ScaleCMax
+                            this.lblInputParam5.Text = "妯悜缂╂斁鏈�灏忓��";
+                            this.dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"].ToString();
+                            this.lblInputParam5.Visible = true;
+                            this.dtxtInputParam5.Visible = true;
+                            this.dtxtInputParam5.Enabled = true;
+                            lblInputParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�灏忓�糞caleCMin");
+
+                            this.lblInputParam6.Text = "妯悜缂╂斁鏈�澶у��";
+                            this.dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"].ToString();
+                            this.lblInputParam6.Visible = true;
+                            this.dtxtInputParam6.Visible = true;
+                            this.dtxtInputParam6.Enabled = true;
+                            lblInputParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�澶у�糞caleCMax");
+
+                            //, MinScore, NumMatches, MaxOverlap, ResultType
+                            this.lblInputParam7.Text = "鏈�灏忓垎鏁�";
+                            this.dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"].ToString();
+                            this.lblInputParam7.Visible = true;
+                            this.dtxtInputParam7.Visible = true;
+                            this.dtxtInputParam7.Enabled = true;
+                            lblInputParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "琚壘鍒扮殑妯℃澘鏈�灏忓垎鏁癕inScore");
+
+                            this.lblInputParam8.Text = "鏈熸湜涓暟";
+                            this.dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"].ToString();
+                            this.lblInputParam8.Visible = true;
+                            this.dtxtInputParam8.Visible = true;
+                            this.dtxtInputParam8.Enabled = true;
+                            lblInputParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "瑕佹壘鍒扮殑妯℃澘鏈�澶氱殑瀹炰緥鏁癗umMatches,'0'鍒欐壘鍒版墍鏈夊彲鑳界殑鍖归厤");
+
+                            this.lblInputParam9.Text = "鏈�澶ч噸鍙犳瘮渚�";
+                            this.dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"].ToString();
+                            this.lblInputParam9.Visible = true;
+                            this.dtxtInputParam9.Visible = true;
+                            this.dtxtInputParam9.Enabled = true;
+                            lblInputParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "鍏佽鎵惧埌鐨勬ā鍨嬪疄渚嬬殑鏈�澶ч噸鍙犳瘮渚婱axOverlap[杈冨皬鐨勫�间細閬垮厤鎵惧埌澶氫釜鐩镐技鐨勫尮閰峕");
+
+                            this.lblInputParam10.Text = "SubPixel";
+                            this.dtxtInputParam10.Text = Subject.Params.Inputs["SubPixel"].ToString();
+                            this.lblInputParam10.Visible = true;
+                            this.dtxtInputParam10.Visible = true;
+                            this.dtxtInputParam10.Enabled = false;
+                            lblInputParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "璁$畻绮惧害鐨勮缃甋ubPixel['none'鏈�澶ц宸负鍗婁釜鍍忕礌]");
+
+                            //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
+                            //, Greediness, , new HTuple(), new HTuple()
+                            this.lblInputParam11.Text = "鎼滅储鏃堕噾瀛楀鐨勫眰绾�";
+                            this.dtxtInputParam11.Text = "0";
+                            this.lblInputParam11.Visible = true;
+                            this.dtxtInputParam11.Visible = true;
+                            this.dtxtInputParam11.Enabled = false;
+                            lblInputParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃堕噾瀛楀鐨勫眰绾�");
+
+                            this.lblInputParam12.Text = "璐┆搴�";
+                            this.dtxtInputParam12.Text = "2";
+                            this.lblInputParam12.Visible = true;
+                            this.dtxtInputParam12.Visible = true;
+                            this.dtxtInputParam12.Enabled = true;
+                            lblInputParam12.MouseHover += (s, e) => ShowToolTip((Control)s, "璐┆搴�,瓒婂皬閫熷害瓒婂揩[涓�鑸兘璁句负2,澶皬瀹规槗鍑虹幇鎵句笉鍒扮殑鎯呭喌]");
+
+                            this.lblInputParam13.Text = "鏈�灏忔暟閲�";
+                            this.dtxtInputParam13.Text = "0";
+                            this.lblInputParam13.Visible = true;
+                            this.dtxtInputParam13.Visible = true;
+                            this.dtxtInputParam13.Enabled = true;
+                            lblInputParam13.MouseHover += (s, e) => ShowToolTip((Control)s, "鍖归厤缁撴灉瑕佹眰鐨勬渶灏忔暟閲�");
+
+                            this.lblInputParam14.Text = "鏈�澶ф暟閲�";
+                            this.dtxtInputParam14.Text = "9999";
+                            this.lblInputParam14.Visible = true;
+                            this.dtxtInputParam14.Visible = true;
+                            this.dtxtInputParam14.Enabled = true;
+                            lblInputParam14.MouseHover += (s, e) => ShowToolTip((Control)s, "鍖归厤缁撴灉瑕佹眰鐨勬渶澶ф暟閲�");
+                            #endregion
+
+                            //UpdataInputs();
+
+                            //string NumLevels = "auto"
+                            //, double AngleStart = -5, double AngleExtent = 10, string AngleStep = "auto"
+                            //, double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto"
+                            //, double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto"
+                            //, string Optimization = "auto", string Metric = "ignore_local_polarity"
+                            //, string Contrast = "auto", int MinContrast = 10
+
+                            #region 妯℃澘鍙傛暟
+                            //NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
+                            this.lblModelParam1.Text = "閲戝瓧濉旂殑灞傜骇";
+                            this.dtxtModelParam1.Text = "auto";
+                            this.lblModelParam1.Visible = true;
+                            this.dtxtModelParam1.Visible = true;
+                            this.dtxtModelParam1.Enabled = false;
+                            lblModelParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃堕噾瀛楀鐨勫眰绾umLevels,'0'琛ㄧず涓嶄娇鐢ㄩ噾瀛楀");
+
+                            //   , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
+                            this.lblModelParam2.Text = "瑙掑害姝ラ暱";
+                            this.dtxtModelParam2.Text = "auto";
+                            this.lblModelParam2.Visible = true;
+                            this.dtxtModelParam2.Visible = true;
+                            this.dtxtModelParam2.Enabled = false;
+                            lblModelParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "瑙掑害鑼冨洿鍐呰繘琛屾棆杞殑姝ラ暱AngleStep,'auto'琛ㄧず鐢辩郴缁熻嚜鍔ㄩ�夋嫨鍚堥�傜殑姝ラ暱");
+
+                            this.lblModelParam3.Text = "璧峰瑙掑害";
+                            this.dtxtModelParam3.Text = "-5";
+                            this.lblModelParam3.Visible = true;
+                            this.dtxtModelParam3.Visible = true;
+                            this.dtxtModelParam3.Enabled = true;
+                            lblModelParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑璧峰瑙掑害AngleStart");
+
+                            this.lblModelParam4.Text = "瑙掑害鑼冨洿";
+                            this.dtxtModelParam4.Text = "10";
+                            this.lblModelParam4.Visible = true;
+                            this.dtxtModelParam4.Visible = true;
+                            this.dtxtModelParam4.Enabled = true;
+                            lblModelParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "鎼滅储鏃剁殑瑙掑害鑼冨洿AngleExtent,'0'琛ㄧず鏃犺搴︽悳绱�");
+
+                            //, double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto"
+                            this.lblModelParam5.Text = "绾靛悜缂╂斁鏈�灏忓��";
+                            this.dtxtModelParam5.Text = "0.9";
+                            this.lblModelParam5.Visible = true;
+                            this.dtxtModelParam5.Visible = true;
+                            this.dtxtModelParam5.Enabled = true;
+                            lblModelParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�灏忓�糞caleRMin");
+
+                            this.lblModelParam6.Text = "绾靛悜缂╂斁鏈�澶у��";
+                            this.dtxtModelParam6.Text = "1.1";
+                            this.lblModelParam6.Visible = true;
+                            this.dtxtModelParam6.Visible = true;
+                            this.dtxtModelParam6.Enabled = true;
+                            lblModelParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "绾靛悜缂╂斁鏈�澶у�糞caleRMax");
+
+                            //, double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto"
+                            this.lblModelParam7.Text = "妯悜缂╂斁鏈�灏忓��";
+                            this.dtxtModelParam7.Text = "0.9";
+                            this.lblModelParam7.Visible = true;
+                            this.dtxtModelParam7.Visible = true;
+                            this.dtxtModelParam7.Enabled = true;
+                            lblModelParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�灏忓�糞caleCMin");
+
+                            this.lblModelParam8.Text = "妯悜缂╂斁鏈�澶у��";
+                            this.dtxtModelParam8.Text = "1.1";
+                            this.lblModelParam8.Visible = true;
+                            this.dtxtModelParam8.Visible = true;
+                            this.dtxtModelParam8.Enabled = true;
+                            lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "妯悜缂╂斁鏈�澶у�糞caleCMax");
+
+                            //, string Optimization = "auto", string Metric = "ignore_local_polarity"
+                            this.lblModelParam9.Text = "浼樺寲";
+                            this.dtxtModelParam9.Text = "auto";
+                            this.lblModelParam9.Visible = true;
+                            this.dtxtModelParam9.Visible = true;
+                            this.dtxtModelParam9.Enabled = false;
+                            lblModelParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "褰卞搷褰㈢姸妯″瀷鍒涘缓鏃剁殑閫熷害鍜岀簿搴︾殑浼樺寲閫夐」Optimization");
+
+                            this.lblModelParam10.Text = "鏋佹��";
+                            this.dtxtModelParam10.Text = "ignore_local_polarity";
+                            this.lblModelParam10.Visible = true;
+                            this.dtxtModelParam10.Visible = true;
+                            this.dtxtModelParam10.Enabled = false;
+                            lblModelParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "鏋佹�т俊鎭殑搴﹂噺鏂规硶Metric");
+
+                            //, string Contrast = "auto", int MinContrast = 10
+                            this.lblModelParam11.Text = "瀵规瘮搴﹀弬鏁�";
+                            this.dtxtModelParam11.Text = "auto";
+                            this.lblModelParam11.Visible = true;
+                            this.dtxtModelParam11.Visible = true;
+                            this.dtxtModelParam11.Enabled = false;
+                            lblModelParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "鍒涘缓妯℃澘鏃剁殑瀵规瘮搴ontrast");
+
+                            this.lblModelParam12.Text = "鏈�灏忓姣斿害鍙傛暟";
+                            this.dtxtModelParam12.Text = "10";
+                            this.lblModelParam12.Visible = true;
+                            this.dtxtModelParam12.Visible = true;
+                            this.dtxtModelParam12.Enabled = true;
+                            lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "妯″瀷鍖归厤杩囩▼涓�冭檻鐨勬渶灏忓姣斿害MinContrast");
+                            #endregion
+                            break;
+                    }
+                }
+
+            });
+        }
+
+        private void btnCreateModel_Click(object sender, EventArgs e)
+        {
+            if (InputImage != null && InputImage is Mat)
+            {
+                imgTabControl.SelectedTab = tabPageModelImage;
+                TAlgorithm.Mat2HObject((Mat)InputImage, out HObject hoDomainImage);
+
+                HOperatorSet.GetImageSize(hoDomainImage, out HTuple hv_imageWidth, out HTuple hv_imageHeight);
+                createModelImageHSmartWindowControl.ShowHoImage((HObject)hoDomainImage);
+                createModelImageHSmartWindowControl.bAollowDraw = true;
+                createModelImageHSmartWindowControl.oRoi = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2
+                    , 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
+            }
+        }
+
+        private void btnSaveModel_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                if (InputImage != null && InputImage is Mat)
+                {
+                    double result = 0;
+
+                    if (Enum.TryParse(cmbModelType.Text, out ModelType modelType))
+                    {
+                        string NumLevels = this.dtxtModelParam1.Text;
+                        string AngleStep = this.dtxtModelParam2.Text;
+
+                        double AngleStart = Convert.ToDouble(this.dtxtModelParam3.Text);
+                        double AngleExtent = Convert.ToDouble(this.dtxtModelParam4.Text);
+                        double ScaleRMin = Convert.ToDouble(this.dtxtModelParam5.Text);
+                        double ScaleRMax = Convert.ToDouble(this.dtxtModelParam6.Text);
+                        double ScaleCMin = Convert.ToDouble(this.dtxtModelParam7.Text);
+                        double ScaleCMax = Convert.ToDouble(this.dtxtModelParam8.Text);
+
+                        string Optimization = this.dtxtModelParam9.Text;
+                        string Metric = this.dtxtModelParam10.Text;
+                        string Contrast = this.dtxtModelParam11.Text;
+                        int MinContrast = Convert.ToInt16(this.dtxtModelParam12.Text);
+                        HRectangle2 ROI = (HRectangle2)createModelImageHSmartWindowControl.oRoi;
+
+                        HOperatorSet.GenRectangle2(out HObject hRectangle, ROI.Row, ROI.Column, ROI.Phi, ROI.SemiLength1, ROI.SemiLength2);
+                        TAlgorithm.Mat2HObject((Mat)InputImage, out HObject hoDomainImage);
+                        HTuple hv_Channels = new HTuple();
+                        //鍒ゆ柇鏄惁涓虹伆搴﹀浘
+                        using (HDevDisposeHelper dh = new HDevDisposeHelper())
+                        {
+                            try
+                            {
+                                HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                                if (hv_Channels.TupleInt() != 1)
+                                    HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+
+                                //杞崲鍚庡啀娆℃鏌ユ槸鍚︿负鐏板害鍥�
+                                HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
+                                if (hv_Channels.TupleInt() != 1)
+                                    HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
+                            }
+                            catch { }
+                        }
+                        HOperatorSet.ReduceDomain(hoDomainImage, hRectangle, out HObject hoImageReduced);
+                        HOperatorSet.CropDomain(hoImageReduced, out hoImageReduced);
+                        TAlgorithm.HObject2Mat(hoImageReduced, out Mat hoModelImage);
+                        bool bCreateModel = false;
+
+                        switch (modelType)
+                        {
+                            case ModelType.鐏板害鍖归厤:
+                                bCreateModel = ((FindModelTool)Subject).CreateModel
+                                    (hoModelImage, modelType, NumLevels
+                                    , AngleStart, AngleExtent, AngleStep
+                                    , ScaleRMin, ScaleRMax, "auto"
+                                    , ScaleCMin, ScaleCMax, "auto"
+                                    , Optimization, Metric, Contrast, MinContrast);
+                                break;
+                            default:
+                                bCreateModel = ((FindModelTool)Subject).CreateModel
+                                    (hoModelImage, modelType, NumLevels
+                                    , AngleStart, AngleExtent, AngleStep
+                                    , ScaleRMin, ScaleRMax, "auto"
+                                    , ScaleCMin, ScaleCMax, "auto"
+                                    , Optimization, Metric, Contrast, MinContrast);
+                                break;
+                        }
+
+                        if (bCreateModel)
+                        {
+                            HObject ho_ModelContours = new HObject();
+                            //switch (((FindModelTool)Subject).ModelID.Type)
+                            //{
+                            //    case ModelType.灞�閮ㄥ彉褰㈡ā鏉�:
+                            //        HOperatorSet.GetDeformableModelContours(out ho_ModelContours, ((HFindModelTool)Subject).ModelID.hvModel, 1);
+                            //        break;
+                            //    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                            //    default:
+                            //        HOperatorSet.GetShapeModelContours(out ho_ModelContours, ((HFindModelTool)Subject).ModelID.hvModel, 1);
+                            //        break;
+                            //}
+                            //HOperatorSet.GetImageSize(((HFindModelTool)Subject).ModelID.hoImage, out HTuple hv_Width, out HTuple hv_Height);
+                            //HOperatorSet.VectorAngleToRigid(-hv_Height / 2, -hv_Width / 2, 0, 0, 0, 0, out HTuple hv_HomMat2D);
+                            //HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ModelContours, hv_HomMat2D);
+
+                            //寤烘ā鎴愬姛瀵艰埅鍒板瓙椤�
+                            parasTabControl.SelectedTab = tabPageRunParas;
+                            //modelImageHSmartWindowControl.ShowHoImage(((HFindModelTool)Subject).ModelID.hoImage);
+                            TAlgorithm.Mat2HObject(((FindModelTool)Subject).ModelID.hoImage, out HObject modelImage);
+                            modelImageHSmartWindowControl.ShowHoImage(modelImage);
+                            modelImageHSmartWindowControl.DispObj(ho_ModelContours, false);
+                            modelImageHSmartWindowControl.ShowMsg("鍒涘缓妯℃澘鎴愬姛", true);
+                        }
+                    }
+                }
+            }
+            catch { }
+        }
+
+        public void ShowModel(OModel ModelID)
+        {
+            try
+            {
+                ((FindModelTool)Subject).ModelID = ModelID;
+
+                if (ModelID != null && ModelID.Width > 0)
+                {
+                    HOperatorSet.GenEmptyObj(out HObject ho_ModelContours);
+                    //switch (ModelID.Type)
+                    //{
+                    //    case ModelType.鍚勫悜寮傚舰妯℃澘:
+                    //        HOperatorSet.GetDeformableModelContours(out ho_ModelContours, ModelID.hvModel, 1);
+                    //        break;
+                    //    default:
+                    //        HOperatorSet.GetShapeModelContours(out ho_ModelContours, ModelID.hvModel, 1);
+                    //        break;
+                    //}
+
+                    //HOperatorSet.GetImageSize(ModelID.hoImage, out HTuple hv_Width, out HTuple hv_Height);
+                    //HOperatorSet.VectorAngleToRigid(-hv_Height / 2, -hv_Width / 2, 0, 0, 0, 0, out HTuple hv_HomMat2D);
+                    //HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ModelContours, hv_HomMat2D);
+
+                    modelImageHSmartWindowControl.ClearObj();
+                    TAlgorithm.Mat2HObject(ModelID.hoImage, out HObject hoImage);
+                    //modelImageHSmartWindowControl.ShowHoImage(ModelID.hoImage);
+                    modelImageHSmartWindowControl.ShowHoImage(hoImage);
+                    modelImageHSmartWindowControl.DispObj(ho_ModelContours, false);
+                    modelImageHSmartWindowControl.ShowMsg("鍒涘缓妯℃澘鎴愬姛", true);
+                }
+            }
+            catch { }
+        }
+
+        private void HFindModelToolEdit_SizeChanged(object sender, EventArgs e)
+        {
+            ShowModel(((FindModelTool)Subject).ModelID);
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.resx b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.resx
new file mode 100644
index 0000000..43793ba
--- /dev/null
+++ b/LB_VisionProcesses/Alogrithms/OpenCvSharp/FindModelTool/FindModelToolEdit.resx
@@ -0,0 +1,129 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="lblMsgToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="TopToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>181, 17</value>
+  </metadata>
+  <metadata name="BtmStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>335, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Cameras/2DCameraForm.Designer.cs b/LB_VisionProcesses/Cameras/2DCameraForm.Designer.cs
new file mode 100644
index 0000000..90ab464
--- /dev/null
+++ b/LB_VisionProcesses/Cameras/2DCameraForm.Designer.cs
@@ -0,0 +1,861 @@
+锘縩amespace LB_VisionProcesses.Cameras
+{
+    partial class CameraForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CameraForm));
+            cmbBrand = new ComboBox();
+            cmbSN = new ComboBox();
+            label1 = new Label();
+            label2 = new Label();
+            btnStartGrab = new Button();
+            btnCloseGrab = new Button();
+            btnGrabOnce = new Button();
+            btnOpen = new Button();
+            btnClose = new Button();
+            label5 = new Label();
+            lblPicCount = new Label();
+            txtGain = new TextBox();
+            txtExp = new TextBox();
+            label4 = new Label();
+            label3 = new Label();
+            groupBox1 = new GroupBox();
+            panel_Picture = new Panel();
+            radioButtonSoft = new RadioButton();
+            radioButtonHard = new RadioButton();
+            splitContainer1 = new SplitContainer();
+            groupBox2 = new GroupBox();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            tableLayoutPanel3 = new TableLayoutPanel();
+            tableLayoutPanel4 = new TableLayoutPanel();
+            tableLayoutPanel5 = new TableLayoutPanel();
+            btnEdit = new Button();
+            tableLayoutPanel6 = new TableLayoutPanel();
+            btnSaveImage = new Button();
+            tableLayoutPanel7 = new TableLayoutPanel();
+            tableLayoutPanel8 = new TableLayoutPanel();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            btnStartHard = new Button();
+            ckbUpParams = new CheckBox();
+            ckbRegrab = new CheckBox();
+            tableLayoutPanel12 = new TableLayoutPanel();
+            lblCapTime = new Label();
+            label7 = new Label();
+            tableLayoutPanel11 = new TableLayoutPanel();
+            cmbImagesPath = new ComboBox();
+            tableLayoutPanel9 = new TableLayoutPanel();
+            ckbLocalTest = new CheckBox();
+            btnAddImages = new Button();
+            btnLocalGrab = new Button();
+            tableLayoutPanel10 = new TableLayoutPanel();
+            label6 = new Label();
+            txtTimeout = new TextBox();
+            theme_2DCameraForm = new ReaLTaiizor.Forms.ThemeForm();
+            controlBox1 = new ReaLTaiizor.Controls.ControlBox();
+            panel_2DCameraForm = new ReaLTaiizor.Controls.Panel();
+            groupBox1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
+            splitContainer1.Panel1.SuspendLayout();
+            splitContainer1.Panel2.SuspendLayout();
+            splitContainer1.SuspendLayout();
+            groupBox2.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            tableLayoutPanel3.SuspendLayout();
+            tableLayoutPanel4.SuspendLayout();
+            tableLayoutPanel5.SuspendLayout();
+            tableLayoutPanel6.SuspendLayout();
+            tableLayoutPanel7.SuspendLayout();
+            tableLayoutPanel8.SuspendLayout();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel12.SuspendLayout();
+            tableLayoutPanel11.SuspendLayout();
+            tableLayoutPanel9.SuspendLayout();
+            tableLayoutPanel10.SuspendLayout();
+            theme_2DCameraForm.SuspendLayout();
+            panel_2DCameraForm.SuspendLayout();
+            SuspendLayout();
+            // 
+            // cmbBrand
+            // 
+            cmbBrand.Dock = DockStyle.Fill;
+            cmbBrand.FormattingEnabled = true;
+            cmbBrand.Location = new Point(53, 3);
+            cmbBrand.Name = "cmbBrand";
+            cmbBrand.Size = new Size(297, 25);
+            cmbBrand.TabIndex = 0;
+            // 
+            // cmbSN
+            // 
+            cmbSN.Dock = DockStyle.Fill;
+            cmbSN.FormattingEnabled = true;
+            cmbSN.Location = new Point(53, 3);
+            cmbSN.Name = "cmbSN";
+            cmbSN.Size = new Size(297, 25);
+            cmbSN.TabIndex = 1;
+            cmbSN.SelectedIndexChanged += cmbSN_SelectedIndexChanged;
+            cmbSN.MouseDown += cmbSN_MouseDown;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Dock = DockStyle.Fill;
+            label1.Location = new Point(3, 0);
+            label1.Name = "label1";
+            label1.Size = new Size(44, 34);
+            label1.TabIndex = 2;
+            label1.Text = "鍝佺墝";
+            label1.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.Dock = DockStyle.Fill;
+            label2.Location = new Point(3, 0);
+            label2.Name = "label2";
+            label2.Size = new Size(44, 34);
+            label2.TabIndex = 3;
+            label2.Text = "SN";
+            label2.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // btnStartGrab
+            // 
+            btnStartGrab.Dock = DockStyle.Fill;
+            btnStartGrab.ForeColor = SystemColors.ControlText;
+            btnStartGrab.Location = new Point(91, 3);
+            btnStartGrab.Name = "btnStartGrab";
+            btnStartGrab.Size = new Size(82, 28);
+            btnStartGrab.TabIndex = 5;
+            btnStartGrab.Text = "杩炵画閲囬泦";
+            btnStartGrab.UseVisualStyleBackColor = true;
+            btnStartGrab.Click += btnStartGrab_Click;
+            // 
+            // btnCloseGrab
+            // 
+            btnCloseGrab.Dock = DockStyle.Fill;
+            btnCloseGrab.ForeColor = SystemColors.Desktop;
+            btnCloseGrab.Location = new Point(179, 3);
+            btnCloseGrab.Name = "btnCloseGrab";
+            btnCloseGrab.Size = new Size(82, 28);
+            btnCloseGrab.TabIndex = 6;
+            btnCloseGrab.Text = "鍏抽棴閲囬泦";
+            btnCloseGrab.UseVisualStyleBackColor = true;
+            btnCloseGrab.Click += btnCloseGrab_Click;
+            // 
+            // btnGrabOnce
+            // 
+            btnGrabOnce.Dock = DockStyle.Fill;
+            btnGrabOnce.ForeColor = SystemColors.ControlText;
+            btnGrabOnce.Location = new Point(3, 3);
+            btnGrabOnce.Name = "btnGrabOnce";
+            btnGrabOnce.Size = new Size(82, 28);
+            btnGrabOnce.TabIndex = 7;
+            btnGrabOnce.Text = "鍗曞紶閲囬泦";
+            btnGrabOnce.UseVisualStyleBackColor = true;
+            btnGrabOnce.Click += btnGrabOnce_Click;
+            // 
+            // btnOpen
+            // 
+            btnOpen.Dock = DockStyle.Fill;
+            btnOpen.ForeColor = SystemColors.ControlText;
+            btnOpen.Location = new Point(3, 3);
+            btnOpen.Name = "btnOpen";
+            btnOpen.Size = new Size(82, 28);
+            btnOpen.TabIndex = 8;
+            btnOpen.Text = "鎵撳紑";
+            btnOpen.UseVisualStyleBackColor = true;
+            btnOpen.Click += btnOpen_Click;
+            // 
+            // btnClose
+            // 
+            btnClose.Dock = DockStyle.Fill;
+            btnClose.ForeColor = SystemColors.ControlText;
+            btnClose.Location = new Point(91, 3);
+            btnClose.Name = "btnClose";
+            btnClose.Size = new Size(82, 28);
+            btnClose.TabIndex = 9;
+            btnClose.Text = "鍏抽棴";
+            btnClose.UseVisualStyleBackColor = true;
+            btnClose.Click += btnClose_Click;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Dock = DockStyle.Fill;
+            label5.Location = new Point(3, 0);
+            label5.Name = "label5";
+            label5.Size = new Size(114, 34);
+            label5.TabIndex = 15;
+            label5.Text = "鍙栧浘鏁伴噺锛�";
+            label5.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // lblPicCount
+            // 
+            lblPicCount.AutoSize = true;
+            lblPicCount.Dock = DockStyle.Fill;
+            lblPicCount.Location = new Point(123, 0);
+            lblPicCount.Name = "lblPicCount";
+            lblPicCount.Size = new Size(227, 34);
+            lblPicCount.TabIndex = 16;
+            lblPicCount.Text = "0";
+            lblPicCount.TextAlign = ContentAlignment.MiddleLeft;
+            // 
+            // txtGain
+            // 
+            txtGain.Dock = DockStyle.Fill;
+            txtGain.Location = new Point(53, 3);
+            txtGain.Name = "txtGain";
+            txtGain.Size = new Size(297, 23);
+            txtGain.TabIndex = 21;
+            txtGain.TextChanged += txtGain_TextChanged;
+            // 
+            // txtExp
+            // 
+            txtExp.Dock = DockStyle.Fill;
+            txtExp.Location = new Point(53, 3);
+            txtExp.Name = "txtExp";
+            txtExp.Size = new Size(297, 23);
+            txtExp.TabIndex = 20;
+            txtExp.TextChanged += txtExp_TextChanged;
+            // 
+            // label4
+            // 
+            label4.AutoSize = true;
+            label4.Dock = DockStyle.Fill;
+            label4.Location = new Point(3, 0);
+            label4.Name = "label4";
+            label4.Size = new Size(44, 34);
+            label4.TabIndex = 19;
+            label4.Text = "澧炵泭";
+            label4.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // label3
+            // 
+            label3.AutoSize = true;
+            label3.Dock = DockStyle.Fill;
+            label3.Location = new Point(3, 0);
+            label3.Name = "label3";
+            label3.Size = new Size(44, 34);
+            label3.TabIndex = 18;
+            label3.Text = "鏇濆厜";
+            label3.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // groupBox1
+            // 
+            groupBox1.BackColor = Color.FromArgb(39, 51, 63);
+            groupBox1.Controls.Add(panel_Picture);
+            groupBox1.Dock = DockStyle.Fill;
+            groupBox1.ForeColor = SystemColors.Control;
+            groupBox1.Location = new Point(0, 0);
+            groupBox1.Name = "groupBox1";
+            groupBox1.Size = new Size(486, 591);
+            groupBox1.TabIndex = 17;
+            groupBox1.TabStop = false;
+            groupBox1.Text = "瀹炴椂閲囬泦";
+            // 
+            // panel_Picture
+            // 
+            panel_Picture.Dock = DockStyle.Fill;
+            panel_Picture.Location = new Point(3, 19);
+            panel_Picture.Name = "panel_Picture";
+            panel_Picture.Size = new Size(480, 569);
+            panel_Picture.TabIndex = 0;
+            // 
+            // radioButtonSoft
+            // 
+            radioButtonSoft.AutoSize = true;
+            radioButtonSoft.Dock = DockStyle.Fill;
+            radioButtonSoft.Location = new Point(3, 123);
+            radioButtonSoft.Name = "radioButtonSoft";
+            radioButtonSoft.Size = new Size(353, 34);
+            radioButtonSoft.TabIndex = 23;
+            radioButtonSoft.TabStop = true;
+            radioButtonSoft.Text = "杞Е鍙�";
+            radioButtonSoft.UseVisualStyleBackColor = true;
+            radioButtonSoft.CheckedChanged += radioButtonSoft_CheckedChanged;
+            // 
+            // radioButtonHard
+            // 
+            radioButtonHard.AutoSize = true;
+            radioButtonHard.Dock = DockStyle.Fill;
+            radioButtonHard.Location = new Point(3, 203);
+            radioButtonHard.Name = "radioButtonHard";
+            radioButtonHard.Size = new Size(353, 34);
+            radioButtonHard.TabIndex = 24;
+            radioButtonHard.TabStop = true;
+            radioButtonHard.Text = "纭Е鍙�";
+            radioButtonHard.UseVisualStyleBackColor = true;
+            // 
+            // splitContainer1
+            // 
+            splitContainer1.Dock = DockStyle.Fill;
+            splitContainer1.Location = new Point(5, 5);
+            splitContainer1.Name = "splitContainer1";
+            // 
+            // splitContainer1.Panel1
+            // 
+            splitContainer1.Panel1.Controls.Add(groupBox2);
+            // 
+            // splitContainer1.Panel2
+            // 
+            splitContainer1.Panel2.Controls.Add(groupBox1);
+            splitContainer1.Size = new Size(855, 591);
+            splitContainer1.SplitterDistance = 365;
+            splitContainer1.TabIndex = 19;
+            // 
+            // groupBox2
+            // 
+            groupBox2.BackColor = Color.FromArgb(39, 51, 63);
+            groupBox2.Controls.Add(tableLayoutPanel2);
+            groupBox2.Dock = DockStyle.Fill;
+            groupBox2.ForeColor = SystemColors.Control;
+            groupBox2.Location = new Point(0, 0);
+            groupBox2.MinimumSize = new Size(261, 61);
+            groupBox2.Name = "groupBox2";
+            groupBox2.Size = new Size(365, 591);
+            groupBox2.TabIndex = 0;
+            groupBox2.TabStop = false;
+            groupBox2.Text = "鐩告満鍙傛暟";
+            // 
+            // tableLayoutPanel2
+            // 
+            tableLayoutPanel2.ColumnCount = 1;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel3, 0, 0);
+            tableLayoutPanel2.Controls.Add(radioButtonHard, 0, 5);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel4, 0, 1);
+            tableLayoutPanel2.Controls.Add(radioButtonSoft, 0, 3);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel5, 0, 2);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel6, 0, 4);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel7, 0, 7);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel8, 0, 8);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel1, 0, 6);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel12, 0, 13);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel11, 0, 12);
+            tableLayoutPanel2.Controls.Add(cmbImagesPath, 0, 11);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel9, 0, 10);
+            tableLayoutPanel2.Controls.Add(tableLayoutPanel10, 0, 9);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 19);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 14;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.14301062F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.143011F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.143011F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.143011F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.143011F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.143011F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.143011F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.143011F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.143011F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.143011F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.143011F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.14301062F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.143011F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 7.14086771F));
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel2.Size = new Size(359, 569);
+            tableLayoutPanel2.TabIndex = 25;
+            // 
+            // tableLayoutPanel3
+            // 
+            tableLayoutPanel3.ColumnCount = 2;
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Controls.Add(label1, 0, 0);
+            tableLayoutPanel3.Controls.Add(cmbBrand, 1, 0);
+            tableLayoutPanel3.Dock = DockStyle.Fill;
+            tableLayoutPanel3.Location = new Point(3, 3);
+            tableLayoutPanel3.Name = "tableLayoutPanel3";
+            tableLayoutPanel3.RowCount = 1;
+            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel3.Size = new Size(353, 34);
+            tableLayoutPanel3.TabIndex = 0;
+            // 
+            // tableLayoutPanel4
+            // 
+            tableLayoutPanel4.ColumnCount = 2;
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel4.Controls.Add(label2, 0, 0);
+            tableLayoutPanel4.Controls.Add(cmbSN, 1, 0);
+            tableLayoutPanel4.Dock = DockStyle.Fill;
+            tableLayoutPanel4.Location = new Point(3, 43);
+            tableLayoutPanel4.Name = "tableLayoutPanel4";
+            tableLayoutPanel4.RowCount = 1;
+            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel4.Size = new Size(353, 34);
+            tableLayoutPanel4.TabIndex = 1;
+            // 
+            // tableLayoutPanel5
+            // 
+            tableLayoutPanel5.ColumnCount = 4;
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25F));
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25F));
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25F));
+            tableLayoutPanel5.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25F));
+            tableLayoutPanel5.Controls.Add(btnOpen, 0, 0);
+            tableLayoutPanel5.Controls.Add(btnClose, 1, 0);
+            tableLayoutPanel5.Controls.Add(btnEdit, 3, 0);
+            tableLayoutPanel5.Dock = DockStyle.Fill;
+            tableLayoutPanel5.Location = new Point(3, 83);
+            tableLayoutPanel5.Name = "tableLayoutPanel5";
+            tableLayoutPanel5.RowCount = 1;
+            tableLayoutPanel5.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel5.Size = new Size(353, 34);
+            tableLayoutPanel5.TabIndex = 2;
+            // 
+            // btnEdit
+            // 
+            btnEdit.Dock = DockStyle.Fill;
+            btnEdit.Enabled = false;
+            btnEdit.ForeColor = SystemColors.ControlText;
+            btnEdit.Location = new Point(267, 3);
+            btnEdit.Name = "btnEdit";
+            btnEdit.Size = new Size(83, 28);
+            btnEdit.TabIndex = 10;
+            btnEdit.Text = "缂栬緫";
+            btnEdit.UseVisualStyleBackColor = true;
+            btnEdit.Click += btnEdit_Click;
+            // 
+            // tableLayoutPanel6
+            // 
+            tableLayoutPanel6.ColumnCount = 4;
+            tableLayoutPanel6.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25.0006237F));
+            tableLayoutPanel6.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25.0006275F));
+            tableLayoutPanel6.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25.0006237F));
+            tableLayoutPanel6.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 24.9981289F));
+            tableLayoutPanel6.Controls.Add(btnGrabOnce, 0, 0);
+            tableLayoutPanel6.Controls.Add(btnStartGrab, 1, 0);
+            tableLayoutPanel6.Controls.Add(btnCloseGrab, 2, 0);
+            tableLayoutPanel6.Controls.Add(btnSaveImage, 3, 0);
+            tableLayoutPanel6.Dock = DockStyle.Fill;
+            tableLayoutPanel6.Location = new Point(3, 163);
+            tableLayoutPanel6.Name = "tableLayoutPanel6";
+            tableLayoutPanel6.RowCount = 1;
+            tableLayoutPanel6.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel6.Size = new Size(353, 34);
+            tableLayoutPanel6.TabIndex = 24;
+            // 
+            // btnSaveImage
+            // 
+            btnSaveImage.Dock = DockStyle.Fill;
+            btnSaveImage.ForeColor = SystemColors.Desktop;
+            btnSaveImage.Location = new Point(266, 2);
+            btnSaveImage.Margin = new Padding(2);
+            btnSaveImage.Name = "btnSaveImage";
+            btnSaveImage.Size = new Size(85, 30);
+            btnSaveImage.TabIndex = 8;
+            btnSaveImage.Text = "淇濆瓨鍥剧墖";
+            btnSaveImage.UseVisualStyleBackColor = true;
+            btnSaveImage.Click += btnSaveImage_Click;
+            // 
+            // tableLayoutPanel7
+            // 
+            tableLayoutPanel7.ColumnCount = 2;
+            tableLayoutPanel7.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel7.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel7.Controls.Add(label3, 0, 0);
+            tableLayoutPanel7.Controls.Add(txtExp, 1, 0);
+            tableLayoutPanel7.Dock = DockStyle.Fill;
+            tableLayoutPanel7.Location = new Point(3, 283);
+            tableLayoutPanel7.Name = "tableLayoutPanel7";
+            tableLayoutPanel7.RowCount = 1;
+            tableLayoutPanel7.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+            tableLayoutPanel7.Size = new Size(353, 34);
+            tableLayoutPanel7.TabIndex = 25;
+            // 
+            // tableLayoutPanel8
+            // 
+            tableLayoutPanel8.ColumnCount = 2;
+            tableLayoutPanel8.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel8.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel8.Controls.Add(label4, 0, 0);
+            tableLayoutPanel8.Controls.Add(txtGain, 1, 0);
+            tableLayoutPanel8.Dock = DockStyle.Fill;
+            tableLayoutPanel8.Location = new Point(3, 323);
+            tableLayoutPanel8.Name = "tableLayoutPanel8";
+            tableLayoutPanel8.RowCount = 1;
+            tableLayoutPanel8.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel8.Size = new Size(353, 34);
+            tableLayoutPanel8.TabIndex = 26;
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.ColumnCount = 3;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
+            tableLayoutPanel1.Controls.Add(btnStartHard, 0, 0);
+            tableLayoutPanel1.Controls.Add(ckbUpParams, 1, 0);
+            tableLayoutPanel1.Controls.Add(ckbRegrab, 2, 0);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(3, 243);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 1;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Size = new Size(353, 34);
+            tableLayoutPanel1.TabIndex = 29;
+            // 
+            // btnStartHard
+            // 
+            btnStartHard.Dock = DockStyle.Fill;
+            btnStartHard.Location = new Point(3, 3);
+            btnStartHard.Name = "btnStartHard";
+            btnStartHard.Size = new Size(64, 28);
+            btnStartHard.TabIndex = 22;
+            btnStartHard.Text = "绛夊緟瑙﹀彂";
+            btnStartHard.UseVisualStyleBackColor = true;
+            btnStartHard.Click += btnStartHard_Click;
+            // 
+            // ckbUpParams
+            // 
+            ckbUpParams.AutoSize = true;
+            ckbUpParams.Dock = DockStyle.Fill;
+            ckbUpParams.Location = new Point(73, 3);
+            ckbUpParams.Name = "ckbUpParams";
+            ckbUpParams.Size = new Size(135, 28);
+            ckbUpParams.TabIndex = 23;
+            ckbUpParams.Text = "鏄惁姣忔鍐欏叆鍙傛暟";
+            ckbUpParams.UseVisualStyleBackColor = true;
+            // 
+            // ckbRegrab
+            // 
+            ckbRegrab.AutoSize = true;
+            ckbRegrab.Dock = DockStyle.Fill;
+            ckbRegrab.Location = new Point(214, 3);
+            ckbRegrab.Name = "ckbRegrab";
+            ckbRegrab.Size = new Size(136, 28);
+            ckbRegrab.TabIndex = 24;
+            ckbRegrab.Text = "鏄惁澶辫触閲嶆柊鍙栧浘";
+            ckbRegrab.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel12
+            // 
+            tableLayoutPanel12.ColumnCount = 2;
+            tableLayoutPanel12.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 120F));
+            tableLayoutPanel12.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel12.Controls.Add(lblCapTime, 1, 0);
+            tableLayoutPanel12.Controls.Add(label7, 0, 0);
+            tableLayoutPanel12.Dock = DockStyle.Fill;
+            tableLayoutPanel12.Location = new Point(3, 523);
+            tableLayoutPanel12.Name = "tableLayoutPanel12";
+            tableLayoutPanel12.RowCount = 1;
+            tableLayoutPanel12.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel12.Size = new Size(353, 43);
+            tableLayoutPanel12.TabIndex = 31;
+            // 
+            // lblCapTime
+            // 
+            lblCapTime.AutoSize = true;
+            lblCapTime.Dock = DockStyle.Fill;
+            lblCapTime.Location = new Point(123, 0);
+            lblCapTime.Name = "lblCapTime";
+            lblCapTime.Size = new Size(227, 43);
+            lblCapTime.TabIndex = 16;
+            lblCapTime.Text = "0ms";
+            lblCapTime.TextAlign = ContentAlignment.MiddleLeft;
+            // 
+            // label7
+            // 
+            label7.AutoSize = true;
+            label7.Dock = DockStyle.Fill;
+            label7.Location = new Point(3, 0);
+            label7.Name = "label7";
+            label7.Size = new Size(114, 43);
+            label7.TabIndex = 15;
+            label7.Text = "鍙栧浘鏃堕棿锛�";
+            label7.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // tableLayoutPanel11
+            // 
+            tableLayoutPanel11.ColumnCount = 2;
+            tableLayoutPanel11.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 120F));
+            tableLayoutPanel11.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel11.Controls.Add(label5, 0, 0);
+            tableLayoutPanel11.Controls.Add(lblPicCount, 1, 0);
+            tableLayoutPanel11.Dock = DockStyle.Fill;
+            tableLayoutPanel11.Location = new Point(3, 483);
+            tableLayoutPanel11.Name = "tableLayoutPanel11";
+            tableLayoutPanel11.RowCount = 1;
+            tableLayoutPanel11.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel11.Size = new Size(353, 34);
+            tableLayoutPanel11.TabIndex = 30;
+            // 
+            // cmbImagesPath
+            // 
+            cmbImagesPath.BackColor = Color.White;
+            cmbImagesPath.Dock = DockStyle.Fill;
+            cmbImagesPath.ForeColor = SystemColors.ControlText;
+            cmbImagesPath.FormattingEnabled = true;
+            cmbImagesPath.Location = new Point(3, 443);
+            cmbImagesPath.Name = "cmbImagesPath";
+            cmbImagesPath.Size = new Size(353, 25);
+            cmbImagesPath.TabIndex = 0;
+            cmbImagesPath.SelectedIndexChanged += cmbImagesPath_SelectedIndexChanged;
+            cmbImagesPath.MouseHover += cmbImagesPath_MouseHover;
+            // 
+            // tableLayoutPanel9
+            // 
+            tableLayoutPanel9.ColumnCount = 3;
+            tableLayoutPanel9.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
+            tableLayoutPanel9.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
+            tableLayoutPanel9.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
+            tableLayoutPanel9.Controls.Add(ckbLocalTest, 0, 0);
+            tableLayoutPanel9.Controls.Add(btnAddImages, 1, 0);
+            tableLayoutPanel9.Controls.Add(btnLocalGrab, 2, 0);
+            tableLayoutPanel9.Dock = DockStyle.Fill;
+            tableLayoutPanel9.Location = new Point(3, 403);
+            tableLayoutPanel9.Name = "tableLayoutPanel9";
+            tableLayoutPanel9.RowCount = 1;
+            tableLayoutPanel9.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel9.Size = new Size(353, 34);
+            tableLayoutPanel9.TabIndex = 27;
+            // 
+            // ckbLocalTest
+            // 
+            ckbLocalTest.AutoSize = true;
+            ckbLocalTest.Dock = DockStyle.Fill;
+            ckbLocalTest.Location = new Point(3, 3);
+            ckbLocalTest.Name = "ckbLocalTest";
+            ckbLocalTest.Size = new Size(111, 28);
+            ckbLocalTest.TabIndex = 0;
+            ckbLocalTest.Text = "鏈湴鍙栧浘";
+            ckbLocalTest.UseVisualStyleBackColor = true;
+            // 
+            // btnAddImages
+            // 
+            btnAddImages.Dock = DockStyle.Fill;
+            btnAddImages.ForeColor = SystemColors.Desktop;
+            btnAddImages.Location = new Point(120, 3);
+            btnAddImages.Name = "btnAddImages";
+            btnAddImages.Size = new Size(111, 28);
+            btnAddImages.TabIndex = 1;
+            btnAddImages.Text = "娣诲姞鍥剧墖";
+            btnAddImages.UseVisualStyleBackColor = true;
+            btnAddImages.Click += btnAddImages_Click;
+            // 
+            // btnLocalGrab
+            // 
+            btnLocalGrab.Dock = DockStyle.Fill;
+            btnLocalGrab.ForeColor = SystemColors.Desktop;
+            btnLocalGrab.Location = new Point(237, 3);
+            btnLocalGrab.Name = "btnLocalGrab";
+            btnLocalGrab.Size = new Size(113, 28);
+            btnLocalGrab.TabIndex = 2;
+            btnLocalGrab.Text = "鏈湴鍙栧浘";
+            btnLocalGrab.UseVisualStyleBackColor = true;
+            btnLocalGrab.Click += btnLocalGrab_Click;
+            // 
+            // tableLayoutPanel10
+            // 
+            tableLayoutPanel10.ColumnCount = 2;
+            tableLayoutPanel10.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel10.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel10.Controls.Add(label6, 0, 0);
+            tableLayoutPanel10.Controls.Add(txtTimeout, 1, 0);
+            tableLayoutPanel10.Dock = DockStyle.Fill;
+            tableLayoutPanel10.Location = new Point(3, 363);
+            tableLayoutPanel10.Name = "tableLayoutPanel10";
+            tableLayoutPanel10.RowCount = 1;
+            tableLayoutPanel10.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel10.Size = new Size(353, 34);
+            tableLayoutPanel10.TabIndex = 32;
+            // 
+            // label6
+            // 
+            label6.AutoSize = true;
+            label6.Dock = DockStyle.Fill;
+            label6.Location = new Point(3, 0);
+            label6.Name = "label6";
+            label6.Size = new Size(44, 34);
+            label6.TabIndex = 0;
+            label6.Text = "瓒呮椂";
+            label6.TextAlign = ContentAlignment.MiddleCenter;
+            // 
+            // txtTimeout
+            // 
+            txtTimeout.Dock = DockStyle.Fill;
+            txtTimeout.Location = new Point(53, 3);
+            txtTimeout.Name = "txtTimeout";
+            txtTimeout.Size = new Size(297, 23);
+            txtTimeout.TabIndex = 1;
+            // 
+            // theme_2DCameraForm
+            // 
+            theme_2DCameraForm.AllowDrop = true;
+            theme_2DCameraForm.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
+            theme_2DCameraForm.BackColor = Color.FromArgb(32, 41, 50);
+            theme_2DCameraForm.Controls.Add(controlBox1);
+            theme_2DCameraForm.Controls.Add(panel_2DCameraForm);
+            theme_2DCameraForm.Font = new Font("Microsoft YaHei UI", 9F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            theme_2DCameraForm.Image = (Image)resources.GetObject("theme_2DCameraForm.Image");
+            theme_2DCameraForm.Location = new Point(0, 0);
+            theme_2DCameraForm.Name = "theme_2DCameraForm";
+            theme_2DCameraForm.Padding = new Padding(10, 70, 10, 9);
+            theme_2DCameraForm.RoundCorners = true;
+            theme_2DCameraForm.Sizable = true;
+            theme_2DCameraForm.Size = new Size(885, 680);
+            theme_2DCameraForm.SmartBounds = true;
+            theme_2DCameraForm.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            theme_2DCameraForm.TabIndex = 20;
+            theme_2DCameraForm.Text = "2D鐩告満璁剧疆鐣岄潰";
+            // 
+            // controlBox1
+            // 
+            controlBox1.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            controlBox1.BackColor = Color.FromArgb(32, 34, 37);
+            controlBox1.CloseHoverColor = Color.FromArgb(230, 17, 35);
+            controlBox1.DefaultLocation = true;
+            controlBox1.EnableHoverHighlight = true;
+            controlBox1.EnableMaximizeButton = false;
+            controlBox1.EnableMinimizeButton = false;
+            controlBox1.ForeColor = Color.FromArgb(155, 155, 155);
+            controlBox1.Location = new Point(785, 18);
+            controlBox1.MaximizeHoverColor = Color.FromArgb(74, 74, 74);
+            controlBox1.MinimizeHoverColor = Color.FromArgb(63, 63, 65);
+            controlBox1.Name = "controlBox1";
+            controlBox1.Size = new Size(90, 25);
+            controlBox1.TabIndex = 24;
+            controlBox1.Text = "controlBox1";
+            // 
+            // panel_2DCameraForm
+            // 
+            panel_2DCameraForm.BackColor = Color.FromArgb(39, 51, 63);
+            panel_2DCameraForm.Controls.Add(splitContainer1);
+            panel_2DCameraForm.Dock = DockStyle.Fill;
+            panel_2DCameraForm.EdgeColor = Color.FromArgb(32, 41, 50);
+            panel_2DCameraForm.Location = new Point(10, 70);
+            panel_2DCameraForm.Name = "panel_2DCameraForm";
+            panel_2DCameraForm.Padding = new Padding(5);
+            panel_2DCameraForm.Size = new Size(865, 601);
+            panel_2DCameraForm.SmoothingType = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
+            panel_2DCameraForm.TabIndex = 20;
+            panel_2DCameraForm.Text = "panel2";
+            // 
+            // CameraForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(885, 680);
+            Controls.Add(theme_2DCameraForm);
+            FormBorderStyle = FormBorderStyle.None;
+            MinimumSize = new Size(261, 61);
+            Name = "CameraForm";
+            Text = "2D鐩告満璁剧疆鐣岄潰";
+            TransparencyKey = Color.Fuchsia;
+            FormClosing += CameraForm_FormClosing;
+            FormClosed += CameraForm_FormClosed;
+            Load += CameraForm_Load;
+            groupBox1.ResumeLayout(false);
+            splitContainer1.Panel1.ResumeLayout(false);
+            splitContainer1.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit();
+            splitContainer1.ResumeLayout(false);
+            groupBox2.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            tableLayoutPanel2.PerformLayout();
+            tableLayoutPanel3.ResumeLayout(false);
+            tableLayoutPanel3.PerformLayout();
+            tableLayoutPanel4.ResumeLayout(false);
+            tableLayoutPanel4.PerformLayout();
+            tableLayoutPanel5.ResumeLayout(false);
+            tableLayoutPanel6.ResumeLayout(false);
+            tableLayoutPanel7.ResumeLayout(false);
+            tableLayoutPanel7.PerformLayout();
+            tableLayoutPanel8.ResumeLayout(false);
+            tableLayoutPanel8.PerformLayout();
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel1.PerformLayout();
+            tableLayoutPanel12.ResumeLayout(false);
+            tableLayoutPanel12.PerformLayout();
+            tableLayoutPanel11.ResumeLayout(false);
+            tableLayoutPanel11.PerformLayout();
+            tableLayoutPanel9.ResumeLayout(false);
+            tableLayoutPanel9.PerformLayout();
+            tableLayoutPanel10.ResumeLayout(false);
+            tableLayoutPanel10.PerformLayout();
+            theme_2DCameraForm.ResumeLayout(false);
+            panel_2DCameraForm.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ComboBox cmbBrand;
+        private ComboBox cmbSN;
+        private Label label1;
+        private Label label2;
+        private Button btnStartGrab;
+        private Button btnCloseGrab;
+        private Button btnGrabOnce;
+        private Button btnOpen;
+        private Button btnClose;
+        private TextBox txtGain;
+        private TextBox txtExp;
+        private Label label4;
+        private Label label3;
+        private Label label5;
+        private Label lblPicCount;
+        private GroupBox groupBox1;
+        private Panel panel_Picture;
+        private RadioButton radioButtonHard;
+        private RadioButton radioButtonSoft;
+        private SplitContainer splitContainer1;
+        private GroupBox groupBox2;
+        private TableLayoutPanel tableLayoutPanel2;
+        private TableLayoutPanel tableLayoutPanel3;
+        private TableLayoutPanel tableLayoutPanel4;
+        private TableLayoutPanel tableLayoutPanel5;
+        private TableLayoutPanel tableLayoutPanel6;
+        private TableLayoutPanel tableLayoutPanel7;
+        private TableLayoutPanel tableLayoutPanel8;
+        private TableLayoutPanel tableLayoutPanel9;
+        private TableLayoutPanel tableLayoutPanel1;
+        private Button btnStartHard;
+        private TableLayoutPanel tableLayoutPanel11;
+        private Label lblCapTime;
+        private Label label7;
+        private TableLayoutPanel tableLayoutPanel12;
+        private ComboBox cmbImagesPath;
+        private CheckBox ckbLocalTest;
+        private Button btnAddImages;
+        private Button btnLocalGrab;
+        private Button btnEdit;
+        private CheckBox ckbUpParams;
+        private Button btnSaveImage;
+        private TableLayoutPanel tableLayoutPanel10;
+        private Label label6;
+        private TextBox txtTimeout;
+        private CheckBox ckbRegrab;
+        private ReaLTaiizor.Forms.ThemeForm theme_2DCameraForm;
+        private ReaLTaiizor.Controls.Panel panel_2DCameraForm;
+        private ReaLTaiizor.Controls.ThunderControlBox thunderControlBox1;
+        private ReaLTaiizor.Controls.MetroControlBox metroControlBox1;
+        private ReaLTaiizor.Controls.ControlBox controlBox1;
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionProcesses/Cameras/2DCameraForm.cs b/LB_VisionProcesses/Cameras/2DCameraForm.cs
new file mode 100644
index 0000000..1bbdd63
--- /dev/null
+++ b/LB_VisionProcesses/Cameras/2DCameraForm.cs
@@ -0,0 +1,660 @@
+锘縰sing HalconDotNet;
+using LB_VisionControl;
+using MVSDK_Net;
+using Newtonsoft.Json.Linq;
+using OpenCvSharp;
+using System;
+using System.Collections.Concurrent;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Text;
+using System.Windows.Forms;
+using System.Xml.Linq;
+
+namespace LB_VisionProcesses.Cameras
+{
+    public partial class CameraForm : Form
+    {
+        Bitmap Bitmap = null;
+
+        BaseCamera camera { get; set; }
+
+        CameraConfig camConfig { get; set; }
+
+        ConcurrentDictionary<string, BaseCamera> dicCameras { get; set; }
+
+        string fullPath = string.Empty;
+
+        public CameraForm()
+        {
+            InitializeComponent();
+        }
+
+        public CameraForm(ConcurrentDictionary<string, BaseCamera> dicCameras, CameraConfig camConfig, string fullPath)
+        {
+            InitializeComponent();
+            //浼犲叆鐩告満鍙ユ焺鍚庣鐢ㄨ繛鎺�/鏂紑鎸夐敭
+            this.btnOpen.Enabled = false;
+            this.btnClose.Enabled = false;
+            this.cmbBrand.Enabled = false;
+            this.panel_Picture.Controls.Clear();
+
+            this.dicCameras = dicCameras;
+            this.fullPath = fullPath;
+            this.camConfig = camConfig;
+
+            foreach (var CamSN in dicCameras.Keys)
+                cmbSN.Items.Add(CamSN);
+
+            Enum.TryParse(camConfig.Params.Inputs["瑙﹀彂鏂瑰紡"].ToString(), out TriggerSource TriggerSource);
+
+            if (TriggerSource == TriggerSource.Software)
+                radioButtonSoft.Checked = true;
+            else
+                radioButtonSoft.Checked = false;
+
+            this.Text = camConfig.strProcessName;
+            txtExp.Text = camConfig.Params.Inputs["鏇濆厜鏃堕棿"].ToString();
+            txtGain.Text = camConfig.Params.Inputs["澧炵泭"].ToString();
+
+            ckbLocalTest.Checked = Convert.ToBoolean(camConfig.Params.Inputs["鏄惁鏈湴鍙栧浘"].ToString());
+            if (camConfig.Params.Inputs["鏈湴鍙栧浘璺緞"] is List<string>)
+            {
+                List<string> lstPaths = camConfig.Params.Inputs["鏈湴鍙栧浘璺緞"] as List<string>;
+                if (lstPaths != null && lstPaths.Count > 0)
+                {
+                    foreach (var path in lstPaths)
+                        cmbImagesPath.Items.Add(path);
+                    cmbImagesPath.Text = lstPaths[0];
+                }
+            }
+        }
+
+        UserPictureBox onlinePictureBox { get; set; }
+        private System.Windows.Forms.Timer updateTimer;
+        Total total = new Total { iImageCount = 0, iScanCount = 0 };
+        DateTime startGrabtime = DateTime.Now;
+
+        private void CameraForm_Load(object sender, EventArgs e)
+        {
+            // 璁剧疆涓�涓畾鏃跺櫒锛屾瘡 100 姣瑙﹀彂涓�娆�
+            updateTimer = new System.Windows.Forms.Timer();
+            updateTimer.Interval = 1000;  // 璁剧疆瀹氭椂鍣ㄩ棿闅斾负 1000 姣
+            updateTimer.Tick += (sender, e) => UpdateUI();
+            updateTimer.Start();
+
+            onlinePictureBox = new UserPictureBox(panel_Picture);
+            this.panel_Picture.Controls.Clear();
+            this.panel_Picture.Controls.Add(onlinePictureBox);
+            onlinePictureBox.Dock = DockStyle.Fill;
+
+            // 浣跨敤 LINQ 鑾峰彇鎵�鏈夋灇涓惧�煎苟鎵撳嵃
+            var brands = Enum.GetValues(typeof(CameraBrand)).Cast<CameraBrand>();
+            foreach (var brand in brands)
+            {
+                cmbBrand.Items.Add(brand.ToString());
+            }
+
+            //閫夋嫨Cam浼氳Е鍙慥alueChanged浜嬩欢锛屾病鏈夎緭鍏ョ浉鏈虹殑鎯呭喌涓嬮�夋嫨鍒�-1
+            if (camConfig != null)
+            {
+                string SN = camConfig.Params.Inputs["鐩告満SN"].ToString();
+                int Index = cmbSN.FindString(SN);
+
+                cmbSN.Text = SN;
+                cmbSN.SelectedIndex = Index;
+
+                ckbLocalTest.Checked = Convert.ToBoolean(camConfig.Params.Inputs["鏄惁鏈湴鍙栧浘"].ToString());
+                ckbUpParams.Checked = Convert.ToBoolean(camConfig.Params.Inputs["鏄惁姣忔鍐欏叆鍙傛暟"].ToString());
+                ckbRegrab.Checked = Convert.ToBoolean(camConfig.Params.Inputs["鏄惁澶辫触閲嶆柊鍙栧浘"].ToString());
+                txtTimeout.Text = camConfig.Params.Inputs["瓒呮椂鏃堕棿"].ToString();
+
+                if (camConfig.OutputImage != null && camConfig.OutputImage is Bitmap bitmap)
+                    onlinePictureBox.Image = bitmap;
+                lblCapTime.Text = $"{camConfig.RunTime}ms";
+            }
+        }
+
+        private void UpdateUI()
+        {
+            try
+            {
+                // 濡傛灉褰撳墠涓嶆槸 UI 绾跨▼锛屽垯閫氳繃 Invoke 灏嗘搷浣滆皟搴﹀埌 UI 绾跨▼
+                if (this.InvokeRequired)
+                {
+                    this.Invoke(new Action(() =>
+                    {
+                        double fps = total.iImageCount / (DateTime.Now - startGrabtime).TotalSeconds;
+                        this.lblPicCount.Text = total.iImageCount.ToString();
+                    }));
+                }
+                else
+                {
+                    // 濡傛灉宸茬粡鍦� UI 绾跨▼涓婏紝鐩存帴鏇存柊 
+                    double fps = total.iImageCount / (DateTime.Now - startGrabtime).TotalSeconds;
+                    this.lblPicCount.Text = total.iImageCount.ToString();
+                }
+            }
+            catch { }
+        }
+
+        private void cmbSN_MouseDown(object sender, MouseEventArgs e)
+        {
+            if (dicCameras != null && dicCameras.Count > 0)
+                return;
+
+            cmbSN.Items.Clear();
+            // 灏濊瘯灏嗚緭鍏ュ瓧绗︿覆杞崲涓烘灇涓惧��
+            if (Enum.TryParse(cmbBrand.Text, true, out CameraBrand brand))
+            {
+                // 浣跨敤 switch 璇彞鏉ュ垽鏂灇涓惧��
+                switch (brand)
+                {
+                    case CameraBrand.HRCamera:
+                        //camera = new HRCamera();
+                        break;
+                    case CameraBrand.LBCamera:
+                        //camera = new LBCamera();
+                        break;
+                    default:
+                        Debug.WriteLine("鏈煡鍝佺墝");
+                        break;
+                }
+
+                foreach (var item in camera.GetListEnum())
+                {
+                    if (!cmbSN.Items.Contains(item))
+                        cmbSN.Items.Add(item);
+                }
+            }
+            else
+            {
+                Debug.WriteLine("鏃犳晥鐨勬灇涓惧�硷紒");
+            }
+        }
+
+        private void cmbSN_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            btnEdit.Enabled = false;
+            //camConfig涓嶄负绌猴紙杈撳叆鏈夌浉鏈猴級锛屾洿鏀圭浉鏈洪�夋嫨闇�瑕侀噸鏂板姞杞藉埛鍥句簨浠�
+            if (camConfig != null && camera != null)
+            {
+                camera.ImageGrabbed -= GetImageBllComplete;
+            }
+            //杈撳叆鏃燾amConfig锛屼絾鏄鐩告満宸茬粡鎵撳紑杩囦簡闇�瑕侀噴鏀惧師鐩告満
+            else if (camera != null)
+            {
+                camera.ImageGrabbed -= GetImageBllComplete;
+                camera.Dispose();
+            }
+
+            if (dicCameras != null && dicCameras.Count > 0 && dicCameras.ContainsKey(cmbSN.Text))
+                camera = dicCameras[cmbSN.Text];
+
+            //璇存槑鐩告満宸茬粡鍒濆鍖栨垚鍔�
+            if (camera != null && camera.isGrabbing)
+            {
+                camera.ImageGrabbed -= GetImageBllComplete;
+                camera.ImageGrabbed += GetImageBllComplete;
+
+                int Index = cmbBrand.FindString(camera.Brand.ToString()); ;
+                cmbBrand.Text = camera.Brand.ToString();
+                cmbBrand.SelectedIndex = Index;
+            }
+        }
+
+        private void btnOpen_Click(object sender, EventArgs e)
+        {
+            // 灏濊瘯灏嗚緭鍏ュ瓧绗︿覆杞崲涓烘灇涓惧��
+            if (Enum.TryParse(cmbBrand.Text, true, out CameraBrand brand))
+            {
+                if (camera != null)
+                {
+                    camera.ImageGrabbed -= GetImageBllComplete;
+                    camera.Dispose();
+                }
+
+                // 浣跨敤 switch 璇彞鏉ュ垽鏂灇涓惧��
+                switch (brand)
+                {
+                    case CameraBrand.LBCamera:
+                        //camera = new LBCamera();
+                        break;
+                    case CameraBrand.HRCamera:
+                        //camera = new HRCamera();
+                        break;
+                    default:
+                        Debug.WriteLine($"銆恵DateTime.Now:HH:mm:ss.fff}銆戞湭鐭ュ搧鐗�");
+                        return;
+                }
+
+                if (cmbSN.Items.Count > 0 && camera.InitDevice(cmbSN.Text.ToString(), this.Handle))
+                {
+                    camera.ImageGrabbed -= GetImageBllComplete;
+                    camera.ImageGrabbed += GetImageBllComplete;
+                    MessageBox.Show(camera.SN + "鎵撳紑鎴愬姛");
+                }
+            }
+            else
+            {
+                Debug.WriteLine($"銆恵DateTime.Now:HH:mm:ss.fff}銆戞棤鏁堢殑鏋氫妇鍊硷紒");
+            }
+
+            if (camera != null)
+            {
+                this.BeginInvoke(new Action(() =>
+                {
+                    double exp = 0;
+                    double gain = 0;
+                    camera.GetExpouseTime(out exp);
+                    txtExp.Text = exp.ToString();
+
+                    camera.GetGain(out gain);
+                    txtGain.Text = gain.ToString();
+
+                    camera.GetTriggerMode(out TriggerMode mode, out TriggerSource source);
+
+                    if (source != TriggerSource.Software)
+                        radioButtonHard.Checked = true;
+                    else
+                        radioButtonSoft.Checked = true;
+                }));
+            }
+        }
+
+        private void btnClose_Click(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+            this.btnEdit.Enabled = false;
+
+            if (camera.CloseDevice())
+            {
+                MessageBox.Show(camera.SN + "鏂紑鎴愬姛");
+                this.panel_Picture.Controls.Clear();
+            }
+        }
+
+        private void btnEdit_Click(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+        }
+
+        /// <summary>
+        /// 鐩告満鍥炶皟杩愯
+        /// </summary>
+        /// <param name="CCDName"></param>
+        /// <param name="image"></param>
+        private void GetImageBllComplete(object sender, CameraEventArgs e)
+        {
+            if (e.Bitmap == null)
+                return;
+
+            lock (e.Bitmap)
+            {
+                if (this.InvokeRequired) // 妫�鏌ユ槸鍚﹂渶瑕佸湪UI绾跨▼涓婅皟鐢�
+                {
+                    this.Invoke(new Action(() =>
+                    {
+                        onlinePictureBox.Image = e.Bitmap;
+                    })); // 閫掑綊璋冪敤鑷韩锛屼絾杩欐鍦║I绾跨▼涓�
+                }
+                else
+                {
+                    onlinePictureBox.Image = e.Bitmap;
+                }
+            }
+
+            total.iImageCount++;
+            try
+            {
+                Bitmap = e.Bitmap.Clone() as Bitmap;
+            }
+            catch { }
+        }
+
+
+        private ulong ImageWidth;
+        private ulong ImageHeight;
+        private Pen pen = new Pen(Color.Blue, 3f);
+
+        private System.Drawing.Point[] stPointList = new System.Drawing.Point[4];
+        private void btnGrabOnce_Click(object sender, EventArgs e)
+        {
+            DateTime StartTime = DateTime.Now;
+            if (camera == null)
+                return;
+
+            Task.Factory.StartNew(() =>
+            {
+                //camera.GetCamConfig(out CameraConfig OriCamConfig);
+
+                camera.SetExpouseTime(Convert.ToDouble(txtExp.Text));
+                camera.SetGain(Convert.ToDouble(txtGain.Text));
+
+                camera.GetImageWithSoftTrigger(out Bitmap bitmap);
+
+                this.BeginInvoke(new Action(() =>
+                {
+                    if (bitmap != null)
+                        this.lblCapTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
+                    else
+                        this.lblCapTime.Text = "-1ms";
+                }));
+
+                //澶嶅師鍘熼�氳鍙h缃�
+                //camera.SetCamConfig(OriCamConfig);
+            });
+        }
+
+        private void btnStartHard_Click(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+
+            total.Clear();
+
+            // 灏濊瘯灏嗚緭鍏ュ瓧绗︿覆杞崲涓烘灇涓惧��
+            if (Enum.TryParse(cmbBrand.Text, true, out CameraBrand brand))
+            {
+                camera.StopGrabbing();
+                camera.StartWith_HardTriggerModel();
+            }
+
+            startGrabtime = DateTime.Now;
+
+            cmbSN.Enabled = false;
+            cmbBrand.Enabled = false;
+        }
+
+        private void btnStartGrab_Click(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+
+            total.Clear();
+
+            // 灏濊瘯灏嗚緭鍏ュ瓧绗︿覆杞崲涓烘灇涓惧��
+            if (Enum.TryParse(cmbBrand.Text, true, out CameraBrand brand))
+            {
+                Task.Factory.StartNew(() =>
+                {
+                    camera.StopGrabbing();
+                    camera.StartWith_SoftTriggerModel();
+
+                });
+            }
+
+            startGrabtime = DateTime.Now;
+            cmbSN.Enabled = false;
+            cmbBrand.Enabled = false;
+        }
+
+        private void btnCloseGrab_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                if (camera == null)
+                    return;
+
+                // 灏濊瘯灏嗚緭鍏ュ瓧绗︿覆杞崲涓烘灇涓惧��
+                if (Enum.TryParse(cmbBrand.Text, true, out CameraBrand brand))
+                {
+                    Task.Factory.StartNew(() =>
+                    {
+                        camera.StopGrabbing();
+                        camera.SetTriggerMode(TriggerMode.On, TriggerSource.Software);
+                        camera.StartGrabbing();
+                    });
+                }
+
+                cmbSN.Enabled = true;
+                cmbBrand.Enabled = true;
+            }
+            catch { }
+        }
+
+        private void btnLocalGrab_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                if (cmbImagesPath.Items.Count <= 0)
+                    return;
+
+                DateTime StartTime = DateTime.Now;
+
+                int index = cmbImagesPath.SelectedIndex;
+                if (cmbImagesPath.Items.Count > index + 1)
+                    cmbImagesPath.Text = cmbImagesPath.Items[index + 1].ToString();
+                else
+                    cmbImagesPath.Text = cmbImagesPath.Items[0].ToString();
+
+                using (Mat src = Cv2.ImRead(cmbImagesPath.Text))
+                {
+                    if (src != null && !src.Empty())
+                    {
+                        using (Bitmap bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(src))
+                        {
+                            this.Invoke(new Action(() =>
+                            {
+                                this.lblCapTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
+                            }));
+                            onlinePictureBox.Image = bitmap;
+                        }
+                    }
+                }
+            }
+            catch { }
+        }
+
+        private void txtExp_TextChanged(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+
+            double exp = 1000;
+            if (double.TryParse(txtExp.Text.ToString(), out exp))
+                camera.SetExpouseTime(exp);
+        }
+
+        private void txtGain_TextChanged(object sender, EventArgs e)
+        {
+            if (camera == null)
+                return;
+
+            double gain = 10;
+            if (double.TryParse(txtGain.Text.ToString(), out gain))
+                camera.SetGain(gain);
+        }
+
+        private void btnAddImages_Click(object sender, EventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+
+            // 璁剧疆鏂囦欢瀵硅瘽妗嗙殑灞炴��
+            openFileDialog.Multiselect = true; // 涓嶅厑璁稿閫�
+                                               // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+            // 鏄剧ず鏂囦欢瀵硅瘽妗�
+            DialogResult result = openFileDialog.ShowDialog();
+
+            // 澶勭悊瀵硅瘽妗嗚繑鍥炵粨鏋�
+            if (result == DialogResult.OK)
+            {
+                cmbImagesPath.Items.Clear();
+                // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠跺悕
+                string[] selectedFiles = openFileDialog.FileNames;
+                // 灏嗘枃浠惰矾寰勬坊鍔犲埌闃熷垪涓�
+                foreach (string file in selectedFiles)
+                    cmbImagesPath.Items.Add(file);
+
+                if (selectedFiles.Length > 0)
+                    cmbImagesPath.Text = selectedFiles[0];
+            }
+        }
+
+        private void CameraForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            //璺緞涓虹┖璇存槑鏃犻渶淇濆瓨
+            if (string.IsNullOrEmpty(fullPath))
+            {
+                e.Cancel = false;  //纭鍏抽棴绐椾綋
+                return;
+            }
+
+            DialogResult res = MessageBox.Show("鏄惁淇濆瓨锛�", "鎻愮ず", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);  //淇濆瓨缁撴灉淇℃伅
+            /// 鍙傛暟1锛氭樉绀烘枃鏈紝鍙傛暟2锛氭爣棰橈紝鍙傛暟3锛氭寜閿被鍨嬶紝鍙傛暟4锛氭樉绀哄浘鏍�
+            if (res == DialogResult.Cancel)  //鍙栨秷
+            {
+                e.Cancel = true;  //鍙栨秷鍏抽棴绐椾綋
+                return;
+            }
+
+            if (res == DialogResult.Yes)  //淇濆瓨VPP
+            {
+                camConfig.Params.Inputs.Add("鐩告満SN", cmbSN.Text);
+                camConfig.Params.Inputs.Add("瑙﹀彂妯″紡", TriggerMode.On);
+                camConfig.Params.Inputs.Add("瑙﹀彂鏂瑰紡", radioButtonSoft.Checked ? TriggerSource.Software : TriggerSource.Line0);
+                camConfig.Params.Inputs.Add("鏄惁鏈湴鍙栧浘", ckbLocalTest.Checked);
+                camConfig.Params.Inputs.Add("鏈湴鍙栧浘璺緞", cmbImagesPath.Items.Cast<string>().ToList());
+                camConfig.Params.Inputs.Add("鏄惁澶辫触閲嶆柊鍙栧浘", ckbRegrab.Checked);
+
+                if (int.TryParse(txtTimeout.Text, out int timeout))
+                    camConfig.Params.Inputs.Add("瓒呮椂鏃堕棿", timeout);
+
+                if (float.TryParse(txtExp.Text, out float exp))
+                    camConfig.Params.Inputs.Add("鏇濆厜鏃堕棿", exp);
+
+                if (float.TryParse(txtGain.Text, out float gain))
+                    camConfig.Params.Inputs.Add("澧炵泭", gain);
+
+                string filePath = Path.GetDirectoryName(fullPath);
+                camConfig.Save(filePath);
+                e.Cancel = false;  //纭鍏抽棴绐椾綋
+                return;
+            }
+        }
+
+        private void CameraForm_FormClosed(object sender, FormClosedEventArgs e)
+        {
+            this.onlinePictureBox.Image = null;
+            if (camera != null)
+            {
+                camera.ImageGrabbed -= GetImageBllComplete;
+                camera.StopGrabbing();
+
+                if (radioButtonSoft.Checked)
+                    camera.SetTriggerMode(TriggerMode.On, TriggerSource.Software);
+                else
+                    camera.SetTriggerMode(TriggerMode.On, TriggerSource.Line0);
+
+                camera.StartGrabbing();
+            }
+
+            //璺緞涓虹┖璇存槑涓烘祴璇曟ā寮忥紝闇�瑕侀噴鏀剧浉鏈�
+            if (string.IsNullOrEmpty(fullPath) && camera != null)
+                camera.Dispose();
+        }
+
+        private ImageFormat GetImageFormat(string extension)
+        {
+            return extension.ToLower() switch
+            {
+                ".jpg" or ".jpeg" => ImageFormat.Jpeg,
+                ".png" => ImageFormat.Png,
+                ".bmp" => ImageFormat.Bmp,
+                ".gif" => ImageFormat.Gif,
+                ".tiff" => ImageFormat.Tiff,
+                _ => ImageFormat.Png // 榛樿鏍煎紡
+            };
+        }
+
+        private void btnSaveImage_Click(object sender, EventArgs e)
+        {
+            if (Bitmap == null)
+            {
+                MessageBox.Show("娌℃湁鍥惧儚鍙繚瀛�!", "寮傚父");
+                return;
+            }
+
+            // 鍒涘缓 SaveFileDialog 瀹炰緥
+            using (SaveFileDialog saveFileDialog = new SaveFileDialog())
+            {
+                // 璁剧疆瀵硅瘽妗嗘爣棰�
+                saveFileDialog.Title = "淇濆瓨鏂囦欢";
+
+                // 璁剧疆榛樿璺緞
+                saveFileDialog.InitialDirectory = Application.StartupPath;
+
+                // 璁剧疆鏂囦欢杩囨护鍣紝鏀寔澶氱鏂囦欢绫诲瀷
+                saveFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
+
+                // 璁剧疆榛樿鏂囦欢鍚�
+                saveFileDialog.FileName = "output.jpg";
+
+                // 鏄剧ず瀵硅瘽妗嗗苟妫�鏌ョ敤鎴锋槸鍚︾偣鍑讳簡淇濆瓨鎸夐挳
+                if (saveFileDialog.ShowDialog() == DialogResult.OK)
+                {
+                    // 鑾峰彇鐢ㄦ埛閫夋嫨鐨勬枃浠惰矾寰�
+                    string fullPath = saveFileDialog.FileName;
+                    Debug.WriteLine("閫夋嫨鐨勬枃浠惰矾寰勬槸: " + fullPath);
+
+                    if (!string.IsNullOrEmpty(fullPath))
+                    {
+                        Bitmap.Save(fullPath, GetImageFormat(Path.GetExtension(fullPath)));
+                    }
+                }
+            }
+        }
+
+        private void radioButtonSoft_CheckedChanged(object sender, EventArgs e)
+        {
+            btnGrabOnce.Enabled = radioButtonSoft.Checked;
+            btnStartGrab.Enabled = radioButtonSoft.Checked;
+            btnCloseGrab.Enabled = radioButtonSoft.Checked;
+            btnStartHard.Enabled = !radioButtonSoft.Checked;
+
+            if (camera == null)
+                return;
+            if (radioButtonSoft.Checked)
+                camera.SetTriggerMode(TriggerMode.On, TriggerSource.Software);
+            else
+                camera.SetTriggerMode(TriggerMode.On, TriggerSource.Line0);
+        }
+
+        System.Windows.Forms.ToolTip ToolTip = new System.Windows.Forms.ToolTip();
+        private void cmbImagesPath_MouseHover(object sender, EventArgs e)
+        {
+            if (cmbImagesPath.SelectedIndex != -1
+                && camConfig != null
+                && int.TryParse(camConfig.Params.Inputs["鏈湴鍙栧浘搴忓彿"]?.ToString(), out int indexPath))
+            {
+                // 鏄剧ずToolTip锛堢浉瀵逛簬鎺т欢鐨勪綅缃級
+                ToolTip.Show($"褰撳墠绱㈠紩搴忓彿:{indexPath}", (Control)sender,
+                                   ((Control)sender).Width / 2, // x鍋忕Щ
+                                   -20,                      // y鍋忕Щ锛堣礋鍊艰〃绀轰笂鏂癸級
+                                   2000);                    // 鏄剧ず鏃堕棿(ms)
+            }
+        }
+
+        private void cmbImagesPath_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if (camConfig != null)
+                camConfig.Params.Inputs["鏈湴鍙栧浘搴忓彿"] = cmbImagesPath.SelectedIndex;
+        }
+
+        private void controlBox_2DCameraForm_Click(object sender, EventArgs e)
+        {
+            
+        }
+
+        private void dungeonControlBox_2DCameraForm_Click(object sender, EventArgs e)
+        {
+           // this.Close();
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Cameras/2DCameraForm.resx b/LB_VisionProcesses/Cameras/2DCameraForm.resx
new file mode 100644
index 0000000..b9f4bed
--- /dev/null
+++ b/LB_VisionProcesses/Cameras/2DCameraForm.resx
@@ -0,0 +1,144 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="theme_2DCameraForm.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        vAAADrwBlbxySQAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
+        BkVBUPCBCEG8BXNQ48GLeImCehIJxMsqhsSZruod46K4HtSIGjU+4iOr0c1I9fSsM3/PLNtCPO0H36m/
+        evz/X11VnreKVRTAHPOZumkY6lFwqURws3BwZ8ywTQnuiCP/+iTCzY1qaUPzdm/Atf3PaHre6XPsjyQM
+        2xLGV4XwIyX4QRj+UMK/lPFvJTyhBMeV8IgQvmRJuH4Ko+l5p9UjGBbCJ5RxTgj+VMZmXxKcSAjekHE/
+        NNs5DgaTKLinEQYVO4Trf1mkV81wixLUslPmA3bzF2XcKeP+hWY/u3n0fCXcrQwLyjAvjNsb1dI6N05P
+        mFAIHlHG73sEypPgGwnhfpn0zzH7jzddcK4Q7kqfKNMI4a9K+MwBDgbdeF04MBWsFYYdQvhbLlBvfhKT
+        f+vMtLfG7C0JJXxKGY67WnvCmPAFGRs7z42boul5AzHBfdK6TjdQtzPGk8oos5F/5Y7sfVvPhg+lp+1h
+        0yIsxARPmtaN78WEl8eEX+SNclxUhne0glUrNrN9zfMGlPAuZTzaQ99FYfwuDv3ruoLvq5bWaQSvZCfL
+        GXUYLwrj240Qxtu2lkSN4FpdWfKZH9jb9RQ1Cq62f9sVOlxUxn3KQXnJ0PO8QxU/jBm1h74v7ZniEG9K
+        Hdg/quzvXO709k0Y3u08ucGqWgheX862H4XgxbR47SqU8D1X0EXC2VmGizqDz0xPr0kYH9eO360gNe0b
+        jWppozB+1kOQEb5MCLa0C64NoeGrhOGrvH6lhK81GiIvnggmrDLzgvTkvwvDA+5wsU4nhG/m9AUoBD/F
+        HFzWN4H0XQn2vF8eXN8Z3FAPYasl59oUYjuB+sTImDB+nhfgYQ39STf4fmu1DHtz+oIUgiM1KkWtwcFw
+        sOujVT3hrnaL7UQc+hcL5W+sKIXhw0OVjaW0iwnBc47gqIQ45QY32PKRzv8eTguRYM9SS5YouEEZjv37
+        EffbzbjBDdZyxZYQ12EB2qS0bWrJqRVazPDWkojwZbuZrsgZtDJ0iY1g12khEtTicMTvclwn2CKE32YJ
+        7G5PORfZ1HtMCH7MOV4BrQ3XCe92+4onk5Nn2PolDAvWXnuOzAwzo6Nnx4Q3SrojwqfKeMxWMpsXWVs+
+        2WrfKRdbW1W6Hf0shM/33Y7my4PrleFZIfhAaWjU/e5ivlw+y3S2FySMtynjvcrwsFiLJv/RhPBB2ws1
+        hK2WcBLBFf1qawlplwvxaQlxe786OOU4PBWsjSO85mBlQ8n99r/BisSdAas4FfgHpdEUZpwUX7sAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Cameras/BaseCamera.cs b/LB_VisionProcesses/Cameras/BaseCamera.cs
new file mode 100644
index 0000000..5f6db1d
--- /dev/null
+++ b/LB_VisionProcesses/Cameras/BaseCamera.cs
@@ -0,0 +1,299 @@
+锘縰sing HalconDotNet;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Threading;
+
+namespace LB_VisionProcesses.Cameras
+{
+    public abstract class BaseCamera : ICamera
+    {
+        protected BaseCamera() { }
+
+        #region Parm
+        public string SN { get; set; } = string.Empty;
+        public CameraBrand Brand { get; set; } = CameraBrand.UNSUPPORTED;
+
+        public bool isGrabbing = false;
+
+        //public EventHandler<CameraEventArgs> ImageGrabbed = delegate { };
+
+        private EventHandler<CameraEventArgs> _imageGrabbed;
+        public EventHandler<CameraEventArgs> ImageGrabbed
+        {
+            get => _imageGrabbed;
+            set
+            {
+                Debug.WriteLine($"ImageGrabbed 琚缃紝鏂板��: {value?.Method}");
+                Debug.WriteLine($"璋冪敤鍫嗘爤: {Environment.StackTrace}");
+                _imageGrabbed = value;
+            }
+        }
+
+        protected static Bitmap CallBackImg { get; set; }
+
+        private Dictionary<string, List<Bitmap>> _collectedImages;
+        public Dictionary<string, List<Bitmap>> CollectedImages
+        {
+            get => _collectedImages;
+            set
+            {
+                _collectedImages = value;
+            }
+        }
+
+        public Bitmap Bitmap;
+        #endregion
+
+        #region  operate
+
+        public virtual void Dispose()
+        {
+            try
+            {
+                CloseDevice();
+            }
+            catch { }
+        }
+        public abstract bool CloseDevice();
+
+        public abstract List<string> GetListEnum();
+
+        public abstract bool InitDevice(string SN, object Handle = null);
+
+        public bool StartWith_SoftTriggerModel()
+        {
+            SetTriggerMode(TriggerMode.Off, TriggerSource.Software);
+            return StartGrabbing();
+        }
+
+        public bool StartWith_HardTriggerModel(TriggerSource hardtriggeritem = TriggerSource.Line0)
+        {
+            if (hardtriggeritem == TriggerSource.Software) hardtriggeritem = TriggerSource.Line0;
+            SetTriggerMode(TriggerMode.On, hardtriggeritem);
+            return StartGrabbing();
+        }
+
+        /// <summary>
+        /// 绛夊緟纭Е鍙戣幏鍙栧浘鍍�
+        /// </summary>
+        /// <param name="bitmap"></param>
+        /// <param name="outtime"></param>
+        /// <returns></returns>
+        public bool GetImage(out Bitmap bitmap, int outtime = 3000)
+        {
+            bitmap = null;
+
+            try
+            {
+                // 璁剧疆瓒呮椂鏃堕棿
+                DateTime lastTime = DateTime.Now.AddMilliseconds(outtime);
+                // 鍒ゆ柇鏄惁瓒呮椂
+                while (lastTime > DateTime.Now)// 璁剧疆瓒呮椂鏃堕棿涓� 3 绉�
+                {
+                    if (CallBackImg != null)
+                    {
+                        lock (CallBackImg)
+                        {
+                            // 淇濆瓨鏃� Bitmap 骞堕噴鏀�
+                            bitmap = CallBackImg.Clone() as Bitmap; // 鍒涘缓鍓湰
+                        }
+
+                        // 閲婃斁鏃ц祫婧�
+                        CallBackImg.Dispose();
+                        CallBackImg = null;
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+            catch { return bitmap == null ? false : true; }
+        }
+
+        /// <summary>
+        /// 杞Е鍙戣幏鍙栧浘鍍�
+        /// </summary>
+        /// <param name="bitmap"></param>
+        /// <param name="outtime"></param>
+        /// <returns></returns>
+        public bool GetImageWithSoftTrigger(out Bitmap bitmap, int outtime = 3000)
+        {
+            if (!isGrabbing)
+                StartGrabbing();
+
+            GetTriggerMode(out TriggerMode triggerMode, out TriggerSource triggerSource);
+
+            if (triggerMode != TriggerMode.On && triggerSource != TriggerSource.Software)
+                SetTriggerMode(TriggerMode.On, TriggerSource.Software);
+
+            bitmap = null;
+            CallBackImg = null;
+
+            if (!SoftTrigger())
+                return false;
+
+            // 寮�濮嬫椂闂�
+            DateTime startTime = DateTime.Now; // 褰撳墠鏃堕棿
+
+            // 鍒ゆ柇鏄惁瓒呮椂
+            while (DateTime.Now < startTime.AddMilliseconds(outtime))// 璁剧疆瓒呮椂鏃堕棿涓� 3 绉�
+            {
+                GetImage(out bitmap, 50);
+                if (bitmap != null)
+                    break;
+
+                Thread.Sleep(10);
+            }
+
+            if (triggerMode != TriggerMode.On)
+                SetTriggerMode(TriggerMode.On, triggerSource);
+
+            return (bitmap != null);
+        }
+
+        /// <summary>
+        /// 杞Е鍙�
+        /// </summary>
+        /// <returns></returns>
+        public abstract bool SoftTrigger();
+
+        public void Bitmap2HObject(Bitmap bmp, out HObject image)
+        {
+            try
+            {
+                if (bmp == null)
+                {
+                    image = null;
+                    return;
+                }
+                BitmapData srcBmpData;
+                switch (bmp.PixelFormat)
+                {
+                    case PixelFormat.Format24bppRgb:
+                        srcBmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
+                        HOperatorSet.GenImageInterleaved(out image, srcBmpData.Scan0, "bgr", bmp.Width, bmp.Height, 0, "byte", 0, 0, 0, 0, -1, 0);
+                        bmp.UnlockBits(srcBmpData);
+                        break;
+                    default:
+                        srcBmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
+
+                        HOperatorSet.GenImage1(out image, "byte", bmp.Width, bmp.Height, srcBmpData.Scan0);
+                        bmp.UnlockBits(srcBmpData);
+                        break;
+                }
+            }
+            catch (Exception ex)
+            {
+                image = null;
+            }
+        }
+
+        #endregion
+
+        #region SettingConfig
+        public void SetCamConfig(CameraConfig config)
+        {
+            if (Enum.TryParse(config.Params.Inputs["瑙﹀彂妯″紡"].ToString(), out TriggerMode TriggerMode)
+                && Enum.TryParse(config.Params.Inputs["瑙﹀彂鏂瑰紡"].ToString(), out TriggerSource TriggerSource)
+                && Enum.TryParse(config.Params.Inputs["瑙﹀彂鏋佹��"].ToString(), out TriggerPolarity TriggerPolarity)
+                )
+            {
+                SetTriggerMode(TriggerMode, TriggerSource);
+                SetTriggerPolarity(TriggerPolarity);
+                SetTriggerFliter(Convert.ToDouble(config.Params.Inputs["瑙﹀彂娑堟姈"].ToString()));
+                SetTriggerDelay(Convert.ToDouble(config.Params.Inputs["瑙﹀彂寤舵椂"].ToString()));
+                SetExpouseTime(Convert.ToDouble(config.Params.Inputs["鏇濆厜鏃堕棿"].ToString()));
+                SetGain(Convert.ToDouble(config.Params.Inputs["澧炵泭"].ToString()));
+            }
+        }
+
+        public void GetCamConfig(out CameraConfig config)
+        {
+            GetTriggerMode(out TriggerMode triggerMode, out TriggerSource triggerSource);
+            GetTriggerPolarity(out TriggerPolarity triggerPolarity);
+            GetTriggerFliter(out double triggerfilter);
+            GetTriggerDelay(out double triggerdelay);
+            GetExpouseTime(out double expouseTime);
+            GetGain(out double gain);
+
+            config = new CameraConfig(null);
+            config.Params.Inputs.Add("瑙﹀彂妯″紡", triggerMode);
+            config.Params.Inputs.Add("瑙﹀彂鏂瑰紡", triggerSource);
+            config.Params.Inputs.Add("瑙﹀彂鏋佹��", triggerPolarity);
+            config.Params.Inputs.Add("瑙﹀彂娑堟姈", triggerfilter);
+            config.Params.Inputs.Add("瑙﹀彂寤舵椂", triggerdelay);
+            config.Params.Inputs.Add("鏇濆厜鏃堕棿", expouseTime);
+            config.Params.Inputs.Add("澧炵泭", gain);
+        }
+
+        /// <summary>
+        /// 璁剧疆瑙﹀彂妯″紡鍙婅Е鍙戞簮
+        /// </summary>
+        /// <param name="mode"></param>
+        /// <param name="triggerEnum"></param>
+        /// <returns></returns>
+        public abstract bool SetTriggerMode(TriggerMode mode, TriggerSource triggerEnum = TriggerSource.Line0);
+
+        public abstract bool GetTriggerMode(out TriggerMode mode, out TriggerSource source);
+
+        public abstract bool SetExpouseTime(double value);
+
+        public abstract bool GetExpouseTime(out double value);
+
+        public abstract bool SetTriggerPolarity(TriggerPolarity polarity);
+
+        public abstract bool GetTriggerPolarity(out TriggerPolarity polarity);
+
+        /// <summary>
+        /// 璁剧疆瑙﹀彂婊ゆ尝鏃堕棿 锛坲s锛�
+        /// </summary>
+        /// <param name="flitertime"></param>
+        /// <returns></returns>
+        public abstract bool SetTriggerFliter(double flitertime);
+
+        /// <summary>
+        /// 鑾峰彇瑙﹀彂鍙傛暟鏃堕棿 锛坲s锛�
+        /// </summary>
+        /// <param name="flitertime"></param>
+        /// <returns></returns>
+        public abstract bool GetTriggerFliter(out double flitertime);
+
+        public abstract bool SetTriggerDelay(double delay);
+
+        public abstract bool GetTriggerDelay(out double delay);
+
+        public abstract bool SetGain(double gain);
+
+        public abstract bool GetGain(out double gain);
+
+        public abstract bool SetLineMode(IOLines line, LineMode mode);
+
+        public abstract bool SetLineStatus(IOLines line, LineStatus linestatus);
+
+        public abstract bool GetLineStatus(IOLines line, out LineStatus lineStatus);
+
+        public abstract bool AutoBalanceWhite();
+
+        #endregion
+
+        #region  protected abstract
+        /// <summary>
+        /// 寮�濮嬮噰鍥�
+        /// </summary>
+        /// <returns></returns>
+        public abstract bool StartGrabbing();
+
+        /// <summary>
+        /// 鍋滄閲囧浘
+        /// </summary>
+        /// <returns></returns>
+        public abstract bool StopGrabbing();
+        #endregion
+    }
+}
+
+
diff --git a/LB_VisionProcesses/Cameras/CameraConfig.cs b/LB_VisionProcesses/Cameras/CameraConfig.cs
new file mode 100644
index 0000000..fa0bb79
--- /dev/null
+++ b/LB_VisionProcesses/Cameras/CameraConfig.cs
@@ -0,0 +1,315 @@
+锘縰sing Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using OpenCvSharp;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+using System.Text;
+
+namespace LB_VisionProcesses.Cameras
+{
+    [Process("鐩告満鍙栧浘", Category = "鍙栧儚宸ュ叿", Description = "鍒涘缓鐩告満鍙栧浘宸ュ叿")]
+    public class CameraConfig : IProcess
+    {
+        /// <summary>
+        /// 鐩告満闆嗗悎(Key:鐩告満SN锛孷alue:鐩告満鍙ユ焺)
+        /// </summary>
+        public ConcurrentDictionary<string, BaseCamera> dicCameras { get; set; }
+
+        public BaseCamera Camera { get; set; }
+
+        public CameraConfig(ConcurrentDictionary<string, BaseCamera> dicCameras = null)
+        {
+            this.dicCameras = dicCameras;
+
+            strProcessName = "鐩告満鍙栧浘";
+            strProcessClass = "LB_VisionProcesses.CameraConfig.CommunicatorConfig";
+
+            Params.Inputs.Add("鐩告満SN", "");
+            Params.Inputs.Add("瑙﹀彂妯″紡", TriggerMode.On);
+            Params.Inputs.Add("瑙﹀彂鏂瑰紡", TriggerSource.Software);
+            Params.Inputs.Add("瑙﹀彂鏋佹��", TriggerPolarity.RisingEdge);
+            Params.Inputs.Add("瑙﹀彂娑堟姈", 0);
+            Params.Inputs.Add("瑙﹀彂寤舵椂", 0);
+            Params.Inputs.Add("鏇濆厜鏃堕棿", 1000);
+            Params.Inputs.Add("澧炵泭", 1);
+            Params.Inputs.Add("鏄惁姣忔鍐欏叆鍙傛暟", false);
+            Params.Inputs.Add("鏄惁鏈湴鍙栧浘", false);
+            Params.Inputs.Add("鏈湴鍙栧浘璺緞", "");
+            Params.Inputs.Add("鏈湴鍙栧浘搴忓彿", 0);
+
+            Params.Inputs.Add("瓒呮椂鏃堕棿", 1000);
+            Params.Inputs.Add("鏄惁澶辫触閲嶆柊鍙栧浘", false);
+        }
+
+        /// <summary>
+        /// 鍔犺浇绠楁硶
+        /// </summary>
+        /// <param name="fullPath">瀹屾暣璺緞甯�.json</param>
+        /// <returns></returns>
+        public override bool Load(string fullPath = null)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                if (!fullPath.Contains(".json"))
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+                if (string.IsNullOrEmpty(fullPath) || fullPath.Trim() == "")
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                string directoryPath = Path.GetDirectoryName(fullPath);
+                strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+
+                if (!File.Exists(fullPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    Save(directoryPath);
+                    return true;
+                }
+
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+                Params = JsonConvert.DeserializeObject<ProcessParams>(strJson);
+                if (Params == null)
+                    return false;
+                Params.FixDeserializedData();
+
+                #region 鍔犺浇鍚庢妸鍙傛暟鍐欏叆鍒扮浉鏈轰腑
+                bool isLocal = Convert.ToBoolean(Params.Inputs["鏄惁鏈湴鍙栧浘"].ToString());
+                if (!isLocal)
+                {
+                    string SN = Params.Inputs["鐩告満SN"].ToString();
+
+                    if (dicCameras == null || !dicCameras.ContainsKey(SN))
+                        return false;
+
+                    BaseCamera BaseCamera = dicCameras[SN];
+                    if (BaseCamera == null)
+                        return false;
+
+                    if (!BaseCamera.isGrabbing)
+                    {
+                        if (!BaseCamera.StartGrabbing())
+                            return false;
+                    }
+                    BaseCamera.SetCamConfig(this);
+                }
+                #endregion
+
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨绠楁硶
+        /// </summary>
+        /// <param name="filePath">涓嶅甫.json</param>
+        /// <returns></returns>
+        public override bool Save(string filePath = null)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(filePath) || filePath.Trim() == "")
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                string strJson = string.Empty;
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Newtonsoft.Json.Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+                strJson = JsonConvert.SerializeObject(Params, settings);
+
+                Params = JsonConvert.DeserializeObject<ProcessParams>(strJson);
+                if (Params == null)
+                    return false;
+
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                if (!Directory.Exists(filePath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(filePath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+
+                File.WriteAllText(filePath + "//" + strProcessName + ".json", strJson, Encoding.UTF8);
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public override bool Run()
+        {
+            DateTime StartTime = DateTime.Now;
+            try
+            {
+                InitRunParams();
+                string SN = string.Empty;
+                bool isLocal = Convert.ToBoolean(Params.Inputs["鏄惁鏈湴鍙栧浘"]?.ToString());
+                bool isUpParams = Convert.ToBoolean(Params.Inputs["鏄惁姣忔鍐欏叆鍙傛暟"]?.ToString());
+                bool isRegrab = Convert.ToBoolean(Params.Inputs["鏄惁澶辫触閲嶆柊鍙栧浘"]?.ToString());
+                int timeout = Convert.ToInt16(Params.Inputs["瓒呮椂鏃堕棿"]?.ToString());
+
+                if (isLocal)
+                {
+                    if (Params.Inputs["鏈湴鍙栧浘璺緞"] is List<string>)
+                    {
+                        List<string> lstPaths = Params.Inputs["鏈湴鍙栧浘璺緞"] as List<string>;
+                        if (lstPaths != null && int.TryParse(Params.Inputs["鏈湴鍙栧浘搴忓彿"]?.ToString(), out int indexPath)
+                            && lstPaths.Count > indexPath)
+                        {
+                            SN = lstPaths[indexPath];
+
+                            if (lstPaths.Count > indexPath + 1)
+                                Params.Inputs["鏈湴鍙栧浘搴忓彿"] = indexPath + 1;
+                            else
+                                Params.Inputs["鏈湴鍙栧浘搴忓彿"] = 0;
+
+                            Mat src = Cv2.ImRead(SN);
+                            if (src != null && !src.Empty())
+                                OutputImage = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(src);
+                        }
+                    }
+                }
+                else
+                {
+                    SN = Params.Inputs["鐩告満SN"].ToString();
+
+                    if (dicCameras == null || !dicCameras.ContainsKey(SN))
+                    {
+                        Msg = $"鐩告満[{SN}]涓嶅瓨鍦�";
+                        Result = false;
+                        RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
+                        return Result;
+                    }
+
+                    if (Camera == null || Camera.SN != SN)
+                    {
+                        if (dicCameras.ContainsKey(SN))
+                            Camera = dicCameras[SN];
+                        else
+                            Camera = null;
+                    }
+
+                    if (Camera == null)
+                    {
+                        Msg = $"鐩告満[{SN}]鏈疄渚嬪寲";
+                        Result = false;
+                        RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
+                        return Result;
+                    }
+
+                    CameraConfig oriConfig = new CameraConfig();
+
+                    if (isUpParams)
+                    {
+                        Camera.GetCamConfig(out oriConfig);
+                        Camera.SetCamConfig(this);
+                    }
+
+                    if (!Enum.TryParse(Params.Inputs["瑙﹀彂鏂瑰紡"].ToString(), out TriggerSource TriggerSource))
+                    {
+                        Msg = $"鐩告満[{SN}]璁剧疆鐨勮Е鍙戞柟寮忎笉姝g‘,鍊间负:{Params.Inputs["瑙﹀彂鏂瑰紡"].ToString()}";
+                        Result = false;
+                        RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
+                        return Result;
+                    }
+
+                    Bitmap bitmap = null;
+                    int times = 5;
+                    do
+                    {
+                        times--;
+                        if (TriggerSource == TriggerSource.Software)
+                            Camera.GetImageWithSoftTrigger(out bitmap, timeout);
+                        else
+                            Camera.GetImage(out bitmap, timeout);
+
+                        if (bitmap != null)
+                            break;
+                        else if (isRegrab)
+                        {
+                            Debug.WriteLine($"鍙栧浘澶辫触,閲嶆柊鍙栧浘,鍓╀綑娆℃暟:{times}");
+                        }
+                    } while (times > 0 && isRegrab);
+
+                    if (isUpParams)
+                        Camera.SetCamConfig(oriConfig);
+
+                    OutputImage = bitmap;
+                }
+
+                if (OutputImage == null)
+                {
+                    Msg = $"鐩告満[{SN}]鑾峰彇鍥惧儚澶辫触";
+                    Result = false;
+                }
+            }
+            catch (Exception ex)
+            {
+                Msg = ex.Message;
+                Result = false;
+            }
+            RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
+            return Result;
+        }
+
+        public override void InitRunParams()
+        {
+            Result = true;
+            Msg = "";
+            OutputImage = null;
+
+            if (Record != null)
+                Record.Dispose();
+        }
+
+        public override void Dispose()
+        {
+            return;
+        }
+
+        public override object Clone()
+        {
+            try
+            {
+                var obj = (CameraConfig)MemberwiseClone(); // 娴呮嫹璐�
+
+                // 鎵嬪姩澶勭悊寮曠敤绫诲瀷
+                if (OutputImage != null)
+                {
+                    if (OutputImage is Bitmap)
+                        obj.OutputImage = ((Bitmap)OutputImage).Clone();
+                }
+
+                return obj;
+            }
+            catch { return (CameraConfig)MemberwiseClone(); }
+        }
+    }
+}
+
+
diff --git a/LB_VisionProcesses/Cameras/ICamera.cs b/LB_VisionProcesses/Cameras/ICamera.cs
new file mode 100644
index 0000000..055a5e5
--- /dev/null
+++ b/LB_VisionProcesses/Cameras/ICamera.cs
@@ -0,0 +1,312 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Reflection;
+
+namespace LB_VisionProcesses.Cameras
+{
+    public class Total
+    {
+        public int iImageCount { get; set; } = 0;
+        public int iScanCount { get; set; } = 0;
+
+        public Total() { }
+
+        public Total(int iImageCount, int iScanCount)
+        {
+            this.iImageCount = iImageCount;
+            this.iScanCount = iScanCount;
+        }
+
+        public void Clear()
+        {
+            iImageCount = 0;
+            iScanCount = 0;
+        }
+    }
+    public interface ICamera : IDisposable
+    {
+
+        #region  operate
+
+        Dictionary<string, List<Bitmap>> CollectedImages { get; set; }
+        /// <summary>
+        /// 鑾峰彇鐩告満SN鏋氫妇
+        /// </summary>
+        /// <returns></returns>
+        List<string> GetListEnum();
+
+        /// <summary>
+        /// 鍒濆鍖栫浉鏈�
+        /// </summary>
+        /// <param name="CamInfo"></param>
+        /// <returns></returns>
+        bool InitDevice(string SN, object Handle);
+
+        /// <summary>
+        /// 娉ㄩ攢鐩告満
+        /// </summary>
+        bool CloseDevice();
+
+        /// <summary>
+        /// 杞Е鍙戞ā寮� 鍚姩鐩告満
+        /// </summary>
+        /// <returns></returns>
+        bool StartWith_SoftTriggerModel();
+
+        /// <summary>
+        /// 纭Е鍙戞ā寮� 鍚姩鐩告満
+        /// </summary>
+        /// <param name="hardtriggeritem"></param>
+        /// <returns></returns>
+        bool StartWith_HardTriggerModel(TriggerSource hardtriggeritem = TriggerSource.Line0);
+
+        /// <summary>
+        /// 绛夊緟纭Е鍙戣幏鍙栧浘鍍�
+        /// </summary>
+        /// <param name="bitmap"></param>
+        /// <param name="outtime"></param>
+        /// <returns></returns>
+        bool GetImage(out Bitmap bitmap, int outtime = 3000);
+
+        /// <summary>
+        /// 杞Е鍙戣幏鍙栧浘鍍�
+        /// </summary>
+        /// <param name="bitmap"></param>
+        /// <param name="outtime"></param>
+        /// <returns></returns>
+        bool GetImageWithSoftTrigger(out Bitmap bitmap, int outtime = 3000);
+
+        /// <summary>
+        /// 杞Е鍙�
+        /// </summary>
+        /// <returns></returns>
+        bool SoftTrigger();
+
+        #endregion
+
+        #region SettingConfig
+        /// <summary>
+        /// 璁剧疆鐩告満鍙傛暟
+        /// </summary>
+        /// <param name="config"></param>
+        void SetCamConfig(CameraConfig config);
+        /// <summary>
+        /// 鑾峰彇鐩告満鍙傛暟
+        /// </summary>
+        /// <param name="config"></param>
+        void GetCamConfig(out CameraConfig config);
+
+        /// <summary>
+        /// 璁剧疆瑙﹀彂妯″紡鍙婅Е鍙戞簮
+        /// </summary>
+        /// <param name="mode"></param>
+        /// <param name="triggerEnum"></param>
+        /// <returns></returns>
+        bool SetTriggerMode(TriggerMode mode, TriggerSource source = TriggerSource.Line0);
+
+        /// <summary>
+        /// 鑾峰彇瑙﹀彂妯″紡鍙婅Е鍙戞簮
+        /// </summary>
+        /// <param name="mode"></param>
+        /// <param name="hardTriggerModel"></param>
+        /// <returns></returns>
+        bool GetTriggerMode(out TriggerMode mode, out TriggerSource source);
+
+        /// <summary>
+        /// 璁剧疆鏇濆厜鏃堕暱
+        /// </summary>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        bool SetExpouseTime(double value);
+
+        /// <summary>
+        /// 鑾峰彇鏇濆厜鏃堕暱
+        /// </summary>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        bool GetExpouseTime(out double value);
+
+        /// <summary>
+        /// 璁剧疆纭Е鍙戞瀬鎬�
+        /// </summary>
+        /// <param name="polarity"></param>
+        /// <returns></returns>
+        bool SetTriggerPolarity(TriggerPolarity polarity);
+
+        /// <summary>
+        /// 鑾峰彇纭Е鍙戞瀬鎬�
+        /// </summary>
+        /// <param name="polarity"></param>
+        /// <returns></returns>
+        bool GetTriggerPolarity(out TriggerPolarity polarity);
+
+        /// <summary>
+        /// 璁剧疆瑙﹀彂婊ゆ尝鏃堕棿 锛坲s锛�
+        /// </summary>
+        /// <param name="flitertime"></param>
+        /// <returns></returns>
+        bool SetTriggerFliter(double flitertime);
+
+        /// <summary>
+        /// 鑾峰彇瑙﹀彂婊ゆ尝鏃堕棿 锛坲s锛�
+        /// </summary>
+        /// <param name="flitertime"></param>
+        /// <returns></returns>
+        bool GetTriggerFliter(out double flitertime);
+
+        /// <summary>
+        /// 璁剧疆瑙﹀彂寤舵椂
+        /// </summary>
+        /// <param name="delay"></param>
+        /// <returns></returns>
+        bool SetTriggerDelay(double delay);
+
+        /// <summary>
+        /// 鑾峰彇瑙﹀彂寤舵椂
+        /// </summary>
+        /// <param name="delay"></param>
+        /// <returns></returns>
+        bool GetTriggerDelay(out double delay);
+
+        /// <summary>
+        /// 璁剧疆澧炵泭
+        /// </summary>
+        /// <param name="gain"></param>
+        /// <returns></returns>
+        bool SetGain(double gain);
+
+        /// <summary>
+        /// 鑾峰彇澧炵泭鍊�
+        /// </summary>
+        /// <param name="gain"></param>
+        /// <returns></returns>
+        bool GetGain(out double gain);
+
+        /// <summary>
+        /// 璁剧疆淇″彿绾挎ā寮�
+        /// </summary>
+        /// <param name="line"></param>
+        /// <param name="mode"></param>
+        /// <returns></returns>
+        bool SetLineMode(IOLines line, LineMode mode);
+
+        /// <summary>
+        /// 璁剧疆淇″彿绾跨數骞崇姸鎬�
+        /// </summary>
+        /// <param name="line"></param>
+        /// <param name="linestatus"></param>
+        /// <returns></returns>
+        bool SetLineStatus(IOLines line, LineStatus linestatus);
+
+        /// <summary>
+        /// 鑾峰彇淇″彿绾跨數骞崇姸鎬�
+        /// </summary>
+        /// <param name="line"></param>
+        /// <param name="lineStatus"></param>
+        /// <returns></returns>
+        bool GetLineStatus(IOLines line, out LineStatus lineStatus);
+
+        /// <summary>
+        /// 鑷姩鐧藉钩琛�
+        /// </summary>
+        /// <returns></returns>
+        bool AutoBalanceWhite();
+
+        /// <summary>
+        /// 寮�濮嬮噰鍥�
+        /// </summary>
+        /// <returns></returns>
+        bool StartGrabbing();
+
+        /// <summary>
+        /// 鍋滄閲囧浘
+        /// </summary>
+        /// <returns></returns>
+        bool StopGrabbing();
+        #endregion
+    }
+
+    public enum CameraBrand
+    {
+        /// <summary>
+        /// 鍗庣澘宸ヤ笟鐩告満
+        /// </summary>
+        HRCamera,
+        /// <summary>
+        /// 鍏板疂宸ヤ笟鐩告満
+        /// </summary>
+        LBCamera,
+        /// <summary>
+        /// 鏈煡鐩告満
+        /// </summary>
+        UNSUPPORTED
+    }
+
+    public enum IOLines
+    {
+        Line0,
+        Line1,
+        Line2,
+        Line3,
+        Line4,
+        Line5
+    }
+
+    public enum LineMode
+    {
+        Input,
+        Output
+    }
+
+    public enum LineStatus
+    {
+        Hight,
+        Low
+    }
+
+    public enum TriggerMode
+    {
+        Off,
+        On
+    }
+
+    public enum TriggerPolarity
+    {
+        RisingEdge,
+        FallingEdge,
+        HighLevel,
+        LowLevel
+    }
+
+    public enum TriggerSource
+    {
+        Software,
+        Line0,
+        Line1,
+        Line2,
+        Line3,
+        Line4,
+        Line5,
+        None
+    }
+
+    public class CameraEventArgs
+    {
+        public string SN { get; set; }
+
+        public Bitmap Bitmap { get; set; }
+
+        public string[] arrResult;
+        public CameraEventArgs() { }
+
+        public CameraEventArgs(string sn, Bitmap bitmap, string[] arrResult = null)
+        {
+            this.SN = sn;
+            this.Bitmap = bitmap;
+            this.arrResult = arrResult;
+        }
+    }
+}
+
diff --git a/LB_VisionProcesses/Communicators/BaseCommunicator.cs b/LB_VisionProcesses/Communicators/BaseCommunicator.cs
new file mode 100644
index 0000000..c0bcef3
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/BaseCommunicator.cs
@@ -0,0 +1,180 @@
+锘縩amespace LB_VisionProcesses.Communicators
+{
+    public abstract class BaseCommunicator : ICommunicator
+    {
+        /// <summary>
+        /// 閫氳鍚嶇О
+        /// </summary>
+        public string CommunicatorName { get; set; } = string.Empty;
+
+        /// <summary>
+        /// 閫氳绫诲悕
+        /// </summary>
+        public CommunicatorBrand CommunicatorBrand { get; set; } = CommunicatorBrand.UARTPort;
+
+        /// <summary>
+        /// 鏄惁杩炴帴
+        /// </summary>
+        public bool bConnected = true;
+
+        /// <summary>
+        /// 鏄惁鏈夊績璺�
+        /// </summary>
+        protected bool bHeart = true;
+
+        /// <summary>
+        /// 杩炴帴鍙傛暟
+        /// </summary>
+        public CommunicatorCollections<object> CommunicatorConnections = new CommunicatorCollections<object>();
+
+        /// <summary>
+        /// 杩愯鏃ュ織
+        /// </summary>
+        public string Msg = string.Empty;
+
+        /// <summary>
+        /// 鎺ュ彈鍒扮殑娑堟伅
+        /// </summary>
+        public string strReceiveMsg = string.Empty;
+
+        /// <summary>
+        /// 鍙戦�佺殑娑堟伅
+        /// </summary>
+        public string strSendMsg = string.Empty;
+
+        /// <summary>
+        /// 鑾峰彇娑堟伅鍥炶皟
+        /// </summary>
+        public Action<string> MessageReceived;
+
+        /// <summary>
+        /// 鑾峰彇娑堟伅鍥炶皟
+        /// </summary>
+        public Action<string, string> TriggerRunMessageReceived;
+
+        /// <summary>
+        /// 蹇冭烦淇″彿
+        /// </summary>
+        public string strHeartbeat = "\0";
+
+        /// <summary>
+        /// 蹇冭烦闂撮殧
+        /// </summary>
+        private const int HeartbeatInterval = 2; // 蹇冭烦闂撮殧锛�2绉掞級
+
+        /// <summary>
+        /// 蹇冭烦鍙戦�佺嚎绋�
+        /// </summary>
+        public Thread heartbeatThread;
+
+        public BaseCommunicator(string name = "")
+        {
+            CommunicatorName = name;
+        }
+
+        public virtual void SendHeartbeat()
+        {
+            while (true)
+            {
+                Thread.Sleep(50);
+                if (!bConnected)
+                    return;
+                try
+                {
+                    // 鍙戦�佸け璐ュ垯閲嶈繛
+                    if (!SendMessage(strHeartbeat) || !bHeart)
+                    {
+                        bHeart = false;
+                        Connect();
+                    }
+                    else
+                        bHeart = true;
+
+                    // 涓洪伩鍏嶅績璺冲欢鏃跺鑷村叧闂蒋浠跺欢鏃堕噰鐢╢or寰幆,杩囩▼涓垽鏂槸鍚﹁繛鎺ュ凡鏂紑
+                    for (int i = 0; i < HeartbeatInterval; i++)
+                    {
+                        Thread.Sleep(1000);
+                        if (!bConnected)
+                            return;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    Msg = $"蹇冭烦涓㈠け+{ex.Message}";
+                    return;
+                }
+            }
+        }
+
+        public abstract bool Connect();
+
+        public abstract bool Disconnect();
+
+        public virtual string ReceiveMsg()
+        {
+            string msg = string.Empty;
+            for (int i = 0; i <= 3; i++)
+            {
+                if (string.IsNullOrEmpty(strReceiveMsg))
+                    Thread.Sleep(25);
+                else
+                {
+                    msg = strReceiveMsg;
+                    strReceiveMsg = string.Empty;
+                    return msg;
+                }
+            }
+            return msg;
+        }
+
+        public abstract bool SendMessage(string message);
+
+        // 娓呯┖缂撳啿鍖�
+        public void ClearMessage()
+        {
+            strReceiveMsg = string.Empty;
+        }
+
+        public virtual void Dispose()
+        {
+            Disconnect();
+        }
+
+        public static ushort[] CRC_TABLE = new ushort[]{
+             0x0000,0x1021,0x2042,0x3063,0x4084,0x50A5,0x60C6,0x70E7,
+             0x8108,0x9129,0xA14A,0xB16B,0xC18C,0xD1AD,0xE1CE,0xF1EF
+             };
+
+        public static ushort CRC16Calculate(byte[] data, int length)
+        {
+            ushort uwCRC = 0xFFFF;
+            byte ucTemp;
+            for (int index = 0; index < length; index++)
+            {
+                ucTemp = (byte)(uwCRC >> 0x0C); // 鎻愬彇CRC鐨勯珮4浣�
+                uwCRC <<= 4;                    // CRC宸︾Щ4浣�
+                uwCRC ^= CRC_TABLE[ucTemp ^ data[index] >> 0x04]; // 楂�4浣嶆暟鎹笌CRC琛ㄨ繘琛屽紓鎴�
+
+                ucTemp = (byte)(uwCRC >> 0x0C); // 鍐嶆鎻愬彇CRC鐨勯珮4浣�
+                uwCRC <<= 4;                    // CRC鍐嶆宸︾Щ4浣�
+                uwCRC ^= CRC_TABLE[ucTemp ^ data[index] & 0x0F]; // 浣�4浣嶆暟鎹笌CRC琛ㄨ繘琛屽紓鎴�
+            }
+            return uwCRC;
+        }
+
+        public static byte[] strToHexByte(string hexString)
+        {
+            try
+            {
+                hexString = hexString.Replace(" ", "");
+                if (hexString.Length % 2 != 0)
+                    hexString += " ";
+                byte[] returnBytes = new byte[hexString.Length / 2];
+                for (int i = 0; i < returnBytes.Length; i++)
+                    returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
+                return returnBytes;
+            }
+            catch { return new byte[] { }; }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Communicators/CommunicatorCollections.cs b/LB_VisionProcesses/Communicators/CommunicatorCollections.cs
new file mode 100644
index 0000000..8d557c4
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/CommunicatorCollections.cs
@@ -0,0 +1,224 @@
+锘縰sing Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Xml.Linq;
+
+namespace LB_VisionProcesses.Communicators
+{
+    [Serializable]
+    public class CommunicatorCollections<T> : ICollection<CommunicatorCollectionItem<T>>
+    {
+        private List<CommunicatorCollectionItem<T>> _items = new List<CommunicatorCollectionItem<T>>();
+
+        // 閫氳繃鍚嶇О鏌ユ壘
+        public CommunicatorCollectionItem<T> Get(string name)
+        {
+            var item = _items.FirstOrDefault(item => item.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
+            if (item == null)
+                return default;
+            return item;
+        }
+
+        // 閫氳繃绱㈠紩鏌ユ壘
+        public CommunicatorCollectionItem<T> Get(int index)
+        {
+            var item = _items.FirstOrDefault(item => item.Index == index);
+            if (item == null)
+                return default;
+            return item;
+        }
+
+        // ICollection<NamedItem<T>> 瀹炵幇
+        public int Count => _items.Count;
+
+        public bool IsReadOnly => false;
+
+        void ICollection<CommunicatorCollectionItem<T>>.Add(CommunicatorCollectionItem<T> item)
+        {
+            var existingItem = Get(item.Name);
+
+            if (existingItem != null)
+            {
+                // 濡傛灉宸插瓨鍦紝鏇存柊鐜版湁椤圭殑鍊�
+                existingItem = item;
+            }
+            else
+            {
+                // 濡傛灉涓嶅瓨鍦紝鍒涘缓鏂伴」骞跺垎閰嶇储寮�
+                _items.Add(item);
+            }
+
+            // 鏇存柊鍚庤嚜鍔ㄦ帓搴�
+            SortItems();
+        }
+        // 娣诲姞椤规椂涓烘柊椤瑰垎閰嶄竴涓储寮�
+        public void Add(string name, T value)
+        {
+            var existingItem = Get(name);
+
+            if (existingItem != null)
+            {
+                // 濡傛灉宸插瓨鍦紝鏇存柊鐜版湁椤圭殑鍊�
+                existingItem.Value = value;
+            }
+            else
+            {
+                // 濡傛灉涓嶅瓨鍦紝鍒涘缓鏂伴」骞跺垎閰嶇储寮�
+                var newItem = new CommunicatorCollectionItem<T>(name, _items.Count > 0 ? _items.Max(i => i.Index) + 1 : 0, value);
+                _items.Add(newItem);
+            }
+
+            // 鏇存柊鍚庤嚜鍔ㄦ帓搴�
+            SortItems();
+        }
+        // 鎸� Index 鎺掑簭闆嗗悎
+        private void SortItems()
+        {
+            _items = _items.OrderBy(item => item.Index).ToList();
+        }
+
+        // 閫氳繃绱㈠紩鍣ㄥ疄鐜板熀浜庡簭鍙风殑璁块棶
+        public T this[int index]
+        {
+            get
+            {
+                if (index < 0 || index >= _items.Count)
+                {
+                    return default;
+                }
+                return _items[index].Value;
+            }
+            set
+            {
+                if (index < 0 || index >= _items.Count)
+                {
+                    return;
+                }
+                _items[index].Value = value;
+            }
+        }
+
+        public T this[string name]
+        {
+            get
+            {
+                var existingItem = Get(name);
+                if (existingItem != null)
+                {
+                    // 濡傛灉宸插瓨鍦紝鏇存柊鐜版湁椤圭殑鍊�
+                    return existingItem.Value;
+                }
+                return default;
+            }
+            set
+            {
+                var item = _items.FirstOrDefault(i => i.Name == name);
+                if (item != null)
+                {
+                    item.Value = value;
+                }
+            }
+        }
+
+        public void Clear()
+        {
+            _items.Clear();
+        }
+
+        public bool Contains(CommunicatorCollectionItem<T> item)
+        {
+            return _items.Contains(item);
+        }
+
+        public bool Contains(string name)
+        {
+            var item = _items.FirstOrDefault(i => i.Name == name);
+            if (item != null)
+                return true;
+
+            return false;
+        }
+
+        public void CopyTo(CommunicatorCollectionItem<T>[] array, int arrayIndex)
+        {
+            _items.CopyTo(array, arrayIndex);
+        }
+
+        public bool Remove(CommunicatorCollectionItem<T> item)
+        {
+            var removed = _items.Remove(item);
+            if (removed)
+            {
+                // 绉婚櫎鍏冪礌鍚庯紝璋冩暣鍚庣画鍏冪礌鐨勭储寮�
+                UpdateIndexes();
+            }
+            return removed;
+        }
+
+        public IEnumerator<CommunicatorCollectionItem<T>> GetEnumerator()
+        {
+            return _items.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return _items.GetEnumerator();
+        }
+
+        // 閫氳繃鍚嶇О鍒犻櫎
+        public bool Remove(string name)
+        {
+            var namedItem = Get(name);
+            if (namedItem != null)
+            {
+                return Remove(namedItem);
+            }
+            return false;
+        }
+
+        // 閫氳繃绱㈠紩鍒犻櫎
+        public bool Remove(int index)
+        {
+            var namedItem = Get(index);
+            if (namedItem != null)
+            {
+                return Remove(namedItem);
+            }
+            return false;
+        }
+
+        // 鍒犻櫎椤瑰悗锛岃皟鏁村叾浠栭」鐨勭储寮�
+        private void UpdateIndexes()
+        {
+            for (int i = 0; i < _items.Count; i++)
+            {
+                _items[i].Index = i;
+            }
+        }
+    }
+
+    public class CommunicatorCollectionItem<T>
+    {
+        public string Name { get; set; }
+        public int Index { get; set; }
+        public T Value { get; set; }       // 瀛樺偍鐨勫璞�
+
+        public CommunicatorCollectionItem(string name, int index, T value)
+        {
+            Name = name;
+            Index = index;
+            Value = value;
+        }
+
+        public override string ToString()
+        {
+            return $"{Name} (Index: {Index}, Value: {Value})";
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Communicators/CommunicatorConfig.cs b/LB_VisionProcesses/Communicators/CommunicatorConfig.cs
new file mode 100644
index 0000000..bb0f4bd
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/CommunicatorConfig.cs
@@ -0,0 +1,243 @@
+锘縰sing Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+using System.Text;
+
+namespace LB_VisionProcesses.Communicators
+{
+    [Serializable]
+    [Process("閫氳娴嬭瘯", Category = "閫氳宸ュ叿", Description = "鍒涘缓閫氳娴嬭瘯宸ュ叿")]
+    public class CommunicatorConfig : IProcess
+    {
+        /// <summary>
+        /// 閫氳闆嗗悎(Key:閫氳鍚嶏紝Value:閫氳鍙ユ焺)
+        /// </summary>
+        public ConcurrentDictionary<string, BaseCommunicator> dicCommunicators { get; set; }
+
+        public CommunicatorConfig(ConcurrentDictionary<string, BaseCommunicator> dicCommunicators)
+        {
+            this.dicCommunicators = dicCommunicators;
+
+            strProcessName = "閫氳娴嬭瘯";
+            strProcessClass = "LB_VisionProcesses.Communicators.CommunicatorConfig";
+
+            Params.Inputs.Add("閫氳鍙e悕", "");
+            Params.Inputs.Add("閫氳绫诲瀷", CommunicatorType.Receiver);
+            Params.Inputs.Add("鏄惁鍚敤CRC鏍¢獙", false);
+            Params.Inputs.Add("閫氳娑堟伅", "");
+            Params.Outputs.Add("鏀跺埌娑堟伅", "");
+        }
+
+        /// <summary>
+        /// 鍔犺浇绠楁硶
+        /// </summary>
+        /// <param name="fullPath">瀹屾暣璺緞甯�.json</param>
+        /// <returns></returns>
+        public override bool Load(string fullPath = null)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                    return false;
+
+                if (!fullPath.Contains(".json"))
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+                if (string.IsNullOrEmpty(fullPath) || fullPath.Trim() == "")
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                string directoryPath = Path.GetDirectoryName(fullPath);
+                strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+
+                if (!File.Exists(fullPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    Save(directoryPath);
+                    return true;
+                }
+
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+                Params = JsonConvert.DeserializeObject<ProcessParams>(strJson);
+                if (Params == null)
+                    return false;
+
+                Params.FixDeserializedData();
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨绠楁硶
+        /// </summary>
+        /// <param name="filePath">涓嶅甫.json</param>
+        /// <returns></returns>
+        public override bool Save(string filePath = null)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(filePath) || filePath.Trim() == "")
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                string strJson = string.Empty;
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Newtonsoft.Json.Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+                strJson = JsonConvert.SerializeObject(Params, settings);
+
+                Params = JsonConvert.DeserializeObject<ProcessParams>(strJson);
+                if (Params == null)
+                    return false;
+
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                if (!Directory.Exists(filePath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(filePath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+                File.WriteAllText(filePath + "//" + strProcessName + ".json", strJson, Encoding.UTF8);
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public override bool Run()
+        {
+            try
+            {
+                InitRunParams();
+                Params.Outputs["鏀跺埌娑堟伅"] = "";
+                string CommunicatorName = Params.Inputs["閫氳鍙e悕"].ToString();
+
+                if (!dicCommunicators.ContainsKey(CommunicatorName))
+                {
+                    Msg = $"閫氳鍙{CommunicatorName}]涓嶅瓨鍦�";
+                    Result = false;
+                    return Result;
+                }
+
+                BaseCommunicator BaseCommunicator = dicCommunicators[CommunicatorName];
+
+                if (BaseCommunicator == null)
+                {
+                    Msg = $"閫氳鍙{CommunicatorName}]鏈疄渚嬪寲";
+                    Result = false;
+                    return Result;
+                }
+
+                if (!BaseCommunicator.bConnected)
+                {
+                    Msg = $"閫氳鍙{CommunicatorName}]鏈繛鎺�";
+                    Result = false;
+                    return Result;
+                }
+
+                if (!Enum.TryParse(Params.Inputs["閫氳绫诲瀷"].ToString(), out CommunicatorType CommunicatorType))
+                {
+                    Msg = $"閫氳鍙{CommunicatorName}]閫氳绫诲瀷涓嶆纭�,鍊间负:{Params.Inputs["閫氳绫诲瀷"].ToString()}";
+                    Result = false;
+                    return Result;
+                }
+
+
+                if (Params.Inputs["閫氳娑堟伅"] is List<string>)
+                {
+                    List<string> listMsg = (List<string>)Params.Inputs["閫氳娑堟伅"];
+                    if (listMsg.Count > 0)
+                        Params.Inputs["閫氳娑堟伅"] = string.Join(',', listMsg);
+                }
+
+                string SendMsg = Params.Inputs["閫氳娑堟伅"].ToString();
+                string ShouldReceiveMsg = Params.Inputs["閫氳娑堟伅"].ToString();
+                bool CheckRule = Convert.ToBoolean(Params.Inputs["鏄惁鍚敤CRC鏍¢獙"]);
+
+                switch (CommunicatorType)
+                {
+                    case CommunicatorType.Sender:
+                        if (CheckRule)
+                        {
+                            byte[] HexByte = BaseCommunicator.strToHexByte(SendMsg);
+                            ushort crcHexByte = BaseCommunicator.CRC16Calculate(HexByte, HexByte.Length);
+
+                            string crcString = crcHexByte.ToString("X4");
+                            //HexByte = strToHexByte(strSendMsg + crcString);
+                            SendMsg = SendMsg + crcString;
+                        }
+                        Result = BaseCommunicator.SendMessage(SendMsg);
+                        break;
+                    case CommunicatorType.Receiver:
+                        string receiveMsg = BaseCommunicator.ReceiveMsg();
+                        Params.Outputs["鏀跺埌娑堟伅"] = receiveMsg;
+
+                        //涓嶈缃秷鎭椂榛樿PASS
+                        if (ShouldReceiveMsg == "")
+                        {
+                            Result = true;
+                            return Result;
+                        }
+
+                        if (!receiveMsg.Contains(ShouldReceiveMsg))
+                        {
+                            Msg = $"閫氳鍙{CommunicatorName}]鏀跺埌娑堟伅涓嶅叏,搴斿寘鍚珄ShouldReceiveMsg}";
+                            Result = false;
+                        }
+                        break;
+                    default:
+                        Msg = $"閫氳绫诲瀷鍙敮鎸佸彂閫佹秷鎭拰鎺ユ敹娑堟伅锛�";
+                        Result = false;
+                        break;
+                }
+            }
+            catch (Exception ex)
+            {
+                Msg = $"閫氳寮傚父,鍘熷洜鏄�:{ex.Message}";
+                Result = false;
+            }
+            return Result;
+        }
+
+        public override void InitRunParams()
+        {
+            Result = true;
+            Msg = "";
+
+            if (Record != null)
+                Record.Dispose();
+        }
+
+        public override void Dispose()
+        {
+            return;
+        }
+
+        public override object Clone()
+        {
+            return MemberwiseClone();
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Communicators/CommunicatorForm.Designer.cs b/LB_VisionProcesses/Communicators/CommunicatorForm.Designer.cs
new file mode 100644
index 0000000..07dedd3
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/CommunicatorForm.Designer.cs
@@ -0,0 +1,392 @@
+锘縩amespace LB_VisionProcesses.Communicators
+{
+    partial class CommunicatorForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CommunicatorForm));
+            grpSetting = new GroupBox();
+            txtIP = new TextBox();
+            txtPort = new TextBox();
+            lblPort = new Label();
+            btnDisconnect = new Button();
+            btnConnect = new Button();
+            cmbIP = new ComboBox();
+            lblIP = new Label();
+            grpReceive = new GroupBox();
+            txtReceiveMsg = new TextBox();
+            txtSendMsg = new TextBox();
+            btnSend = new Button();
+            grpTest = new GroupBox();
+            lblCom = new Label();
+            ckbRuleCheck = new CheckBox();
+            cmbCom = new ComboBox();
+            cmbType = new ComboBox();
+            lblType = new Label();
+            btnRun = new Button();
+            lblMsg = new Label();
+            txtMsg = new TextBox();
+            btnRuleSend = new Button();
+            label6 = new Label();
+            themeForm1 = new ReaLTaiizor.Forms.ThemeForm();
+            controlBox1 = new ReaLTaiizor.Controls.ControlBox();
+            grpSetting.SuspendLayout();
+            grpReceive.SuspendLayout();
+            grpTest.SuspendLayout();
+            themeForm1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // grpSetting
+            // 
+            grpSetting.Controls.Add(txtIP);
+            grpSetting.Controls.Add(txtPort);
+            grpSetting.Controls.Add(lblPort);
+            grpSetting.Controls.Add(btnDisconnect);
+            grpSetting.Controls.Add(btnConnect);
+            grpSetting.Controls.Add(cmbIP);
+            grpSetting.Controls.Add(lblIP);
+            grpSetting.ForeColor = SystemColors.Control;
+            grpSetting.Location = new Point(18, 74);
+            grpSetting.Name = "grpSetting";
+            grpSetting.Size = new Size(200, 146);
+            grpSetting.TabIndex = 0;
+            grpSetting.TabStop = false;
+            grpSetting.Text = "閫氳閰嶇疆";
+            // 
+            // txtIP
+            // 
+            txtIP.Location = new Point(83, 32);
+            txtIP.Name = "txtIP";
+            txtIP.Size = new Size(100, 23);
+            txtIP.TabIndex = 7;
+            // 
+            // txtPort
+            // 
+            txtPort.Location = new Point(83, 70);
+            txtPort.Name = "txtPort";
+            txtPort.Size = new Size(100, 23);
+            txtPort.TabIndex = 6;
+            // 
+            // lblPort
+            // 
+            lblPort.AutoSize = true;
+            lblPort.Location = new Point(17, 73);
+            lblPort.Name = "lblPort";
+            lblPort.Size = new Size(32, 17);
+            lblPort.TabIndex = 4;
+            lblPort.Text = "绔彛";
+            // 
+            // btnDisconnect
+            // 
+            btnDisconnect.ForeColor = SystemColors.WindowText;
+            btnDisconnect.Location = new Point(118, 109);
+            btnDisconnect.Name = "btnDisconnect";
+            btnDisconnect.Size = new Size(75, 23);
+            btnDisconnect.TabIndex = 3;
+            btnDisconnect.Text = "鏂紑";
+            btnDisconnect.UseVisualStyleBackColor = true;
+            btnDisconnect.Click += btnDisconnect_Click;
+            // 
+            // btnConnect
+            // 
+            btnConnect.ForeColor = SystemColors.WindowText;
+            btnConnect.Location = new Point(14, 109);
+            btnConnect.Name = "btnConnect";
+            btnConnect.Size = new Size(75, 23);
+            btnConnect.TabIndex = 2;
+            btnConnect.Text = "杩炴帴";
+            btnConnect.UseVisualStyleBackColor = true;
+            btnConnect.Click += btnConnect_Click;
+            // 
+            // cmbIP
+            // 
+            cmbIP.FormattingEnabled = true;
+            cmbIP.Location = new Point(83, 31);
+            cmbIP.Name = "cmbIP";
+            cmbIP.Size = new Size(100, 25);
+            cmbIP.TabIndex = 1;
+            cmbIP.Click += cmbIP_Click;
+            cmbIP.MouseClick += cmbIP_MouseClick;
+            // 
+            // lblIP
+            // 
+            lblIP.AutoSize = true;
+            lblIP.Location = new Point(17, 36);
+            lblIP.Name = "lblIP";
+            lblIP.Size = new Size(32, 17);
+            lblIP.TabIndex = 0;
+            lblIP.Text = "鍦板潃";
+            // 
+            // grpReceive
+            // 
+            grpReceive.Controls.Add(txtReceiveMsg);
+            grpReceive.ForeColor = SystemColors.Control;
+            grpReceive.Location = new Point(18, 311);
+            grpReceive.Name = "grpReceive";
+            grpReceive.Size = new Size(543, 174);
+            grpReceive.TabIndex = 5;
+            grpReceive.TabStop = false;
+            grpReceive.Text = "閫氳璁板綍";
+            // 
+            // txtReceiveMsg
+            // 
+            txtReceiveMsg.Dock = DockStyle.Fill;
+            txtReceiveMsg.Location = new Point(3, 19);
+            txtReceiveMsg.Multiline = true;
+            txtReceiveMsg.Name = "txtReceiveMsg";
+            txtReceiveMsg.ReadOnly = true;
+            txtReceiveMsg.ScrollBars = ScrollBars.Both;
+            txtReceiveMsg.Size = new Size(537, 152);
+            txtReceiveMsg.TabIndex = 0;
+            // 
+            // txtSendMsg
+            // 
+            txtSendMsg.ForeColor = SystemColors.WindowText;
+            txtSendMsg.Location = new Point(18, 249);
+            txtSendMsg.Name = "txtSendMsg";
+            txtSendMsg.Size = new Size(543, 23);
+            txtSendMsg.TabIndex = 10;
+            // 
+            // btnSend
+            // 
+            btnSend.ForeColor = SystemColors.WindowText;
+            btnSend.Location = new Point(18, 282);
+            btnSend.Name = "btnSend";
+            btnSend.Size = new Size(75, 23);
+            btnSend.TabIndex = 11;
+            btnSend.Text = "鍙戦��";
+            btnSend.UseVisualStyleBackColor = true;
+            btnSend.Click += btnSend_Click;
+            // 
+            // grpTest
+            // 
+            grpTest.Controls.Add(lblCom);
+            grpTest.Controls.Add(ckbRuleCheck);
+            grpTest.Controls.Add(cmbCom);
+            grpTest.Controls.Add(cmbType);
+            grpTest.Controls.Add(lblType);
+            grpTest.Controls.Add(btnRun);
+            grpTest.Controls.Add(lblMsg);
+            grpTest.Controls.Add(txtMsg);
+            grpTest.ForeColor = SystemColors.Control;
+            grpTest.Location = new Point(241, 74);
+            grpTest.Name = "grpTest";
+            grpTest.Size = new Size(320, 146);
+            grpTest.TabIndex = 12;
+            grpTest.TabStop = false;
+            grpTest.Text = "閫氳娴嬭瘯";
+            // 
+            // lblCom
+            // 
+            lblCom.AutoSize = true;
+            lblCom.Location = new Point(165, 40);
+            lblCom.Name = "lblCom";
+            lblCom.Size = new Size(32, 17);
+            lblCom.TabIndex = 9;
+            lblCom.Text = "閫氳";
+            // 
+            // ckbRuleCheck
+            // 
+            ckbRuleCheck.AutoSize = true;
+            ckbRuleCheck.Location = new Point(55, 173);
+            ckbRuleCheck.Name = "ckbRuleCheck";
+            ckbRuleCheck.Size = new Size(99, 21);
+            ckbRuleCheck.TabIndex = 6;
+            ckbRuleCheck.Text = "鏄惁瑙勫垯鏍¢獙";
+            ckbRuleCheck.UseVisualStyleBackColor = true;
+            // 
+            // cmbCom
+            // 
+            cmbCom.FormattingEnabled = true;
+            cmbCom.Location = new Point(204, 35);
+            cmbCom.Name = "cmbCom";
+            cmbCom.Size = new Size(100, 25);
+            cmbCom.TabIndex = 8;
+            cmbCom.SelectedIndexChanged += cmbCom_SelectedIndexChanged;
+            // 
+            // cmbType
+            // 
+            cmbType.FormattingEnabled = true;
+            cmbType.Location = new Point(59, 36);
+            cmbType.Name = "cmbType";
+            cmbType.Size = new Size(94, 25);
+            cmbType.TabIndex = 5;
+            // 
+            // lblType
+            // 
+            lblType.AutoSize = true;
+            lblType.Location = new Point(21, 39);
+            lblType.Name = "lblType";
+            lblType.Size = new Size(32, 17);
+            lblType.TabIndex = 4;
+            lblType.Text = "绫诲瀷";
+            // 
+            // btnRun
+            // 
+            btnRun.ForeColor = SystemColors.WindowText;
+            btnRun.Location = new Point(215, 109);
+            btnRun.Name = "btnRun";
+            btnRun.Size = new Size(75, 23);
+            btnRun.TabIndex = 3;
+            btnRun.Text = "杩愯娴嬭瘯";
+            btnRun.UseVisualStyleBackColor = true;
+            btnRun.Click += btnRun_Click;
+            // 
+            // lblMsg
+            // 
+            lblMsg.AutoSize = true;
+            lblMsg.Location = new Point(20, 78);
+            lblMsg.Name = "lblMsg";
+            lblMsg.Size = new Size(32, 17);
+            lblMsg.TabIndex = 1;
+            lblMsg.Text = "娑堟伅";
+            // 
+            // txtMsg
+            // 
+            txtMsg.Location = new Point(59, 76);
+            txtMsg.Name = "txtMsg";
+            txtMsg.Size = new Size(245, 23);
+            txtMsg.TabIndex = 0;
+            // 
+            // btnRuleSend
+            // 
+            btnRuleSend.ForeColor = SystemColors.WindowText;
+            btnRuleSend.Location = new Point(118, 282);
+            btnRuleSend.Name = "btnRuleSend";
+            btnRuleSend.Size = new Size(75, 23);
+            btnRuleSend.TabIndex = 13;
+            btnRuleSend.Text = "鏍¢獙鍙戦��";
+            btnRuleSend.UseVisualStyleBackColor = true;
+            btnRuleSend.Click += btnRuleSend_Click;
+            // 
+            // label6
+            // 
+            label6.AutoSize = true;
+            label6.ForeColor = SystemColors.Control;
+            label6.Location = new Point(18, 223);
+            label6.Name = "label6";
+            label6.Size = new Size(56, 17);
+            label6.TabIndex = 9;
+            label6.Text = "鍙戦�佷俊鎭�";
+            // 
+            // themeForm1
+            // 
+            themeForm1.BackColor = Color.FromArgb(32, 41, 50);
+            themeForm1.Controls.Add(controlBox1);
+            themeForm1.Dock = DockStyle.Fill;
+            themeForm1.Font = new Font("Microsoft Sans Serif", 9F);
+            themeForm1.Image = (Image)resources.GetObject("themeForm1.Image");
+            themeForm1.Location = new Point(0, 0);
+            themeForm1.Name = "themeForm1";
+            themeForm1.Padding = new Padding(10, 70, 10, 9);
+            themeForm1.RoundCorners = true;
+            themeForm1.Sizable = true;
+            themeForm1.Size = new Size(581, 496);
+            themeForm1.SmartBounds = true;
+            themeForm1.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            themeForm1.TabIndex = 14;
+            themeForm1.Text = "閫氳娴嬭瘯";
+            // 
+            // controlBox1
+            // 
+            controlBox1.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            controlBox1.BackColor = Color.FromArgb(32, 34, 37);
+            controlBox1.CloseHoverColor = Color.FromArgb(230, 17, 35);
+            controlBox1.DefaultLocation = true;
+            controlBox1.EnableHoverHighlight = true;
+            controlBox1.EnableMaximizeButton = false;
+            controlBox1.EnableMinimizeButton = false;
+            controlBox1.ForeColor = Color.FromArgb(155, 155, 155);
+            controlBox1.Location = new Point(479, 12);
+            controlBox1.MaximizeHoverColor = Color.FromArgb(74, 74, 74);
+            controlBox1.MinimizeHoverColor = Color.FromArgb(63, 63, 65);
+            controlBox1.Name = "controlBox1";
+            controlBox1.Size = new Size(90, 25);
+            controlBox1.TabIndex = 0;
+            controlBox1.Text = "controlBox1";
+            // 
+            // CommunicatorForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(581, 496);
+            Controls.Add(btnRuleSend);
+            Controls.Add(grpTest);
+            Controls.Add(btnSend);
+            Controls.Add(txtSendMsg);
+            Controls.Add(label6);
+            Controls.Add(grpReceive);
+            Controls.Add(grpSetting);
+            Controls.Add(themeForm1);
+            FormBorderStyle = FormBorderStyle.None;
+            MinimumSize = new Size(261, 61);
+            Name = "CommunicatorForm";
+            Text = "閫氳娴嬭瘯";
+            TransparencyKey = Color.Fuchsia;
+            FormClosing += CommunicatorForm_FormClosing;
+            FormClosed += CommunicatorForm_FormClosed;
+            Load += CommunicatorForm_Load;
+            grpSetting.ResumeLayout(false);
+            grpSetting.PerformLayout();
+            grpReceive.ResumeLayout(false);
+            grpReceive.PerformLayout();
+            grpTest.ResumeLayout(false);
+            grpTest.PerformLayout();
+            themeForm1.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private GroupBox grpSetting;
+        private GroupBox grpReceive;
+        private Button btnDisconnect;
+        private Button btnConnect;
+        private ComboBox cmbIP;
+        private Label lblIP;
+        private TextBox txtReceiveMsg;
+        private TextBox txtSendMsg;
+        private Button btnSend;
+        private TextBox txtPort;
+        private Label lblPort;
+        private TextBox txtIP;
+        private GroupBox grpTest;
+        private Button btnRun;
+        private Label lblMsg;
+        private TextBox txtMsg;
+        private Label lblType;
+        private ComboBox cmbType;
+        private CheckBox ckbRuleCheck;
+        private Button btnRuleSend;
+        private Label lblCom;
+        private ComboBox cmbCom;
+        private Label label6;
+        private ReaLTaiizor.Forms.ThemeForm themeForm1;
+        private ReaLTaiizor.Controls.ControlBox controlBox1;
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionProcesses/Communicators/CommunicatorForm.cs b/LB_VisionProcesses/Communicators/CommunicatorForm.cs
new file mode 100644
index 0000000..ca5526d
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/CommunicatorForm.cs
@@ -0,0 +1,353 @@
+锘縰sing System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO.Ports;
+using System.Linq;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using LB_VisionProcesses.Communicators.TCom;
+using RJCP.IO.Ports;
+
+namespace LB_VisionProcesses.Communicators
+{
+    public partial class CommunicatorForm : Form
+    {
+        BaseCommunicator communicator = new UARTPort();
+        CommunicatorConfig comConfig { get; set; }
+
+        ConcurrentDictionary<string, BaseCommunicator> dicCommunicators { get; set; }
+
+        string fullPath = string.Empty;
+
+        public CommunicatorForm()
+        {
+            InitializeComponent();
+            //娌℃湁浼犲叆閫氳鍙ユ焺鎯呭喌涓嬪彲鑷敱杩炴帴
+            btnConnect.Enabled = true;
+            btnDisconnect.Enabled = false;
+            btnSend.Enabled = false;
+            btnRuleSend.Enabled = false;
+
+            //娴嬭瘯鍔熻兘绂佺敤
+            grpTest.Enabled = false;
+        }
+
+        public CommunicatorForm(ConcurrentDictionary<string, BaseCommunicator> dicCommunicators, CommunicatorConfig comConfig, string fullPath)
+        {
+            InitializeComponent();
+            //浼犲叆閫氳鍙ユ焺鍚庣鐢ㄨ繛鎺�/鏂紑鎸夐敭鍜岃緭鍏ユ帶浠�
+            grpSetting.Enabled = false;
+
+            this.dicCommunicators = dicCommunicators;
+            this.comConfig = comConfig;
+            this.fullPath = fullPath;
+            this.Text = comConfig.strProcessName;
+
+            foreach (var name in dicCommunicators.Keys)
+                cmbCom.Items.Add(name);
+        }
+
+        private void CommunicatorForm_Load(object sender, EventArgs e)
+        {
+            // 浣跨敤 Enum.GetValues 鑾峰彇 enum 绫诲瀷鐨勬墍鏈夊��
+            foreach (CommunicatorType type in Enum.GetValues(typeof(CommunicatorType)))
+            {
+                cmbType.Items.Add(type.ToString());
+            }
+
+            //閫夋嫨Com浼氳Е鍙慥alueChanged浜嬩欢锛屾病鏈夎緭鍏ラ�氳鍙g殑鎯呭喌涓嬮�夋嫨鍒�-1
+            if (comConfig != null)
+            {
+                string CommunicatorName = comConfig.Params.Inputs["閫氳鍙e悕"].ToString();
+                // 灏濊瘯杞崲瀛楃涓蹭负鏋氫妇
+                if (!Enum.TryParse(comConfig.Params.Inputs["閫氳绫诲瀷"].ToString(), out CommunicatorType type))
+                    type = CommunicatorType.Receiver;
+
+                bool bRuleCheck = Convert.ToBoolean(comConfig.Params.Inputs["鏄惁鍚敤CRC鏍¢獙"].ToString());
+                string Msg = comConfig.Params.Inputs["閫氳娑堟伅"].ToString();
+
+                int Index = cmbCom.FindString(CommunicatorName);
+                if (Index == -1 && cmbCom.Items.Count > 0)
+                {
+                    //濡傛灉娌℃湁鎵惧埌瀵瑰簲鐨勯�氳鍙e悕锛屽垯閫夋嫨绗竴涓彲鐢ㄧ殑閫氳鍙�
+                    CommunicatorName = cmbCom.Items[0].ToString();
+                    Index = 0;
+                }
+                cmbCom.Text = CommunicatorName;
+                cmbCom.SelectedIndex = Index;
+                cmbType.Text = type.ToString();
+                ckbRuleCheck.Checked = bRuleCheck;
+                txtMsg.Text = Msg;
+            }
+        }
+
+        private void cmbCom_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            //澶嶅師鍘熼�氳鍙h缃�
+            if (comConfig != null)
+            {
+                communicator.MessageReceived -= ShowReceiveMsg;
+            }
+
+            string name = cmbCom.Text;
+            if (dicCommunicators == null || !dicCommunicators.ContainsKey(name))
+            {
+                MessageBox.Show("璇ラ�氳鍙d笉瀛樺湪!");
+                return;
+            }
+
+            //鏇存崲閫氳鍙�
+
+            communicator = dicCommunicators[name];
+            communicator.MessageReceived += ShowReceiveMsg;
+
+            if (communicator is UARTPort)
+            {
+                btnSend.Enabled = communicator.bConnected;
+                btnRuleSend.Enabled = communicator.bConnected;
+
+                cmbIP.Visible = true;
+                txtIP.Visible = false;
+
+                lblIP.Text = "涓插彛鍙�";
+                lblIP.Text = "娉㈢壒鐜�";
+
+                cmbIP.Text = communicator.CommunicatorConnections["鍦板潃"].ToString();
+                txtPort.Text = communicator.CommunicatorConnections["绔彛"].ToString();
+            }
+            else if (communicator is LocalMonitor)
+            {
+                btnSend.Enabled = communicator.bConnected;
+                btnRuleSend.Enabled = communicator.bConnected;
+
+                cmbIP.Visible = false;
+                txtIP.Visible = true;
+
+                lblIP.Text = "鐩戞帶鏂囦欢";
+                lblIP.Text = "鍐欏叆鏂囦欢";
+
+                txtIP.Text = communicator.CommunicatorConnections["鍦板潃"].ToString();
+                txtPort.Text = communicator.CommunicatorConnections["绔彛"].ToString();
+            }
+            else
+            {
+                btnSend.Enabled = communicator.bConnected;
+                btnRuleSend.Enabled = false;
+
+                cmbIP.Visible = false;
+                txtIP.Visible = true;
+
+                lblIP.Text = " IP";
+                lblIP.Text = "绔彛";
+
+                txtIP.Text = communicator.CommunicatorConnections["鍦板潃"].ToString();
+                txtPort.Text = communicator.CommunicatorConnections["绔彛"].ToString();
+            }
+        }
+
+        private void cmbIP_Click(object sender, EventArgs e)
+        {
+            //缁熻鍙敤绔彛
+            SerialPortStream temp = new SerialPortStream();
+            string[] ArryPort = temp.GetPortNames();
+            for (int i = 0; i < ArryPort.Length; i++)
+                cmbIP.Items.Add(ArryPort[i]);
+        }
+
+        private void btnConnect_Click(object sender, EventArgs e)
+        {
+            if (communicator == null)
+                return;
+
+            if (communicator is UARTPort)
+            {
+                communicator.CommunicatorConnections.Add("鍦板潃", cmbIP.SelectedItem.ToString());
+                communicator.CommunicatorConnections.Add("绔彛", txtPort.Text);
+            }
+            else
+            {
+                communicator.CommunicatorConnections.Add("鍦板潃", txtIP.Text);
+                communicator.CommunicatorConnections.Add("绔彛", txtPort.Text);
+            }
+
+            bool connectSuccess = communicator.Connect();
+            if (connectSuccess)
+            {
+                communicator.MessageReceived -= ShowReceiveMsg;
+                communicator.MessageReceived += ShowReceiveMsg;
+            }
+            MessageBox.Show(connectSuccess ? "杩炴帴鎴愬姛" : "杩炴帴澶辫触,鍘熷洜鏄�" + communicator.Msg);
+        }
+
+        private void ShowReceiveMsg(string strReceiveMsg)
+        {
+            // 濡傛灉褰撳墠涓嶆槸 UI 绾跨▼锛屽垯閫氳繃 Invoke 灏嗘搷浣滆皟搴﹀埌 UI 绾跨▼
+            if (this.InvokeRequired)
+            {
+                this.Invoke(new Action<string>((msg) =>
+                {
+                    // 鏇存柊 UI 鎺т欢锛屾瘮濡傛樉绀烘帴鏀跺埌鐨勬秷鎭�
+                    this.txtReceiveMsg.Text += ("[鎺ユ敹]" + DateTime.Now.ToString() + "锛�" + msg + "\r\n");
+                }), strReceiveMsg);
+            }
+            else
+            {
+                // 濡傛灉宸茬粡鍦� UI 绾跨▼涓婏紝鐩存帴鏇存柊 UI
+                this.txtReceiveMsg.Text += ("[鎺ユ敹]" + DateTime.Now.ToString() + "锛�" + strReceiveMsg + "\r\n");
+            }
+        }
+
+        private void ShowSendMsg(string strSendMsg)
+        {
+            // 濡傛灉褰撳墠涓嶆槸 UI 绾跨▼锛屽垯閫氳繃 Invoke 灏嗘搷浣滆皟搴﹀埌 UI 绾跨▼
+            if (this.InvokeRequired)
+            {
+                this.Invoke(new Action<string>((msg) =>
+                {
+                    // 鏇存柊 UI 鎺т欢锛屾瘮濡傛樉绀烘帴鏀跺埌鐨勬秷鎭�
+                    this.txtReceiveMsg.Text += ("[鍙戦�乚" + DateTime.Now.ToString() + "锛�" + msg + "\r\n");
+                }), strSendMsg);
+            }
+            else
+            {
+                // 濡傛灉宸茬粡鍦� UI 绾跨▼涓婏紝鐩存帴鏇存柊 UI
+                this.txtReceiveMsg.Text += ("[鍙戦�乚" + DateTime.Now.ToString() + "锛�" + strSendMsg + "\r\n");
+            }
+        }
+
+        private void btnDisconnect_Click(object sender, EventArgs e)
+        {
+            if (communicator == null)
+                return;
+
+            bool result = communicator.Disconnect();
+
+            if (result)
+                communicator.MessageReceived -= ShowReceiveMsg;
+
+            MessageBox.Show(result ? "鏂紑鎴愬姛" : "鏂紑澶辫触,鍘熷洜鏄�:" + communicator.Msg);
+        }
+
+        private void btnSend_Click(object sender, EventArgs e)
+        {
+            if (communicator == null)
+                return;
+
+            communicator.SendMessage(txtSendMsg.Text);
+
+            ShowSendMsg(txtSendMsg.Text);
+        }
+
+        private void btnRuleSend_Click(object sender, EventArgs e)
+        {
+            if (communicator == null)
+                return;
+
+            string SendMsg = txtSendMsg.Text;
+
+            byte[] HexByte = BaseCommunicator.strToHexByte(SendMsg);
+            ushort crcHexByte = BaseCommunicator.CRC16Calculate(HexByte, HexByte.Length);
+
+            string crcString = crcHexByte.ToString("X4");
+            //HexByte = strToHexByte(strSendMsg + crcString);
+            SendMsg = SendMsg + crcString;
+
+            communicator.SendMessage(SendMsg);
+        }
+
+        private void btnRun_Click(object sender, EventArgs e)
+        {
+            if (communicator == null)
+                return;
+
+            // 灏濊瘯杞崲瀛楃涓蹭负鏋氫妇
+            if (!Enum.TryParse(cmbType.Text, out CommunicatorType type))
+                return;
+
+            CommunicatorConfig OriComConfig = new CommunicatorConfig(dicCommunicators);
+
+            OriComConfig.Params.Inputs.Add("閫氳鍙e悕", cmbCom.Text);
+            OriComConfig.Params.Inputs.Add("閫氳绫诲瀷", type);
+            OriComConfig.Params.Inputs.Add("鏄惁鍚敤CRC鏍¢獙", ckbRuleCheck.Checked);
+            OriComConfig.Params.Inputs.Add("閫氳娑堟伅", txtMsg.Text);
+
+            if (OriComConfig.Run())
+            {
+                btnRun.BackColor = Color.Green;
+                if (type == CommunicatorType.Receiver)
+                    ShowReceiveMsg(OriComConfig.Params.Outputs["鏀跺埌娑堟伅"].ToString());
+                else
+                    ShowSendMsg(txtMsg.Text);
+            }
+            else
+                btnRun.BackColor = Color.Red;
+
+        }
+
+        private void cmbIP_MouseClick(object sender, MouseEventArgs e)
+        {
+            cmbIP.Items.Clear();
+            //缁熻鍙敤绔彛
+            SerialPortStream temp = new SerialPortStream();
+            string[] ArryPort = temp.GetPortNames();
+            for (int i = 0; i < ArryPort.Length; i++)
+                cmbIP.Items.Add(ArryPort[i]);
+        }
+
+        private void CommunicatorForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            //璺緞涓虹┖璇存槑鏃犻渶淇濆瓨
+            if (string.IsNullOrEmpty(fullPath))
+            {
+                e.Cancel = false;  //纭鍏抽棴绐椾綋
+                return;
+            }
+
+            DialogResult res = MessageBox.Show("鏄惁淇濆瓨锛�", "鎻愮ず", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);  //淇濆瓨缁撴灉淇℃伅
+            /// 鍙傛暟1锛氭樉绀烘枃鏈紝鍙傛暟2锛氭爣棰橈紝鍙傛暟3锛氭寜閿被鍨嬶紝鍙傛暟4锛氭樉绀哄浘鏍�
+            if (res != DialogResult.Yes && res != DialogResult.No)  //鍙栨秷
+            {
+                e.Cancel = true;  //鍙栨秷鍏抽棴绐椾綋
+                return;
+            }
+
+            if (res == DialogResult.Yes)  //淇濆瓨VPP
+            {
+                // 灏濊瘯杞崲瀛楃涓蹭负鏋氫妇
+                if (!Enum.TryParse(cmbType.Text, out CommunicatorType type))
+                {
+                    Debug.WriteLine("淇濆瓨澶辫触");
+                    e.Cancel = false;  //纭鍏抽棴绐椾綋
+                    return;
+                }
+
+                comConfig.Params.Inputs.Add("閫氳鍙e悕", cmbCom.Text);
+                comConfig.Params.Inputs.Add("閫氳绫诲瀷", type);
+                comConfig.Params.Inputs.Add("鏄惁鍚敤CRC鏍¢獙", ckbRuleCheck.Checked);
+                comConfig.Params.Inputs.Add("閫氳娑堟伅", txtMsg.Text);
+
+                string directoryPath = Path.GetDirectoryName(fullPath);
+                comConfig.Save(directoryPath);
+
+                e.Cancel = false;  //纭鍏抽棴绐椾綋
+                return;
+            }
+        }
+
+        private void CommunicatorForm_FormClosed(object sender, FormClosedEventArgs e)
+        {
+            if (communicator != null)
+                communicator.MessageReceived -= ShowReceiveMsg;
+
+            //璺緞涓虹┖璇存槑涓烘祴璇曟ā寮忥紝闇�瑕侀噴鏀鹃�氳鍙�
+            if (string.IsNullOrEmpty(fullPath) && communicator != null)
+                communicator.Dispose();
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Communicators/CommunicatorForm.resx b/LB_VisionProcesses/Communicators/CommunicatorForm.resx
new file mode 100644
index 0000000..3384e6d
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/CommunicatorForm.resx
@@ -0,0 +1,144 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="themeForm1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAPiSURBVFhH7VZLiBxlEG7d+IjBKKtktqt6d8kybLqqZyfi
+        +lgUXcGooKIXxYBKLgZFQVDwgQhBvAVzUOPBi3iJgnoSCcTLKobEma7qHeOiuB7UiBo1PuIjq9HNSPX0
+        rDN/zyzbQjztB9+pv3r8/19dVZ63ilUUwBzzmbppGOpRcKlEcLNwcGfMsE0J7ogj//okws2NamlD83Zv
+        wLX9z2h63ulz7I8kDNsSxleF8CMl+EEY/lDCv5TxbyU8oQTHlfCIEL5kSbh+CqPpeafVIxgWwieUcU4I
+        /lTGZl8SnEgI3pBxPzTbOQ4Gkyi4pxEGFTuE639ZpFfNcIsS1LJT5gN28xdl3Cnj/oVmP7t59Hwl3K0M
+        C8owL4zbG9XSOjdOT5hQCB5Rxu97BMqT4BsJ4X6Z9M8x+483XXCuEO5KnyjTCOGvSvjMAQ4G3XhdODAV
+        rBWGHUL4Wy5Qb34Sk3/rzLS3xuwtCSV8ShmOu1p7wpjwBRkbO8+Nm6LpeQMxwX3Suk43ULczxpPKKLOR
+        f+WO7H1bz4YPpaftYdMiLMQET5rWje/FhJfHhF/kjXJcVIZ3tIJVKzazfc3zBpTwLmU82kPfRWH8Lg79
+        67qC76uW1mkEr2Qnyxl1GC8K49uNEMbbtpZEjeBaXVnymR/Y2/UUNQqutn/bFTpcVMZ9ykF5ydDzvEMV
+        P4wZtYe+L+2Z4hBvSh3YP6rs71zu9PZNGN7tPLnBqloIXl/Oth+F4MW0eO0qlPA9V9BFwtlZhos6g89M
+        T69JGB/Xjt+tIDXtG41qaaMwftZDkBG+TAi2tAuuDaHhq4Thq7x+pYSvNRoiL54IJqwy84L05L8LwwPu
+        cLFOJ4Rv5vQFKAQ/xRxc1jeB9F0J9rxfHlzfGdxQD2GrJefaFGI7gfrEyJgwfp4X4GEN/Uk3+H5rtQx7
+        c/qCFIIjNSpFrcHBcLDro1U94a52i+1EHPoXC+VvrCiF4cNDlY2ltIsJwXOO4KiEOOUGN9jykc7/Hk4L
+        kWDPUkuWKLhBGY79+xH32824wQ3WcsWWENdhAdqktG1qyakVWszw1pKI8GW7ma7IGbQydImNYNdpIRLU
+        4nDE73JcJ9gihN9mCexuTzkX2dR7TAh+zDleAa0N1wnvdvuKJ5OTZ9j6JQwL1l57jswMM6OjZ8eEN0q6
+        I8KnynjMVjKbF1lbPtlq3ykXW1tVuh39LITP992O5suD65XhWSH4QGlo1P3uYr5cPst0thckjLcp473K
+        8LBYiyb/0YTwQdsLNYStlnASwRX9amsJaZcL8WkJcXu/OjjlODwVrI0jvOZgZUPJ/fa/wYrEnQGrOBX4
+        B6XRFGacFF+7AAAAAElFTkSuQmCC
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Communicators/ICommunicator.cs b/LB_VisionProcesses/Communicators/ICommunicator.cs
new file mode 100644
index 0000000..f43f316
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/ICommunicator.cs
@@ -0,0 +1,69 @@
+锘縩amespace LB_VisionProcesses.Communicators
+{
+    public interface ICommunicator : IDisposable
+    {
+        /// <summary>
+        /// 杩炴帴閫氳
+        /// </summary>
+        /// <returns></returns>
+        bool Connect();
+
+        /// <summary>
+        /// 鏂紑杩炴帴
+        /// </summary>
+        /// <returns></returns>
+        bool Disconnect();
+
+        /// <summary>
+        /// 鎺ユ敹娑堟伅
+        /// </summary>
+        /// <returns></returns>
+        string ReceiveMsg();
+
+        /// <summary>
+        /// 鍙戦�佹秷鎭�
+        /// </summary>
+        /// <param name="message"></param>
+        /// <returns></returns>
+        bool SendMessage(string message);
+
+        /// <summary>
+        /// 鍙戦�佸績璺充俊鍙�
+        /// </summary>
+        void SendHeartbeat();
+    }
+
+    public enum CommunicatorType { Sender, Receiver }
+
+    public enum CommunicatorBrand
+    {
+        /// <summary>
+        /// 涓插彛閫氳
+        /// </summary>
+        UARTPort,
+        /// <summary>
+        /// TCP瀹㈡埛绔�
+        /// </summary>
+        TCPClient,
+        /// <summary>
+        /// TCP鏈嶅姟鍣�
+        /// </summary>
+        TCPServer,
+        /// <summary>
+        /// 鏈湴閫氳
+        /// </summary>
+        LocalMonitor,
+        /// <summary>
+        /// 瑗块棬瀛怱7
+        /// </summary>
+        SiemensS7,
+        /// <summary>
+        /// MES閫氳
+        /// </summary>
+        MESCommunicate,
+        /// <summary>
+        /// 鏆備笉鏀寔
+        /// </summary>
+        UNSUPPORTED
+    }
+}
diff --git a/LB_VisionProcesses/Communicators/TCom/LocalMonitor.cs b/LB_VisionProcesses/Communicators/TCom/LocalMonitor.cs
new file mode 100644
index 0000000..cd2bc7e
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/TCom/LocalMonitor.cs
@@ -0,0 +1,162 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Communicators.TCom
+{
+    public class LocalMonitor : BaseCommunicator
+    {
+        // 浣跨敤 FileSystemWatcher 鏉ュ疄鏃剁洃鍚枃浠跺す鍙樺寲
+        FileSystemWatcher watcher = null;
+
+        string DirectoryPath = string.Empty;
+        string TriggerFileName = string.Empty;
+        string ReturnFileName = string.Empty;
+
+        public LocalMonitor(string name = "鏈湴鐩戞帶")
+        {
+            CommunicatorConnections.Add("鍦板潃", @"\LocalMonitor\Start.txt");
+            CommunicatorConnections.Add("绔彛", "result.txt");
+            CommunicatorBrand = CommunicatorBrand.LocalMonitor;
+            CommunicatorName = name;
+        }
+
+        public override bool Connect()
+        {
+            try
+            {
+                Disconnect();
+
+                if (string.IsNullOrEmpty(CommunicatorConnections["鍦板潃"].ToString())
+                    || string.IsNullOrEmpty(CommunicatorConnections["绔彛"].ToString()))
+                    return false;
+
+                DirectoryPath = Path.GetDirectoryName(CommunicatorConnections["鍦板潃"].ToString());
+                TriggerFileName = Path.GetFileName(CommunicatorConnections["鍦板潃"].ToString());
+                ReturnFileName = CommunicatorConnections["绔彛"].ToString();
+
+                if (string.IsNullOrEmpty(DirectoryPath) || string.IsNullOrEmpty(TriggerFileName) || string.IsNullOrEmpty(ReturnFileName))
+                    return false;
+
+                if (!Directory.Exists(DirectoryPath))
+                    Directory.CreateDirectory(DirectoryPath);
+
+                if (File.Exists(CommunicatorConnections["鍦板潃"].ToString()))
+                    File.Delete(CommunicatorConnections["鍦板潃"].ToString());
+
+                watcher = new FileSystemWatcher(DirectoryPath)
+                {
+                    Filter = TriggerFileName,
+                    NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite
+                };
+
+                watcher.Created += MonitorTrigger;
+                watcher.EnableRaisingEvents = true;
+                bConnected = true;
+
+                this.CommunicatorBrand = CommunicatorBrand.LocalMonitor;
+                this.CommunicatorName = CommunicatorName;
+                return true;
+            }
+            catch (Exception ex)
+            {
+                Msg = $"澶辫触,鏈湴鐩戞帶鏈惎鍔�: {ex.Message}";
+                return false;
+            }
+        }
+
+        public override bool Disconnect()
+        {
+            try
+            {
+                bConnected = false;
+                if (watcher == null)
+                    return true;
+
+                // 绉婚櫎鎵�鏈変簨浠跺鐞嗙▼搴�
+                watcher.Created -= MonitorTrigger;
+                // 鍋滄骞堕噴鏀�
+                watcher.EnableRaisingEvents = false;
+                watcher.Dispose();
+                watcher = null;
+                return true;
+            }
+            catch
+            {
+                bConnected = false;
+                return true;
+            }
+        }
+
+        void MonitorTrigger(object sender, FileSystemEventArgs e)
+        {
+            string path = e.FullPath; // 鑾峰彇鍒涘缓鐨勬枃浠惰矾寰�
+            try
+            {
+                Thread.Sleep(50);
+                string[] lines = File.ReadAllLines(path);
+                string message = string.Empty;
+                if (lines.Length >= 1)
+                    message = lines[0];
+
+                strReceiveMsg = message;
+                try
+                {
+                    MessageReceived?.Invoke(strReceiveMsg); // 瑙﹀彂鍥炶皟
+                }
+                catch { }
+                try
+                {
+                    TriggerRunMessageReceived?.Invoke(CommunicatorName, strReceiveMsg);  // 瑙﹀彂杩愯浜嬩欢
+                }
+                catch { }
+            }
+            catch (Exception ex)
+            {
+                Msg = $"鏈湴鐩戞帶澶勭悊鏂囦欢鏃跺彂鐢熷紓甯�: {ex.Message}";
+            }
+            finally
+            {
+                File.Delete(path);
+            }
+        }
+
+        // 鍙戦�佹秷鎭埌鏈嶅姟鍣�
+        public override bool SendMessage(string message)
+        {
+            if (!bConnected || watcher == null)
+            {
+                Msg = "灏氭湭鍒涘缓鏈湴鐩戞帶";
+                return false;
+            }
+
+            try
+            {
+                if (!Directory.Exists(DirectoryPath))
+                    Directory.CreateDirectory(DirectoryPath);
+
+                if (File.Exists(CommunicatorConnections["鍦板潃"].ToString()))
+                    File.Delete(CommunicatorConnections["鍦板潃"].ToString());
+
+                string FileFullPath = Path.Combine(DirectoryPath, ReturnFileName);
+
+                if (File.Exists(FileFullPath))
+                    File.Delete(FileFullPath);
+
+                FileStream fs = new FileStream(FileFullPath, FileMode.Create);
+                byte[] data = System.Text.Encoding.Default.GetBytes(message);
+                fs.Write(data, 0, data.Length);
+                fs.Flush();
+                fs.Close();
+                return true;
+            }
+            catch (Exception ex)
+            {
+                Msg = $"鍙戦�佹秷鎭椂鍙戠敓閿欒: {ex.Message}";
+                return false;
+            }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Communicators/TCom/TCPClient.cs b/LB_VisionProcesses/Communicators/TCom/TCPClient.cs
new file mode 100644
index 0000000..6eb0199
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/TCom/TCPClient.cs
@@ -0,0 +1,155 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Communicators.TCom
+{
+    public class TCPClient : BaseCommunicator
+    {
+        private TcpClient _tcpClient = new TcpClient();
+        private NetworkStream _networkStream;
+        private StreamReader _reader;
+        private StreamWriter _writer;
+
+        public TCPClient(string name = "TCP瀹㈡埛绔�")
+        {
+            CommunicatorConnections.Add("鍦板潃", "127.0.0.1");
+            CommunicatorConnections.Add("绔彛", "1111");
+            CommunicatorBrand = CommunicatorBrand.TCPClient;
+            CommunicatorName = name;
+        }
+
+        public override bool Connect()
+        {
+            try
+            {
+                Disconnect();
+
+                int PORT = 0;
+                if (!int.TryParse(this.CommunicatorConnections["绔彛"].ToString(), out PORT))
+                {
+                    Msg = string.Format("绔彛鏈缃�");
+                    return false;
+                }
+                if (!CommunicatorConnections.Contains("鍦板潃"))
+                {
+                    Msg = string.Format("鍦板潃鏈缃�");
+                    return false;
+                }
+                string IP = CommunicatorConnections["鍦板潃"].ToString();
+
+                _tcpClient.Connect(IPAddress.Parse(IP), PORT);
+                _networkStream = _tcpClient.GetStream();
+                _reader = new StreamReader(_networkStream, Encoding.UTF8);
+                //_writer = new StreamWriter(_networkStream, Encoding.UTF8) { AutoFlush = true };
+                _writer = new StreamWriter(_networkStream, Encoding.UTF8) { AutoFlush = true };
+                bConnected = true;
+                bHeart = true;
+
+                // 鍚姩蹇冭烦绾跨▼
+                heartbeatThread = new Thread(SendHeartbeat);
+                heartbeatThread.IsBackground = true;
+                heartbeatThread.Start();
+
+                // 鍚姩鎺ユ敹绾跨▼
+                Task.Run(HandleServerComm);
+                return true;
+            }
+            catch (Exception ex)
+            {
+                Msg = $"澶辫触,鏈嶅姟鍣ㄦ湭鍚姩: {ex.Message}";
+                return false;
+            }
+        }
+
+        public override bool Disconnect()
+        {
+            try
+            {
+                bConnected = false;
+                if (_tcpClient.Connected)
+                {
+                    _reader.Close();
+                    _writer.Close();
+                    _networkStream.Close();
+                    _tcpClient.Close();
+                }
+                _tcpClient = new TcpClient();
+                return true;
+            }
+            catch
+            {
+                bConnected = false;
+                return true;
+            }
+        }
+
+        private async Task HandleServerComm()
+        {
+            while (bConnected)
+            {
+                try
+                {
+                    await Task.Delay(25); // 绛夊緟 25ms 鍚庡啀灏濊瘯妫�鏌ユ暟鎹�
+
+                    byte[] buffer = new byte[1024];
+                    int bytesRead = _networkStream.Read(buffer, 0, buffer.Length);
+                    if (bytesRead > 0)
+                    {
+                        string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
+                        if (message != null)
+                        {
+                            strReceiveMsg = message;
+                            try
+                            {
+                                TriggerRunMessageReceived?.Invoke(CommunicatorName, strReceiveMsg);  // 瑙﹀彂杩愯浜嬩欢
+                            }
+                            catch { }
+                            try
+                            {
+                                MessageReceived?.Invoke(strReceiveMsg); // 瑙﹀彂鍥炶皟
+                            }
+                            catch { }
+                        }
+                    }
+                }
+                catch (Exception ex)
+                {
+                    bHeart = false;
+                    Debug.WriteLine($"鎺ユ敹娑堟伅鏃跺彂鐢熼敊璇�: {ex.Message}");
+                }
+            }
+        }
+
+        // 鍙戦�佹秷鎭埌鏈嶅姟鍣�
+        public override bool SendMessage(string message)
+        {
+            if (!bConnected)
+            {
+                Msg = "灏氭湭杩炴帴鍒版湇鍔″櫒";
+                return false;
+            }
+
+            try
+            {
+                //绌烘秷鎭笉鍙戦��
+                if (string.IsNullOrEmpty(message) || message.Trim() == "")
+                    return true;
+                _writer.Write(message);
+                //_writer.Flush();  // 寮哄埗灏嗙紦鍐插尯涓殑鏁版嵁鍐欏叆缃戠粶娴�
+                return true;
+            }
+            catch (Exception ex)
+            {
+                bHeart = false;
+                Msg = $"鍙戦�佹秷鎭椂鍙戠敓閿欒: {ex.Message}";
+                return false;
+            }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Communicators/TCom/TCPServer.cs b/LB_VisionProcesses/Communicators/TCom/TCPServer.cs
new file mode 100644
index 0000000..c33de94
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/TCom/TCPServer.cs
@@ -0,0 +1,231 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Communicators.TCom
+{
+    public class TCPServer : BaseCommunicator
+    {
+        private TcpListener _tcpListener;
+        private Task _tcpListenerTask;
+        CancellationTokenSource ctsListener = new CancellationTokenSource();
+        private List<TcpClient> _clients = new List<TcpClient>(); // 鐢ㄤ簬瀛樺偍鎵�鏈夎繛鎺ョ殑瀹㈡埛绔�
+
+        /// <summary>
+        /// 鏄惁澶氭挱妯″紡(澶氭挱妯″紡浼氬皢鏀跺埌鐨勫鎴风娑堟伅杞彂缁欏叾浠栧鎴风)
+        /// </summary>
+        bool isMultiBroadcast = true;
+
+        public TCPServer(string name = "TCP鏈嶅姟鍣�")
+        {
+            CommunicatorConnections.Add("鍦板潃", "127.0.0.1");
+            CommunicatorConnections.Add("绔彛", "1111");
+            CommunicatorBrand = CommunicatorBrand.TCPServer;
+            CommunicatorName = name;
+        }
+
+        public override bool Connect()
+        {
+            try
+            {
+                // 鍒涘缓涓�涓猅CP鐩戝惉鍣�
+                if (bConnected)
+                    Disconnect();
+
+                int PORT = 0;
+                if (!int.TryParse(this.CommunicatorConnections["绔彛"].ToString(), out PORT))
+                {
+                    Msg = string.Format("绔彛鏈缃�");
+                    return false;
+                }
+                if (!CommunicatorConnections.Contains("鍦板潃"))
+                {
+                    Msg = string.Format("鍦板潃鏈缃�");
+                    return false;
+                }
+                string IP = CommunicatorConnections["鍦板潃"].ToString();
+
+                _tcpListener = new TcpListener(IPAddress.Parse(IP), PORT);
+                _tcpListener.Start();
+                bConnected = true;
+
+                //// 鍚姩蹇冭烦绾跨▼(鏈嶅姟鍣ㄤ笉闇�瑕佸績璺崇嚎绋�)
+                //heartbeatThread = new Thread(SendHeartbeat);
+                //heartbeatThread.IsBackground = true;
+                //heartbeatThread.Start();
+
+                // 鍚姩鐩戝惉绾跨▼
+                ctsListener = new CancellationTokenSource();
+                _tcpListenerTask = ListenForClientsAsync(ctsListener.Token);
+
+                return true;
+            }
+            catch (Exception ex)
+            {
+                Msg = $"澶辫触,鏈嶅姟鍣ㄥ凡缁忓惎鍔�: {ex.Message}";
+                return false;
+            }
+        }
+
+        public override bool Disconnect()
+        {
+            try
+            {
+                bConnected = false;
+
+                if (_tcpListenerTask != null)
+                    ctsListener.Cancel();
+
+                if (_tcpListener != null)
+                {
+                    _tcpListener.Stop();
+                    _tcpListener = null;
+                }
+
+                return true;
+            }
+            catch
+            {
+                bConnected = false;
+                Msg = "澶辫触,鏈嶅姟鍣ㄥ凡缁忓仠姝�";
+                return true;
+            }
+        }
+
+        private async Task ListenForClientsAsync(CancellationToken cancellationToken)
+        {
+            while (bConnected && !cancellationToken.IsCancellationRequested)
+            {
+                try
+                {
+                    //// 闃诲绛夊緟瀹㈡埛绔繛鎺�
+                    //var tcpClient = _tcpListener.AcceptTcpClient();
+
+                    //// 灏嗗鎴风娣诲姞鍒板鎴风鍒楄〃涓�
+                    //lock (_clients)
+                    //{
+                    //    _clients.Add(tcpClient);
+                    //}
+
+                    //// 鍚姩涓�涓嚎绋嬫潵澶勭悊瀹㈡埛绔秷鎭�
+                    //var clientThread = new Thread(HandleClientComm);
+                    //clientThread.Start(tcpClient);
+
+                    // 寮傛绛夊緟瀹㈡埛绔繛鎺ワ紙鍙彇娑堬級
+                    var tcpClient = await _tcpListener.AcceptTcpClientAsync(cancellationToken);
+
+                    lock (_clients)
+                    {
+                        _clients.Add(tcpClient);
+                    }
+
+                    // 浣跨敤 Task.Run 浠f浛 Thread
+                    _ = Task.Run(() => HandleClientComm(tcpClient), cancellationToken);
+                }
+                catch { }
+            }
+        }
+
+        private void HandleClientComm(object obj)
+        {
+            if (obj == null || !(obj is TcpClient))
+                return;
+
+            try
+            {
+                var tcpClient = (TcpClient)obj;
+                NetworkStream stream = tcpClient.GetStream();
+                while (bConnected)
+                {
+                    byte[] buffer = new byte[1024];
+                    int bytesRead = stream.Read(buffer, 0, buffer.Length);
+
+                    if (bytesRead == 0)
+                        break;
+
+                    strReceiveMsg = Encoding.UTF8.GetString(buffer, 0, bytesRead);
+
+
+                    List<TcpClient> listRemoveTcpClients = new List<TcpClient>();
+                    foreach (var client in _clients)
+                    {
+                        if (isMultiBroadcast && client != tcpClient) // 濡傛灉鏄鎾ā寮忎笖涓嶆槸鍙戦�佽��
+                        {
+                            try
+                            {
+                                SendMessageToClient(client, strReceiveMsg);
+                            }
+                            catch (Exception ex)
+                            {
+                                Debug.WriteLine($"鍙戦�佹秷鎭埌 {client.ToString()} 瀹㈡埛绔椂鍙戠敓閿欒: {ex.Message}");
+                                listRemoveTcpClients.Add(client);
+                            }
+                        }
+                    }
+                    foreach (var offlineTcpClient in listRemoveTcpClients)
+                    {
+                        lock (_clients)
+                        {
+                            _clients.Remove(offlineTcpClient);
+                        }
+                    }
+
+                    try
+                    {
+                        TriggerRunMessageReceived?.Invoke(CommunicatorName, strReceiveMsg);  // 瑙﹀彂杩愯浜嬩欢
+                    }
+                    catch { }
+                    try
+                    {
+                        MessageReceived?.Invoke(strReceiveMsg);  // 瑙﹀彂娑堟伅鎺ユ敹浜嬩欢
+                    }
+                    catch { }
+                }
+            }
+            catch { }
+        }
+
+        public void SendMessageToClient(TcpClient client, string message)
+        {
+            NetworkStream stream = client.GetStream();
+            byte[] messageBytes = Encoding.UTF8.GetBytes(message);
+            stream.Write(messageBytes, 0, messageBytes.Length);
+            stream.Flush();
+        }
+
+        public override bool SendMessage(string message)
+        {
+            //绌烘秷鎭笉鍙戦��
+            if (string.IsNullOrEmpty(message) || message.Trim() == "")
+                return true;
+            List<TcpClient> listRemoveTcpClients = new List<TcpClient>();
+            foreach (var client in _clients)
+            {
+                try
+                {
+                    SendMessageToClient(client, message);
+                }
+                catch (Exception ex)
+                {
+                    Debug.WriteLine($"鍙戦�佹秷鎭埌 {client.ToString()} 瀹㈡埛绔椂鍙戠敓閿欒: {ex.Message}");
+                    listRemoveTcpClients.Add(client);
+                }
+            }
+
+            foreach (var offlineTcpClient in listRemoveTcpClients)
+            {
+                lock (_clients)
+                {
+                    _clients.Remove(offlineTcpClient);
+                }
+            }
+
+            return true;
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Communicators/TCom/UARTPort.cs b/LB_VisionProcesses/Communicators/TCom/UARTPort.cs
new file mode 100644
index 0000000..c40ad45
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/TCom/UARTPort.cs
@@ -0,0 +1,245 @@
+锘縰sing RJCP.IO.Ports;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Communicators.TCom
+{
+    public class UARTPort : BaseCommunicator
+    {
+        private RJCP.IO.Ports.SerialPortStream SerialPort = new RJCP.IO.Ports.SerialPortStream();
+
+        // 鏋勯�犲嚱鏁�
+        public UARTPort(string name = "UART涓插彛")
+        {
+            CommunicatorConnections.Add("鍦板潃", "COM1");
+            CommunicatorConnections.Add("绔彛", "9600");
+            CommunicatorBrand = CommunicatorBrand.UARTPort;
+            CommunicatorName = name;
+        }
+
+        /// <summary>
+        /// 閰嶇疆涓插彛鍙傛暟
+        /// </summary>
+        /// <param name="portName"></param>
+        /// <param name="baudRate"></param>
+        /// <param name="parity"></param>
+        /// <param name="dataBits"></param>
+        /// <param name="stopBits"></param>
+        public void SetConfigure(string portName, int baudRate = 9600, RJCP.IO.Ports.Parity parity = RJCP.IO.Ports.Parity.None,
+            int dataBits = 8, RJCP.IO.Ports.StopBits stopBits = RJCP.IO.Ports.StopBits.One)
+        {
+            SerialPort.PortName = portName;
+            SerialPort.BaudRate = baudRate;
+            SerialPort.Parity = parity;
+            SerialPort.DataBits = dataBits;
+            SerialPort.StopBits = stopBits;
+            SerialPort.NewLine = "\r\n";  // 璁剧疆琛岀粨鏉熺
+            SerialPort.ReadTimeout = 500; // 璁剧疆璇诲彇瓒呮椂
+            SerialPort.WriteTimeout = 500; // 璁剧疆鍐欏叆瓒呮椂
+        }
+
+        public override bool Connect()
+        {
+            try
+            {
+                Disconnect();
+
+                //娉㈢壒鐜�
+                int PORT = 0;
+                if (!int.TryParse(this.CommunicatorConnections["绔彛"].ToString(), out PORT))
+                {
+                    Msg = string.Format("绔彛鏈缃�");
+                    return false;
+                }
+                if (!CommunicatorConnections.Contains("鍦板潃"))
+                {
+                    Msg = string.Format("鍦板潃鏈缃�");
+                    return false;
+                }
+                //涓插彛鍙�
+                string IP = CommunicatorConnections["鍦板潃"].ToString();
+
+                if (!SerialPort.IsOpen)
+                {
+                    SerialPort = new SerialPortStream();
+                    SetConfigure(IP, PORT);
+                    SerialPort.Open();
+                    bConnected = true;
+                    SerialPort.DataReceived += SerialPort_DataReceived;
+
+                    // 鍚姩蹇冭烦绾跨▼
+                    heartbeatThread = new Thread(SendHeartbeat);
+                    heartbeatThread.IsBackground = true;
+                    heartbeatThread.Start();
+
+                    bConnected = true;
+                    return true;
+                }
+                else
+                {
+                    Msg = $"鍘熶覆鍙e叧闂け璐ユ棤娉曢噸鏂版墦寮�";
+                    return false;
+                }
+            }
+            catch (Exception ex)
+            {
+                Msg = $"澶辫触,涓插彛宸茬粡鍚姩: {ex.Message}";
+                return false;
+            }
+        }
+
+        public override bool Disconnect()
+        {
+            try
+            {
+                bConnected = false;
+                if (SerialPort == null)
+                {
+                    SerialPort = new SerialPortStream();
+                    return true;
+                }
+
+                if (SerialPort.IsOpen)
+                {
+                    SerialPort.DataReceived -= SerialPort_DataReceived;
+                    SerialPort.Close(); // 鍏抽棴涓插彛
+                }
+
+                SerialPort = new SerialPortStream();
+                return true;
+            }
+            catch (Exception ex)
+            {
+                bConnected = false;
+                Msg = $"鏂紑涓插彛鏃跺嚭閿�: {ex.Message}";
+                return true;
+            }
+        }
+
+        public bool SendMessageBytes(byte[] sBytes)
+        {
+            bool bret = false;
+            if (SerialPort == null || !SerialPort.IsOpen) return bret;
+            try
+            {
+                SerialPort.Write(sBytes, 0, sBytes.Length);
+                bret = true;
+            }
+            catch { }
+            return bret;
+        }
+
+        public override bool SendMessage(string message)
+        {
+            if (bConnected)
+            {
+                try
+                {
+                    //绌烘秷鎭笉鍙戦��
+                    if (string.IsNullOrEmpty(message) || message.Trim() == "")
+                        return true;
+
+                    //鍙戦�佸墠娓呯┖鎺ユ敹娑堟伅
+                    strReceiveMsg = string.Empty;
+                    SerialPort.Write(message); // 鍙戦�佹秷鎭�
+                    return true;
+                }
+                catch (Exception ex)
+                {
+                    Msg = $"鍙戦�佹秷鎭椂鍑洪敊: {ex.Message}";
+                    return false;
+                }
+            }
+            else
+            {
+                Msg = "涓插彛鏈墦寮�";
+                return false;
+            }
+        }
+
+        private void ReadSerialData()
+        {
+            while (bConnected)
+            {
+                try
+                {
+                    string message = SerialPort.ReadLine(); // 璇诲彇涓�琛屾暟鎹�
+                    if (message != null)
+                    {
+                        strReceiveMsg = message;
+                        MessageReceived?.Invoke(message); // 瑙﹀彂鍥炶皟
+                        TriggerRunMessageReceived?.Invoke(CommunicatorName, strReceiveMsg);  // 瑙﹀彂杩愯浜嬩欢
+                    }
+                }
+                //catch (TimeoutException) { /* 璇诲彇瓒呮椂锛屽彲浠ュ拷鐣� */ }
+                catch (Exception ex)
+                {
+                    Msg = $"璇诲彇涓插彛鏁版嵁鏃跺嚭閿�: {ex.Message}";
+                }
+            }
+        }
+
+        private System.Threading.Timer _clearTimer;  // 鐢ㄤ簬寤舵椂娓呯┖鐨勮鏃跺櫒
+
+        private void SerialPort_DataReceived(object? sender, RJCP.IO.Ports.SerialDataReceivedEventArgs e)
+        {
+            try
+            {
+                if (SerialPort == null || !SerialPort.IsOpen)
+                    return;
+
+                string message = SerialPort.ReadExisting();
+                if (string.IsNullOrEmpty(message))
+                    return;
+
+                if (string.IsNullOrEmpty(strReceiveMsg))
+                {
+                    // 閲嶇疆鎴栧惎鍔ㄨ鏃跺櫒锛�1绉掑悗娓呯┖锛�
+                    _clearTimer?.Dispose();  // 鍙栨秷涔嬪墠鐨勮鏃跺櫒
+                    _clearTimer = new System.Threading.Timer(
+                        _ => ClearMessage(),
+                        null,
+                        TimeSpan.FromSeconds(1),  // 1绉掑悗瑙﹀彂
+                        Timeout.InfiniteTimeSpan  // 鍙Е鍙戜竴娆�
+                    );
+                }
+
+                //涓插彛鍥炶皟鐢ㄧ疮鍔犵殑鏂瑰紡
+                lock (strReceiveMsg)
+                {
+                    strReceiveMsg += message;
+                    MessageReceived?.Invoke(strReceiveMsg); // 瑙﹀彂鍥炶皟
+                    TriggerRunMessageReceived?.Invoke(CommunicatorName, strReceiveMsg);  // 瑙﹀彂杩愯浜嬩欢
+                }
+            }
+            catch (Exception ex)
+            {
+                Msg = $"璇诲彇涓插彛鏁版嵁鏃跺嚭閿�: {ex.Message}";
+            }
+        }
+
+        public override string ReceiveMsg()
+        {
+            string msg = string.Empty;
+            for (int i = 0; i <= 3; i++)
+            {
+                if (string.IsNullOrEmpty(strReceiveMsg))
+                    Thread.Sleep(50);
+                else
+                {
+                    lock (strReceiveMsg)
+                    {
+                        msg += strReceiveMsg;
+                        strReceiveMsg = string.Empty;
+                    }
+                    //涓插彛鏁版嵁闇�瑕佷娇鐢ㄧ疮鍔犳柟寮�
+                    //return msg;
+                }
+            }
+            return msg;
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Communicators/UserCommunicator/T306Command/T306CommandTool.cs b/LB_VisionProcesses/Communicators/UserCommunicator/T306Command/T306CommandTool.cs
new file mode 100644
index 0000000..a8a1b21
--- /dev/null
+++ b/LB_VisionProcesses/Communicators/UserCommunicator/T306Command/T306CommandTool.cs
@@ -0,0 +1,145 @@
+锘縰sing LB_VisionProcesses.Communicators.TCom;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Communicators.UserCommunicator.T306Command
+{
+    internal class T306CommandTool : CommunicatorConfig
+    {
+        string HDCP14CHECK = "0422CCF2";
+        string HDCP22CHECK = "0422C2E8";
+        string ok = "031114";
+
+        public T306CommandTool(ConcurrentDictionary<string, BaseCommunicator> dicCommunicators)
+            : base(dicCommunicators)
+        {
+            strProcessName = "T306閫氳";
+            strProcessClass = "LB_VisionProcesses.Communicators.T306CommandTool";
+
+            Params.Inputs.Add("閫氳鍙e悕", "");
+            Params.Inputs.Add("HDMI1", false);
+            Params.Inputs.Add("HDMI2", false);
+            Params.Inputs.Add("HDCP1.4", false);
+            Params.Inputs.Add("HDCP2.2", false);
+            Params.Outputs.Add("鏀跺埌娑堟伅", "");
+
+            //淇敼鍩虹被CommunicatorConfig鐨勯粯璁ゅ��
+            Params.Inputs.Add("閫氳绫诲瀷", CommunicatorType.Sender);
+            Params.Inputs.Add("鏄惁鍚敤CRC鏍¢獙", false);
+            Params.Inputs.Add("閫氳娑堟伅", "T306绯荤粺棰勮鎸囦护");
+        }
+
+        public override bool Run()
+        {
+            try
+            {
+                InitRunParams();
+                Params.Outputs["鏀跺埌娑堟伅"] = "";
+                string CommunicatorName = Params.Inputs["閫氳鍙e悕"].ToString();
+
+                if (!dicCommunicators.ContainsKey(CommunicatorName))
+                {
+                    Msg = $"閫氳鍙{CommunicatorName}]涓嶅瓨鍦�";
+                    Result = false;
+                    return Result;
+                }
+
+                BaseCommunicator BaseCommunicator = dicCommunicators[CommunicatorName];
+
+                if (BaseCommunicator == null)
+                {
+                    Msg = $"閫氳鍙{CommunicatorName}]鏈疄渚嬪寲";
+                    Result = false;
+                    return Result;
+                }
+
+                if (!(BaseCommunicator is UARTPort port))
+                {
+                    Msg = $"閫氳鍙{CommunicatorName}]涓嶆槸涓插彛";
+                    Result = false;
+                    return Result;
+                }
+
+                if (!BaseCommunicator.bConnected)
+                {
+                    Msg = $"閫氳鍙{CommunicatorName}]鏈繛鎺�";
+                    Result = false;
+                    return Result;
+                }
+
+                bool isCheckHDMI1 = (bool)Params.Inputs["HDMI1"];
+                bool isCheckHDMI2 = (bool)Params.Inputs["HDMI2"];
+                bool isCheckHDCP14 = (bool)Params.Inputs["HDCP1.4"];
+                bool isCheckHDCP22 = (bool)Params.Inputs["HDCP2.2"];
+                bool bHDMI1 = true, bHDMI2 = true;
+
+                if (isCheckHDMI1 && isCheckHDCP14)
+                    bHDMI1 = CheckHDMIHDCP(port, "HDMI1", true, false);
+
+                if (isCheckHDMI2 && bHDMI1 && isCheckHDCP22)
+                    bHDMI2 = CheckHDMIHDCP(port, "HDMI2", false, false);
+
+                if (!bHDMI1 || !bHDMI2)
+                {
+                    Msg = !bHDMI1 ? $"HDCP1.4妫�娴嬪け璐�" : $"HDCP2.2妫�娴嬪け璐�";
+                    Result = false;
+                    return Result;
+                }
+            }
+            catch (Exception ex)
+            {
+                Msg = $"閫氳寮傚父,鍘熷洜鏄�:{ex.Message}";
+                Result = false;
+            }
+            return Result;
+        }
+
+        bool CheckHDMIHDCP(UARTPort port, string strHDMI, bool check14, bool check22)
+        {
+            try
+            {
+                string response = string.Empty;
+                switch (strHDMI)
+                {
+                    case "HDMI1":
+                        port.SendMessageBytes(BaseCommunicator.strToHexByte("41"));
+                        break;
+                    case "HDMI2":
+                        port.SendMessageBytes(BaseCommunicator.strToHexByte("14"));
+                        break;
+                    default:
+                        return false;
+                }
+
+                response = string.Empty;
+                for (int i = 0; i < 3; i++)
+                {
+                    if (check14)
+                    {
+                        port.SendMessageBytes(BaseCommunicator.strToHexByte(HDCP14CHECK));
+                        response += port.ReceiveMsg();
+                        if (response.Contains(ok))
+                            return true;
+                    }
+
+                    if (check22)
+                    {
+                        port.SendMessageBytes(BaseCommunicator.strToHexByte(HDCP22CHECK));
+                        response += port.ReceiveMsg();
+                        if (response.Contains(ok))
+                            return true;
+                    }
+                }
+
+                return false;
+            }
+            catch (Exception e) { Debug.WriteLine($"CheckHDMIHDCP:{e.Message}[{e.StackTrace}]"); return false; }
+        }
+    }
+
+}
diff --git a/LB_VisionProcesses/Forms/GlobalVarControl.Designer.cs b/LB_VisionProcesses/Forms/GlobalVarControl.Designer.cs
new file mode 100644
index 0000000..bed31eb
--- /dev/null
+++ b/LB_VisionProcesses/Forms/GlobalVarControl.Designer.cs
@@ -0,0 +1,99 @@
+锘縩amespace LB_VisionProcesses.Forms
+{
+    partial class GlobalVarControl
+    {
+        /// <summary> 
+        /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆�
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆�
+        /// </summary>
+        /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜
+
+        /// <summary> 
+        /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼
+        /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广��
+        /// </summary>
+        private void InitializeComponent()
+        {
+            tableLayoutPanel1 = new TableLayoutPanel();
+            cmbType = new ComboBox();
+            ckbLabel = new CheckBox();
+            tableLayoutPanel1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // tableLayoutPanel1
+            // 
+            tableLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            tableLayoutPanel1.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
+            tableLayoutPanel1.ColumnCount = 3;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 250F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 80F));
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(cmbType, 1, 0);
+            tableLayoutPanel1.Controls.Add(ckbLabel, 0, 0);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.ForeColor = SystemColors.Control;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 1;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
+            tableLayoutPanel1.Size = new Size(578, 32);
+            tableLayoutPanel1.TabIndex = 0;
+            // 
+            // cmbType
+            // 
+            cmbType.Dock = DockStyle.Fill;
+            cmbType.FormattingEnabled = true;
+            cmbType.Items.AddRange(new object[] { "string", "bool", "double", "int", "List<string>", "Enum" });
+            cmbType.Location = new Point(255, 4);
+            cmbType.Name = "cmbType";
+            cmbType.Size = new Size(74, 25);
+            cmbType.TabIndex = 2;
+            cmbType.SelectedIndexChanged += cmbType_SelectedIndexChanged;
+            // 
+            // ckbLabel
+            // 
+            ckbLabel.AutoSize = true;
+            ckbLabel.Dock = DockStyle.Fill;
+            ckbLabel.Location = new Point(4, 4);
+            ckbLabel.Name = "ckbLabel";
+            ckbLabel.Size = new Size(244, 24);
+            ckbLabel.TabIndex = 3;
+            ckbLabel.Text = "GlobalVar.娴佺▼0.Result";
+            ckbLabel.TextAlign = ContentAlignment.MiddleRight;
+            ckbLabel.UseVisualStyleBackColor = true;
+            ckbLabel.MouseDown += ckbLabel_MouseDown;
+            // 
+            // GlobalVarControl
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            Controls.Add(tableLayoutPanel1);
+            Name = "GlobalVarControl";
+            Size = new Size(578, 32);
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel1.PerformLayout();
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private TableLayoutPanel tableLayoutPanel1;
+        private TextBox textBox1;
+        private ComboBox cmbType;
+        private CheckBox ckbLabel;
+    }
+}
diff --git a/LB_VisionProcesses/Forms/GlobalVarControl.cs b/LB_VisionProcesses/Forms/GlobalVarControl.cs
new file mode 100644
index 0000000..ee37157
--- /dev/null
+++ b/LB_VisionProcesses/Forms/GlobalVarControl.cs
@@ -0,0 +1,164 @@
+锘縰sing LB_VisionProcesses;
+using VisionControl.Forms;
+
+namespace LB_VisionProcesses.Forms
+{
+    public partial class GlobalVarControl : UserControl
+    {
+        NumericUpDown numericUpDown = new NumericUpDown();
+        CheckBox checkBox = new CheckBox();
+        TextBox textBox = new TextBox();
+        ComboBox comboBox = new ComboBox();
+
+        public bool isSelected
+        {
+            get { return ckbLabel.Checked; }
+        }
+
+        public string Key
+        {
+            get { return ckbLabel.Text; }
+        }
+
+        public object Value
+        {
+            get
+            {
+                string type = cmbType.Text;
+                switch (type)
+                {
+                    case "int":
+                        return Convert.ToInt32(numericUpDown.Value);
+                    case "double":
+                        return Convert.ToDouble(numericUpDown.Value);
+                    case "bool":
+                        return checkBox.Checked;
+                    case "List<string>":
+                        return textBox.Text.Split(',').ToList();
+                    case "string":
+                    default:
+                        return textBox.Text;
+                }
+            }
+        }
+
+        public GlobalVarControl(string key, object value = null)
+        {
+            InitializeComponent();
+            ckbLabel.Text = key;
+
+            if (value == null)
+            {
+                cmbType.Text = "string";
+                return;
+            }
+
+            Type type = value?.GetType();
+            switch (type)
+            {
+                case Type t when t == typeof(int):
+                    cmbType.Text = "int";
+                    numericUpDown.Value = Convert.ToDecimal((int)value);
+                    break;
+                case Type t when t == typeof(double):
+                    cmbType.Text = "double";
+                    numericUpDown.Value = Convert.ToDecimal((double)value);
+                    break;
+                case Type t when t == typeof(bool):
+                    cmbType.Text = "bool";
+                    checkBox.Checked = Convert.ToBoolean(value);
+                    break;
+                case Type t when t == typeof(List<string>):
+                    cmbType.Text = "string";
+                    textBox.Text = string.Join(',', value as List<string>);
+                    break;
+                default:
+                    cmbType.Text = "string";
+                    textBox.Text = value.ToString();
+                    break;
+            }
+        }
+
+        private void cmbType_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            numericUpDown.Visible = false;
+            checkBox.Visible = false;
+            textBox.Visible = false;
+            comboBox.Visible = false;
+
+            string type = cmbType.Text;
+            switch (type)
+            {
+                case "int":
+                    numericUpDown.Increment = 1;
+                    numericUpDown.Value = 0;
+                    tableLayoutPanel1.Controls.Add(numericUpDown, 2, 0);
+                    numericUpDown.Dock = DockStyle.Fill;
+                    numericUpDown.Visible = true;
+                    numericUpDown.Maximum = 999;
+                    numericUpDown.Minimum = -999;
+                    break;
+                case "double":
+                    numericUpDown.Increment = Convert.ToDecimal(0.1);
+                    numericUpDown.Value = Convert.ToDecimal(0.0);
+                    tableLayoutPanel1.Controls.Add(numericUpDown, 2, 0);
+                    numericUpDown.Dock = DockStyle.Fill;
+                    numericUpDown.Visible = true;
+                    numericUpDown.Maximum = 999;
+                    numericUpDown.Minimum = -999;
+                    break;
+                case "bool":
+                    checkBox.Checked = false;
+                    checkBox.Text = "";
+                    tableLayoutPanel1.Controls.Add(checkBox, 2, 0);
+                    checkBox.Dock = DockStyle.Fill;
+                    checkBox.Visible = true;
+                    break;
+                case "List<string>":
+                case "string":
+                default:
+                    textBox.Text = "";
+                    tableLayoutPanel1.Controls.Add(textBox, 2, 0);
+                    textBox.Dock = DockStyle.Fill;
+                    textBox.Visible = true;
+                    break;
+            }
+        }
+
+        private System.Windows.Forms.ToolTip toolTip = new System.Windows.Forms.ToolTip();
+        private void ShowToolTip(Control control, string message) => toolTip.SetToolTip(control, message);
+
+        private void ckbLabel_MouseDown(object sender, MouseEventArgs e)
+        {
+            if (e.Button.ToString() == "Right")
+            {
+                if (ckbLabel.Text.Contains("."))
+                {
+                    MessageBox.Show($"鍙橀噺銆恵ckbLabel.Text}銆戜笉鍏佽閲嶅懡鍚�!", "寮傚父");
+                    return;
+                }
+
+                RenameForm renameForm = new RenameForm(ckbLabel.Text);
+                renameForm.ShowDialog();
+                if (renameForm.bRename)
+                {
+                    string oriName = renameForm.strOriName;
+                    string newName = renameForm.strNewName;
+
+                    if (IProcess.dicGlobalVars.ContainsKey(newName))
+                        MessageBox.Show($"鍙橀噺銆恵newName}銆戝凡瀛樺湪锛岃鏇存崲鍚嶇О", "寮傚父");
+                    else
+                    {
+                        if (!IProcess.dicGlobalVars.TryRemove(oriName, out object obj)
+                           || !IProcess.dicGlobalVars.TryAdd(newName, obj))
+                        {
+                            MessageBox.Show($"閲嶅懡鍚嶄负銆恵newName}銆戝け璐�!", "寮傚父");
+                            return;
+                        }
+                        ckbLabel.Text = newName;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Forms/GlobalVarControl.resx b/LB_VisionProcesses/Forms/GlobalVarControl.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_VisionProcesses/Forms/GlobalVarControl.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/LB_VisionProcesses/Forms/GlobalVarForm.Designer.cs b/LB_VisionProcesses/Forms/GlobalVarForm.Designer.cs
new file mode 100644
index 0000000..27631ef
--- /dev/null
+++ b/LB_VisionProcesses/Forms/GlobalVarForm.Designer.cs
@@ -0,0 +1,203 @@
+锘縩amespace LB_VisionProcesses.Forms
+{
+    partial class GlobalVarForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(GlobalVarForm));
+            theme_GlobalVarForm = new ReaLTaiizor.Forms.ThemeForm();
+            controlBox_GlobalVarForm = new ReaLTaiizor.Controls.ControlBox();
+            controlsPanel = new ReaLTaiizor.Controls.Panel();
+            tlp_GlobalVarForm = new Sunny.UI.UITableLayoutPanel();
+            tlp_GlobalVarFormOperator = new Sunny.UI.UITableLayoutPanel();
+            btn_Delete = new ReaLTaiizor.Controls.Button();
+            btn_Add = new ReaLTaiizor.Controls.Button();
+            theme_GlobalVarForm.SuspendLayout();
+            controlsPanel.SuspendLayout();
+            tlp_GlobalVarForm.SuspendLayout();
+            tlp_GlobalVarFormOperator.SuspendLayout();
+            SuspendLayout();
+            // 
+            // theme_GlobalVarForm
+            // 
+            theme_GlobalVarForm.BackColor = Color.FromArgb(32, 41, 50);
+            theme_GlobalVarForm.Controls.Add(controlBox_GlobalVarForm);
+            theme_GlobalVarForm.Controls.Add(controlsPanel);
+            theme_GlobalVarForm.Dock = DockStyle.Fill;
+            theme_GlobalVarForm.Font = new Font("Microsoft Sans Serif", 9F);
+            theme_GlobalVarForm.Image = (Image)resources.GetObject("theme_GlobalVarForm.Image");
+            theme_GlobalVarForm.Location = new Point(0, 0);
+            theme_GlobalVarForm.Name = "theme_GlobalVarForm";
+            theme_GlobalVarForm.Padding = new Padding(10, 70, 10, 9);
+            theme_GlobalVarForm.RoundCorners = true;
+            theme_GlobalVarForm.Sizable = true;
+            theme_GlobalVarForm.Size = new Size(800, 600);
+            theme_GlobalVarForm.SmartBounds = true;
+            theme_GlobalVarForm.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            theme_GlobalVarForm.TabIndex = 0;
+            theme_GlobalVarForm.Text = "鍏ㄥ眬鍙橀噺";
+            // 
+            // controlBox_GlobalVarForm
+            // 
+            controlBox_GlobalVarForm.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            controlBox_GlobalVarForm.BackColor = Color.FromArgb(32, 34, 37);
+            controlBox_GlobalVarForm.CloseHoverColor = Color.FromArgb(230, 17, 35);
+            controlBox_GlobalVarForm.DefaultLocation = true;
+            controlBox_GlobalVarForm.EnableHoverHighlight = true;
+            controlBox_GlobalVarForm.EnableMaximizeButton = false;
+            controlBox_GlobalVarForm.EnableMinimizeButton = false;
+            controlBox_GlobalVarForm.ForeColor = Color.FromArgb(155, 155, 155);
+            controlBox_GlobalVarForm.Location = new Point(700, 12);
+            controlBox_GlobalVarForm.MaximizeHoverColor = Color.FromArgb(74, 74, 74);
+            controlBox_GlobalVarForm.MinimizeHoverColor = Color.FromArgb(63, 63, 65);
+            controlBox_GlobalVarForm.Name = "controlBox_GlobalVarForm";
+            controlBox_GlobalVarForm.Size = new Size(90, 25);
+            controlBox_GlobalVarForm.TabIndex = 1;
+            // 
+            // controlsPanel
+            // 
+            controlsPanel.BackColor = Color.FromArgb(39, 51, 63);
+            controlsPanel.Controls.Add(tlp_GlobalVarForm);
+            controlsPanel.Dock = DockStyle.Fill;
+            controlsPanel.EdgeColor = Color.FromArgb(32, 41, 50);
+            controlsPanel.Location = new Point(10, 70);
+            controlsPanel.Name = "controlsPanel";
+            controlsPanel.Padding = new Padding(5);
+            controlsPanel.Size = new Size(780, 521);
+            controlsPanel.SmoothingType = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
+            controlsPanel.TabIndex = 0;
+            controlsPanel.Text = "panel1";
+            controlsPanel.SizeChanged += controlsPanel_SizeChanged;
+            // 
+            // tlp_GlobalVarForm
+            // 
+            tlp_GlobalVarForm.ColumnCount = 1;
+            tlp_GlobalVarForm.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tlp_GlobalVarForm.Controls.Add(tlp_GlobalVarFormOperator, 0, 1);
+            tlp_GlobalVarForm.Dock = DockStyle.Fill;
+            tlp_GlobalVarForm.Location = new Point(5, 5);
+            tlp_GlobalVarForm.Name = "tlp_GlobalVarForm";
+            tlp_GlobalVarForm.RowCount = 2;
+            tlp_GlobalVarForm.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tlp_GlobalVarForm.RowStyles.Add(new RowStyle(SizeType.Absolute, 60F));
+            tlp_GlobalVarForm.Size = new Size(770, 511);
+            tlp_GlobalVarForm.TabIndex = 0;
+            tlp_GlobalVarForm.TagString = null;
+            // 
+            // tlp_GlobalVarFormOperator
+            // 
+            tlp_GlobalVarFormOperator.ColumnCount = 6;
+            tlp_GlobalVarFormOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666718F));
+            tlp_GlobalVarFormOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666679F));
+            tlp_GlobalVarFormOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666679F));
+            tlp_GlobalVarFormOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666679F));
+            tlp_GlobalVarFormOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666679F));
+            tlp_GlobalVarFormOperator.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.6666679F));
+            tlp_GlobalVarFormOperator.Controls.Add(btn_Delete, 4, 0);
+            tlp_GlobalVarFormOperator.Controls.Add(btn_Add, 5, 0);
+            tlp_GlobalVarFormOperator.Dock = DockStyle.Fill;
+            tlp_GlobalVarFormOperator.Location = new Point(3, 454);
+            tlp_GlobalVarFormOperator.Name = "tlp_GlobalVarFormOperator";
+            tlp_GlobalVarFormOperator.RowCount = 1;
+            tlp_GlobalVarFormOperator.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tlp_GlobalVarFormOperator.Size = new Size(764, 54);
+            tlp_GlobalVarFormOperator.TabIndex = 0;
+            tlp_GlobalVarFormOperator.TagString = null;
+            // 
+            // btn_Delete
+            // 
+            btn_Delete.BackColor = Color.Transparent;
+            btn_Delete.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_Delete.Dock = DockStyle.Fill;
+            btn_Delete.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Delete.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_Delete.Font = new Font("Microsoft Sans Serif", 12F);
+            btn_Delete.Image = null;
+            btn_Delete.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_Delete.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_Delete.Location = new Point(511, 3);
+            btn_Delete.Name = "btn_Delete";
+            btn_Delete.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Delete.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_Delete.Size = new Size(121, 48);
+            btn_Delete.TabIndex = 0;
+            btn_Delete.Text = "绉婚櫎";
+            btn_Delete.TextAlignment = StringAlignment.Center;
+            btn_Delete.Click += btn_Delete_Click;
+            // 
+            // btn_Add
+            // 
+            btn_Add.BackColor = Color.Transparent;
+            btn_Add.BorderColor = Color.FromArgb(32, 34, 37);
+            btn_Add.Dock = DockStyle.Fill;
+            btn_Add.EnteredBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Add.EnteredColor = Color.FromArgb(32, 34, 37);
+            btn_Add.Font = new Font("Microsoft Sans Serif", 12F);
+            btn_Add.Image = null;
+            btn_Add.ImageAlign = ContentAlignment.MiddleLeft;
+            btn_Add.InactiveColor = Color.FromArgb(32, 34, 37);
+            btn_Add.Location = new Point(638, 3);
+            btn_Add.Name = "btn_Add";
+            btn_Add.PressedBorderColor = Color.FromArgb(165, 37, 37);
+            btn_Add.PressedColor = Color.FromArgb(165, 37, 37);
+            btn_Add.Size = new Size(123, 48);
+            btn_Add.TabIndex = 1;
+            btn_Add.Text = "娣诲姞";
+            btn_Add.TextAlignment = StringAlignment.Center;
+            btn_Add.Click += btn_Add_Click;
+            // 
+            // GlobalVarForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(800, 600);
+            Controls.Add(theme_GlobalVarForm);
+            FormBorderStyle = FormBorderStyle.None;
+            MinimumSize = new Size(261, 61);
+            Name = "GlobalVarForm";
+            Text = "鍏ㄥ眬鍙橀噺";
+            TransparencyKey = Color.Fuchsia;
+            FormClosing += GlobalVarForm_FormClosing;
+            Load += GlobalVarForm_Load;
+            theme_GlobalVarForm.ResumeLayout(false);
+            controlsPanel.ResumeLayout(false);
+            tlp_GlobalVarForm.ResumeLayout(false);
+            tlp_GlobalVarFormOperator.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ReaLTaiizor.Forms.ThemeForm theme_GlobalVarForm;
+        private ReaLTaiizor.Controls.Panel controlsPanel;
+        private Sunny.UI.UITableLayoutPanel tlp_GlobalVarForm;
+        private Sunny.UI.UITableLayoutPanel tlp_GlobalVarFormOperator;
+        private ReaLTaiizor.Controls.Button btn_Delete;
+        private ReaLTaiizor.Controls.Button btn_Add;
+        private ReaLTaiizor.Controls.ControlBox controlBox_GlobalVarForm;
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionProcesses/Forms/GlobalVarForm.cs b/LB_VisionProcesses/Forms/GlobalVarForm.cs
new file mode 100644
index 0000000..7f099b0
--- /dev/null
+++ b/LB_VisionProcesses/Forms/GlobalVarForm.cs
@@ -0,0 +1,160 @@
+锘縰sing LB_VisionProcesses.Forms;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_VisionProcesses.Forms
+{
+    public partial class GlobalVarForm : Form
+    {
+        public bool isSave = false;
+        private string fullPath = string.Empty;
+
+        public GlobalVarForm(string path = "")
+        {
+            InitializeComponent();
+            fullPath = path;
+        }
+
+        private void GlobalVarForm_Load(object sender, EventArgs e)
+        {
+            var sortedKeys = IProcess.dicGlobalVars.Keys
+                                     .OrderBy(k => k, new NaturalStringComparer())
+                                     .ToList();
+            int index = 0;
+            foreach (var key in sortedKeys)
+            {
+                GlobalVarControl control = new GlobalVarControl(key, IProcess.dicGlobalVars[key]);
+                control.Size = new Size(this.controlsPanel.Size.Width, control.Size.Height);
+                control.Location = new Point(0, control.Size.Height * index);
+                this.controlsPanel.Controls.Add(control);
+                index++;
+            }
+        }
+
+        private void controlsPanel_SizeChanged(object sender, EventArgs e)
+        {
+            int index = 0;
+
+            foreach (var control in controlsPanel.Controls)
+            {
+                if (control is GlobalVarControl globalVarControl)
+                {
+                    globalVarControl.Size = new Size(this.controlsPanel.Size.Width, globalVarControl.Size.Height);
+                    globalVarControl.Location = new Point(0, globalVarControl.Size.Height * index);
+                    index++;
+                }
+            }
+        }
+
+        private void btn_Add_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                string name = "鍏ㄥ眬鍙橀噺";
+                while (IProcess.dicGlobalVars.ContainsKey(name))
+                    name += "(鍓湰)";
+
+                GlobalVarControl control = new GlobalVarControl(name);
+                control.Size = new Size(this.controlsPanel.Size.Width, control.Size.Height);
+                control.Location = new Point(0, control.Size.Height * IProcess.dicGlobalVars.Count);
+                this.controlsPanel.Controls.Add(control);
+                IProcess.dicGlobalVars.TryAdd(name, "");
+            }
+            catch (Exception ex) { Debug.WriteLine($"btnAdd_Click澶辫触:{ex.Message}銆恵ex.StackTrace}銆�"); }
+        }
+
+        private void GlobalVarForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath))
+                {
+                    e.Cancel = false;  //纭鍏抽棴绐椾綋
+                    return;
+                }
+
+                DialogResult res = MessageBox.Show("鏄惁淇濆瓨锛�", "鎻愮ず", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);  //淇濆瓨缁撴灉淇℃伅
+                /// 鍙傛暟1锛氭樉绀烘枃鏈紝鍙傛暟2锛氭爣棰橈紝鍙傛暟3锛氭寜閿被鍨嬶紝鍙傛暟4锛氭樉绀哄浘鏍�
+                if (res != DialogResult.Yes && res != DialogResult.No)  //鍙栨秷
+                {
+                    e.Cancel = true;  //鍙栨秷鍏抽棴绐椾綋
+                    return;
+                }
+
+                if (res == DialogResult.Yes)  //淇濆瓨
+                {
+                    IProcess.dicGlobalVars.Clear();
+                    foreach (var control in controlsPanel.Controls)
+                    {
+                        if (control is GlobalVarControl globalVarControl)
+                            IProcess.dicGlobalVars.AddOrUpdate(globalVarControl.Key, globalVarControl.Value
+                                , (key, oldValue) => globalVarControl.Value);
+                    }
+
+                    string strJson = string.Empty;
+                    var settings = new JsonSerializerSettings
+                    {
+                        Formatting = Newtonsoft.Json.Formatting.Indented,
+                        // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                        ContractResolver = new DefaultContractResolver
+                        {
+                            NamingStrategy = new CamelCaseNamingStrategy()
+                        }
+                    };
+                    strJson = JsonConvert.SerializeObject(IProcess.dicGlobalVars, settings);
+
+                    string filePath = Path.GetDirectoryName(fullPath);
+                    //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                    if (!Directory.Exists(filePath))
+                    {
+                        try
+                        {
+                            Directory.CreateDirectory(filePath);
+                        }
+                        catch (Exception)
+                        { }
+                    }
+                    File.WriteAllText(fullPath, strJson, Encoding.UTF8);
+
+                    e.Cancel = false;  //纭鍏抽棴绐椾綋
+                    return;
+                }
+
+                e.Cancel = false;  //纭鍏抽棴绐椾綋
+                return;
+            }
+            catch { }
+            finally { }
+
+        }
+
+        private void btn_Delete_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                List<GlobalVarControl> removeControls = new List<GlobalVarControl>();
+                foreach (var control in controlsPanel.Controls)
+                {
+                    if (control is GlobalVarControl globalVarControl && globalVarControl.isSelected)
+                        removeControls.Add(globalVarControl);
+                }
+
+                foreach (var control in removeControls)
+                    controlsPanel.Controls.Remove(control);
+            }
+            catch (Exception ex) { Debug.WriteLine($"btnDelete_Click澶辫触:{ex.Message}銆恵ex.StackTrace}銆�"); }
+
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Forms/GlobalVarForm.resx b/LB_VisionProcesses/Forms/GlobalVarForm.resx
new file mode 100644
index 0000000..e790f9d
--- /dev/null
+++ b/LB_VisionProcesses/Forms/GlobalVarForm.resx
@@ -0,0 +1,144 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="theme_GlobalVarForm.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        vAAADrwBlbxySQAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
+        BkVBUPCBCEG8BXNQ48GLeImCehIJxMsqhsSZruod46K4HtSIGjU+4iOr0c1I9fSsM3/PLNtCPO0H36m/
+        evz/X11VnreKVRTAHPOZumkY6lFwqURws3BwZ8ywTQnuiCP/+iTCzY1qaUPzdm/Atf3PaHre6XPsjyQM
+        2xLGV4XwIyX4QRj+UMK/lPFvJTyhBMeV8IgQvmRJuH4Ko+l5p9UjGBbCJ5RxTgj+VMZmXxKcSAjekHE/
+        NNs5DgaTKLinEQYVO4Trf1mkV81wixLUslPmA3bzF2XcKeP+hWY/u3n0fCXcrQwLyjAvjNsb1dI6N05P
+        mFAIHlHG73sEypPgGwnhfpn0zzH7jzddcK4Q7kqfKNMI4a9K+MwBDgbdeF04MBWsFYYdQvhbLlBvfhKT
+        f+vMtLfG7C0JJXxKGY67WnvCmPAFGRs7z42boul5AzHBfdK6TjdQtzPGk8oos5F/5Y7sfVvPhg+lp+1h
+        0yIsxARPmtaN78WEl8eEX+SNclxUhne0glUrNrN9zfMGlPAuZTzaQ99FYfwuDv3ruoLvq5bWaQSvZCfL
+        GXUYLwrj240Qxtu2lkSN4FpdWfKZH9jb9RQ1Cq62f9sVOlxUxn3KQXnJ0PO8QxU/jBm1h74v7ZniEG9K
+        Hdg/quzvXO709k0Y3u08ucGqWgheX862H4XgxbR47SqU8D1X0EXC2VmGizqDz0xPr0kYH9eO360gNe0b
+        jWppozB+1kOQEb5MCLa0C64NoeGrhOGrvH6lhK81GiIvnggmrDLzgvTkvwvDA+5wsU4nhG/m9AUoBD/F
+        HFzWN4H0XQn2vF8eXN8Z3FAPYasl59oUYjuB+sTImDB+nhfgYQ39STf4fmu1DHtz+oIUgiM1KkWtwcFw
+        sOujVT3hrnaL7UQc+hcL5W+sKIXhw0OVjaW0iwnBc47gqIQ45QY32PKRzv8eTguRYM9SS5YouEEZjv37
+        EffbzbjBDdZyxZYQ12EB2qS0bWrJqRVazPDWkojwZbuZrsgZtDJ0iY1g12khEtTicMTvclwn2CKE32YJ
+        7G5PORfZ1HtMCH7MOV4BrQ3XCe92+4onk5Nn2PolDAvWXnuOzAwzo6Nnx4Q3SrojwqfKeMxWMpsXWVs+
+        2WrfKRdbW1W6Hf0shM/33Y7my4PrleFZIfhAaWjU/e5ivlw+y3S2FySMtynjvcrwsFiLJv/RhPBB2ws1
+        hK2WcBLBFf1qawlplwvxaQlxe786OOU4PBWsjSO85mBlQ8n99r/BisSdAas4FfgHpdEUZpwUX7sAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/IProcess.cs b/LB_VisionProcesses/IProcess.cs
new file mode 100644
index 0000000..4aad660
--- /dev/null
+++ b/LB_VisionProcesses/IProcess.cs
@@ -0,0 +1,268 @@
+锘縰sing LB_VisionProcesses.Alogrithms;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses
+{
+    public abstract class IProcess : IDisposable, ICloneable
+    {
+        /// <summary>
+        /// 娴佺▼闆嗗悎锛堟寚鍚慞luginManager鐨勫凡鍔犺浇宸ュ叿锛�
+        /// </summary>
+        public static Dictionary<string, string> dicProcesses
+        {
+            get
+            {
+                // 寤惰繜鍒濆鍖栵紝纭繚PluginManager宸插姞杞�
+                if (!_initialized)
+                {
+                    InitializePluginManager();
+                }
+                return PluginManager.LoadedProcesses;
+            }
+        }
+
+        private static bool _initialized = false;
+
+        static IProcess()
+        {
+            // 寤惰繜鍒濆鍖朠luginManager
+            InitializePluginManager();
+
+            // 娉ㄥ唽鎻掍欢浜嬩欢
+            PluginManager.PluginLoaded += OnPluginLoaded;
+            PluginManager.PluginUnloaded += OnPluginUnloaded;
+
+            // 鍔犺浇鎵�鏈夋彃浠�
+            PluginManager.LoadAllPlugins();
+
+        }
+
+        /// <summary>
+        /// 鍒濆鍖栨彃浠剁鐞嗗櫒
+        /// </summary>
+        private static void InitializePluginManager()
+        {
+            if (!_initialized)
+            {
+                // 娉ㄥ唽鎻掍欢浜嬩欢
+                PluginManager.PluginLoaded += OnPluginLoaded;
+                PluginManager.PluginUnloaded += OnPluginUnloaded;
+
+                // 鍔犺浇鎵�鏈夋彃浠�
+                PluginManager.LoadAllPlugins();
+
+                _initialized = true;
+            }
+        }
+
+        private static void OnPluginLoaded(object sender, PluginEventArgs e)
+        {
+            Debug.WriteLine($"鎻掍欢鍔犺浇鎴愬姛: {e.PluginInfo.Name}, 鍖呭惈 {e.PluginInfo.Processes.Count} 涓伐鍏�");
+        }
+
+        private static void OnPluginUnloaded(object sender, PluginEventArgs e)
+        {
+            Debug.WriteLine($"鎻掍欢鍗歌浇鎴愬姛: {e.PluginInfo.Name}");
+        }
+
+        /// <summary>
+        /// 鍔ㄦ�佸垱寤哄伐鍏峰疄渚�
+        /// </summary>
+        public static IProcess CreateProcess(string displayName)
+        {
+            return PluginManager.CreateProcess(displayName);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎵�鏈夊伐鍏峰垎绫�
+        /// </summary>
+        public static List<string> GetCategories()
+        {
+            return PluginManager.GetCategories();
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎸囧畾鍒嗙被鐨勫伐鍏�
+        /// </summary>
+        public static Dictionary<string, string> GetProcessesByCategory(string category)
+        {
+            return PluginManager.GetProcessesByCategory(category);
+        }
+
+        /// <summary>
+        /// 閲嶆柊鍔犺浇鎵�鏈夋彃浠�
+        /// </summary>
+        public static void ReloadPlugins()
+        {
+            PluginManager.ReloadPlugins();
+        }
+
+
+        /// <summary>
+        /// 娴佺▼闆嗗悎
+        /// </summary>
+        public static ConcurrentDictionary<string, Fixture> dicFixtures = new ConcurrentDictionary<string, Fixture>();
+
+        /// <summary>
+        /// 鍏ㄥ眬鍙橀噺闆嗗悎(Key:鍙橀噺鍚嶏紝Value:鍙橀噺鍊�)
+        /// </summary>
+        public static ConcurrentDictionary<string, object> dicGlobalVars = new ConcurrentDictionary<string, object>();
+
+        /// <summary>
+        /// 杩愯鏃ュ織
+        /// </summary>
+        public string Msg = "杩愯鎴愬姛";
+
+        /// <summary>
+        /// 杩愯缁撴灉
+        /// </summary>
+        public bool Result = true;
+
+        /// <summary>
+        /// 杩愯鏃堕棿
+        /// </summary>
+        public double RunTime = 0;
+
+        /// <summary>
+        /// 鍏佽杩愯鏃堕棿
+        /// </summary>
+        public double MaxTimeOut = 2000;
+
+        /// <summary>
+        /// 宸ュ叿鍚嶇О
+        /// </summary>
+        public string strProcessName = string.Empty;
+
+        /// <summary>
+        /// 宸ュ叿绫诲悕
+        /// </summary>
+        public string strProcessClass = "LB_VisionProcesses.IProcess";
+
+        /// <summary>
+        /// 绠楁硶鍙傛暟
+        /// </summary>
+        public ProcessParams Params = new ProcessParams();
+
+        /// <summary>
+        /// 杈撳叆鍥剧墖
+        /// </summary>
+        public object InputImage;
+
+        /// <summary>
+        /// 杈撳嚭鍥剧墖
+        /// </summary>
+        public object OutputImage;
+
+        /// <summary>
+        /// 缁撴灉鍖哄煙
+        /// </summary>
+        public ObjectRecord Record = null;
+
+        /// <summary>
+        /// 杩愯瀹屾垚鏍囪
+        /// </summary>
+        public bool bCompleted = false;
+
+        public abstract void InitRunParams();
+
+        public abstract bool Run();
+
+        public abstract bool Load(string fullPath);
+
+        public abstract bool Save(string filePath);
+
+        public static Assembly GetExecutingAssembly()
+        {
+            return Assembly.GetExecutingAssembly();
+        }
+
+        public abstract object Clone();
+
+        public abstract void Dispose();
+    }
+
+
+    [Serializable]
+    public class Fixture
+    {
+        /// <summary>
+        /// 妯潗鏍嘪
+        /// </summary>
+        public double X = 0;
+        public double Column
+        {
+            get { return X; }
+            set { X = value; }
+        }
+
+        /// <summary>
+        /// 绾靛潗鏍嘫
+        /// </summary>
+        public double Y = 0;
+        public double Row
+        {
+            get { return Y; }
+            set { Y = value; }
+        }
+
+        /// <summary>
+        /// 寮у害Phi
+        /// </summary>
+        public double Phi = 0;
+        public double Angle
+        {
+            get { return Phi / Math.PI * 180; }
+            set { Phi = value / 180 * Math.PI; }
+        }
+
+        public string strName = "";
+
+        public Fixture() { }
+
+        [JsonConstructor]  // 鏍囪涓虹敤浜庡弽搴忓垪鍖�
+        public Fixture(double x, double y, double phi, string strName)
+        {
+            this.X = x; this.Y = y; this.Phi = phi;
+            this.strName = strName;
+        }
+
+        public Fixture(Fixture fixture)
+        {
+            if (fixture == null)
+                return;
+            this.X = fixture.X; this.Y = fixture.Y; this.Phi = fixture.Phi;
+            this.strName = fixture.strName;
+        }
+
+        public Fixture(string strName) => this.strName = strName;
+
+        public void GetOffset(double x, double y, double phi, out double offsetX, out double offsetY, out double offsetPhi)
+        {
+            offsetX = X - x; offsetY = Y - y; offsetPhi = Phi - phi;
+        }
+
+        public object Clone()
+        {
+            return MemberwiseClone();
+        }
+    }
+
+    public class NaturalStringComparer : IComparer<string>
+    {
+        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
+        public static extern int StrCmpLogicalW(string psz1, string psz2);
+        public int Compare(string x, string y)
+        {
+            return StrCmpLogicalW(x, y);
+        }
+    }
+}
diff --git a/LB_VisionProcesses/LB_VisionProcesses.csproj b/LB_VisionProcesses/LB_VisionProcesses.csproj
new file mode 100644
index 0000000..0ae546d
--- /dev/null
+++ b/LB_VisionProcesses/LB_VisionProcesses.csproj
@@ -0,0 +1,67 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Library</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <Nullable>enable</Nullable>
+    <UseWindowsForms>true</UseWindowsForms>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+    <ApplicationIcon>logo.ico</ApplicationIcon>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Content Include="logo.ico" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="MessagePack" Version="3.1.4" />
+    <PackageReference Include="Microsoft.CodeAnalysis.Common" Version="5.0.0" />
+    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
+    <PackageReference Include="Microsoft.Windows.Compatibility" Version="10.0.1" />
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
+    <PackageReference Include="RJCP.SerialPortStream" Version="3.0.4" />
+    <PackageReference Include="S7netplus" Version="0.20.0" />
+    <PackageReference Include="ZXing.Net" Version="0.16.11" />
+    <PackageReference Include="ZXing.Net.Bindings.Windows.Compatibility" Version="0.16.14" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Reference Include="halcondotnet">
+      <HintPath>ref\halcondotnet.dll</HintPath>
+    </Reference>
+    <Reference Include="MVSDK_Net">
+      <HintPath>ref\MVSDK_Net.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="Alogrithms\VisualLargeModel\" />
+    <Folder Include="Cameras\HRCameras\" />
+    <Folder Include="Cameras\LBCameras\" />
+    <Folder Include="Communicators\SiemensS7\" />
+    <Folder Include="Communicators\MES\" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\LB_SmartVisionCameraDevice\LB_SmartVisionCameraDevice.csproj" />
+    <ProjectReference Include="..\LB_SmartVisionCommon\LB_SmartVisionCommon.csproj" />
+    <ProjectReference Include="..\LB_VisionControl\LB_VisionControl.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Update="Properties\Resources.Designer.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <EmbeddedResource Update="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+
+</Project>
\ No newline at end of file
diff --git a/LB_VisionProcesses/MainForm.Designer.cs b/LB_VisionProcesses/MainForm.Designer.cs
new file mode 100644
index 0000000..051f6f8
--- /dev/null
+++ b/LB_VisionProcesses/MainForm.Designer.cs
@@ -0,0 +1,72 @@
+锘縩amespace LB_VisionProcesses
+{
+    partial class MainForm
+    {
+        /// <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()
+        {
+            btn_Camera = new Button();
+            btn_Com = new Button();
+            SuspendLayout();
+            // 
+            // btn_Camera
+            // 
+            btn_Camera.Location = new Point(12, 12);
+            btn_Camera.Name = "btn_Camera";
+            btn_Camera.Size = new Size(75, 23);
+            btn_Camera.TabIndex = 0;
+            btn_Camera.Text = "Cameras";
+            btn_Camera.UseVisualStyleBackColor = true;
+            btn_Camera.Click += btn_Camera_Click;
+            // 
+            // btn_Com
+            // 
+            btn_Com.Location = new Point(12, 41);
+            btn_Com.Name = "btn_Com";
+            btn_Com.Size = new Size(162, 23);
+            btn_Com.TabIndex = 1;
+            btn_Com.Text = "Communicators";
+            btn_Com.UseVisualStyleBackColor = true;
+            btn_Com.Click += btn_Com_Click;
+            // 
+            // MainForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(421, 236);
+            Controls.Add(btn_Com);
+            Controls.Add(btn_Camera);
+            Name = "MainForm";
+            Text = "MainForm";
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private Button btn_Camera;
+        private Button btn_Com;
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionProcesses/MainForm.cs b/LB_VisionProcesses/MainForm.cs
new file mode 100644
index 0000000..2b5a8bd
--- /dev/null
+++ b/LB_VisionProcesses/MainForm.cs
@@ -0,0 +1,34 @@
+锘縰sing LB_VisionProcesses.Cameras;
+using LB_VisionProcesses.Communicators;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_VisionProcesses
+{
+    public partial class MainForm : Form
+    {
+        public MainForm()
+        {
+            InitializeComponent();
+        }
+
+        private void btn_Camera_Click(object sender, EventArgs e)
+        {
+            CameraForm cameraForm = new CameraForm();
+            cameraForm.Show();
+        }
+
+        private void btn_Com_Click(object sender, EventArgs e)
+        {
+            CommunicatorForm communicatorForm = new CommunicatorForm();
+            communicatorForm.Show();
+        }
+    }
+}
diff --git a/LB_VisionProcesses/MainForm.resx b/LB_VisionProcesses/MainForm.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/LB_VisionProcesses/MainForm.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/LB_VisionProcesses/PluginInfo.cs b/LB_VisionProcesses/PluginInfo.cs
new file mode 100644
index 0000000..71fd941
--- /dev/null
+++ b/LB_VisionProcesses/PluginInfo.cs
@@ -0,0 +1,45 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses
+{
+    /// <summary>
+    /// 鎻掍欢淇℃伅
+    /// </summary>
+    public class PluginInfo
+    {
+        public string Name { get; set; }
+        public string AssemblyPath { get; set; }
+        public string Version { get; set; }
+        public DateTime LoadedTime { get; set; }
+        public Dictionary<string, ProcessInfo> Processes { get; } = new Dictionary<string, ProcessInfo>();
+    }
+
+    /// <summary>
+    /// 鎻掍欢閰嶇疆
+    /// </summary>
+    public class PluginConfig
+    {
+        public string Name { get; set; }
+        public string AssemblyName { get; set; }
+        public bool Enabled { get; set; } = true;
+        public string Description { get; set; }
+    }
+
+    /// <summary>
+    /// 鎻掍欢浜嬩欢鍙傛暟
+    /// </summary>
+    public class PluginEventArgs : EventArgs
+    {
+        public PluginInfo PluginInfo { get; }
+
+        public PluginEventArgs(PluginInfo pluginInfo)
+        {
+            PluginInfo = pluginInfo;
+        }
+    }
+
+}
diff --git a/LB_VisionProcesses/PluginLoadContext.cs b/LB_VisionProcesses/PluginLoadContext.cs
new file mode 100644
index 0000000..29785d0
--- /dev/null
+++ b/LB_VisionProcesses/PluginLoadContext.cs
@@ -0,0 +1,46 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.Loader;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses
+{
+    /// <summary>
+    /// 鑷畾涔夌▼搴忛泦鍔犺浇涓婁笅鏂囷紝鏀寔鍗歌浇
+    /// </summary>
+    public class PluginLoadContext : AssemblyLoadContext
+    {
+        private readonly AssemblyDependencyResolver _resolver;
+
+        public PluginLoadContext(string pluginPath) : base(isCollectible: true)
+        {
+            _resolver = new AssemblyDependencyResolver(pluginPath);
+        }
+
+        protected override Assembly Load(AssemblyName assemblyName)
+        {
+            // 灏濊瘯瑙f瀽渚濊禆
+            var assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
+            if (assemblyPath != null)
+            {
+                return LoadFromAssemblyPath(assemblyPath);
+            }
+
+            return null;
+        }
+
+        protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
+        {
+            var libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
+            if (libraryPath != null)
+            {
+                return LoadUnmanagedDllFromPath(libraryPath);
+            }
+
+            return IntPtr.Zero;
+        }
+    }
+}
diff --git a/LB_VisionProcesses/PluginManager.cs b/LB_VisionProcesses/PluginManager.cs
new file mode 100644
index 0000000..1cfbbd3
--- /dev/null
+++ b/LB_VisionProcesses/PluginManager.cs
@@ -0,0 +1,432 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.Loader;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses
+{
+    public class PluginManager
+    {
+        private static readonly List<Assembly> _loadedAssemblies = new List<Assembly>();
+        private static readonly Dictionary<string, AssemblyLoadContext> _loadContexts =
+            new Dictionary<string, AssemblyLoadContext>();
+        private static readonly object _lock = new object();
+
+        /// <summary>
+        /// 宸插姞杞界殑宸ュ叿瀛楀吀锛堥敭锛氭樉绀哄悕绉帮紝鍊硷細绫诲瀷瀹屽叏闄愬畾鍚嶏級
+        /// </summary>
+        public static Dictionary<string, string> LoadedProcesses { get; } = new Dictionary<string, string>();
+
+        /// <summary>
+        /// 鎸夊垎绫荤粍缁囩殑宸ュ叿
+        /// </summary>
+        public static Dictionary<string, Dictionary<string, string>> CategorizedProcesses { get; } =
+            new Dictionary<string, Dictionary<string, string>>();
+
+        /// <summary>
+        /// 鎻掍欢淇℃伅
+        /// </summary>
+        public static List<PluginInfo> PluginInfos { get; } = new List<PluginInfo>();
+
+        /// <summary>
+        /// 鎻掍欢鐩綍璺緞
+        /// </summary>
+        public static string PluginDirectory { get; set; } = "Plugins";
+
+        /// <summary>
+        /// 鎻掍欢鍔犺浇浜嬩欢
+        /// </summary>
+        public static event EventHandler<PluginEventArgs> PluginLoaded;
+        public static event EventHandler<PluginEventArgs> PluginUnloaded;
+
+        static PluginManager()
+        {
+            // 纭繚鎻掍欢鐩綍瀛樺湪
+            if (!Directory.Exists(PluginDirectory))
+            {
+                Directory.CreateDirectory(PluginDirectory);
+            }
+        }
+
+        /// <summary>
+        /// 鍔犺浇鎵�鏈夋彃浠�
+        /// </summary>
+        public static void LoadAllPlugins()
+        {
+            lock (_lock)
+            {
+                ClearLoadedAssemblies();
+
+                // 鍔犺浇涓荤▼搴忛泦鐨勫伐鍏�
+                ScanAssemblyForProcesses(Assembly.GetExecutingAssembly(), "LB_VisionProcesses");
+
+                // 鍔犺浇鎻掍欢鐩綍鐨凞LL
+                LoadAssembliesFromDirectory(PluginDirectory);
+
+                // 鍔犺浇閰嶇疆鏂囦欢鎸囧畾鐨勬彃浠�
+                LoadFromConfig();
+            }
+        }
+
+        /// <summary>
+        /// 鍔犺浇鎸囧畾绋嬪簭闆�
+        /// </summary>
+        public static bool LoadAssembly(string assemblyPath, string pluginName = null)
+        {
+            lock (_lock)
+            {
+                try
+                {
+                    if (!File.Exists(assemblyPath))
+                    {
+                        Debug.WriteLine($"绋嬪簭闆嗘枃浠朵笉瀛樺湪: {assemblyPath}");
+                        return false;
+                    }
+
+                    // 妫�鏌ユ槸鍚﹀凡鍔犺浇
+                    var fileName = Path.GetFileName(assemblyPath);
+                    if (_loadContexts.ContainsKey(fileName))
+                    {
+                        Debug.WriteLine($"绋嬪簭闆嗗凡鍔犺浇: {fileName}");
+                        return false;
+                    }
+
+                    // 鍒涘缓闅旂鐨勫姞杞戒笂涓嬫枃
+                    var context = new PluginLoadContext(assemblyPath);
+                    var assembly = context.LoadFromAssemblyPath(assemblyPath);
+
+                    _loadedAssemblies.Add(assembly);
+                    _loadContexts[fileName] = context;
+
+                    // 鎵弿宸ュ叿绫�
+                    var pluginInfo = ScanAssemblyForProcesses(assembly, pluginName ?? Path.GetFileNameWithoutExtension(assemblyPath));
+                    PluginInfos.Add(pluginInfo);
+
+                    // 瑙﹀彂浜嬩欢
+                    PluginLoaded?.Invoke(null, new PluginEventArgs(pluginInfo));
+
+                    return true;
+                }
+                catch (Exception ex)
+                {
+                    Debug.WriteLine($"鍔犺浇绋嬪簭闆嗗け璐�: {assemblyPath}, 閿欒: {ex.Message}");
+                    return false;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鍔犺浇鎸囧畾鐩綍涓嬫墍鏈塂LL
+        /// </summary>
+        public static void LoadAssembliesFromDirectory(string directoryPath)
+        {
+            if (!Directory.Exists(directoryPath))
+            {
+                Debug.WriteLine($"鎻掍欢鐩綍涓嶅瓨鍦�: {directoryPath}");
+                return;
+            }
+
+            // 鍔犺浇涓籇LL
+            var dllFiles = Directory.GetFiles(directoryPath, "*.dll")
+                .Where(f => !f.EndsWith(".resources.dll") &&
+                           !f.Contains("\\ref\\") &&
+                           !Path.GetFileName(f).StartsWith("System.") &&
+                           !Path.GetFileName(f).StartsWith("Microsoft."))
+                .ToList();
+
+            // 鍏堝姞杞芥病鏈変緷璧栫殑锛屽啀鍔犺浇鍙兘鏈変緷璧栫殑
+            var orderedFiles = dllFiles.OrderBy(f =>
+                File.ReadAllBytes(f).Length).ToList(); // 鎸夋枃浠跺ぇ灏忔帓搴忥紝灏忕殑鍏堝姞杞�
+
+            foreach (var dllFile in orderedFiles)
+            {
+                try
+                {
+                    LoadAssembly(dllFile);
+                }
+                catch (Exception ex)
+                {
+                    Debug.WriteLine($"鍔犺浇DLL澶辫触: {dllFile}, 閿欒: {ex.Message}");
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鍗歌浇鎸囧畾鎻掍欢
+        /// </summary>
+        public static bool UnloadPlugin(string pluginName)
+        {
+            lock (_lock)
+            {
+                var pluginInfo = PluginInfos.FirstOrDefault(p => p.Name == pluginName);
+                if (pluginInfo == null)
+                    return false;
+
+                try
+                {
+                    // 浠庡伐鍏峰瓧鍏镐腑绉婚櫎
+                    foreach (var process in pluginInfo.Processes)
+                    {
+                        LoadedProcesses.Remove(process.Key);
+
+                        // 浠庡垎绫诲瓧鍏镐腑绉婚櫎
+                        if (CategorizedProcesses.ContainsKey(process.Value.Category))
+                        {
+                            CategorizedProcesses[process.Value.Category].Remove(process.Key);
+                        }
+                    }
+
+                    // 瑙﹀彂浜嬩欢
+                    PluginUnloaded?.Invoke(null, new PluginEventArgs(pluginInfo));
+
+                    // 浠庡垪琛ㄤ腑绉婚櫎
+                    PluginInfos.Remove(pluginInfo);
+
+                    // 灏濊瘯鍗歌浇绋嬪簭闆嗭紙闇�瑕�.NET Core 3.0+锛�
+                    var fileName = Path.GetFileName(pluginInfo.AssemblyPath);
+                    if (_loadContexts.TryGetValue(fileName, out var context))
+                    {
+                        _loadContexts.Remove(fileName);
+                        if (context.IsCollectible)
+                        {
+                            context.Unload();
+                        }
+                    }
+
+                    return true;
+                }
+                catch (Exception ex)
+                {
+                    Debug.WriteLine($"鍗歌浇鎻掍欢澶辫触: {pluginName}, 閿欒: {ex.Message}");
+                    return false;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鎵弿绋嬪簭闆嗕腑鐨勫伐鍏风被
+        /// </summary>
+        private static PluginInfo ScanAssemblyForProcesses(Assembly assembly, string pluginName)
+        {
+            var pluginInfo = new PluginInfo
+            {
+                Name = pluginName,
+                AssemblyPath = assembly.Location,
+                Version = assembly.GetName().Version?.ToString() ?? "1.0.0",
+                LoadedTime = DateTime.Now
+            };
+
+            try
+            {
+                var processTypes = assembly.GetTypes()
+                    .Where(t => t.IsClass && !t.IsAbstract &&
+                               typeof(IProcess).IsAssignableFrom(t))
+                    .ToList();
+                foreach (var type in processTypes)
+                {
+                    try
+                    {
+                        if (type.IsDefined(typeof(ProcessAttribute), false) || type.IsDefined(typeof(CategoryAttribute), false))
+                        {
+                            // 浣跨敤鐗规�ц幏鍙栧厓鏁版嵁锛岄伩鍏嶅疄渚嬪寲
+                            var processAttr = type.GetCustomAttribute<ProcessAttribute>();
+                            var categoryAttr = type.GetCustomAttribute<CategoryAttribute>();
+
+                            string displayName;
+                            string category = "鍏朵粬";
+                            string description = "";
+                            int order = 0;
+
+                            if (processAttr != null)
+                            {
+                                displayName = processAttr.DisplayName;
+                                category = processAttr.Category;
+                                description = processAttr.Description;
+                                order = processAttr.Order;
+                            }
+                            else
+                            {
+                                // 濡傛灉娌℃湁鐗规�э紝浣跨敤绫诲瀷鍚嶇О
+                                displayName = type.Name;
+                            }
+
+                            if (categoryAttr != null)
+                            {
+                                category = categoryAttr.Category;
+                            }
+
+                            // 閬垮厤閲嶅鍚嶇О
+                            int suffix = 1;
+                            string originalName = displayName;
+                            while (LoadedProcesses.ContainsKey(displayName))
+                            {
+                                displayName = $"{originalName}_{suffix}";
+                                suffix++;
+                            }
+
+                            string fullName = type.AssemblyQualifiedName;
+
+                            // 娣诲姞鍒版�诲瓧鍏�
+                            LoadedProcesses[displayName] = fullName;
+
+                            // 鎸夊垎绫荤粍缁�
+                            if (!CategorizedProcesses.ContainsKey(category))
+                            {
+                                CategorizedProcesses[category] = new Dictionary<string, string>();
+                            }
+                            CategorizedProcesses[category][displayName] = fullName;
+
+                            // 娣诲姞鍒版彃浠朵俊鎭�
+                            pluginInfo.Processes[displayName] = new ProcessInfo
+                            {
+                                TypeName = fullName,
+                                DisplayName = displayName,
+                                Category = category,
+                                Description = description,
+                                Order = order
+                            };
+
+                            Debug.WriteLine($"娉ㄥ唽宸ュ叿: {displayName} ({category})");
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        Debug.WriteLine($"娉ㄥ唽宸ュ叿绫诲瀷 {type.Name} 澶辫触: {ex.Message}");
+                    }
+                }
+            }
+            catch (ReflectionTypeLoadException ex)
+            {
+                Debug.WriteLine($"鎵弿绋嬪簭闆� {assembly.FullName} 鏃剁被鍨嬪姞杞藉け璐�: {ex.Message}");
+                foreach (var loaderEx in ex.LoaderExceptions)
+                {
+                    Debug.WriteLine($"鍔犺浇寮傚父: {loaderEx?.Message}");
+                }
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine($"鎵弿绋嬪簭闆� {assembly.FullName} 澶辫触: {ex.Message}");
+            }
+
+            return pluginInfo;
+        }
+
+        /// <summary>
+        /// 浠庨厤缃枃浠跺姞杞芥彃浠�
+        /// </summary>
+        private static void LoadFromConfig()
+        {
+            var configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugin.config.json");
+            if (File.Exists(configPath))
+            {
+                try
+                {
+                    var config = File.ReadAllText(configPath);
+                    var pluginConfigs = JsonConvert.DeserializeObject<List<PluginConfig>>(config);
+
+                    foreach (var pluginConfig in pluginConfigs)
+                    {
+                        if (pluginConfig.Enabled)
+                        {
+                            var pluginPath = Path.Combine(PluginDirectory, pluginConfig.AssemblyName);
+                            LoadAssembly(pluginPath, pluginConfig.Name);
+                        }
+                    }
+                }
+                catch (Exception ex)
+                {
+                    Debug.WriteLine($"璇诲彇鎻掍欢閰嶇疆澶辫触: {ex.Message}");
+                }
+            }
+        }
+
+        /// <summary>
+        /// 娓呯┖宸插姞杞界殑绋嬪簭闆�
+        /// </summary>
+        private static void ClearLoadedAssemblies()
+        {
+            lock (_lock)
+            {
+                _loadedAssemblies.Clear();
+                _loadContexts.Clear();
+                LoadedProcesses.Clear();
+                CategorizedProcesses.Clear();
+                PluginInfos.Clear();
+            }
+        }
+
+        /// <summary>
+        /// 閲嶆柊鍔犺浇鎵�鏈夋彃浠�
+        /// </summary>
+        public static void ReloadPlugins()
+        {
+            lock (_lock)
+            {
+                ClearLoadedAssemblies();
+                LoadAllPlugins();
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎵�鏈夊垎绫�
+        /// </summary>
+        public static List<string> GetCategories()
+        {
+            return CategorizedProcesses.Keys.OrderBy(k => k).ToList();
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎸囧畾鍒嗙被鐨勫伐鍏�
+        /// </summary>
+        public static Dictionary<string, string> GetProcessesByCategory(string category)
+        {
+            return CategorizedProcesses.ContainsKey(category)
+                ? CategorizedProcesses[category]
+                : new Dictionary<string, string>();
+        }
+
+        /// <summary>
+        /// 鍒涘缓宸ュ叿瀹炰緥
+        /// </summary>
+        public static IProcess CreateProcess(string displayName)
+        {
+            lock (_lock)
+            {
+                if (!LoadedProcesses.TryGetValue(displayName, out string typeName))
+                {
+                    throw new KeyNotFoundException($"鏈壘鍒板伐鍏�: {displayName}");
+                }
+
+                try
+                {
+                    var type = Type.GetType(typeName);
+                    if (type == null)
+                    {
+                        // 灏濊瘯浠庡凡鍔犺浇鐨勭▼搴忛泦涓煡鎵�
+                        foreach (var assembly in _loadedAssemblies)
+                        {
+                            type = assembly.GetType(typeName.Split(',')[0]);
+                            if (type != null) break;
+                        }
+                    }
+
+                    if (type == null)
+                    {
+                        throw new TypeLoadException($"鏃犳硶鍔犺浇绫诲瀷: {typeName}");
+                    }
+
+                    return Activator.CreateInstance(type) as IProcess;
+                }
+                catch (Exception ex)
+                {
+                    throw new ApplicationException($"鍒涘缓宸ュ叿瀹炰緥澶辫触: {displayName}", ex);
+                }
+            }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/ProcessAttribute.cs b/LB_VisionProcesses/ProcessAttribute.cs
new file mode 100644
index 0000000..ed2ce02
--- /dev/null
+++ b/LB_VisionProcesses/ProcessAttribute.cs
@@ -0,0 +1,40 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses
+{
+    // 鑷畾涔夌壒鎬х敤浜庢爣璁板伐鍏风被
+    /// <summary>
+    /// 宸ュ叿鐗规��
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Class)]
+    public class ProcessAttribute : Attribute
+    {
+        public string DisplayName { get; }
+        public string Category { get; set; } = "閫氱敤";
+        public string Description { get; set; } = "";
+        public int Order { get; set; } = 0;
+
+        public ProcessAttribute(string displayName)
+        {
+            DisplayName = displayName;
+        }
+    }
+
+    /// <summary>
+    /// 鍒嗙被鐗规��
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Class)]
+    public class CategoryAttribute : Attribute
+    {
+        public string Category { get; }
+
+        public CategoryAttribute(string category)
+        {
+            Category = category;
+        }
+    }
+}
diff --git a/LB_VisionProcesses/ProcessCollections.cs b/LB_VisionProcesses/ProcessCollections.cs
new file mode 100644
index 0000000..93451aa
--- /dev/null
+++ b/LB_VisionProcesses/ProcessCollections.cs
@@ -0,0 +1,324 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses
+{
+    [Serializable]
+    public class ProcessCollections<T> : ICollection<ProcessCollectionItem<T>>
+    {
+        private readonly object _lock = new object(); // 绾跨▼瀹夊叏閿�
+        private List<ProcessCollectionItem<T>> _items = new List<ProcessCollectionItem<T>>();
+
+        // 閫氳繃鍚嶇О鏌ユ壘
+        public ProcessCollectionItem<T> Get(string name)
+        {
+            lock (_lock)
+            {
+                var item = _items.FirstOrDefault(item => item.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
+                if (item == null)
+                {
+                    //// 濡傛灉涓嶅瓨鍦紝鍒涘缓鏂伴」骞跺垎閰嶇储寮�
+                    //_items.Add(item);
+                    return default;
+                }
+                return item;
+            }
+        }
+
+        // 閫氳繃绱㈠紩鏌ユ壘
+        public ProcessCollectionItem<T> Get(int index)
+        {
+            lock (_lock)
+            {
+                var item = _items.FirstOrDefault(item => item.Index == index);
+                if (item == null)
+                {
+                    // 濡傛灉涓嶅瓨鍦紝鍒涘缓鏂伴」骞跺垎閰嶇储寮�
+                    _items.Add(item);
+                    return default;
+                }
+                return item;
+            }
+        }
+
+        public Dictionary<string, object> GetAllByName()
+        {
+            try
+            {
+                Dictionary<string, object> dic = new Dictionary<string, object>();
+
+                for (int i = 0; i <= _items.Count - 1; i++)
+                    dic.TryAdd(_items[i].Name, _items[i].Value);
+
+                return dic;
+            }
+            catch { return new Dictionary<string, object>(); }
+        }
+
+        public List<object> GetAllByIndex()
+        {
+            try
+            {
+                List<object> list = new List<object>();
+
+                for (int i = 0; i <= _items.Count - 1; i++)
+                    list.Add(_items[i].Value);
+
+                return list;
+            }
+            catch { return new List<object>(); }
+        }
+
+        // ICollection<NamedItem<T>> 瀹炵幇
+        public int Count => _items.Count;
+
+        public bool IsReadOnly => false;
+
+        void ICollection<ProcessCollectionItem<T>>.Add(ProcessCollectionItem<T> item)
+        {
+            lock (_lock)
+            {
+                var existingItem = Get(item.Name);
+
+                if (existingItem != null)
+                {
+                    // 濡傛灉宸插瓨鍦紝鏇存柊鐜版湁椤圭殑鍊�
+                    existingItem = item;
+                }
+                else
+                {
+                    // 濡傛灉涓嶅瓨鍦紝鍒涘缓鏂伴」骞跺垎閰嶇储寮�
+                    _items.Add(item);
+                }
+
+                // 鏇存柊鍚庤嚜鍔ㄦ帓搴�
+                SortItems();
+            }
+
+        }
+        // 娣诲姞椤规椂涓烘柊椤瑰垎閰嶄竴涓储寮�
+        public void Add(string name, T value)
+        {
+            lock (_lock)
+            {
+                var existingItem = Get(name);
+
+                if (existingItem != null)
+                {
+                    // 濡傛灉宸插瓨鍦紝鏇存柊鐜版湁椤圭殑鍊�
+                    existingItem.Value = value;
+                }
+                else
+                {
+                    // 濡傛灉涓嶅瓨鍦紝鍒涘缓鏂伴」骞跺垎閰嶇储寮�
+                    var newItem = new ProcessCollectionItem<T>(name, _items.Count > 0 ? _items.Max(i => i.Index) + 1 : 0, value);
+                    _items.Add(newItem);
+                }
+
+                // 鏇存柊鍚庤嚜鍔ㄦ帓搴�
+                SortItems();
+            }
+        }
+        // 鎸� Index 鎺掑簭闆嗗悎
+        private void SortItems()
+        {
+            lock (_lock)
+            {
+                _items = _items.OrderBy(item => item.Index).ToList();
+            }
+        }
+
+        // 閫氳繃绱㈠紩鍣ㄥ疄鐜板熀浜庡簭鍙风殑璁块棶
+        public T this[int index]
+        {
+            get
+            {
+                if (index < 0 || index >= _items.Count)
+                {
+                    return default;
+                }
+                return _items[index].Value;
+            }
+            set
+            {
+                lock (_lock)
+                {
+                    if (index < 0 || index >= _items.Count)
+                    {
+                        return;
+                    }
+                    _items[index].Value = value;
+                }
+            }
+        }
+
+        public T this[string name]
+        {
+            get
+            {
+                var existingItem = Get(name);
+                if (existingItem != null)
+                {
+                    // 濡傛灉宸插瓨鍦紝鏇存柊鐜版湁椤圭殑鍊�
+                    return existingItem.Value;
+                }
+                return default;
+            }
+            set
+            {
+                lock (_lock)
+                {
+                    var item = _items.FirstOrDefault(i => i.Name == name);
+                    if (item != null)
+                    {
+                        item.Value = value;
+                    }
+                }
+            }
+        }
+
+        public void Clear()
+        {
+            lock (_lock)
+            {
+                _items.Clear();
+                _items.TrimExcess(); // 灏嗗閲忕缉鍑忓埌瀹為檯鍏冪礌鏁伴噺
+            }
+        }
+
+        public bool Contains(ProcessCollectionItem<T> item)
+        {
+            return _items.Contains(item);
+        }
+
+        public bool Contains(string name)
+        {
+            var item = _items.FirstOrDefault(i => i.Name == name);
+            if (item != null)
+                return true;
+
+            return false;
+        }
+
+        public bool ContainsKey(string name)
+        {
+            var item = _items.FirstOrDefault(i => i.Name == name);
+            if (item != null)
+                return true;
+
+            return false;
+        }
+
+        public bool GetKey(int index, out string name)
+        {
+            if (index < 0 || index >= _items.Count)
+            {
+                name = null;
+                return false;
+            }
+            name = _items[index].Name;
+            return true;
+        }
+
+        public void CopyTo(ProcessCollectionItem<T>[] array, int arrayIndex)
+        {
+            lock (_lock)
+            {
+                _items.CopyTo(array, arrayIndex);
+            }
+        }
+
+        public bool Remove(ProcessCollectionItem<T> item)
+        {
+            lock (_lock)
+            {
+                var removed = _items.Remove(item);
+                if (removed)
+                {
+                    // 绉婚櫎鍏冪礌鍚庯紝璋冩暣鍚庣画鍏冪礌鐨勭储寮�
+                    UpdateIndexes();
+                }
+                return removed;
+            }
+        }
+
+        public IEnumerator<ProcessCollectionItem<T>> GetEnumerator()
+        {
+            lock (_lock)
+            {
+                return _items.GetEnumerator();
+            }
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            lock (_lock)
+            {
+                return _items.GetEnumerator();
+            }
+        }
+
+        // 閫氳繃鍚嶇О鍒犻櫎
+        public bool Remove(string name)
+        {
+            lock (_lock)
+            {
+                var namedItem = Get(name);
+                if (namedItem != null)
+                {
+                    return Remove(namedItem);
+                }
+                return false;
+            }
+        }
+
+        // 閫氳繃绱㈠紩鍒犻櫎
+        public bool Remove(int index)
+        {
+            lock (_lock)
+            {
+                var namedItem = Get(index);
+                if (namedItem != null)
+                {
+                    return Remove(namedItem);
+                }
+                return false;
+            }
+        }
+
+        // 鍒犻櫎椤瑰悗锛岃皟鏁村叾浠栭」鐨勭储寮�
+        private void UpdateIndexes()
+        {
+            lock (_lock)
+            {
+                for (int i = 0; i < _items.Count; i++)
+                {
+                    _items[i].Index = i;
+                }
+            }
+        }
+    }
+
+    public class ProcessCollectionItem<T>
+    {
+        public string Name { get; set; }
+        public int Index { get; set; }
+        public T Value { get; set; }       // 瀛樺偍鐨勫璞�
+
+        public ProcessCollectionItem(string name, int index, T value)
+        {
+            Name = name;
+            Index = index;
+            Value = value;
+        }
+
+        public override string ToString()
+        {
+            return $"{Name} (Index: {Index}, Value: {Value})";
+        }
+    }
+}
diff --git a/LB_VisionProcesses/ProcessEditForm.Designer.cs b/LB_VisionProcesses/ProcessEditForm.Designer.cs
new file mode 100644
index 0000000..6c30a1a
--- /dev/null
+++ b/LB_VisionProcesses/ProcessEditForm.Designer.cs
@@ -0,0 +1,109 @@
+锘縩amespace LB_VisionProcesses
+{
+    partial class ProcessEditForm
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProcessEditForm));
+            theme_AlgorithmForm = new ReaLTaiizor.Forms.ThemeForm();
+            pnl_ProcessEditForm = new ReaLTaiizor.Controls.Panel();
+            controlB_ProcessEditForm = new ReaLTaiizor.Controls.ControlBox();
+            theme_AlgorithmForm.SuspendLayout();
+            SuspendLayout();
+            // 
+            // theme_AlgorithmForm
+            // 
+            theme_AlgorithmForm.BackColor = Color.FromArgb(32, 41, 50);
+            theme_AlgorithmForm.Controls.Add(pnl_ProcessEditForm);
+            theme_AlgorithmForm.Controls.Add(controlB_ProcessEditForm);
+            theme_AlgorithmForm.Dock = DockStyle.Fill;
+            theme_AlgorithmForm.Font = new Font("Microsoft Sans Serif", 9F);
+            theme_AlgorithmForm.Image = (Image)resources.GetObject("theme_AlgorithmForm.Image");
+            theme_AlgorithmForm.Location = new Point(0, 0);
+            theme_AlgorithmForm.Name = "theme_AlgorithmForm";
+            theme_AlgorithmForm.Padding = new Padding(10, 70, 10, 9);
+            theme_AlgorithmForm.RoundCorners = true;
+            theme_AlgorithmForm.Sizable = true;
+            theme_AlgorithmForm.Size = new Size(944, 601);
+            theme_AlgorithmForm.SmartBounds = true;
+            theme_AlgorithmForm.StartPosition = FormStartPosition.WindowsDefaultLocation;
+            theme_AlgorithmForm.TabIndex = 0;
+            theme_AlgorithmForm.Text = "AlgorithmForm";
+            // 
+            // pnl_ProcessEditForm
+            // 
+            pnl_ProcessEditForm.BackColor = Color.FromArgb(39, 51, 63);
+            pnl_ProcessEditForm.Dock = DockStyle.Fill;
+            pnl_ProcessEditForm.EdgeColor = Color.FromArgb(32, 41, 50);
+            pnl_ProcessEditForm.Location = new Point(10, 70);
+            pnl_ProcessEditForm.Name = "pnl_ProcessEditForm";
+            pnl_ProcessEditForm.Padding = new Padding(5);
+            pnl_ProcessEditForm.Size = new Size(924, 522);
+            pnl_ProcessEditForm.SmoothingType = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
+            pnl_ProcessEditForm.TabIndex = 1;
+            // 
+            // controlB_ProcessEditForm
+            // 
+            controlB_ProcessEditForm.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+            controlB_ProcessEditForm.BackColor = Color.FromArgb(32, 34, 37);
+            controlB_ProcessEditForm.CloseHoverColor = Color.FromArgb(230, 17, 35);
+            controlB_ProcessEditForm.DefaultLocation = true;
+            controlB_ProcessEditForm.EnableHoverHighlight = true;
+            controlB_ProcessEditForm.EnableMaximizeButton = false;
+            controlB_ProcessEditForm.EnableMinimizeButton = false;
+            controlB_ProcessEditForm.ForeColor = Color.FromArgb(155, 155, 155);
+            controlB_ProcessEditForm.Location = new Point(844, 18);
+            controlB_ProcessEditForm.MaximizeHoverColor = Color.FromArgb(74, 74, 74);
+            controlB_ProcessEditForm.MinimizeHoverColor = Color.FromArgb(63, 63, 65);
+            controlB_ProcessEditForm.Name = "controlB_ProcessEditForm";
+            controlB_ProcessEditForm.Size = new Size(90, 25);
+            controlB_ProcessEditForm.TabIndex = 0;
+            // 
+            // ProcessEditForm
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(944, 601);
+            Controls.Add(theme_AlgorithmForm);
+            FormBorderStyle = FormBorderStyle.None;
+            MinimumSize = new Size(261, 61);
+            Name = "ProcessEditForm";
+            Text = "AlgorithmForm";
+            TransparencyKey = Color.Fuchsia;
+            FormClosing += ProcessEditForm_FormClosing;
+            Load += ProcessEditForm_Load;
+            theme_AlgorithmForm.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+        public TextBox textBox = new TextBox();
+        private ReaLTaiizor.Forms.ThemeForm theme_AlgorithmForm;
+        private ReaLTaiizor.Controls.Panel pnl_ProcessEditForm;
+        private ReaLTaiizor.Controls.ControlBox controlB_ProcessEditForm;
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionProcesses/ProcessEditForm.cs b/LB_VisionProcesses/ProcessEditForm.cs
new file mode 100644
index 0000000..9bb0a63
--- /dev/null
+++ b/LB_VisionProcesses/ProcessEditForm.cs
@@ -0,0 +1,159 @@
+锘縰sing LB_VisionProcesses.Alogrithms;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_VisionProcesses
+{
+    public partial class ProcessEditForm : Form
+    {
+        public UserControl userControl = new UserControl();
+        IProcess OriProcess = null;
+        string fullPath = string.Empty;
+        public bool hasChanged = false;
+
+        public ProcessEditForm(IProcess subject = null, string fullPath = "")
+        {
+            InitializeComponent();
+            this.fullPath = fullPath;
+            this.OriProcess = subject;
+        }
+
+        private void ProcessEditForm_Load(object sender, EventArgs e)
+        {
+            IProcess subject = OriProcess;
+            if (subject != null)
+            {
+                //鍒╃敤鍙嶅皠鍒涘缓瀹炰緥锛屽懡鍚嶈鑼冿細Tool+Edit锛屽懡鍚嶇┖闂翠篃瑕佺浉鍚�
+                string ClassName = subject.GetType().FullName + "Edit";
+                // 鑾峰彇缂栬緫鎺т欢绫诲瀷
+                Type type = Type.GetType(ClassName)
+                    ?? Assembly.GetExecutingAssembly().GetTypes()
+                              .FirstOrDefault(t => t.Name == ClassName);
+
+                if (type != null)
+                {
+                    // 浣跨敤Activator.CreateInstance甯﹀弬鏁板垱寤�
+                    userControl = (UserControl)Activator.CreateInstance(type, subject);
+
+                    if (userControl == null)
+                        return;
+                }
+                else if (File.Exists(fullPath))
+                {
+                    try
+                    {
+                        this.Text = Path.GetFileNameWithoutExtension(fullPath);
+                        this.fullPath = fullPath;
+                        // 璇诲彇 JSON 鏂囦欢鍐呭
+                        string jsonContent = this.Text;
+                        if (File.Exists(fullPath))
+                            jsonContent = File.ReadAllText(fullPath);
+
+                        // 鏄剧ず鍦� TextBox 涓�
+                        pnl_ProcessEditForm.Controls.Clear();
+                        pnl_ProcessEditForm.Controls.Add(this.textBox);
+                        this.textBox.Dock = DockStyle.Fill;
+                        this.textBox.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+                        this.textBox.Multiline = true;
+                        this.textBox.ScrollBars = ScrollBars.Both;
+                        this.textBox.Text = jsonContent;
+                    }
+                    catch { }
+                    return;
+                }
+                pnl_ProcessEditForm.Controls.Clear();
+                pnl_ProcessEditForm.Controls.Add(userControl);
+                userControl.Dock = DockStyle.Fill;
+                OriProcess = subject;
+                this.Text = subject.strProcessName;
+
+            }
+        }
+
+        private void ProcessEditForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(fullPath) || OriProcess == null)
+                {
+                    e.Cancel = false;  //纭鍏抽棴绐椾綋
+                    return;
+                }
+
+                DialogResult res = MessageBox.Show("鏄惁淇濆瓨锛�", "鎻愮ず", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);  //淇濆瓨缁撴灉淇℃伅
+                /// 鍙傛暟1锛氭樉绀烘枃鏈紝鍙傛暟2锛氭爣棰橈紝鍙傛暟3锛氭寜閿被鍨嬶紝鍙傛暟4锛氭樉绀哄浘鏍�
+                if (res != DialogResult.Yes && res != DialogResult.No)  //鍙栨秷
+                {
+                    e.Cancel = true;  //鍙栨秷鍏抽棴绐椾綋
+                    return;
+                }
+
+                if (res == DialogResult.Yes && OriProcess != null)  //淇濆瓨VPP
+                {
+                    //鍒╃敤鍙嶅皠鍒涘缓瀹炰緥锛屽懡鍚嶈鑼冿細Tool+Edit
+                    string ClassName = OriProcess.GetType().FullName + "Edit";
+                    // 鑾峰彇缂栬緫鎺т欢绫诲瀷
+                    Type type = Type.GetType(ClassName)
+                        ?? Assembly.GetExecutingAssembly().GetTypes()
+                                  .FirstOrDefault(t => t.Name == ClassName);
+
+                    if (type != null && userControl is TAlgorithmEdit)
+                    {
+                        ((TAlgorithmEdit)userControl).UpdataInputs();
+                        (((TAlgorithmEdit)userControl).Subject).Save(Path.GetDirectoryName(fullPath));
+                        OriProcess = ((TAlgorithmEdit)userControl).Subject;
+                    }
+                    else
+                    {
+                        //娌℃湁鎵惧埌瀵瑰簲鐨勭紪杈戞帶浠剁被鍨嬶紝鐩存帴淇濆瓨JSON
+                        // 鑾峰彇 TextBox 涓殑鍐呭
+                        string jsonContent = this.textBox.Text;
+                        if (!string.IsNullOrEmpty(jsonContent))
+                        {
+                            // 鏍¢獙 JSON 鏍煎紡鏄惁姝g‘
+                            var obj = JsonConvert.DeserializeObject(jsonContent);
+                            // 淇濆瓨鍒版枃浠讹紝瑕嗙洊鍘熸枃浠�
+                            File.WriteAllText(fullPath, jsonContent);
+                        }
+                    }
+
+                    hasChanged = true;
+                    e.Cancel = false;  //纭鍏抽棴绐椾綋
+                    return;
+                }
+
+                if (OriProcess != null)
+                {
+                    if (userControl is TAlgorithmEdit edit)
+                        edit.Dispose();
+
+                    OriProcess.Dispose();
+                }
+
+                e.Cancel = false;  //纭鍏抽棴绐椾綋
+                return;
+            }
+            catch { }
+            finally
+            {
+                if (OriProcess != null && !e.Cancel)
+                {
+                    userControl.Dispose();
+                    OriProcess.Dispose();
+                }
+            }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/ProcessEditForm.resx b/LB_VisionProcesses/ProcessEditForm.resx
new file mode 100644
index 0000000..ab9e96e
--- /dev/null
+++ b/LB_VisionProcesses/ProcessEditForm.resx
@@ -0,0 +1,144 @@
+锘�<?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>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="theme_AlgorithmForm.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        wQAADsEBuJFr7QAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
+        BkVBUPCBCEG8BXNQ48GLeImCehIJxMsqhsSZruod46K4HtSIGjU+4iOr0c1I9fSsM3/PLNtCPO0H36m/
+        evz/X11VnreKVRTAHPOZumkY6lFwqURws3BwZ8ywTQnuiCP/+iTCzY1qaUPzdm/Atf3PaHre6XPsjyQM
+        2xLGV4XwIyX4QRj+UMK/lPFvJTyhBMeV8IgQvmRJuH4Ko+l5p9UjGBbCJ5RxTgj+VMZmXxKcSAjekHE/
+        NNs5DgaTKLinEQYVO4Trf1mkV81wixLUslPmA3bzF2XcKeP+hWY/u3n0fCXcrQwLyjAvjNsb1dI6N05P
+        mFAIHlHG73sEypPgGwnhfpn0zzH7jzddcK4Q7kqfKNMI4a9K+MwBDgbdeF04MBWsFYYdQvhbLlBvfhKT
+        f+vMtLfG7C0JJXxKGY67WnvCmPAFGRs7z42boul5AzHBfdK6TjdQtzPGk8oos5F/5Y7sfVvPhg+lp+1h
+        0yIsxARPmtaN78WEl8eEX+SNclxUhne0glUrNrN9zfMGlPAuZTzaQ99FYfwuDv3ruoLvq5bWaQSvZCfL
+        GXUYLwrj240Qxtu2lkSN4FpdWfKZH9jb9RQ1Cq62f9sVOlxUxn3KQXnJ0PO8QxU/jBm1h74v7ZniEG9K
+        Hdg/quzvXO709k0Y3u08ucGqWgheX862H4XgxbR47SqU8D1X0EXC2VmGizqDz0xPr0kYH9eO360gNe0b
+        jWppozB+1kOQEb5MCLa0C64NoeGrhOGrvH6lhK81GiIvnggmrDLzgvTkvwvDA+5wsU4nhG/m9AUoBD/F
+        HFzWN4H0XQn2vF8eXN8Z3FAPYasl59oUYjuB+sTImDB+nhfgYQ39STf4fmu1DHtz+oIUgiM1KkWtwcFw
+        sOujVT3hrnaL7UQc+hcL5W+sKIXhw0OVjaW0iwnBc47gqIQ45QY32PKRzv8eTguRYM9SS5YouEEZjv37
+        EffbzbjBDdZyxZYQ12EB2qS0bWrJqRVazPDWkojwZbuZrsgZtDJ0iY1g12khEtTicMTvclwn2CKE32YJ
+        7G5PORfZ1HtMCH7MOV4BrQ3XCe92+4onk5Nn2PolDAvWXnuOzAwzo6Nnx4Q3SrojwqfKeMxWMpsXWVs+
+        2WrfKRdbW1W6Hf0shM/33Y7my4PrleFZIfhAaWjU/e5ivlw+y3S2FySMtynjvcrwsFiLJv/RhPBB2ws1
+        hK2WcBLBFf1qawlplwvxaQlxe786OOU4PBWsjSO85mBlQ8n99r/BisSdAas4FfgHpdEUZpwUX7sAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/ProcessInfo.cs b/LB_VisionProcesses/ProcessInfo.cs
new file mode 100644
index 0000000..5d722aa
--- /dev/null
+++ b/LB_VisionProcesses/ProcessInfo.cs
@@ -0,0 +1,21 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses
+{
+    /// <summary>
+    /// 宸ュ叿淇℃伅
+    /// </summary>
+    public class ProcessInfo
+    {
+        public string TypeName { get; set; }
+        public string DisplayName { get; set; }
+        public string Category { get; set; }
+        public string Description { get; set; }
+        public int Order { get; set; }
+    }
+
+}
diff --git a/LB_VisionProcesses/ProcessParams.cs b/LB_VisionProcesses/ProcessParams.cs
new file mode 100644
index 0000000..b01ceaf
--- /dev/null
+++ b/LB_VisionProcesses/ProcessParams.cs
@@ -0,0 +1,208 @@
+锘縰sing LB_VisionControl;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses
+{
+    [Serializable]
+    public class ProcessParams
+    {
+        /// <summary>
+        /// 杈撳叆闆嗗悎
+        /// </summary>
+        public ProcessCollections<object> Inputs = new ProcessCollections<object>();
+
+        /// <summary>
+        /// 杈撳嚭闆嗗悎
+        /// </summary>
+        public ProcessCollections<object> Outputs = new ProcessCollections<object>();
+
+        /// <summary>
+        /// 鎰熷叴瓒e尯鍩�
+        /// </summary>
+        [JsonConverter(typeof(ROIConverter))]  // 浣跨敤鑷畾涔夌殑 JSON 杞崲鍣�
+        public ROI ROI
+        {
+            get
+            {
+                return UpdataROI();
+            }
+            set
+            {
+                if (value == null)
+                {
+                    _kRoi.Item1 = RoiType.None;
+                    _kRoi.Item2 = new double[] { };
+                    return;
+                }
+
+                if (!(value is ROI))
+                    return;
+
+                Type type = value.GetType();
+
+                if (typeof(HRectangle2) == type)
+                {
+                    _kRoi.Item1 = RoiType.Rectangle2;
+                    _kRoi.Item2 = new double[] { value.X, value.Y
+                    , ((HRectangle2)value).Phi, ((HRectangle2)value).Width, ((HRectangle2)value).Height };
+
+                }
+                else if (typeof(HCircle) == type)
+                {
+                    _kRoi.Item1 = RoiType.Circle;
+                    _kRoi.Item2 = new double[] { value.X, value.Y, ((HCircle)value).Radius };
+                }
+                else if (typeof(HSegment) == type)
+                {
+                    _kRoi.Item1 = RoiType.Segment;
+                    _kRoi.Item2 = new double[] { ((HSegment)value).StartX, ((HSegment)value).StartY
+                        , ((HSegment)value).EndX, ((HSegment)value).EndY };
+                }
+                else
+                {
+                    _kRoi.Item1 = RoiType.None;
+                    _kRoi.Item2 = new double[] { };
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鍥哄畾璺熼殢绌洪棿
+        /// </summary>
+        public Fixture Fixture = new Fixture();
+
+        /// <summary>
+        /// ROI KEY
+        /// </summary>
+        private (RoiType, double[]) _kRoi = (RoiType.None, new double[] { });
+
+        /// <summary>
+        /// 鍒锋柊鎼滅储鍖哄煙
+        /// </summary>
+        private ROI UpdataROI()
+        {
+            if (_kRoi.Item1 == RoiType.Rectangle2)
+            {
+                double[] val = _kRoi.Item2 as double[];
+                return new HRectangle2(val[0], val[1], val[2], val[3], val[4]);
+            }
+            else if (_kRoi.Item1 == RoiType.Circle)
+            {
+                double[] val = _kRoi.Item2 as double[];
+                return new HCircle(val[0], val[1], val[2]);
+            }
+            else if (_kRoi.Item1 == RoiType.Segment)
+            {
+                double[] val = _kRoi.Item2 as double[];
+                return new HSegment(val[0], val[1], val[2], val[3]);
+            }
+            else
+            {
+                return new ROI();
+            }
+        }
+
+        public static string ConvertToString(object data)
+        {
+            try
+            {
+                if (data == null)
+                    return string.Empty;
+
+                Type type = data.GetType();
+                switch (type)
+                {
+                    case Type t when t == typeof(JArray):
+                        return string.Join(",", ((JArray)data).Cast<object>());
+                    case Type t when t == typeof(List<int>):
+                        return string.Join(",", (List<int>)data);
+                    case Type t when t == typeof(List<double>):
+                        return string.Join(",", ((List<double>)data).Select(x => x.ToString("F4")));
+                    case Type t when t == typeof(List<string>):
+                        return string.Join(",", (List<string>)data);
+                    case Type t when t == typeof(List<object>):
+                        return string.Join(",", (List<object>)data);
+                    default:
+                        //throw new ArgumentException("Unsupported data type");
+                        return data?.ToString();
+                }
+            }
+            catch { return string.Empty; }
+        }
+
+        public static int ConvertToInt32(object data)
+        {
+            try
+            {
+                if (data == null)
+                    return -9994;
+
+                Type type = data.GetType();
+                switch (type)
+                {
+                    case Type a when a == typeof(string):
+                    case Type b when b == typeof(short):
+                    case Type c when c == typeof(long):
+                    case Type e when e == typeof(double):
+                        return Convert.ToInt32(data);
+                    default:
+                        //throw new ArgumentException("Unsupported data type");
+                        return Convert.ToInt32(data?.ToString());
+                }
+            }
+            catch { return -9994; }
+        }
+
+        public void FixDeserializedData()
+        {
+            for (int i = 0; i < Inputs.Count; i++)
+            {
+                var value = Inputs[i];
+                if (value == null)
+                    continue;
+
+                var realValue = value;
+
+                if (value is JArray jArray)
+                    realValue = (JArray.FromObject(value)).ToObject<List<string>>();
+                else if (value is JObject jObject)
+                    realValue = JsonConvert.DeserializeObject<JObject>(value.ToString())?.ToObject<Dictionary<string, object>>();
+                else if (value is short || value is long || value is double || value is int)
+                    realValue = Convert.ToDouble(value);
+                else if (value is bool)
+                    realValue = Convert.ToBoolean(value);
+                else
+                    realValue = value?.ToString();
+
+                Inputs[i] = realValue;
+            }
+
+            for (int i = 0; i < Outputs.Count; i++)
+            {
+                var value = Outputs[i];
+                if (value == null)
+                    continue;
+
+                var realValue = value;
+                if (value is JArray jArray)
+                    realValue = (JArray.FromObject(value)).ToObject<List<string>>();
+                else if (value is JObject jObject)
+                    realValue = JsonConvert.DeserializeObject<JObject>(value.ToString())?.ToObject<Dictionary<string, object>>();
+                else if (value is short || value is long || value is double || value is int)
+                    realValue = Convert.ToDouble(value);
+                else if (value is bool)
+                    realValue = Convert.ToBoolean(value);
+                else
+                    realValue = value?.ToString();
+
+                Outputs[i] = realValue;
+            }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Processes/BaseProcess.cs b/LB_VisionProcesses/Processes/BaseProcess.cs
new file mode 100644
index 0000000..c6032c5
--- /dev/null
+++ b/LB_VisionProcesses/Processes/BaseProcess.cs
@@ -0,0 +1,336 @@
+锘縰sing HalconDotNet;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+using System.Xml;
+
+namespace LB_VisionProcesses.Processes
+{
+    public class BaseProcess : IProcess
+    {
+        public override bool Run()
+        {
+            DateTime StartTime = DateTime.Now;
+
+            InitRunParams();
+            HOperatorSet.GenEmptyObj(out HObject EmptyObj);
+            OutputImage = EmptyObj;
+
+            #region 杩愯閫昏緫
+
+            #endregion
+            Result = true;
+            RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
+            return false;
+        }
+
+
+        /// <summary>
+        /// 鍔犺浇绠楁硶
+        /// </summary>
+        /// <param name="fullPath">瀹屾暣璺緞甯�.json</param>
+        /// <returns></returns>
+        public override bool Load(string fullPath = null)
+        {
+            try
+            {
+                if (!fullPath.Contains(".json"))
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                if (fullPath.StartsWith(".\\"))
+                {
+                    // 鍒ゆ柇鍘熷瓧绗︿覆闀垮害鏄惁澶т簬绛変簬2锛岄伩鍏嶈秺鐣�
+                    if (fullPath.Length >= 2)
+                    {
+                        // 鏇挎崲寮�澶翠袱涓瓧绗�
+                        fullPath = Application.StartupPath + fullPath.Substring(2);
+                        Debug.WriteLine($"淇敼鍚庣殑瀛楃涓�: {fullPath}");
+                    }
+                }
+
+                if (string.IsNullOrEmpty(fullPath) || fullPath.Trim() == "")
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                // 鑾峰彇涓嶅甫鏂囦欢鍚嶇殑鐩綍璺緞
+                string directoryPath = Path.GetDirectoryName(fullPath);
+                strProcessName = Path.GetFileNameWithoutExtension(fullPath);
+
+                if (!File.Exists(fullPath))
+                {
+                    Debug.WriteLine("鏂囦欢涓嶅瓨鍦ㄥ垱寤虹┖鏂囦欢");
+                    Save(directoryPath);
+                    return true;
+                }
+                string strJson = string.Empty;
+                using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8))
+                {
+                    strJson = streamReader.ReadToEnd();
+                    streamReader.Close();
+                }
+                Params = JsonConvert.DeserializeObject<ProcessParams>(strJson);
+                if (Params == null)
+                    return false;
+
+                Params.FixDeserializedData();
+                return true;
+            }
+            catch { return false; }
+        }
+
+        /// <summary>
+        /// 淇濆瓨绠楁硶
+        /// </summary>
+        /// <param name="filePath">涓嶅甫.json</param>
+        /// <returns></returns>
+        public override bool Save(string filePath = null)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(filePath) || filePath.Trim() == "")
+                {
+                    Debug.WriteLine("鏂囦欢璺緞涓嶅畬鏁�");
+                    return false;
+                }
+
+                string strJson = string.Empty;
+
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Newtonsoft.Json.Formatting.Indented,
+                    // 鑷畾涔夌缉杩涳紙4绌烘牸锛�
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+
+                strJson = JsonConvert.SerializeObject(Params, settings);
+                //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝闃插憜杈撳叆涓烘枃浠跺悕绉�
+                if (!Directory.Exists(filePath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(filePath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+                File.WriteAllText(filePath + "//" + strProcessName + ".json", strJson, Encoding.UTF8);
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public override void InitRunParams()
+        {
+            Result = true;
+            Msg = string.Empty;
+
+            if (Record != null)
+                Record.Dispose();
+        }
+
+        public override void Dispose()
+        {
+            return;
+        }
+
+        public override object Clone()
+        {
+            return MemberwiseClone();
+        }
+    }
+
+    public class TVInfo
+    {
+        public string ODF { get; set; }
+        public string ProductName { get; set; }
+        public string ProductCode { get; set; }
+
+    }
+
+    public class RootObject4
+    {
+        public string Guid { get; set; }
+
+        public string IsSuccess { get; set; }
+
+        public string Msg { get; set; }
+
+        public string UpdateUser { get; set; }
+    }
+
+    public class MaInfo
+    {
+        public string ODF { get; set; }
+        public string BOM { get; set; }
+        public string SCREEN { get; set; }
+        public string SHIPPING { get; set; }
+        public string SIZE { get; set; }
+        public string Model { get; set; }
+    }
+
+    public class GetWebServer
+    {
+        public static string QueryGetWebService(String URL, String MethodName, Hashtable Pars)
+        {
+            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL + "/" + MethodName + "?" + ParsToString(Pars));
+            request.Method = "GET";
+            request.ContentType = "application/x-www-form-urlencoded";
+            SetWebRequest(request);
+            return ReadXmlResponse(request.GetResponse());
+        }
+
+        /// <summary>
+        /// 鑾峰緱浜у搧淇℃伅
+        /// </summary>
+        /// <param name="URL"></param>
+        /// <param name="MethodName"></param>
+        /// <param name="SN"></param>
+        /// <returns></returns>
+        public static string GetTVInfo(String URL, String MethodName, string SN)
+        {
+            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL + "/" + MethodName + "?" + "SN=" + Uri.EscapeDataString(SN));
+            request.Method = "GET";
+            request.ContentType = "application/x-www-form-urlencoded";
+            SetWebRequest(request);
+            return ReadXmlResponse(request.GetResponse());
+        }
+
+
+        /// <summary>
+        /// 鑾峰緱涓嬩竴宸ュ簭浠g爜
+        /// </summary>
+        /// <param name="URL"></param>
+        /// <param name="MethodName"></param>
+        /// <param name="SN"></param>
+        /// <returns></returns>
+        public static string GetNextProcessCode(String URL, String MethodName, string SN)
+        {
+
+            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL + "/" + MethodName + "?" + "TVSN=" + Uri.EscapeDataString(SN));
+
+            request.Method = "GET";
+            request.ContentType = "application/x-www-form-urlencoded";
+            SetWebRequest(request);
+            return ReadXmlResponse(request.GetResponse());
+        }
+
+        /// <summary>
+        /// 涓婁紶鏉$爜鎵弿璺嚎缁撴灉
+        /// </summary>
+        /// <param name="URL"></param>
+        /// <param name="MethodName"></param>
+        /// <param name="TVSN"></param>
+        /// <param name="LineCode"></param>
+        /// <param name="PcProcessCode"></param>
+        /// <param name="Host"></param>
+        /// <param name="IP"></param>
+        /// <param name="User"></param>
+        /// <param name="UserName"></param>
+        /// <returns></returns>
+        public static string Scan(String URL, String MethodName, string SN, string LineCode, string PcProcessCode, string Host, string IP, string User, string UserName)
+        {
+            try
+            {
+                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL + "/" + MethodName + "?" + "TVSN=" + Uri.EscapeDataString(SN) + "&" + "LineCode=" + LineCode + "&" + "PcProcessCode=" + PcProcessCode + "&" + "Host=" + Host + "&" + "IP=" + IP + "&" + "User=" + User + "&" + "UserName=" + UserName + "&" + "PartStrs=" + "");
+                request.Method = "GET";
+                request.ContentType = "application/x-www-form-urlencoded";
+                SetWebRequest(request);
+                return ReadXmlResponse(request.GetResponse());
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.ToString());
+                return "";
+            }
+        }
+
+        private static void SetWebRequest(HttpWebRequest request)
+        {
+            request.Credentials = CredentialCache.DefaultCredentials;
+            request.Timeout = 50000;
+        }
+
+        private static string ReadXmlResponse(WebResponse response)
+        {
+            StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
+            String retXml = sr.ReadToEnd();
+            sr.Close();
+            XmlDocument doc = new XmlDocument();
+            return retXml;
+        }
+
+        private static String ParsToString(Hashtable Pars)
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach (string k in Pars.Keys)
+            {
+                if (sb.Length > 0)
+                {
+                    sb.Append("&");
+                }
+                sb.Append(HttpUtility.UrlEncode(k) + "=" + HttpUtility.UrlEncode(Pars[k].ToString()));
+            }
+            return sb.ToString();
+
+        }
+
+        public static string PostXml(string url, string SN)
+        {
+            string text = "";
+            Stream stream = null;
+            string text2 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><GetMaInfo xmlns=\"http://tempuri.org/\"><sn>" + SN + "</sn></GetMaInfo></soap:Body></soap:Envelope>";
+            HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
+            httpWebRequest.Method = "POST";
+            httpWebRequest.ContentLength = text2.Length;
+            httpWebRequest.ContentType = "text/xml";
+            httpWebRequest.KeepAlive = false;
+            httpWebRequest.Credentials = CredentialCache.DefaultCredentials;
+            httpWebRequest.Timeout = 7000;
+            Encoding encoding = Encoding.GetEncoding("UTF-8");
+            byte[] bytes = encoding.GetBytes(text2);
+            try
+            {
+                stream = httpWebRequest.GetRequestStream();
+            }
+            catch (Exception)
+            {
+                return "INT ERR";
+            }
+
+            stream.Write(bytes, 0, text2.Length);
+            HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
+            using (StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream()))
+            {
+                text = streamReader.ReadToEnd();
+                streamReader.Close();
+            }
+
+            text = text.Substring(0, text.LastIndexOf("}</GetMaInfoResult>") + 1);
+            text = text.Substring(text.LastIndexOf("<GetMaInfoResult>{") + 17);
+            RootObject4 rootObject = JsonConvert.DeserializeObject<RootObject4>(text);
+            if (rootObject.IsSuccess == "true")
+            {
+                return rootObject.Msg;
+            }
+
+            return "error" + rootObject.Msg;
+        }
+
+    }
+}
diff --git a/LB_VisionProcesses/Processes/DelayTime.cs b/LB_VisionProcesses/Processes/DelayTime.cs
new file mode 100644
index 0000000..4e918b2
--- /dev/null
+++ b/LB_VisionProcesses/Processes/DelayTime.cs
@@ -0,0 +1,41 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Processes
+{
+    [Process("寤舵椂宸ュ叿", Category = "鍏朵粬宸ュ叿", Description = "鍒涘缓寤舵椂宸ュ叿")]
+    public class DelayTime : BaseProcess
+    {
+        public DelayTime()
+        {
+            strProcessClass = "LB_VisionProcesses.Processes.DelayTime";
+            strProcessName = "寤舵椂宸ュ叿";
+
+            Params.Inputs.Add("寤舵椂鏃堕棿", 1000.0);
+        }
+        public override bool Run()
+        {
+            try
+            {
+                InitRunParams();
+                int DelayMilliseconds = 0;
+                if (!int.TryParse(this.Params.Inputs["寤舵椂鏃堕棿"].ToString(), out DelayMilliseconds))
+                {
+                    Msg = string.Format("寤舵椂鏃堕棿鏈缃�");
+                    return false;
+                }
+
+                Thread.Sleep(DelayMilliseconds);
+                return true;
+            }
+            catch
+            {
+                Msg = string.Format("杩愯鍑虹幇寮傚父");
+                return false;
+            }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Processes/RecordTool/RecordTool.cs b/LB_VisionProcesses/Processes/RecordTool/RecordTool.cs
new file mode 100644
index 0000000..00ef3be
--- /dev/null
+++ b/LB_VisionProcesses/Processes/RecordTool/RecordTool.cs
@@ -0,0 +1,62 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Processes.RecordTool
+{
+    [Process("缁樺埗宸ュ叿", Category = "鍏朵粬宸ュ叿", Description = "鍒涘缓缁樺埗宸ュ叿")]
+    public class RecordTool : BaseProcess
+    {
+        public RecordTool()
+        {
+            strProcessClass = "LB_VisionProcesses.Processes.RecordTool";
+            strProcessName = "缁樺埗宸ュ叿";
+        }
+
+        public override bool Run()
+        {
+            try
+            {
+                InitRunParams();
+
+                Dictionary<string, object> dicInputs = GetInputs();
+                foreach (var kvp in dicInputs)
+                    Params.Inputs.Add(kvp.Key, kvp.Value);
+
+                Result = true;
+            }
+            catch (Exception ex)
+            {
+                Msg = $"鑴氭湰寮傚父,鍘熷洜鏄�:{ex.Message}";
+                Result = false;
+            }
+            return Result;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鑴氭湰杈撳叆
+        /// </summary>
+        /// <returns></returns>
+        public Dictionary<string, object> GetInputs()
+        {
+            try
+            {
+                Dictionary<string, object> dicInputs = new Dictionary<string, object>();
+
+                for (int i = 0; i <= Params.Inputs.Count - 1; i++)
+                {
+                    bool isFindKey = Params.Inputs.GetKey(i, out string key);
+                    //蹇界暐涓嶉渶瑕佺殑鍙傛暟
+                    if (!isFindKey)
+                        continue;
+                    dicInputs.TryAdd(key, Params.Inputs[i]);
+                }
+
+                return dicInputs;
+            }
+            catch { return new Dictionary<string, object>(); }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Processes/ScriptTool/ScriptTool.cs b/LB_VisionProcesses/Processes/ScriptTool/ScriptTool.cs
new file mode 100644
index 0000000..f030208
--- /dev/null
+++ b/LB_VisionProcesses/Processes/ScriptTool/ScriptTool.cs
@@ -0,0 +1,478 @@
+锘縰sing Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Emit;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LB_VisionProcesses.Processes.ScriptTool
+{
+    [Process("鑴氭湰宸ュ叿", Category = "鍏朵粬宸ュ叿", Description = "鍒涘缓鑴氭湰宸ュ叿")]
+    public class ScriptTool : BaseProcess
+    {
+        MemoryStream ms = new MemoryStream();
+
+        Type programType = null;
+
+        // 瀹氫箟甯ef鍙傛暟鐨勫鎵橈紙蹇呴』瀹屽叏鍖归厤绛惧悕锛�
+        delegate bool CustomDelegate(ref Dictionary<string, object> dicInputs, ref Dictionary<string, object> dicOutputs, ref string Msg);
+
+        // 澶勭悊甯︿袱涓猺ef鍙傛暟鐨勬柟娉曠鍚嶏細bool Method(ref int a, ref string b)
+        CustomDelegate delegateCall = null;
+
+        // 鑾峰彇鏂规硶骞跺垱寤哄鎵�
+        MethodInfo method = null;
+
+        Assembly assembly = null;
+
+        // 闇�瑕佸厛鍒涘缓UserScript瀹炰緥
+        object instance = null;
+
+        public ScriptTool()
+        {
+            strProcessClass = "LB_VisionProcesses.Processes.ScriptTool";
+            strProcessName = "鑴氭湰宸ュ叿";
+
+            Params.Inputs.Add("Scrip", $"/*\nTime: {DateTime.Now.ToLocalTime()}\nUser: {Environment.UserName}\nLogs: \n*/\n" +
+                "public partial class UserScript\n{\n    " +
+                "bool ScripCode(ref Dictionary<string, object> inputs, ref Dictionary<string, object> outputs, ref string msg)\n    " +
+                "{\n        Init(ref inputs, ref outputs);\n" +
+                "        // TODO: Add Script Here!\n" +
+                "        // public object GetInputs(string key);\n" +
+                "        // public object GetGlobalVars(string key);\n" +
+                "        // public void AddOutputs(string key, object value);\n" +
+                "        // public void AddGlobalVars(string key, object value);\n        \n" +
+                "        return true;\n    }\n}");
+
+            Params.Inputs.Add("OtherDllPaths", new List<string>());
+        }
+
+        public override bool Run()
+        {
+            try
+            {
+                InitRunParams();
+
+                // 閫氳繃鍙嶅皠锛岃皟鐢ㄥ疄渚� 
+                if (ms == null)
+                {
+                    Msg = "鑴氭湰鏈紪璇�";
+                    Result = false;
+                    return Result;
+                }
+
+                if (method == null)
+                {
+                    Msg = "鏂规硶[ScripCode]涓嶅瓨鍦�";
+                    Result = false;
+                    return Result;
+                }
+
+                Dictionary<string, object> dicInputs = GetInputs();
+
+                Dictionary<string, object> dicOutputs = null;
+
+                try
+                {
+                    dicOutputs = Params.Outputs.GetAllByName();
+                    if (dicOutputs == null)
+                        dicOutputs = new Dictionary<string, object>();
+                }
+                catch { dicOutputs = new Dictionary<string, object>(); }
+
+                // 鍒濆鍖栧疄渚嬶紝浼犻�掕緭鍏ヨ緭鍑哄瓧鍏稿拰鍏ㄥ眬瀛楀吀
+                InitializeInstance(dicInputs, dicOutputs);
+
+                // 鍒涘缓濮旀墭
+                delegateCall = (CustomDelegate)Delegate.CreateDelegate(
+                    typeof(CustomDelegate),
+                    instance,  // 瀹炰緥灏嗗湪璋冪敤鏃朵紶閫�
+                    method);
+
+                bool result = delegateCall(ref dicInputs, ref dicOutputs, ref Msg);
+
+                foreach (var kvp in dicInputs)
+                    Params.Inputs.Add(kvp.Key, kvp.Value);
+
+                foreach (var kvp in dicOutputs)
+                    Params.Outputs.Add(kvp.Key, kvp.Value);
+
+                Result = result;
+            }
+            catch (Exception ex)
+            {
+                Msg = $"鑴氭湰寮傚父,鍘熷洜鏄�:{ex.Message}";
+                Result = false;
+            }
+            return Result;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鑴氭湰杈撳叆
+        /// </summary>
+        /// <returns></returns>
+        public Dictionary<string, object> GetInputs()
+        {
+            try
+            {
+                Dictionary<string, object> dicInputs = new Dictionary<string, object>();
+
+                for (int i = 0; i <= Params.Inputs.Count - 1; i++)
+                {
+                    bool isFindKey = Params.Inputs.GetKey(i, out string key);
+                    //蹇界暐涓嶉渶瑕佺殑鍙傛暟
+                    if (!isFindKey || key == "Scrip" || key == "OtherDllPaths" || key == "DictionaryInputs")
+                        continue;
+
+                    dicInputs.TryAdd(key, Params.Inputs[i]);
+                }
+
+                return dicInputs;
+            }
+            catch { return new Dictionary<string, object>(); }
+        }
+
+        /// <summary>
+        /// 璁剧疆鑴氭湰杈撳叆
+        /// </summary>
+        /// <param name="dicInputs"></param>
+        /// <returns></returns>
+        public bool SetInputs(Dictionary<string, object> dicInputs)
+        {
+            try
+            {
+                //璁剧疆杈撳叆鍓嶅皢鍘熷厛鍏朵粬杈撳叆娓呴櫎
+                if (!ClearInputs())
+                    return false;
+
+                foreach (var kvp in dicInputs)
+                {
+                    string key = kvp.Key;
+                    //蹇界暐涓嶉渶瑕佺殑鍙傛暟
+                    if (key == "Scrip" || key == "OtherDllPaths" || key == "DictionaryInputs")
+                        continue;
+
+                    Params.Inputs.Add(key, kvp.Value);
+                }
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool ClearInputs()
+        {
+            try
+            {
+                //璁剧疆杈撳叆鍓嶅皢鍘熷厛鍏朵粬杈撳叆娓呴櫎
+                for (int i = 0; i <= Params.Inputs.Count - 1; i++)
+                {
+                    bool isFindKey = Params.Inputs.GetKey(i, out string key);
+                    //蹇界暐涓嶉渶瑕佺殑鍙傛暟
+                    if (!isFindKey || key == "Scrip" || key == "OtherDllPaths" || key == "DictionaryInputs")
+                        continue;
+
+                    Params.Inputs.Remove(i);
+                }
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public bool ClearOutputs()
+        {
+            try
+            {
+                //璁剧疆杈撳叆鍓嶅皢鍘熷厛鍏朵粬杈撳叆娓呴櫎
+                for (int i = 0; i <= Params.Outputs.Count - 1; i++)
+                {
+                    Params.Outputs.Remove(i);
+                }
+                return true;
+            }
+            catch { return false; }
+        }
+
+        public void CompileCode()
+        {
+            try
+            {
+                // 1. 瀹氫箟绋嬪簭闆嗗悕绉�
+                var assemblyName = Path.GetRandomFileName();
+
+                // 3. 閰嶇疆寮曠敤
+                var references = new List<MetadataReference>
+                {
+                    // 娣诲姞鍩虹绋嬪簭闆�
+                    MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
+                    MetadataReference.CreateFromFile(typeof(Debug).Assembly.Location),
+                    MetadataReference.CreateFromFile(typeof(IProcess).Assembly.Location),
+
+                    // 娣诲姞 System.Collections.Concurrent 绋嬪簭闆�
+                    MetadataReference.CreateFromFile(typeof(System.Collections.Concurrent.ConcurrentDictionary<string, object>).Assembly.Location),
+                    //MetadataReference.CreateFromFile(typeof(System.Collections.Generic.Dictionary<string, object>).Assembly.Location),
+                    //MetadataReference.CreateFromFile(typeof(System.Linq.Enumerable).Assembly.Location),
+
+                    // 娣诲姞鍏朵粬蹇呰绋嬪簭闆�
+                    MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.Runtime.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "mscorlib.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.Core.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.Data.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.Web.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.Xml.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.Xml.Linq.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
+                        "Newtonsoft.Json.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.Collections.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.Linq.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.Data.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.Drawing.dll")),
+                   MetadataReference.CreateFromFile(Path.Combine(
+                        Path.GetDirectoryName(typeof(object).Assembly.Location)!,
+                        "System.Threading.Tasks.dll"))
+                };
+                //compilerParams.ReferencedAssemblies.Add("halcondotnet.dll");
+
+                // 3. 娣诲姞鑷畾涔塂LL寮曠敤
+                List<string> dllPaths = (JArray.FromObject(Params.Inputs["OtherDllPaths"])).ToObject<List<string>>();
+                if (dllPaths != null)
+                {
+                    foreach (var dllPath in dllPaths)
+                    {
+                        if (File.Exists(dllPath))
+                            references.Add(MetadataReference.CreateFromFile(dllPath));
+                    }
+                }
+
+                // 4. 鑾峰彇浠g爜骞舵瀯寤哄畬鏁翠唬鐮�
+                string code = ProcessParams.ConvertToString(Params.Inputs["Scrip"]);
+
+                // 鏋勫缓瀹屾暣鐨勪唬鐮侊紝鍖呭惈鍏ㄥ眬瀛楀吀璁块棶鏂规硶
+                string allCode = BuildCompleteCode(code);
+
+                SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(allCode);
+                var compilation = CSharpCompilation.Create(
+                    assemblyName,
+                    new[] { syntaxTree },
+                    references,
+                    new CSharpCompilationOptions(
+                        OutputKind.DynamicallyLinkedLibrary,
+                        optimizationLevel: OptimizationLevel.Debug,
+                        concurrentBuild: false));
+
+                // 5. 鍐呭瓨娴佺紪璇�
+                ms.Dispose();
+                ms = new MemoryStream();
+                EmitResult result = compilation.Emit(ms);
+
+                // 6. 澶勭悊缂栬瘧閿欒
+                if (!result.Success)
+                {
+                    Msg = "缂栬瘧澶辫触:\r\n";
+                    foreach (Diagnostic diagnostic in result.Diagnostics)
+                    {
+                        // 鑾峰彇閿欒浣嶇疆淇℃伅
+                        FileLinePositionSpan lineSpan = diagnostic.Location.GetLineSpan();
+
+                        // 鏍煎紡鍖栬鍙蜂俊鎭�
+                        string lineInfo = $"琛屽彿: {lineSpan.StartLinePosition.Line + 1},"
+                                        + $"鍒�: {lineSpan.StartLinePosition.Character + 1}";
+
+                        Msg += $"{lineInfo} 鈫� {diagnostic.GetMessage()} [{diagnostic.Id}]\r\n";
+                    }
+                    return;
+                }
+
+                // 7. 鍔犺浇绋嬪簭闆�
+                ms.Seek(0, SeekOrigin.Begin);
+                assembly = Assembly.Load(ms.ToArray());
+
+                programType = assembly.GetType($"{strProcessClass}.UserScript");
+                if (programType == null)
+                {
+                    Msg = $"绫籟{strProcessClass}.UserScript]涓嶅瓨鍦�";
+                    return;
+                }
+
+                method = programType.GetMethod("ScripCode",
+                    BindingFlags.NonPublic | BindingFlags.Instance);
+
+                if (method == null)
+                {
+                    Msg = "缂栬瘧澶辫触,鏂规硶[ScripCode]涓嶅瓨鍦�";
+                    return;
+                }
+
+                // 8. 鍒涘缓瀹炰緥骞跺垵濮嬪寲
+                instance = Activator.CreateInstance(programType);
+                if (instance == null)
+                {
+                    Msg = $"瀹炰緥鍖栧璞{strProcessClass}.UserScript.ScripCode]涓嶅瓨鍦�";
+                    return;
+                }
+
+                Dictionary<string, object> dicInputs = GetInputs();
+
+                Dictionary<string, object> dicOutputs = null;
+
+                try
+                {
+                    dicOutputs = Params.Outputs.GetAllByName();
+                    if (dicOutputs == null)
+                        dicOutputs = new Dictionary<string, object>();
+                }
+                catch { dicOutputs = new Dictionary<string, object>(); }
+
+                // 9. 鍒濆鍖栧疄渚嬶紝浼犻�掕緭鍏ヨ緭鍑哄瓧鍏稿拰鍏ㄥ眬瀛楀吀
+                InitializeInstance(dicInputs, dicOutputs);
+
+                // 10. 鍒涘缓濮旀墭
+                delegateCall = (CustomDelegate)Delegate.CreateDelegate(
+                    typeof(CustomDelegate),
+                    instance,  // 瀹炰緥灏嗗湪璋冪敤鏃朵紶閫�
+                    method);
+
+                Msg = "缂栬瘧鎴愬姛";
+            }
+            catch (Exception ex) { Msg = $"缂栬瘧鍙戠敓寮傚父閿欒锛歿ex.Message}銆恵ex.StackTrace}銆�"; }
+        }
+
+        /// <summary>
+        /// 鍒濆鍖栧疄渚嬶紝浼犻�掑瓧鍏稿紩鐢�
+        /// </summary>
+        private void InitializeInstance(Dictionary<string, object> inputs, Dictionary<string, object> outputs)
+        {
+            // 鑾峰彇Init鏂规硶
+            var initMethod = programType.GetMethod("Init",
+                BindingFlags.Public | BindingFlags.Instance);
+
+            if (initMethod != null)
+            {
+                // 璋冪敤Init鏂规硶锛屼紶閫掑瓧鍏稿紩鐢�
+                object[] initParams = new object[]
+                {
+                    inputs,
+                    outputs // 浼犻�掑瓧鍏稿紩鐢�
+                };
+                initMethod.Invoke(instance, initParams);
+            }
+        }
+
+        /// <summary>
+        /// 鏋勫缓瀹屾暣鐨勪唬鐮侊紝鍖呭惈鍏ㄥ眬瀛楀吀璁块棶鏂规硶
+        /// </summary>
+        private string BuildCompleteCode(string userCode)
+        {
+            return $@"
+                    using System;
+                    using System.Collections.Generic;
+                    using System.Collections.Concurrent;
+                    using LB_VisionProcesses;
+
+                    namespace LB_VisionProcesses.Processes.ScriptTool
+                    {{
+                        public partial class UserScript
+                        {{
+                            private Dictionary<string, object> inputs;
+                            private Dictionary<string, object> outputs;
+
+                            public void Init(
+                                ref Dictionary<string, object> inputs, 
+                                ref Dictionary<string, object> outputs)
+                            {{
+                                this.inputs = inputs;
+                                this.outputs = outputs;
+                            }}
+
+                            public void AddInputs(string key, object value)
+                            {{
+                                if (this.inputs.ContainsKey(key))
+                                    this.inputs[key] = value;
+                                else
+                                    this.inputs.Add(key, value);
+                            }}
+
+                            public void AddOutputs(string key, object value)
+                            {{
+                                if (this.outputs.ContainsKey(key))
+                                    this.outputs[key] = value;
+                                else
+                                    this.outputs.Add(key, value);
+                            }}
+
+                            public object GetInputs(string key)
+                            {{
+                                return this.inputs.TryGetValue(key, out object value) ? value : null;
+                            }}
+
+                            public object GetOutputs(string key)
+                            {{
+                                return this.outputs.TryGetValue(key, out object value) ? value : null;
+                            }}
+
+                            // 鍏ㄥ眬瀛楀吀鎿嶄綔鏂规硶
+                            public void AddGlobalVars(string key, object value)
+                            {{
+                                IProcess.dicGlobalVars?.AddOrUpdate(key, value, (k, v) => value);
+                            }}
+
+                            public object GetGlobalVars(string key)
+                            {{
+                                return IProcess.dicGlobalVars.TryGetValue(key, out object value) ? value : null;
+                            }}                    
+                        }}
+
+                        {userCode}
+                    }}
+                    ";
+        }
+
+        /// <summary>
+        /// 鍔犺浇绠楁硶
+        /// </summary>
+        /// <param name="fullPath">瀹屾暣璺緞甯�.json</param>
+        /// <returns></returns>
+        public override bool Load(string fullPath = null)
+        {
+            try
+            {
+                if (!base.Load(fullPath))
+                    return false;
+
+                CompileCode();
+                return true;
+            }
+            catch { return false; }
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.Designer.cs b/LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.Designer.cs
new file mode 100644
index 0000000..b4bd9d0
--- /dev/null
+++ b/LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.Designer.cs
@@ -0,0 +1,330 @@
+锘�
+namespace LB_VisionProcesses.Processes.ScriptTool
+{
+    partial class ScriptToolEdit
+    {
+        /// <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()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ScriptToolEdit));
+            splitContainer1 = new SplitContainer();
+            splitContainer2 = new SplitContainer();
+            groupBox1 = new GroupBox();
+            DataGridInputs = new DataGridView();
+            groupBox2 = new GroupBox();
+            DataGridOutputs = new DataGridView();
+            splitContainer3 = new SplitContainer();
+            grpScript = new GroupBox();
+            groupBox4 = new GroupBox();
+            richTextBoxLog = new RichTextBox();
+            ToolsStrip = new ToolStrip();
+            btnCompileCode = new ToolStripButton();
+            btnRunCode = new ToolStripButton();
+            statusStrip1 = new StatusStrip();
+            lblRunTime = new ToolStripStatusLabel();
+            panel1 = new Panel();
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
+            splitContainer1.Panel1.SuspendLayout();
+            splitContainer1.Panel2.SuspendLayout();
+            splitContainer1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)splitContainer2).BeginInit();
+            splitContainer2.Panel1.SuspendLayout();
+            splitContainer2.Panel2.SuspendLayout();
+            splitContainer2.SuspendLayout();
+            groupBox1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)DataGridInputs).BeginInit();
+            groupBox2.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)DataGridOutputs).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)splitContainer3).BeginInit();
+            splitContainer3.Panel1.SuspendLayout();
+            splitContainer3.Panel2.SuspendLayout();
+            splitContainer3.SuspendLayout();
+            groupBox4.SuspendLayout();
+            ToolsStrip.SuspendLayout();
+            statusStrip1.SuspendLayout();
+            panel1.SuspendLayout();
+            SuspendLayout();
+            // 
+            // splitContainer1
+            // 
+            splitContainer1.BackColor = Color.FromArgb(32, 41, 50);
+            splitContainer1.Dock = DockStyle.Fill;
+            splitContainer1.Location = new Point(0, 0);
+            splitContainer1.Name = "splitContainer1";
+            // 
+            // splitContainer1.Panel1
+            // 
+            splitContainer1.Panel1.Controls.Add(splitContainer2);
+            // 
+            // splitContainer1.Panel2
+            // 
+            splitContainer1.Panel2.Controls.Add(splitContainer3);
+            splitContainer1.Size = new Size(800, 396);
+            splitContainer1.SplitterDistance = 266;
+            splitContainer1.TabIndex = 0;
+            // 
+            // splitContainer2
+            // 
+            splitContainer2.Dock = DockStyle.Fill;
+            splitContainer2.Location = new Point(0, 0);
+            splitContainer2.Name = "splitContainer2";
+            splitContainer2.Orientation = Orientation.Horizontal;
+            // 
+            // splitContainer2.Panel1
+            // 
+            splitContainer2.Panel1.Controls.Add(groupBox1);
+            // 
+            // splitContainer2.Panel2
+            // 
+            splitContainer2.Panel2.Controls.Add(groupBox2);
+            splitContainer2.Size = new Size(266, 396);
+            splitContainer2.SplitterDistance = 197;
+            splitContainer2.TabIndex = 0;
+            // 
+            // groupBox1
+            // 
+            groupBox1.BackColor = Color.FromArgb(32, 41, 50);
+            groupBox1.Controls.Add(DataGridInputs);
+            groupBox1.Dock = DockStyle.Fill;
+            groupBox1.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            groupBox1.ForeColor = SystemColors.Control;
+            groupBox1.Location = new Point(0, 0);
+            groupBox1.Name = "groupBox1";
+            groupBox1.Size = new Size(266, 197);
+            groupBox1.TabIndex = 0;
+            groupBox1.TabStop = false;
+            groupBox1.Text = "杈撳叆";
+            // 
+            // DataGridInputs
+            // 
+            DataGridInputs.BackgroundColor = Color.FromArgb(32, 46, 50);
+            DataGridInputs.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            DataGridInputs.Dock = DockStyle.Fill;
+            DataGridInputs.GridColor = SystemColors.Control;
+            DataGridInputs.Location = new Point(3, 24);
+            DataGridInputs.Name = "DataGridInputs";
+            DataGridInputs.Size = new Size(260, 170);
+            DataGridInputs.TabIndex = 0;
+            // 
+            // groupBox2
+            // 
+            groupBox2.BackColor = Color.FromArgb(32, 41, 50);
+            groupBox2.Controls.Add(DataGridOutputs);
+            groupBox2.Dock = DockStyle.Fill;
+            groupBox2.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            groupBox2.ForeColor = SystemColors.Control;
+            groupBox2.Location = new Point(0, 0);
+            groupBox2.Name = "groupBox2";
+            groupBox2.Size = new Size(266, 195);
+            groupBox2.TabIndex = 0;
+            groupBox2.TabStop = false;
+            groupBox2.Text = "杈撳嚭";
+            // 
+            // DataGridOutputs
+            // 
+            DataGridOutputs.BackgroundColor = Color.FromArgb(32, 46, 50);
+            DataGridOutputs.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            DataGridOutputs.Dock = DockStyle.Fill;
+            DataGridOutputs.GridColor = SystemColors.Control;
+            DataGridOutputs.Location = new Point(3, 24);
+            DataGridOutputs.Name = "DataGridOutputs";
+            DataGridOutputs.Size = new Size(260, 168);
+            DataGridOutputs.TabIndex = 0;
+            // 
+            // splitContainer3
+            // 
+            splitContainer3.Dock = DockStyle.Fill;
+            splitContainer3.Location = new Point(0, 0);
+            splitContainer3.Name = "splitContainer3";
+            splitContainer3.Orientation = Orientation.Horizontal;
+            // 
+            // splitContainer3.Panel1
+            // 
+            splitContainer3.Panel1.Controls.Add(grpScript);
+            // 
+            // splitContainer3.Panel2
+            // 
+            splitContainer3.Panel2.Controls.Add(groupBox4);
+            splitContainer3.Size = new Size(530, 396);
+            splitContainer3.SplitterDistance = 300;
+            splitContainer3.TabIndex = 1;
+            // 
+            // grpScript
+            // 
+            grpScript.BackColor = Color.FromArgb(32, 41, 50);
+            grpScript.Dock = DockStyle.Fill;
+            grpScript.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            grpScript.ForeColor = SystemColors.Control;
+            grpScript.Location = new Point(0, 0);
+            grpScript.Name = "grpScript";
+            grpScript.Size = new Size(530, 300);
+            grpScript.TabIndex = 1;
+            grpScript.TabStop = false;
+            grpScript.Text = "缂栬緫";
+            // 
+            // groupBox4
+            // 
+            groupBox4.BackColor = Color.FromArgb(32, 41, 50);
+            groupBox4.Controls.Add(richTextBoxLog);
+            groupBox4.Dock = DockStyle.Fill;
+            groupBox4.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            groupBox4.ForeColor = SystemColors.Control;
+            groupBox4.Location = new Point(0, 0);
+            groupBox4.Name = "groupBox4";
+            groupBox4.Size = new Size(530, 92);
+            groupBox4.TabIndex = 1;
+            groupBox4.TabStop = false;
+            groupBox4.Text = "缁撴灉";
+            // 
+            // richTextBoxLog
+            // 
+            richTextBoxLog.BackColor = Color.FromArgb(32, 46, 50);
+            richTextBoxLog.BorderStyle = BorderStyle.None;
+            richTextBoxLog.Dock = DockStyle.Fill;
+            richTextBoxLog.ForeColor = SystemColors.Control;
+            richTextBoxLog.Location = new Point(3, 24);
+            richTextBoxLog.Name = "richTextBoxLog";
+            richTextBoxLog.ReadOnly = true;
+            richTextBoxLog.Size = new Size(524, 65);
+            richTextBoxLog.TabIndex = 0;
+            richTextBoxLog.Text = "";
+            // 
+            // ToolsStrip
+            // 
+            ToolsStrip.BackColor = Color.FromArgb(32, 41, 50);
+            ToolsStrip.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            ToolsStrip.Items.AddRange(new ToolStripItem[] { btnCompileCode, btnRunCode });
+            ToolsStrip.Location = new Point(0, 0);
+            ToolsStrip.Name = "ToolsStrip";
+            ToolsStrip.Size = new Size(800, 28);
+            ToolsStrip.TabIndex = 1;
+            ToolsStrip.Text = "toolStrip1";
+            // 
+            // btnCompileCode
+            // 
+            btnCompileCode.DisplayStyle = ToolStripItemDisplayStyle.Text;
+            btnCompileCode.ForeColor = SystemColors.Control;
+            btnCompileCode.Image = (Image)resources.GetObject("btnCompileCode.Image");
+            btnCompileCode.ImageTransparentColor = Color.Magenta;
+            btnCompileCode.Name = "btnCompileCode";
+            btnCompileCode.Size = new Size(46, 25);
+            btnCompileCode.Text = "缂栬瘧";
+            btnCompileCode.Click += btnCompileCode_Click;
+            // 
+            // btnRunCode
+            // 
+            btnRunCode.DisplayStyle = ToolStripItemDisplayStyle.Text;
+            btnRunCode.ForeColor = SystemColors.Control;
+            btnRunCode.Image = (Image)resources.GetObject("btnRunCode.Image");
+            btnRunCode.ImageTransparentColor = Color.Magenta;
+            btnRunCode.Name = "btnRunCode";
+            btnRunCode.Size = new Size(36, 22);
+            btnRunCode.Text = "杩愯";
+            btnRunCode.Click += btnRunCode_Click;
+            // 
+            // statusStrip1
+            // 
+            statusStrip1.BackColor = Color.FromArgb(32, 41, 50);
+            statusStrip1.Items.AddRange(new ToolStripItem[] { lblRunTime });
+            statusStrip1.Location = new Point(0, 424);
+            statusStrip1.Name = "statusStrip1";
+            statusStrip1.Size = new Size(800, 26);
+            statusStrip1.TabIndex = 2;
+            statusStrip1.Text = "statusStrip1";
+            // 
+            // lblRunTime
+            // 
+            lblRunTime.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            lblRunTime.ForeColor = SystemColors.Control;
+            lblRunTime.Name = "lblRunTime";
+            lblRunTime.Size = new Size(41, 21);
+            lblRunTime.Text = "0ms";
+            // 
+            // panel1
+            // 
+            panel1.Controls.Add(splitContainer1);
+            panel1.Dock = DockStyle.Fill;
+            panel1.Location = new Point(0, 28);
+            panel1.Name = "panel1";
+            panel1.Size = new Size(800, 396);
+            panel1.TabIndex = 3;
+            // 
+            // ScriptToolEdit
+            // 
+            Controls.Add(panel1);
+            Controls.Add(statusStrip1);
+            Controls.Add(ToolsStrip);
+            Name = "ScriptToolEdit";
+            Size = new Size(800, 450);
+            Load += ScriptToolEdit_Load;
+            splitContainer1.Panel1.ResumeLayout(false);
+            splitContainer1.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit();
+            splitContainer1.ResumeLayout(false);
+            splitContainer2.Panel1.ResumeLayout(false);
+            splitContainer2.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer2).EndInit();
+            splitContainer2.ResumeLayout(false);
+            groupBox1.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)DataGridInputs).EndInit();
+            groupBox2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)DataGridOutputs).EndInit();
+            splitContainer3.Panel1.ResumeLayout(false);
+            splitContainer3.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)splitContainer3).EndInit();
+            splitContainer3.ResumeLayout(false);
+            groupBox4.ResumeLayout(false);
+            ToolsStrip.ResumeLayout(false);
+            ToolsStrip.PerformLayout();
+            statusStrip1.ResumeLayout(false);
+            statusStrip1.PerformLayout();
+            panel1.ResumeLayout(false);
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private SplitContainer splitContainer1;
+        private SplitContainer splitContainer2;
+        private GroupBox groupBox1;
+        private GroupBox groupBox2;
+        private GroupBox groupBox4;
+        private GroupBox grpScript;
+        private RichTextBox richTextBoxLog;
+        private ToolStrip ToolsStrip;
+        private ToolStripButton btnCompileCode;
+        private ToolStripButton btnRunCode;
+        private StatusStrip statusStrip1;
+        private ToolStripStatusLabel lblRunTime;
+        private Panel panel1;
+        private TableLayoutPanel tableLayoutPanel2;
+        private DataGridView DataGridInputs;
+        private TableLayoutPanel tableLayoutPanel3;
+        private DataGridView DataGridOutputs;
+        private SplitContainer splitContainer3;
+    }
+}
\ No newline at end of file
diff --git a/LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.cs b/LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.cs
new file mode 100644
index 0000000..d608a85
--- /dev/null
+++ b/LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.cs
@@ -0,0 +1,142 @@
+锘縰sing LB_VisionControl.ScriptEditControl;
+using LB_VisionProcesses.Alogrithms;
+using System.Data;
+
+namespace LB_VisionProcesses.Processes.ScriptTool
+{
+    public partial class ScriptToolEdit : TAlgorithmEdit
+    {
+        DataTable DataTableInputs = new DataTable();
+        DataTable DataTableOutputs = new DataTable();
+
+        ScriptEditControl ScriptEditControl = new ScriptEditControl();
+
+        public ScriptToolEdit(ScriptTool subject = null)
+        {
+            InitializeComponent();
+            if (subject == null)
+                subject = new ScriptTool();
+
+            this.grpScript.Controls.Add(ScriptEditControl);
+            ScriptEditControl.Dock = DockStyle.Fill;
+
+            this.Subject = subject;
+            this.ScriptEditControl.TabStop = false; // 閬垮厤鐒︾偣鍒囨崲
+            this.ScriptEditControl.Focus();// 纭繚鎺т欢鍙幏寰楃劍鐐�
+
+            // 璁剧疆楂樿川閲忔覆鏌撴ā寮�
+            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
+        }
+
+        private void ScriptToolEdit_Load(object sender, EventArgs e)
+        {
+            LoadParas();
+            this.ScriptEditControl.ScriptText = ProcessParams.ConvertToString(Subject.Params.Inputs["Scrip"]);
+        }
+
+        /// <summary>
+        /// 鍔犺浇杩愯鍙傛暟
+        /// </summary>
+        public override void LoadParas()
+        {
+            this.Invoke(new Action(() =>
+            {
+                // 缁戝畾杈撳叆鍙傛暟
+                Dictionary<string, object> dicInputs = ((ScriptTool)Subject).GetInputs();
+                DataTableInputs.Columns.Add("Key", typeof(string));
+                DataTableInputs.Columns.Add("Value", typeof(object));
+
+                DataTableInputs.Rows.Clear();
+                foreach (var item in dicInputs)
+                    DataTableInputs.Rows.Add(item.Key, item.Value);
+                DataGridInputs.DataSource = DataTableInputs;
+
+                // 缁戝畾杈撳嚭鍙傛暟
+                Dictionary<string, object> dicOutputs = Subject.Params.Outputs.GetAllByName();
+                DataTableOutputs.Columns.Add("Key", typeof(string));
+                DataTableOutputs.Columns.Add("Value", typeof(object));
+
+                DataTableOutputs.Rows.Clear();
+                foreach (var item in dicOutputs)
+                    DataTableOutputs.Rows.Add(item.Key, item.Value);
+                DataGridOutputs.DataSource = DataTableOutputs;
+            }));
+        }
+
+        private void btnCompileCode_Click(object sender, EventArgs e)
+        {
+            Subject.Params.Inputs["Scrip"] = this.ScriptEditControl.ScriptText;
+            ((ScriptTool)Subject).CompileCode();
+            this.richTextBoxLog.Text = Subject.Msg;
+        }
+
+        private void btnRunCode_Click(object sender, EventArgs e)
+        {
+            //杩愯鍓嶉渶瑕佹洿鏂拌緭鍏ュ弬鏁癙aras
+            UpdataInputs();
+
+            DateTime StartTime = DateTime.Now;
+            Subject.Run();
+
+            this.lblRunTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds.ToString("F0")}ms";
+            this.richTextBoxLog.Text = Subject.Msg;
+
+            UpdataOutputs();
+        }
+
+        /// <summary>
+        /// 鏇存柊杩愯鍙傛暟
+        /// </summary>
+        public override void UpdataInputs()
+        {
+            //璁剧疆杩愯鍙傛暟
+            int iResult = 0;
+            Subject.Params.Inputs["Scrip"] = this.ScriptEditControl.ScriptText;
+
+            Dictionary<string, object> dicInputs = new Dictionary<string, object>();
+            DataTable modifiedDataInputs = (DataTable)DataGridInputs.DataSource;
+            foreach (DataRow row in modifiedDataInputs.Rows)
+            {
+                if (row["Key"] == null)
+                    continue;
+                string key = row["Key"]?.ToString();
+                object value = row["Value"];
+                dicInputs.Add(key, value);
+            }
+            ((ScriptTool)Subject).SetInputs(dicInputs);
+
+            DataTable modifiedDataOutputs = (DataTable)DataGridOutputs.DataSource;
+            ((ScriptTool)Subject).ClearOutputs();
+            foreach (DataRow row in modifiedDataOutputs.Rows)
+            {
+                if (row["Key"] == null)
+                    continue;
+                string key = row["Key"]?.ToString();
+                object value = row["Value"];
+
+                Subject.Params.Outputs.Add(key, value);
+            }
+
+            return;
+        }
+
+        /// <summary>
+        /// 鏇存柊杈撳嚭缁撴灉
+        /// </summary>
+        public override void UpdataOutputs()
+        {
+            this.BeginInvoke(new Action(() =>
+            {
+                DataTableInputs.Rows.Clear();
+                foreach (var item in ((ScriptTool)Subject).GetInputs())
+                    DataTableInputs.Rows.Add(item.Key, item.Value);
+                DataGridInputs.DataSource = DataTableInputs;
+
+                DataTableOutputs.Rows.Clear();
+                foreach (var item in Subject.Params.Outputs.GetAllByName())
+                    DataTableOutputs.Rows.Add(item.Key, item.Value);
+                DataGridOutputs.DataSource = DataTableOutputs;
+            }));
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.resx b/LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.resx
new file mode 100644
index 0000000..e16c8a1
--- /dev/null
+++ b/LB_VisionProcesses/Processes/ScriptTool/ScriptToolEdit.resx
@@ -0,0 +1,148 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="lblMsgToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="ToolsStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>156, 17</value>
+  </metadata>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="btnCompileCode.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACNSURBVDhPY/j27dt/SjADiHByciILoxjw4f1HkjDJBjy/
+        dfL/iW5TME2WASe6Tf4fqpUCG0KWARAXmBB2waSzr/4vuPQawwB0jNWArH0v/ksvfATGhAzBMABZMzGG
+        oBig07ASQzM2Q0Ds1hMvMQ1A14SOQRpBGMYHuZYkA7BhkKspMgCEqWcAJZiBUgAABzX8nOIkzeMAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+  <data name="btnRunCode.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACNSURBVDhPY/j27dt/SjADiHByciILoxjw4f1HkjDJBjy/
+        dfL/iW5TME2WASe6Tf4fqpUCG0KWARAXmBB2waSzr/4vuPQawwB0jNWArH0v/ksvfATGhAzBMABZMzGG
+        oBig07ASQzM2Q0Ds1hMvMQ1A14SOQRpBGMYHuZYkA7BhkKspMgCEqWcAJZiBUgAABzX8nOIkzeMAAAAA
+        SUVORK5CYII=
+</value>
+  </data>
+  <metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>270, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/LB_VisionProcesses/Program.cs b/LB_VisionProcesses/Program.cs
new file mode 100644
index 0000000..179c508
--- /dev/null
+++ b/LB_VisionProcesses/Program.cs
@@ -0,0 +1,22 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_VisionProcesses
+{
+    internal static class Program
+    {
+        /// <summary>
+        /// 搴旂敤绋嬪簭鐨勪富鍏ュ彛鐐广��
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            Application.EnableVisualStyles();
+            Application.SetCompatibleTextRenderingDefault(false);
+            Application.Run(new MainForm());
+        }
+    }
+}
diff --git a/LB_VisionProcesses/Properties/Resources.Designer.cs b/LB_VisionProcesses/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..8e544ed
--- /dev/null
+++ b/LB_VisionProcesses/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+锘�//------------------------------------------------------------------------------
+// <auto-generated>
+//     姝や唬鐮佺敱宸ュ叿鐢熸垚銆�
+//     杩愯鏃剁増鏈�:4.0.30319.42000
+//
+//     瀵规鏂囦欢鐨勬洿鏀瑰彲鑳戒細瀵艰嚧涓嶆纭殑琛屼负锛屽苟涓斿鏋�
+//     閲嶆柊鐢熸垚浠g爜锛岃繖浜涙洿鏀瑰皢浼氫涪澶便��
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace LB_VisionProcesses.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   涓�涓己绫诲瀷鐨勮祫婧愮被锛岀敤浜庢煡鎵炬湰鍦板寲鐨勫瓧绗︿覆绛夈��
+    /// </summary>
+    // 姝ょ被鏄敱 StronglyTypedResourceBuilder
+    // 绫婚�氳繃绫讳技浜� ResGen 鎴� Visual Studio 鐨勫伐鍏疯嚜鍔ㄧ敓鎴愮殑銆�
+    // 鑻ヨ娣诲姞鎴栫Щ闄ゆ垚鍛橈紝璇风紪杈� .ResX 鏂囦欢锛岀劧鍚庨噸鏂拌繍琛� ResGen
+    // (浠� /str 浣滀负鍛戒护閫夐」)锛屾垨閲嶆柊鐢熸垚 VS 椤圭洰銆�
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.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 (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LB_VisionProcesses.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/LB_VisionProcesses/Properties/Resources.resx b/LB_VisionProcesses/Properties/Resources.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/LB_VisionProcesses/Properties/Resources.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/LB_VisionProcesses/logo.ico b/LB_VisionProcesses/logo.ico
new file mode 100644
index 0000000..5887476
--- /dev/null
+++ b/LB_VisionProcesses/logo.ico
Binary files differ
diff --git a/LB_VisionProcesses/ref/CLIDelegate.dll b/LB_VisionProcesses/ref/CLIDelegate.dll
new file mode 100644
index 0000000..78ebc56
--- /dev/null
+++ b/LB_VisionProcesses/ref/CLIDelegate.dll
Binary files differ
diff --git a/LB_VisionProcesses/ref/MVSDK_Net.XML b/LB_VisionProcesses/ref/MVSDK_Net.XML
new file mode 100644
index 0000000..03dc9b8
--- /dev/null
+++ b/LB_VisionProcesses/ref/MVSDK_Net.XML
@@ -0,0 +1,2589 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>MVSDK_Net</name>
+    </assembly>
+    <members>
+        <member name="T:MVSDK_Net.IMVDefine">
+            <summary>
+            鏁版嵁缁撴瀯绫�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_OK">
+            <summary>
+            鎴愬姛锛屾棤閿欒
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ERROR">
+            <summary>
+            閫氱敤鐨勯敊璇�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_INVALID_HANDLE">
+            <summary>
+            閿欒鎴栨棤鏁堢殑鍙ユ焺
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_INVALID_PARAM">
+            <summary>
+            閿欒鐨勫弬鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_INVALID_FRAME_HANDLE">
+            <summary>
+            閿欒鎴栨棤鏁堢殑甯у彞鏌�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_INVALID_FRAME">
+            <summary>
+            鏃犳晥鐨勫抚
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_INVALID_RESOURCE">
+            <summary>
+            鐩告満/浜嬩欢/娴佺瓑璧勬簮鏃犳晥
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_INVALID_IP">
+            <summary>
+            璁惧涓庝富鏈虹殑IP缃戞涓嶅尮閰�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_NO_MEMORY">
+            <summary>
+            鍐呭瓨涓嶈冻
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_INSUFFICIENT_MEMORY">
+            <summary>
+            浼犲叆鐨勫唴瀛樼┖闂翠笉瓒�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ERROR_PROPERTY_TYPE">
+            <summary>
+            灞炴�х被鍨嬮敊璇�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_INVALID_ACCESS">
+            <summary>
+            灞炴�т笉鍙闂�佹垨涓嶈兘璇�/鍐欍�佹垨璇�/鍐欏け璐�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_INVALID_RANGE">
+            <summary>
+            灞炴�у�艰秴鍑鸿寖鍥淬�佹垨鑰呬笉鏄闀挎暣鏁板��
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_NOT_SUPPORT">
+            <summary>
+            璁惧涓嶆敮鎸佺殑鍔熻兘	
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_MAX_DEVICE_ENUM_NUM">
+            <summary>
+            鏀寔璁惧鏈�澶т釜鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_MAX_STRING_LENTH">
+            <summary>
+            瀛楃涓叉渶澶ч暱搴�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_MAX_ERROR_LIST_NUM">
+            <summary>
+            澶辫触灞炴�у垪琛ㄦ渶澶ч暱搴�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_MSG_EVENT_ID_EXPOSURE_END">
+            <summary>
+            ExposureEnd浜嬩欢ID
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_MSG_EVENT_ID_FRAME_TRIGGER">
+            <summary>
+            FrameTrigger浜嬩欢ID
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_MSG_EVENT_ID_FRAME_START">
+            <summary>
+            FrameStart浜嬩欢ID
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_MSG_EVENT_ID_ACQ_START">
+            <summary>
+            AcquisitionStart浜嬩欢ID
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_MSG_EVENT_ID_ACQ_TRIGGER">
+            <summary>
+            AcquisitionTrigger浜嬩欢ID
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_MSG_EVENT_ID_DATA_READ_OUT">
+            <summary>
+            ReadOut浜嬩欢ID
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_EFeatureType">
+            <summary>
+            鏋氫妇锛氬睘鎬х被鍨�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EFeatureType.featureInt">
+            <summary>
+            鏁村瀷鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EFeatureType.featureFloat">
+            <summary>
+            娴偣鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EFeatureType.featureEnum">
+            <summary>
+            鏋氫妇
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EFeatureType.featureBool">
+            <summary>
+            甯冨皵
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EFeatureType.featureString">
+            <summary>
+            瀛楃涓�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EFeatureType.featureCommand">
+            <summary>
+            鍛戒护
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EFeatureType.featureGroup">
+            <summary>
+            鍒嗙粍鑺傜偣
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EFeatureType.featureReg">
+            <summary>
+            瀵勫瓨鍣ㄨ妭鐐�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EFeatureType.featureUndefined">
+            <summary>
+            鏈畾涔�
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_EInterfaceType">
+            <summary>
+            鏋氫妇锛氭帴鍙g被鍨�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EInterfaceType.interfaceTypeGige">
+            <summary>
+            缃戝崱鎺ュ彛绫诲瀷
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EInterfaceType.interfaceTypeUsb3">
+            <summary>
+            USB3.0鎺ュ彛绫诲瀷
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EInterfaceType.interfaceTypeCL">
+            <summary>
+            CAMERALINK鎺ュ彛绫诲瀷
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EInterfaceType.interfaceTypePCIe">
+            <summary>
+            PCIe鎺ュ彛绫诲瀷
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EInterfaceType.interfaceTypeAll">
+            <summary>
+            蹇界暐鎺ュ彛绫诲瀷
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EInterfaceType.interfaceInvalidType">
+            <summary>
+            鏃犳晥鎺ュ彛绫诲瀷
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_ECameraType">
+            <summary>
+            鏋氫妇锛氳澶囩被鍨�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECameraType.typeGigeCamera">
+            <summary>
+            GIGE鐩告満
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECameraType.typeU3vCamera">
+            <summary>
+            USB3.0鐩告満
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECameraType.typeCLCamera">
+            <summary>
+            CAMERALINK 鐩告満
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECameraType.typePCIeCamera">
+            <summary>
+            PCIe鐩告満
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECameraType.typeUndefinedCamera">
+            <summary>
+            鏈煡绫诲瀷
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_ECreateHandleMode">
+            <summary>
+            鏋氫妇锛氬垱寤哄彞鏌勬柟寮�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECreateHandleMode.modeByIndex">
+            <summary>
+            閫氳繃宸叉灇涓捐澶囩殑绱㈠紩(浠�0寮�濮嬶紝姣斿 0, 1, 2...)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECreateHandleMode.modeByCameraKey">
+            <summary>
+            閫氳繃璁惧閿�"鍘傚晢:搴忓垪鍙�"	
+            </summary>		
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECreateHandleMode.modeByDeviceUserID">
+            <summary>
+            閫氳繃璁惧鑷畾涔夊悕
+            </summary>	
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECreateHandleMode.modeByIPAddress">
+            <summary>
+            閫氳繃璁惧IP鍦板潃
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_ECameraAccessPermission">
+            <summary>
+            鏋氫妇锛氳闂潈闄�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECameraAccessPermission.accessPermissionOpen">
+            <summary>
+            GigE鐩告満娌℃湁琚繛鎺�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECameraAccessPermission.accessPermissionExclusive">
+            <summary>
+            鐙崰璁块棶鏉冮檺
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECameraAccessPermission.accessPermissionControl">
+            <summary>
+            闈炵嫭鍗犲彲璇昏闂潈闄�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECameraAccessPermission.accessPermissionControlWithSwitchover">
+            <summary>
+            鍒囨崲鎺у埗璁块棶鏉冮檺
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECameraAccessPermission.accessPermissionUnknown">
+            <summary>
+            鏃犳硶纭畾
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ECameraAccessPermission.accessPermissionUndefined">
+            <summary>
+            鏈畾涔夎闂潈闄�
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_EGrabStrategy">
+            <summary>
+            鏋氫妇锛氭姄鍥剧瓥鐣�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EGrabStrategy.grabStrartegySequential">
+            <summary>
+            鎸夊埌杈鹃『搴忓鐞嗗浘鐗�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EGrabStrategy.grabStrartegyLatestImage">
+            <summary>
+            鑾峰彇鏈�鏂扮殑鍥剧墖
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EGrabStrategy.grabStrartegyUpcomingImage">
+            <summary>
+            绛夊緟鑾峰彇涓嬩竴寮犲浘鐗�(鍙拡瀵笹igE鐩告満)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EGrabStrategy.grabStrartegyUndefined">
+            <summary>
+            鏈畾涔�
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_EEventStatus">
+            <summary>
+            鏋氫妇锛氭祦浜嬩欢鐘舵��
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EEventStatus.streamEventNormal">
+            <summary>
+            姝e父娴佷簨浠�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EEventStatus.streamEventLostFrame">
+            <summary>
+            涓㈠抚浜嬩欢
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EEventStatus.streamEventLostPacket">
+            <summary>
+            涓㈠寘浜嬩欢
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EEventStatus.streamEventImageError">
+            <summary>
+            鍥惧儚閿欒浜嬩欢
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EEventStatus.streamEventStreamChannelError">
+            <summary>
+            鍙栨祦閿欒浜嬩欢
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EEventStatus.streamEventTooManyConsecutiveResends">
+            <summary>
+            澶杩炵画閲嶄紶
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EEventStatus.streamEventTooManyLostPacket">
+            <summary>
+            澶涓㈠寘
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_EBayerDemosaic">
+            <summary>
+            鏋氫妇锛氬浘鍍忚浆鎹ayer鏍煎紡鎵�鐢ㄧ殑绠楁硶
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EBayerDemosaic.demosaicNearestNeighbor">
+            <summary>
+            鏈�杩戦偦
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EBayerDemosaic.demosaicBilinear">
+            <summary>
+            鍙岀嚎鎬�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EBayerDemosaic.demosaicEdgeSensing">
+            <summary>
+            杈圭紭妫�娴�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EBayerDemosaic.demosaicNotSupport">
+            <summary>
+            涓嶆敮鎸�
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_EVType">
+            <summary>
+            鏋氫妇锛氫簨浠剁被鍨�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EVType.offLine">
+            <summary>
+            璁惧绂荤嚎閫氱煡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EVType.onLine">
+            <summary>
+            璁惧鍦ㄧ嚎閫氱煡
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_EVideoType">
+            <summary>
+            鏋氫妇锛氳棰戞牸寮�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EVideoType.typeVideoFormatAVI">
+            <summary>
+            AVI鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EVideoType.typeVideoFormatNotSupport">
+            <summary>
+            涓嶆敮鎸�
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_EFlipType">
+            <summary>
+            鏋氫妇锛氬浘鍍忕炕杞被鍨�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EFlipType.typeFlipVertical">
+            <summary>
+            鍨傜洿(Y杞�)缈昏浆
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EFlipType.typeFlipHorizontal">
+            <summary>
+            姘村钩(X杞�)缈昏浆
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_ERotationAngle">
+            <summary>
+            鏋氫妇锛氶『鏃堕拡鏃嬭浆瑙掑害
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ERotationAngle.rotationAngle90">
+            <summary>
+            椤烘椂閽堟棆杞�90搴�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ERotationAngle.rotationAngle180">
+            <summary>
+            椤烘椂閽堟棆杞�180搴�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ERotationAngle.rotationAngle270">
+            <summary>
+            椤烘椂閽堟棆杞�270搴�
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_ESaveFileType">
+            <summary>
+            鏋氫妇锛氬浘鍍忎繚瀛樻牸寮�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ESaveFileType.typeSaveBmp">
+            <summary>
+            BMP鍥惧儚鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ESaveFileType.typeSaveJpeg">
+            <summary>
+            JPEG鍥惧儚鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ESaveFileType.typeSavePng">
+            <summary>
+            PNG鍥惧儚鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ESaveFileType.typeSaveTiff">
+            <summary>
+            TIFF鍥惧儚鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ESaveFileType.typeSaveUndefined">
+            <summary>
+            鏈畾涔夌殑鍥惧儚鏍煎紡
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_EPixelType">
+            <summary>
+            鏋氫妇锛氬浘鍍忔牸寮�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelTypeUndefined">
+            <summary>
+            Undefined
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono1p">
+            <summary>
+            Mono1p
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono2p">
+            <summary>
+            Mono2p
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono4p">
+            <summary>
+            Mono4p
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono8">
+            <summary>
+            Mono8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono8S">
+            <summary>
+            Mono8S
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono10">
+            <summary>
+            Mono10
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono10Packed">
+            <summary>
+            Mono10Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono12">
+            <summary>
+            Mono12
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono12Packed">
+            <summary>
+            Mono12Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono14">
+            <summary>
+            Mono14
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono16">
+            <summary>
+            Mono16
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGR8">
+            <summary>
+            BayGR8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayRG8">
+            <summary>
+            BayRG8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGB8">
+            <summary>
+            BayGB8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayBG8">
+            <summary>
+            BayBG8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGR10">
+            <summary>
+            BayGR10
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayRG10">
+            <summary>
+            BayRG10
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGB10">
+            <summary>
+            BayGB10
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayBG10">
+            <summary>
+            BayBG10
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGR12">
+            <summary>
+            BayGR12
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayRG12">
+            <summary>
+            BayRG12
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGB12">
+            <summary>
+            BayGB12
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayBG12">
+            <summary>
+            BayBG12
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGR10Packed">
+            <summary>
+            BayGR10Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayRG10Packed">
+            <summary>
+            BayRG10Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGB10Packed">
+            <summary>
+            BayGB10Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayBG10Packed">
+            <summary>
+            BayBG10Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGR12Packed">
+            <summary>
+            BayGR12Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayRG12Packed">
+            <summary>
+            BayRG12Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGB12Packed">
+            <summary>
+            BayGB12Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayBG12Packed">
+            <summary>
+            BayBG12Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGR16">
+            <summary>
+            BayGR16
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayRG16">
+            <summary>
+            BayRG16
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayGB16">
+            <summary>
+            BayGB16
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayBG16">
+            <summary>
+            BayBG16
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB8">
+            <summary>
+            RGB8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBGR8">
+            <summary>
+            BGR8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGBA8">
+            <summary>
+            RGBA8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBGRA8">
+            <summary>
+            BGRA8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB10">
+            <summary>
+            RGB10
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBGR10">
+            <summary>
+            BGR10
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB12">
+            <summary>
+            RGB12
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBGR12">
+            <summary>
+            BGR12
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB16">
+            <summary>
+            RGB16
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB10V1Packed">
+            <summary>
+            RGB10V1Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB10P32">
+            <summary>
+            RGB10P32
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB12V1Packed">
+            <summary>
+            RGB12V1Packed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB565P">
+            <summary>
+            RGB565P
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBGR565P">
+            <summary>
+            BGR565P
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYUV411_8_UYYVYY">
+            <summary>
+            YUV411_8_UYYVYY
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYUV422_8_UYVY">
+            <summary>
+            YUV422_8_UYVY
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYUV422_8">
+            <summary>
+            YUV422_8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYUV8_UYV">
+            <summary>
+            YUV8_UYV
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr8CbYCr">
+            <summary>
+            YCbCr8CbYCr
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr422_8">
+            <summary>
+            YCbCr422_8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr422_8_CbYCrY">
+            <summary>
+            YCbCr422_8_CbYCrY
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr411_8_CbYYCrYY">
+            <summary>
+            YCbCr411_8_CbYYCrYY
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr601_8_CbYCr">
+            <summary>
+            YCbCr601_8_CbYCr
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr601_422_8">
+            <summary>
+            YCbCr601_422_8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr601_422_8_CbYCrY">
+            <summary>
+            YCbCr601_422_8_CbYCrY
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr601_411_8_CbYYCrYY">
+            <summary>
+            YCbCr601_411_8_CbYYCrYY
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr709_8_CbYCr">
+            <summary>
+            YCbCr709_8_CbYCr
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr709_422_8">
+            <summary>
+            YCbCr709_422_8
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr709_422_8_CbYCrY">
+            <summary>
+            YCbCr709_422_8_CbYCrY
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelYCbCr709_411_8_CbYYCrYY">
+            <summary>
+            YCbCr709_411_8_CbYYCrYY
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB8Planar">
+            <summary>
+            RGB8Planar
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB10Planar">
+            <summary>
+            RGB10Planar
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB12Planar">
+            <summary>
+            RGB12Planar 
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelRGB16Planar">
+            <summary>
+            RGB16Planar
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayRG10p">
+            <summary>
+            BayerRG10p, currently used for specific project, please do not use them
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelBayRG12p">
+            <summary>
+            BayerRG12p, currently used for specific project, please do not use them
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono1c">
+            <summary>
+            mono1c, customized image format, used for binary output
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EPixelType.gvspPixelMono1e">
+            <summary>
+            mono1e, customized image format, used for displaying connected domain
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_TransmissionType">
+            <summary>
+            鏋氫妇锛氫紶杈撴ā寮�(gige)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_TransmissionType.transTypeUnicast">
+            <summary>
+            鍗曟挱妯″紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_TransmissionType.transTypeMulticast">
+            <summary>
+            缁勬挱妯″紡
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_String">
+            <summary>
+            瀛楃涓蹭俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_String.str">
+            <summary>
+            瀛楃涓�.闀垮害涓嶈秴杩�256 
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_GigEInterfaceInfo">
+            <summary>
+            GigE缃戝崱淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEInterfaceInfo.description">
+            <summary>
+            缃戝崱鎻忚堪淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEInterfaceInfo.macAddress">
+            <summary>
+            缃戝崱Mac鍦板潃
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEInterfaceInfo.ipAddress">
+            <summary>
+            璁惧Ip鍦板潃
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEInterfaceInfo.subnetMask">
+            <summary>
+            瀛愮綉鎺╃爜
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEInterfaceInfo.defaultGateWay">
+            <summary>
+            榛樿缃戝叧
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEInterfaceInfo.chReserved">
+            <summary>
+            淇濈暀
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_UsbInterfaceInfo">
+            <summary>
+            USB鎺ュ彛淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbInterfaceInfo.description">
+            <summary>
+            USB鎺ュ彛鎻忚堪淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbInterfaceInfo.vendorID">
+            <summary>
+            USB鎺ュ彛Vendor ID
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbInterfaceInfo.deviceID">
+            <summary>
+            USB鎺ュ彛璁惧ID
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbInterfaceInfo.subsystemID">
+            <summary>
+            USB鎺ュ彛Subsystem ID
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbInterfaceInfo.revision">
+            <summary>
+            USB鎺ュ彛Revision
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbInterfaceInfo.speed">
+            <summary>
+            USB鎺ュ彛speed
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbInterfaceInfo.chReserved">
+            <summary>
+            淇濈暀
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_GigEDeviceInfo">
+            <summary>
+            GigE璁惧淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEDeviceInfo.nIpConfigOptions">
+            <summary>
+            璁惧鏀寔鐨処P閰嶇疆閫夐」
+            </summary>
+            <remarks>
+            <para>value:4 鐩告満鍙敮鎸丩LA</para>
+            <para>value:5 鐩告満鏀寔LLA鍜孭ersistent IP</para>
+            <para>value:6 鐩告満鏀寔LLA鍜孌HCP</para>
+            <para>value:7 鐩告満鏀寔LLA銆丏HCP鍜孭ersistent IP</para>
+            <para>value:0 鑾峰彇澶辫触</para>
+            </remarks>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEDeviceInfo.nIpConfigCurrent">
+            <summary>
+            璁惧褰撳墠鐨処P閰嶇疆閫夐」
+            </summary>
+            <remarks>
+            <para>value:4 LLA澶勪簬娲诲姩鐘舵��</para>
+            <para>value:5 LLA鍜孭ersistent IP澶勪簬娲诲姩鐘舵��</para>
+            <para>value:6 LLA鍜孌HCP澶勪簬娲诲姩鐘舵��</para>
+            <para>value:7 LLA銆丏HCP鍜孭ersistent IP澶勪簬娲诲姩鐘舵��</para>
+            <para>value:0 鑾峰彇澶辫触</para>
+            </remarks>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEDeviceInfo.nReserved">
+            <summary>
+            淇濈暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEDeviceInfo.macAddress">
+            <summary>
+            璁惧Mac鍦板潃
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEDeviceInfo.ipAddress">
+            <summary>
+            璁惧Ip鍦板潃
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEDeviceInfo.subnetMask">
+            <summary>
+            瀛愮綉鎺╃爜
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEDeviceInfo.defaultGateWay">
+            <summary>
+            榛樿缃戝叧
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEDeviceInfo.protocolVersion">
+            <summary>
+            缃戠粶鍗忚鐗堟湰
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEDeviceInfo.ipConfiguration">
+            <summary>
+            Ip閰嶇疆鏈夋晥鎬�
+            </summary>
+            <remarks>
+            <para>Ip閰嶇疆鏈夋晥鏃跺瓧绗︿覆鍊�"Valid"</para>
+            <para>Ip閰嶇疆鏃犳晥鏃跺瓧绗︿覆鍊�"Invalid On This Interface"</para>
+            </remarks>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEDeviceInfo.chReserved">
+            <summary>
+            淇濈暀
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo">
+            <summary>
+            Usb璁惧淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.bLowSpeedSupported">
+            <summary>
+            true鏀寔锛宖alse涓嶆敮鎸侊紝鍏朵粬鍊� 闈炴硶銆�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.bFullSpeedSupported">
+            <summary>
+            true鏀寔锛宖alse涓嶆敮鎸侊紝鍏朵粬鍊� 闈炴硶銆�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.bHighSpeedSupported">
+            <summary>
+            true鏀寔锛宖alse涓嶆敮鎸侊紝鍏朵粬鍊� 闈炴硶銆�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.bSuperSpeedSupported">
+            <summary>
+            true鏀寔锛宖alse涓嶆敮鎸侊紝鍏朵粬鍊� 闈炴硶銆�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.bDriverInstalled">
+            <summary>
+            true鏀寔锛宖alse涓嶆敮鎸侊紝鍏朵粬鍊� 闈炴硶銆�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.boolReserved">
+            <summary>
+            淇濈暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.Reserved">
+            <summary>
+            淇濈暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.configurationValid">
+            <summary>
+            閰嶇疆鏈夋晥鎬�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.genCPVersion">
+            <summary>
+            GenCP 鐗堟湰
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.u3vVersion">
+            <summary>
+            U3V 鐗堟湰鍙�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.deviceGUID">
+            <summary>
+            璁惧寮曞鍙�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.familyName">
+            <summary>
+            璁惧绯诲垪鍙�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.u3vSerialNumber">
+            <summary>
+            璁惧搴忓垪鍙�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.speed">
+            <summary>
+            璁惧浼犺緭閫熷害
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.maxPower">
+            <summary>
+            璁惧鏈�澶т緵鐢甸噺
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_UsbDeviceInfo.chReserved">
+            <summary>
+            淇濈暀
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_DeviceInfo">
+            <summary>
+            璁惧閫氱敤淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.nCameraType">
+            <summary>
+            璁惧绫诲埆
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.nCameraReserved">
+            <summary>
+            淇濈暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.cameraKey">
+            <summary>
+            鍘傚晢:搴忓垪鍙�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.cameraName">
+            <summary>
+            鐢ㄦ埛鑷畾涔夊悕
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.serialNumber">
+            <summary>
+            璁惧搴忓垪鍙�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.vendorName">
+            <summary>
+            鍘傚晢
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.modelName">
+            <summary>
+            璁惧鍨嬪彿
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.manufactureInfo">
+            <summary>
+            璁惧鍒堕�犱俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.deviceVersion">
+            <summary>
+            璁惧鐗堟湰
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.cameraReserved">
+            <summary>
+            淇濈暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.deviceSpecificInfo">
+            <summary>
+            璁惧淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.nInterfaceType">
+            <summary>
+            鎺ュ彛绫诲埆
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.nInterfaceReserved">
+            <summary>
+            淇濈暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.interfaceName">
+            <summary>
+            鎺ュ彛鍚�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.interfaceReserved">
+            <summary>
+            淇濈暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.interfaceInfo">
+            <summary>
+            鎺ュ彛淇℃伅
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_DeviceInfo.DeviceSpecificInfo">
+            <summary>
+            璁惧淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.DeviceSpecificInfo.gigeDeviceInfo">
+            <summary>
+            Gige璁惧淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.DeviceSpecificInfo.usbDeviceInfo">
+            <summary>
+            Usb璁惧淇℃伅
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_DeviceInfo.InterfaceInfo">
+            <summary>
+            鎺ュ彛淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.InterfaceInfo.gigeInterfaceInfo">
+            <summary>
+            GigE缃戝崱淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceInfo.InterfaceInfo.usbInterfaceInfo">
+            <summary>
+            Usb鎺ュ彛淇℃伅
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_TransMission_Type">
+            <summary>
+            缃戠粶浼犺緭妯″紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_TransMission_Type.eTransmissionType">
+            <summary>
+            浼犺緭妯″紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_TransMission_Type.nDesIp">
+            <summary>
+            鐩爣ip鍦板潃
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_TransMission_Type.nDesPort">
+            <summary>
+            鐩爣绔彛鍙�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_TransMission_Type.nReserved">
+            <summary>
+            棰勭暀浣�
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_ErrorList">
+            <summary>
+            鍔犺浇澶辫触鐨勫睘鎬т俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ErrorList.nParamCnt">
+            <summary>
+            鍔犺浇澶辫触鐨勫睘鎬т釜鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ErrorList.paramNameList">
+            <summary>
+            鍔犺浇澶辫触鐨勫睘鎬ч泦鍚堬紝涓婇檺128
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_DeviceList">
+            <summary>
+            璁惧淇℃伅鍒楄〃
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceList.nDevNum">
+            <summary>
+            璁惧鏁伴噺
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_DeviceList.pDevInfo">
+            <summary>
+            璁惧鎭垪琛�(SDK鍐呴儴缂撳瓨)锛屾渶澶�100璁惧
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_SConnectArg">
+            <summary>
+            杩炴帴浜嬩欢淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SConnectArg.EvType">
+            <summary>
+            浜嬩欢绫诲瀷
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SConnectArg.nReserve">
+            <summary>
+            棰勭暀瀛楁
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_SParamUpdateArg">
+            <summary>
+            鍙傛暟鏇存柊浜嬩欢淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SParamUpdateArg.isPoll">
+            <summary>
+            鏄惁鏄畾鏃舵洿鏂�,true:琛ㄧず鏄畾鏃舵洿鏂帮紝false:琛ㄧず闈炲畾鏃舵洿鏂�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SParamUpdateArg.nReserve">
+            <summary>
+            棰勭暀瀛楁
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SParamUpdateArg.nParamCnt">
+            <summary>
+            鏇存柊鐨勫弬鏁颁釜鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SParamUpdateArg.pParamNameList">
+            <summary>
+            鏇存柊鐨勫弬鏁板悕绉伴泦鍚�(SDK鍐呴儴缂撳瓨)
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_SStreamArg">
+            <summary>
+            娴佷簨浠朵俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SStreamArg.channel">
+            <summary>
+            娴侀�氶亾鍙�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SStreamArg.blockId">
+            <summary>
+            娴佹暟鎹瓸lockID
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SStreamArg.timeStamp">
+            <summary>
+            鏃堕棿鎴�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SStreamArg.eStreamEventStatus">
+            <summary>
+            娴佷簨浠剁姸鎬佺爜
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SStreamArg.status">
+            <summary>
+            浜嬩欢鐘舵�侀敊璇爜
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SStreamArg.nReserve">
+            <summary>
+            棰勭暀瀛楁
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_SMsgChannelArg">
+            <summary>
+            娑堟伅閫氶亾浜嬩欢淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SMsgChannelArg.eventId">
+            <summary>
+            浜嬩欢Id
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SMsgChannelArg.channelId">
+            <summary>
+            娑堟伅閫氶亾鍙�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SMsgChannelArg.blockId">
+            <summary>
+            娴佹暟鎹瓸lockID
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SMsgChannelArg.timeStamp">
+            <summary>
+            鏃堕棿鎴�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SMsgChannelArg.nReserve">
+            <summary>
+            棰勭暀瀛楁
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SMsgChannelArg.nParamCnt">
+            <summary>
+            鍙傛暟涓暟
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SMsgChannelArg.pParamNameList">
+            <summary>
+            浜嬩欢鐩稿叧鐨勫睘鎬у悕鍒楅泦鍚�(SDK鍐呴儴缂撳瓨)
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_ChunkDataInfo">
+            <summary>
+            Chunk鏁版嵁淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ChunkDataInfo.chunkID">
+            <summary>
+            ChunkID
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ChunkDataInfo.nParamCnt">
+            <summary>
+            灞炴�у悕涓暟
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_ChunkDataInfo.pParamNameList">
+            <summary>
+            Chunk鏁版嵁瀵瑰簲鐨勫睘鎬у悕闆嗗悎(SDK鍐呴儴缂撳瓨)
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_FrameInfo">
+            <summary>
+            甯у浘鍍忎俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.blockId">
+            <summary>
+            甯d(浠呭GigE/Usb/PCIe鐩告満鏈夋晥)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.status">
+            <summary>
+            鏁版嵁甯х姸鎬�(0鏄甯哥姸鎬�)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.width">
+            <summary>
+            鍥惧儚瀹藉害
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.height">
+            <summary>
+            鍥惧儚楂樺害
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.size">
+            <summary>
+            鍥惧儚澶у皬
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.pixelFormat">
+            <summary>
+            鍥惧儚鍍忕礌鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.timeStamp">
+            <summary>
+            鍥惧儚鏃堕棿鎴�(浠呭GigE/Usb/PCIe鐩告満鏈夋晥)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.chunkCount">
+            <summary>
+            甯ф暟鎹腑鍖呭惈鐨凜hunk涓暟(浠呭GigE/Usb鐩告満鏈夋晥)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.paddingX">
+            <summary>
+            鍥惧儚paddingX(浠呭GigE/Usb/PCIe鐩告満鏈夋晥)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.paddingY">
+            <summary>
+            鍥惧儚paddingY(浠呭GigE/Usb/PCIe鐩告満鏈夋晥)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.recvFrameTime">
+            <summary>
+            鍥惧儚鍦ㄧ綉缁滀紶杈撴墍鐢ㄧ殑鏃堕棿(鍗曚綅:寰,闈濭igE鐩告満璇ュ�间负0)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FrameInfo.nReserved">
+            <summary>
+            棰勭暀瀛楁
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_Frame">
+            <summary>
+            甯у浘鍍忔暟鎹俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_Frame.frameHandle">
+            <summary>
+            甯у浘鍍忓彞鏌�(SDK鍐呴儴甯х鐞嗙敤)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_Frame.pData">
+            <summary>
+            甯у浘鍍忔暟鎹殑鍐呭瓨棣栧湴鍧�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_Frame.frameInfo">
+            <summary>
+            甯т俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_Frame.nReserved">
+            <summary>
+            棰勭暀瀛楁
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_PCIEStreamStatsInfo">
+            <summary>
+            PCIE璁惧缁熻娴佷俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PCIEStreamStatsInfo.imageError">
+            <summary>
+            鍥惧儚閿欒鐨勫抚鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PCIEStreamStatsInfo.lostPacketBlock">
+            <summary>
+            涓㈠寘鐨勫抚鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PCIEStreamStatsInfo.nReserved0">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PCIEStreamStatsInfo.imageReceived">
+            <summary>
+            姝e父鑾峰彇鐨勫抚鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PCIEStreamStatsInfo.fps">
+            <summary>
+            甯х巼
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PCIEStreamStatsInfo.bandwidth">
+            <summary>
+            甯﹀(Mbps)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PCIEStreamStatsInfo.nReserved">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_U3VStreamStatsInfo">
+            <summary>
+            U3V璁惧缁熻娴佷俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_U3VStreamStatsInfo.imageError">
+            <summary>
+            鍥惧儚閿欒鐨勫抚鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_U3VStreamStatsInfo.lostPacketBlock">
+            <summary>
+            涓㈠寘鐨勫抚鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_U3VStreamStatsInfo.nReserved0">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_U3VStreamStatsInfo.imageReceived">
+            <summary>
+            姝e父鑾峰彇鐨勫抚鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_U3VStreamStatsInfo.fps">
+            <summary>
+            甯х巼
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_U3VStreamStatsInfo.bandwidth">
+            <summary>
+            甯﹀(Mbps)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_U3VStreamStatsInfo.nReserved">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_GigEStreamStatsInfo">
+            <summary>
+            Gige璁惧缁熻娴佷俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEStreamStatsInfo.nReserved0">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEStreamStatsInfo.imageError">
+            <summary>
+            鍥惧儚閿欒鐨勫抚鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEStreamStatsInfo.lostPacketBlock">
+            <summary>
+            涓㈠寘鐨勫抚鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEStreamStatsInfo.nReserved1">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEStreamStatsInfo.nReserved2">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEStreamStatsInfo.imageReceived">
+            <summary>
+            姝e父鑾峰彇鐨勫抚鏁�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEStreamStatsInfo.fps">
+            <summary>
+            甯х巼
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEStreamStatsInfo.bandwidth">
+            <summary>
+            甯﹀(Mbps)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_GigEStreamStatsInfo.nReserved">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_StreamStatisticsInfo">
+            <summary>
+            缁熻娴佷俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_StreamStatisticsInfo.nCameraType">
+            <summary>
+            璁惧绫诲瀷
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_StreamStatisticsInfo.pcieStatisticsInfo">
+            <summary>
+            PCIE璁惧缁熻淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_StreamStatisticsInfo.u3vStatisticsInfo">
+            <summary>
+            U3V璁惧缁熻淇℃伅
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_StreamStatisticsInfo.gigeStatisticsInfo">
+            <summary>
+            Gige璁惧缁熻淇℃伅
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_EnumEntryInfo">
+            <summary>
+            鏋氫妇灞炴�х殑鏋氫妇鍊间俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EnumEntryInfo.value">
+            <summary>
+            鏋氫妇鍊�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EnumEntryInfo.name">
+            <summary>
+            symbol鍚�
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_EnumEntryList">
+            <summary>
+            鏋氫妇灞炴�х殑鍙鏋氫妇鍊煎垪琛ㄤ俊鎭�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EnumEntryList.nEnumEntryBufferSize">
+            <summary>
+            瀛樻斁鏋氫妇鍊煎唴瀛樺ぇ灏�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_EnumEntryList.pEnumEntryInfo">
+            <summary>
+            瀛樻斁鍙鏋氫妇鍊煎垪琛�(璋冪敤鑰呭垎閰嶇紦瀛�)
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_PixelConvertParam">
+            <summary>
+            鍍忕礌杞崲缁撴瀯浣�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.nWidth">
+            <summary>
+            鍥惧儚瀹�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.nHeight">
+            <summary>
+            鍥惧儚楂�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.ePixelFormat">
+            <summary>
+            鍍忕礌鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.pSrcData">
+            <summary>
+            杈撳叆鍥惧儚鏁版嵁
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.nSrcDataLen">
+            <summary>
+            杈撳叆鍥惧儚闀垮害
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.nPaddingX">
+            <summary>
+            鍥惧儚瀹藉~鍏�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.nPaddingY">
+            <summary>
+            鍥惧儚楂樺~鍏�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.eBayerDemosaic">
+            <summary>
+            杞崲Bayer鏍煎紡绠楁硶
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.eDstPixelFormat">
+            <summary>
+            鐩爣鍍忕礌鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.pDstBuf">
+            <summary>
+            杈撳嚭鏁版嵁缂撳瓨(璋冪敤鑰呭垎閰嶇紦瀛�)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.nDstBufSize">
+            <summary>
+            鎻愪緵鐨勮緭鍑虹紦鍐插尯澶у皬
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.nDstDataLen">
+            <summary>
+            杈撳嚭鏁版嵁闀垮害
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_PixelConvertParam.nReserved">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_FlipImageParam">
+            <summary>
+            鍥惧儚缈昏浆缁撴瀯浣�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FlipImageParam.nWidth">
+            <summary>
+            鍥惧儚瀹�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FlipImageParam.nHeight">
+            <summary>
+            鍥惧儚楂�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FlipImageParam.ePixelFormat">
+            <summary>
+            鍍忕礌鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FlipImageParam.eFlipType">
+            <summary>
+            缈昏浆绫诲瀷
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FlipImageParam.pSrcData">
+            <summary>
+            杈撳叆鍥惧儚鏁版嵁
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FlipImageParam.nSrcDataLen">
+            <summary>
+            杈撳叆鍥惧儚闀垮害
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FlipImageParam.pDstBuf">
+            <summary>
+            杈撳嚭鏁版嵁缂撳瓨(璋冪敤鑰呭垎閰嶇紦瀛�)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FlipImageParam.nDstBufSize">
+            <summary>
+            鎻愪緵鐨勮緭鍑虹紦鍐插尯澶у皬
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FlipImageParam.nDstDataLen">
+            <summary>
+            杈撳嚭鏁版嵁闀垮害
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_FlipImageParam.nReserved">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_RotateImageParam">
+            <summary>
+            鍥惧儚鏃嬭浆缁撴瀯浣�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_RotateImageParam.nWidth">
+            <summary>
+            鍥惧儚瀹�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_RotateImageParam.nHeight">
+            <summary>
+            鍥惧儚楂�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_RotateImageParam.ePixelFormat">
+            <summary>
+            鍍忕礌鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_RotateImageParam.eRotationAngle">
+            <summary>
+            鏃嬭浆瑙掑害
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_RotateImageParam.pSrcData">
+            <summary>
+            杈撳叆鍥惧儚鏁版嵁
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_RotateImageParam.nSrcDataLen">
+            <summary>
+            杈撳叆鍥惧儚闀垮害
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_RotateImageParam.pDstBuf">
+            <summary>
+            杈撳嚭鏁版嵁缂撳瓨(璋冪敤鑰呭垎閰嶇紦瀛�)
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_RotateImageParam.nDstBufSize">
+            <summary>
+            鎻愪緵鐨勮緭鍑虹紦鍐插尯澶у皬
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_RotateImageParam.nDstDataLen">
+            <summary>
+            杈撳嚭鏁版嵁闀垮害
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_RotateImageParam.nReserved">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam">
+            <summary>
+            淇濆瓨鍥惧儚缁撴瀯浣�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam.nWidth">
+            <summary>
+            鍥惧儚瀹�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam.nHeight">
+            <summary>
+            鍥惧儚楂�
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam.ePixelFormat">
+            <summary>
+            鍍忕礌鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam.pSrcData">
+            <summary>
+            杈撳叆鍥惧儚鏁版嵁
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam.nSrcDataLen">
+            <summary>
+            杈撳叆鏁版嵁澶у皬
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam.eImageType">
+            <summary>
+            杈撳叆鍥剧墖鏍煎紡
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam.pImagePath">
+            <summary>
+            杈撳叆鏂囦欢璺緞
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam.nQuality">
+            <summary>
+            JPG缂栫爜璐ㄩ噺(50-99]锛孭NG缂栫爜璐ㄩ噺[0-9]
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam.eBayerDemosaic">
+            <summary>
+            杞崲Bayer鏍煎紡绠楁硶 
+            </summary>
+        </member>
+        <member name="F:MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam.nReserved">
+            <summary>
+            棰勭暀
+            </summary>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_ConnectCallBack">
+            <summary>
+            璁惧杩炴帴鐘舵�佷簨浠跺洖璋冨嚱鏁板0鏄�
+            </summary>
+            <param name="pConnectArg">[in] 鍥炶皟鏃朵富鍔ㄦ帹閫佺殑璁惧杩炴帴鐘舵�佷簨浠朵俊鎭�</param>
+            <param name="pUser">[in] 鐢ㄦ埛鑷畾涔夋暟鎹�</param>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_ParamUpdateCallBack">
+            <summary>
+            鍙傛暟鏇存柊浜嬩欢鍥炶皟鍑芥暟澹版槑
+            </summary>
+            <param name="pParamUpdateArg">[in] 鍥炶皟鏃朵富鍔ㄦ帹閫佺殑鍙傛暟鏇存柊浜嬩欢淇℃伅</param>
+            <param name="pUser">[in] 鐢ㄦ埛鑷畾涔夋暟鎹�</param>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_StreamCallBack">
+            <summary>
+            娴佷簨浠跺洖璋冨嚱鏁板0鏄�
+            </summary>
+            <param name="pStreamArg">[in] 鍥炶皟鏃朵富鍔ㄦ帹閫佺殑娴佷簨浠朵俊鎭�</param>
+            <param name="pUser">[in] 鐢ㄦ埛鑷畾涔夋暟鎹�</param>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_MsgChannelCallBack">
+            <summary>
+            娑堟伅閫氶亾浜嬩欢鍥炶皟鍑芥暟澹版槑
+            </summary>
+            <param name="pMsgChannelArg">[in] 鍥炶皟鏃朵富鍔ㄦ帹閫佺殑娑堟伅閫氶亾浜嬩欢淇℃伅</param>
+            <param name="pUser">[in] 鐢ㄦ埛鑷畾涔夋暟鎹�</param>
+        </member>
+        <member name="T:MVSDK_Net.IMVDefine.IMV_FrameCallBack">
+            <summary>
+            甯ф暟鎹俊鎭洖璋冨嚱鏁板0鏄�
+            </summary>
+            <param name="pFrame">[in]鍥炶皟鏃朵富鍔ㄦ帹閫佺殑甯т俊鎭�</param>
+            <param name="pUser">[in] 鐢ㄦ埛鑷畾涔夋暟鎹�</param>
+        </member>
+        <member name="T:MVSDK_Net.MyCamera">
+            <summary>
+            鐩告満绫�
+            </summary>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.#ctor">
+            <summary>
+            鐩告満鏋勯�犲嚱鏁�
+            </summary>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetVersion">
+            <summary>
+            鑾峰彇鐗堟湰淇℃伅
+            </summary>
+            <returns>鎴愬姛鏃惰繑鍥炵増鏈俊鎭紝澶辫触鏃惰繑鍥濶ULL</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_EnumDevices(MVSDK_Net.IMVDefine.IMV_DeviceList@,System.UInt32)">
+            <summary>
+            鏋氫妇璁惧
+            </summary>
+            <param name="pDeviceList">[OUT] 璁惧鍒楄〃</param>
+            <param name="interfaceType">[IN] 寰呮灇涓剧殑鎺ュ彛绫诲瀷, 绫诲瀷鍙换鎰忕粍鍚�,濡� interfaceTypeGige | interfaceTypeUsb3</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            <para>1銆佸綋interfaceType = interfaceTypeAll  鏃讹紝鏋氫妇鎵�鏈夋帴鍙d笅鐨勫湪绾胯澶�</para>
+            <para>2銆佸綋interfaceType = interfaceTypeGige 鏃讹紝鏋氫妇鎵�鏈塆igE缃戝彛涓嬬殑鍦ㄧ嚎璁惧</para>
+            <para>3銆佸綋interfaceType = interfaceTypeUsb3 鏃讹紝鏋氫妇鎵�鏈塙SB鎺ュ彛涓嬬殑鍦ㄧ嚎璁惧</para>
+            <para>4銆佸綋interfaceType = interfaceTypeCL   鏃讹紝鏋氫妇鎵�鏈塁ameraLink鎺ュ彛涓嬬殑鍦ㄧ嚎璁惧</para>
+            <para>5銆佽鎺ュ彛涓嬬殑interfaceType鏀寔浠绘剰鎺ュ彛绫诲瀷鐨勭粍鍚�,濡傦紝鑻ユ灇涓炬墍鏈塆igE缃戝彛鍜孶SB3鎺ュ彛涓嬬殑鍦ㄧ嚎璁惧鏃�,</para>
+            <para>鍙皢interfaceType璁剧疆涓� interfaceType = interfaceTypeGige | interfaceTypeUsb3,鍏跺畠鎺ュ彛绫诲瀷缁勫悎浠ユ绫绘帹</para>
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_EnumDevicesByUnicast(MVSDK_Net.IMVDefine.IMV_DeviceList@,System.String)">
+            <summary>
+            浠ュ崟鎾舰寮忔灇涓捐澶�, 浠呴檺Gige璁惧浣跨敤
+            </summary>
+            <param name="pDeviceList">[OUT] 璁惧鍒楄〃</param>
+            <param name="pIpAddress">[IN] 璁惧鐨処P鍦板潃</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_CreateHandle(MVSDK_Net.IMVDefine.IMV_ECreateHandleMode,System.Int32,System.String)">
+            <summary>
+            閫氳繃鎸囧畾鏍囩ず绗﹀垱寤鸿澶囧彞鏌勶紝濡傛寚瀹氱储寮曘�佽澶囬敭銆佽澶囪嚜瀹氫箟鍚嶃�両P鍦板潃.
+            </summary>
+            <param name="mode">[IN] 鍒涘缓璁惧鏂瑰紡</param>
+            <param name="cameraIndex">[IN] 鎸囧畾绱㈠紩</param>
+            <param name="cameraStr">[IN] 璁惧閿�佽澶囪嚜瀹氫箟鍚嶃�両P鍦板潃</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_DestroyHandle">
+            <summary>
+            閿�姣佽澶囧彞鏌�
+            </summary>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetDeviceInfo(MVSDK_Net.IMVDefine.IMV_DeviceInfo@)">
+            <summary>
+            鑾峰彇璁惧淇℃伅
+            </summary>
+            <param name="pDevInfo">[OUT] 璁惧淇℃伅</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_Open">
+            <summary>
+            鎵撳紑璁惧
+            </summary>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_OpenEx(MVSDK_Net.IMVDefine.IMV_ECameraAccessPermission)">
+            <summary>
+            鎵撳紑璁惧
+            </summary>
+            <param name="accessPermission">[IN] 鎺у埗閫氶亾鏉冮檺(IMV_Open榛樿浣跨敤accessPermissionControl鏉冮檺)</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_IsOpen">
+            <summary>
+            鍒ゆ柇璁惧鏄惁宸叉墦寮�
+            </summary>
+            <returns>鎵撳紑鐘舵�侊紝杩斿洖true锛涘叧闂姸鎬佹垨鑰呮帀绾跨姸鎬侊紝杩斿洖false</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_Close">
+            <summary>
+            鍏抽棴璁惧
+            </summary>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GIGE_SetTransmissionType(MVSDK_Net.IMVDefine.IMV_TransMission_Type)">
+            <summary>
+            璁剧疆浼犺緭绫诲瀷
+            </summary>
+            <param name="transmissionType">浼犺緭绫诲瀷缁撴瀯浣�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GIGE_ForceIpAddress(System.String,System.String,System.String)">
+            <summary>
+            淇敼璁惧IP, 浠呴檺Gige璁惧浣跨敤
+            </summary>
+            <param name="pIpAddress">[IN] IP鍦板潃</param>
+            <param name="pSubnetMask">[IN] 瀛愮綉鎺╃爜</param>
+            <param name="pGateway">[IN] 榛樿缃戝叧</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            <para>1銆佽皟鐢ㄨ鍑芥暟鏃跺鏋減SubnetMask鍜宲Gateway閮借缃簡鏈夋晥鍊硷紝鍒欎互姝ゆ湁鏁堝�间负鍑�;</para>
+            <para>2銆佽皟鐢ㄨ鍑芥暟鏃跺鏋減SubnetMask鍜宲Gateway閮借缃簡NULL锛屽垯鍐呴儴瀹炵幇鏃剁敤瀹冩墍杩炴帴缃戝崱鐨勫瓙缃戞帺鐮佸拰缃戝叧浠f浛</para>
+            <para>3銆佽皟鐢ㄨ鍑芥暟鏃跺鏋減SubnetMask鍜宲Gateway涓よ�呬腑鍏朵腑涓�涓负NULL锛屽彟涓�涓潪NULL锛屽垯杩斿洖閿欒</para>
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GIGE_GetAccessPermission(MVSDK_Net.IMVDefine.IMV_ECameraAccessPermission@)">
+            <summary>
+            鑾峰彇璁惧鐨勫綋鍓嶈闂潈闄�, 浠呴檺Gige璁惧浣跨敤
+            </summary>
+            <param name="pAccessPermission">[OUT] 璁惧鐨勫綋鍓嶈闂潈闄�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GIGE_SetAnswerTimeout(System.UInt32)">
+            <summary>
+            璁剧疆璁惧瀵箂dk鍛戒护鐨勫搷搴旇秴鏃舵椂闂�,浠呴檺Gige璁惧浣跨敤
+            </summary>
+            <param name="timeout">[IN] 瓒呮椂鏃堕棿锛屽崟浣峬s</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_DownLoadGenICamXML(System.String)">
+            <summary>
+            涓嬭浇璁惧鎻忚堪XML鏂囦欢锛屽苟淇濆瓨鍒版寚瀹氳矾寰勶紝濡傦細D:\\xml.zip
+            </summary>
+            <param name="pFullFileName">[IN] 鏂囦欢瑕佷繚瀛樼殑璺緞</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SaveDeviceCfg(System.String)">
+            <summary>
+            淇濆瓨璁惧閰嶇疆鍒版寚瀹氱殑浣嶇疆銆傚悓鍚嶆枃浠跺凡瀛樺湪鏃讹紝瑕嗙洊銆�
+            </summary>
+            <param name="pFullFileName">[IN] 瀵煎嚭鐨勮澶囬厤缃枃浠跺叏鍚�(鍚矾寰�)锛屽锛欴:\\config.xml 鎴� D:\\config.mvcfg</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_LoadDeviceCfg(System.String,MVSDK_Net.IMVDefine.IMV_ErrorList@)">
+            <summary>
+            浠庢枃浠跺姞杞借澶噚ml閰嶇疆
+            </summary>
+            <param name="pFullFileName">[IN] 璁惧閰嶇疆(xml)鏂囦欢鍏ㄥ悕(鍚矾寰�)锛屽锛欴:\\config.xml 鎴� D:\\config.mvcfg</param>
+            <param name="pErrorList">[OUT] 鍔犺浇澶辫触鐨勫睘鎬у悕鍒楄〃銆傚瓨鏀惧姞杞藉け璐ョ殑灞炴�т笂闄愪负IMV_MAX_ERROR_LIST_NUM銆�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_WriteUserPrivateData(System.IntPtr,System.UInt32@)">
+            <summary>
+            鍐欑敤鎴疯嚜瀹氫箟鏁版嵁銆傜浉鏈哄唴閮ㄤ繚鐣�32768瀛楄妭鐢ㄤ簬鐢ㄦ埛瀛樺偍鑷畾涔夋暟鎹�(姝ゅ姛鑳介拡瀵规湰鍝佺墝鐩告満锛屽叾瀹冨搧鐗岀浉鏈烘棤姝ゅ姛鑳�)
+            </summary>
+            <param name="pBuffer">[IN] 鏁版嵁缂撳啿鐨勬寚閽�</param>
+            <param name="pLength">[IN] 鏈熸湜鍐欏叆鐨勫瓧鑺傛暟 [OUT] 瀹為檯鍐欏叆鐨勫瓧鑺傛暟</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_ReadUserPrivateData(System.IntPtr,System.UInt32@)">
+            <summary>
+            璇荤敤鎴疯嚜瀹氫箟鏁版嵁銆傜浉鏈哄唴閮ㄤ繚鐣�32768瀛楄妭鐢ㄤ簬鐢ㄦ埛瀛樺偍鑷畾涔夋暟鎹�(姝ゅ姛鑳介拡瀵规湰鍝佺墝鐩告満锛屽叾瀹冨搧鐗岀浉鏈烘棤姝ゅ姛鑳�)
+            </summary>
+            <param name="pBuffer">[OUT] 鏁版嵁缂撳啿鐨勬寚閽�</param>
+            <param name="pLength">[IN] 鏈熸湜璇诲嚭鐨勫瓧鑺傛暟 [OUT] 瀹為檯璇诲嚭鐨勫瓧鑺傛暟</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_WriteUARTData(System.IntPtr,System.UInt32@)">
+            <summary>
+            寰�鐩告満涓插彛瀵勫瓨鍣ㄥ啓鏁版嵁锛屾瘡娆″啓浼氭竻闄ゆ帀涓婃鐨勬暟鎹�(姝ゅ姛鑳藉彧鏀寔鍖呭惈涓插彛鍔熻兘鐨勬湰鍝佺墝鐩告満)
+            </summary>
+            <param name="pBuffer">[IN] 鏁版嵁缂撳啿鐨勬寚閽�</param>
+            <param name="pLength">[IN] 鏈熸湜鍐欏叆鐨勫瓧鑺傛暟 [OUT] 瀹為檯鍐欏叆鐨勫瓧鑺傛暟</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_ReadUARTData(System.IntPtr,System.UInt32@)">
+            <summary>
+            浠庣浉鏈轰覆鍙e瘎瀛樺櫒璇诲彇涓插彛鏁版嵁(姝ゅ姛鑳藉彧鏀寔鍖呭惈涓插彛鍔熻兘鐨勬湰鍝佺墝鐩告満 )
+            </summary>
+            <param name="pBuffer">[OUT] 鏁版嵁缂撳啿鐨勬寚閽�</param>
+            <param name="pLength">[IN] 鏈熸湜璇诲嚭鐨勫瓧鑺傛暟 [OUT] 瀹為檯璇诲嚭鐨勫瓧鑺傛暟</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SubscribeConnectArg(MVSDK_Net.IMVDefine.IMV_ConnectCallBack,System.IntPtr)">
+            <summary>
+            璁惧杩炴帴鐘舵�佷簨浠跺洖璋冩敞鍐�
+            </summary>
+            <param name="proc">[IN] 璁惧杩炴帴鐘舵�佷簨浠跺洖璋冨嚱鏁�</param>
+            <param name="pUser">[IN] 鐢ㄦ埛鑷畾涔夋暟鎹�, 鍙涓篘ULL</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            鍙敮鎸佷竴涓洖璋冨嚱鏁�,涓旇澶囧叧闂悗锛屾敞鍐屼細澶辨晥锛屾墦寮�璁惧鍚庨渶閲嶆柊娉ㄥ唽
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SubscribeParamUpdateArg(MVSDK_Net.IMVDefine.IMV_ParamUpdateCallBack,System.IntPtr)">
+            <summary>
+            鍙傛暟鏇存柊浜嬩欢鍥炶皟娉ㄥ唽
+            </summary>
+            <param name="proc">[IN] 鍙傛暟鏇存柊娉ㄥ唽鐨勪簨浠跺洖璋冨嚱鏁�</param>
+            <param name="pUser">[IN] 鐢ㄦ埛鑷畾涔夋暟鎹�, 鍙涓篘ULL</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            鍙敮鎸佷竴涓洖璋冨嚱鏁�,涓旇澶囧叧闂悗锛屾敞鍐屼細澶辨晥锛屾墦寮�璁惧鍚庨渶閲嶆柊娉ㄥ唽
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SubscribeStreamArg(MVSDK_Net.IMVDefine.IMV_StreamCallBack,System.IntPtr)">
+            <summary>
+            娴侀�氶亾浜嬩欢鍥炶皟娉ㄥ唽
+            </summary>
+            <param name="proc">[IN] 娴侀�氶亾浜嬩欢鍥炶皟娉ㄥ唽鍑芥暟</param>
+            <param name="pUser">[IN] 鐢ㄦ埛鑷畾涔夋暟鎹�, 鍙涓篘ULL</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            鍙敮鎸佷竴涓洖璋冨嚱鏁�,涓旇澶囧叧闂悗锛屾敞鍐屼細澶辨晥锛屾墦寮�璁惧鍚庨渶閲嶆柊娉ㄥ唽
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SubscribeMsgChannelArg(MVSDK_Net.IMVDefine.IMV_MsgChannelCallBack,System.IntPtr)">
+            <summary>
+            娑堟伅閫氶亾浜嬩欢鍥炶皟娉ㄥ唽
+            </summary>
+            <param name="proc">[IN] 娑堟伅閫氶亾浜嬩欢鍥炶皟娉ㄥ唽鍑芥暟</param>
+            <param name="pUser">[IN] 鐢ㄦ埛鑷畾涔夋暟鎹�, 鍙涓篘ULL</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            鍙敮鎸佷竴涓洖璋冨嚱鏁�,涓旇澶囧叧闂悗锛屾敞鍐屼細澶辨晥锛屾墦寮�璁惧鍚庨渶閲嶆柊娉ㄥ唽
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SetBufferCount(System.UInt32)">
+            <summary>
+            璁剧疆甯ф暟鎹紦瀛樹釜鏁�
+            </summary>
+            <param name="nSize">[IN] 缂撳瓨鏁伴噺</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            涓嶈兘鍦ㄦ媺娴佽繃绋嬩腑璁剧疆
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_ClearFrameBuffer">
+            <summary>
+            娓呴櫎甯ф暟鎹紦瀛�
+            </summary>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GIGE_SetInterPacketTimeout(System.UInt32)">
+            <summary>
+            璁剧疆椹卞姩鍖呴棿闅旀椂闂�(MS),浠呭Gige璁惧鏈夋晥
+            </summary>
+            <param name="nTimeout">[IN] 鍖呴棿闅旀椂闂达紝鍗曚綅鏄绉�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            瑙﹀彂妯″紡灏惧寘涓㈠け閲嶄紶鏈哄埗
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GIGE_SetSingleResendMaxPacketNum(System.UInt32)">
+            <summary>
+            璁剧疆鍗曟閲嶄紶鏈�澶у寘涓暟, 浠呭GigE璁惧鏈夋晥
+            </summary>
+            <param name="maxPacketNum">[IN] 鍗曟閲嶄紶鏈�澶у寘涓暟</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            maxPacketNum涓�0鏃讹紝璇ュ姛鑳芥棤鏁�
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GIGE_SetMaxLostPacketNum(System.UInt32)">
+            <summary>
+            璁剧疆鍚屼竴甯ф渶澶т涪鍖呯殑鏁伴噺,浠呭GigE璁惧鏈夋晥
+            </summary>
+            <param name="maxLostPacketNum">[IN] 鏈�澶т涪鍖呯殑鏁伴噺</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            maxLostPacketNum涓�0鏃讹紝璇ュ姛鑳芥棤鏁�
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_USB_SetUrbTransfer(System.UInt32,System.UInt32)">
+            <summary>
+            璁剧疆U3V璁惧鐨勪紶杈撴暟鎹潡鐨勬暟閲忓拰澶у皬,浠呭USB璁惧鏈夋晥
+            </summary>
+            <param name="nNum">[IN] 浼犺緭鏁版嵁鍧楃殑鏁伴噺(鑼冨洿:5-256)</param>
+            <param name="nSize">[IN] 浼犺緭鏁版嵁鍧楃殑澶у皬(鑼冨洿:8-512, 鍗曚綅:KByte)</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            <para>1銆佷紶杈撴暟鎹潡鏁伴噺锛岃寖鍥�5 - 256, 榛樿涓�64锛岄珮鍒嗚鲸鐜囬珮甯х巼鏃跺彲浠ラ�傚綋澧炲姞璇ュ�硷紱澶氬彴鐩告満鍏卞悓浣跨敤鏃讹紝鍙互閫傚綋鍑忓皬璇ュ��</para>
+            <para>2銆佷紶杈撴瘡涓暟鎹潡澶у皬锛岃寖鍥�8 - 512, 榛樿涓�64锛屽崟浣嶆槸KByte</para>
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_StartGrabbing">
+            <summary>
+            寮�濮嬪彇娴�
+            </summary>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_StartGrabbingEx(System.UInt64,MVSDK_Net.IMVDefine.IMV_EGrabStrategy)">
+            <summary>
+            寮�濮嬪彇娴�
+            </summary>
+            <param name="maxImagesGrabbed">[IN] 鍏佽鏈�澶氱殑鍙栧抚鏁帮紝杈惧埌鎸囧畾鍙栧抚鏁板悗鍋滄鍙栨祦锛屽鏋滀负0锛岃〃绀哄拷鐣ユ鍙傛暟杩炵画鍙栨祦(IMV_StartGrabbing榛樿0)</param>
+            <param name="strategy">[IN] 鍙栨祦绛栫暐,(IMV_StartGrabbing榛樿浣跨敤grabStrartegySequential绛栫暐鍙栨祦)</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_IsGrabbing">
+            <summary>
+            鍒ゆ柇璁惧鏄惁姝e湪鍙栨祦
+            </summary>
+            <returns>姝e湪鍙栨祦锛岃繑鍥瀟rue锛涗笉鍦ㄥ彇娴侊紝杩斿洖false</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_StopGrabbing">
+            <summary>
+            鍋滄鍙栨祦
+            </summary>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_AttachGrabbing(MVSDK_Net.IMVDefine.IMV_FrameCallBack,System.IntPtr)">
+            <summary>
+            娉ㄥ唽甯ф暟鎹洖璋冨嚱鏁�(寮傛鑾峰彇甯ф暟鎹満鍒�)
+            </summary>
+            <param name="proc">[IN] 甯ф暟鎹俊鎭洖璋冨嚱鏁帮紝寤鸿涓嶈鍦ㄨ鍑芥暟涓鐞嗚�楁椂鐨勬搷浣滐紝鍚﹀垯浼氶樆濉炲悗缁抚鏁版嵁鐨勫疄鏃舵��</param>
+            <param name="pUser">[IN] 鐢ㄦ埛鑷畾涔夋暟鎹�, 鍙涓篘ULL</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            <para>璇ュ紓姝ヨ幏鍙栧抚鏁版嵁鏈哄埗鍜屽悓姝ヨ幏鍙栧抚鏁版嵁鏈哄埗(IMV_GetFrame)浜掓枼锛屽浜庡悓涓�璁惧锛岀郴缁熶腑涓よ�呭彧鑳介�夊叾涓�</para>
+            <para>鍙敮鎸佷竴涓洖璋冨嚱鏁�, 涓旇澶囧叧闂悗锛屾敞鍐屼細澶辨晥锛屾墦寮�璁惧鍚庨渶閲嶆柊娉ㄥ唽</para>
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetFrame(MVSDK_Net.IMVDefine.IMV_Frame@,System.UInt32)">
+            <summary>
+            鑾峰彇涓�甯у浘鍍�(鍚屾鑾峰彇甯ф暟鎹満鍒�)
+            </summary>
+            <param name="frame">[OUT] 甯ф暟鎹俊鎭�</param>
+            <param name="timeout">[IN] 鑾峰彇涓�甯у浘鍍忕殑瓒呮椂鏃堕棿,INFINITE鏃惰〃绀烘棤闄愮瓑寰�,鐩村埌鏀跺埌涓�甯ф暟鎹垨鑰呭仠姝㈠彇娴併�傚崟浣嶆槸姣</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            <para>璇ユ帴鍙d笉鏀寔澶氱嚎绋嬭皟鐢ㄣ��</para>
+            <para>璇ュ悓姝ヨ幏鍙栧抚鏈哄埗鍜屽紓姝ヨ幏鍙栧抚鏈哄埗(IMV_AttachGrabbing)浜掓枼,瀵逛簬鍚屼竴璁惧锛岀郴缁熶腑涓よ�呭彧鑳介�夊叾涓�銆�</para>
+            <para>浣跨敤鍐呴儴缂撳瓨鑾峰彇鍥惧儚锛岄渶瑕両MV_ReleaseFrame杩涜閲婃斁鍥惧儚缂撳瓨銆�</para>
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_ReleaseFrame(MVSDK_Net.IMVDefine.IMV_Frame@)">
+            <summary>
+            閲婃斁鍥惧儚缂撳瓨
+            </summary>
+            <param name="frame">[IN] 甯ф暟鎹俊鎭�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_CloneFrame(MVSDK_Net.IMVDefine.IMV_Frame@,MVSDK_Net.IMVDefine.IMV_Frame@)">
+            <summary>
+            甯ф暟鎹繁鎷疯礉鍏嬮殕
+            </summary>
+            <param name="frame">[IN] 鍏嬮殕婧愬抚鏁版嵁淇℃伅</param>
+            <param name="pCloneFrame">[OUT] 鏂扮殑甯ф暟鎹俊鎭�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            浣跨敤IMV_ReleaseFrame杩涜閲婃斁鍥惧儚缂撳瓨銆�
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetChunkDataByIndex(MVSDK_Net.IMVDefine.IMV_Frame@,System.UInt32,MVSDK_Net.IMVDefine.IMV_ChunkDataInfo@)">
+            <summary>
+            鑾峰彇Chunk鏁版嵁(浠呭GigE/Usb鐩告満鏈夋晥)
+            </summary>
+            <param name="frame">[IN] 甯ф暟鎹俊鎭�</param>
+            <param name="index">[IN] 绱㈠紩ID</param>
+            <param name="pChunkDataInfo">[OUT] Chunk鏁版嵁淇℃伅</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetStatisticsInfo(MVSDK_Net.IMVDefine.IMV_StreamStatisticsInfo@)">
+            <summary>
+            鑾峰彇娴佺粺璁′俊鎭�(IMV_StartGrabbing / IMV_StartGrabbingEx鎵ц鍚庤皟鐢�)
+            </summary>
+            <param name="param">[OUT] 娴佺粺璁′俊鎭暟鎹�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_ResetStatisticsInfo">
+            <summary>
+            閲嶇疆娴佺粺璁′俊鎭�(IMV_StartGrabbing / IMV_StartGrabbingEx鎵ц鍚庤皟鐢�)
+            </summary>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_FeatureIsAvailable(System.String)">
+            <summary>
+            鍒ゆ柇灞炴�ф槸鍚﹀彲鐢�
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <returns>鍙敤锛岃繑鍥瀟rue锛涗笉鍙敤锛岃繑鍥瀎alse</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_FeatureIsReadable(System.String)">
+            <summary>
+            鍒ゆ柇灞炴�ф槸鍚﹀彲璇�
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <returns>鍙锛岃繑鍥瀟rue锛涗笉鍙锛岃繑鍥瀎alse</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_FeatureIsWriteable(System.String)">
+            <summary>
+            鍒ゆ柇灞炴�ф槸鍚﹀彲鍐�
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <returns>鍙啓锛岃繑鍥瀟rue锛涗笉鍙啓锛岃繑鍥瀎alse</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_FeatureIsStreamable(System.String)">
+            <summary>
+            鍒ゆ柇灞炴�ф槸鍚﹀彲娴�
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <returns>鍙祦锛岃繑鍥瀟rue锛涗笉鍙祦锛岃繑鍥瀎alse</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_FeatureIsValid(System.String)">
+            <summary>
+            鍒ゆ柇灞炴�ф槸鍚︽湁鏁�
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <returns>鏈夋晥锛岃繑鍥瀟rue锛涙棤鏁堬紝杩斿洖false</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetFeatureType(System.String,MVSDK_Net.IMVDefine.IMV_EFeatureType@)">
+            <summary>
+            鑾峰彇灞炴�х被鍨�
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pPropertyType">[OUT] 灞炴�х被鍨�</param>
+            <returns>鑾峰彇鎴愬姛锛岃繑鍥瀟rue锛涜幏鍙栧け璐ワ紝杩斿洖false</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetIntFeatureValue(System.String,System.Int64@)">
+            <summary>
+            鑾峰彇鏁村瀷灞炴�у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pIntValue">[OUT] 鏁村瀷灞炴�у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetIntFeatureMin(System.String,System.Int64@)">
+            <summary>
+            鑾峰彇鏁村瀷灞炴�у彲璁剧殑鏈�灏忓��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pIntValue">[OUT] 鏁村瀷灞炴�у彲璁剧殑鏈�灏忓��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetIntFeatureMax(System.String,System.Int64@)">
+            <summary>
+            鑾峰彇鏁村瀷灞炴�у彲璁剧殑鏈�澶у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pIntValue">[OUT] 鏁村瀷灞炴�у彲璁剧殑鏈�澶у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetIntFeatureInc(System.String,System.Int64@)">
+            <summary>
+            鑾峰彇鏁村瀷灞炴�ф闀�
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pIntValue">[OUT] 鏁村瀷灞炴�ф闀�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SetIntFeatureValue(System.String,System.Int64)">
+            <summary>
+            璁剧疆鏁村瀷灞炴�у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="intValue">[IN] 寰呰缃殑鏁村瀷灞炴�у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetDoubleFeatureValue(System.String,System.Double@)">
+            <summary>
+            鑾峰彇娴偣灞炴�у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pDoubleValue">[OUT] 娴偣灞炴�у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetDoubleFeatureMin(System.String,System.Double@)">
+            <summary>
+            鑾峰彇娴偣灞炴�у彲璁剧殑鏈�灏忓��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pDoubleValue">[OUT] 娴偣灞炴�у彲璁剧殑鏈�灏忓��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetDoubleFeatureMax(System.String,System.Double@)">
+            <summary>
+            鑾峰彇娴偣灞炴�у彲璁剧殑鏈�澶у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pDoubleValue">[OUT] 娴偣灞炴�у彲璁剧殑鏈�澶у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SetDoubleFeatureValue(System.String,System.Double)">
+            <summary>
+            璁剧疆娴偣灞炴�у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="doubleValue">[IN] 寰呰缃殑娴偣灞炴�у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetBoolFeatureValue(System.String,System.Boolean@)">
+            <summary>
+            鑾峰彇甯冨皵灞炴�у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pBoolValue">[OUT] 甯冨皵灞炴�у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SetBoolFeatureValue(System.String,System.Boolean)">
+            <summary>
+            璁剧疆甯冨皵灞炴�у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="boolValue">[IN] 寰呰缃殑甯冨皵灞炴�у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetEnumFeatureValue(System.String,System.UInt64@)">
+            <summary>
+            鑾峰彇鏋氫妇灞炴�у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pEnumValue">[OUT] 鏋氫妇灞炴�у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SetEnumFeatureValue(System.String,System.UInt64)">
+            <summary>
+            璁剧疆鏋氫妇灞炴�у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="enumValue">[IN] 寰呰缃殑鏋氫妇灞炴�у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetEnumFeatureSymbol(System.String,MVSDK_Net.IMVDefine.IMV_String@)">
+            <summary>
+            鑾峰彇鏋氫妇灞炴�ymbol鍊�
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pEnumSymbol">[OUT] 鏋氫妇灞炴�ymbol鍊�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SetEnumFeatureSymbol(System.String,System.String)">
+            <summary>
+            璁剧疆鏋氫妇灞炴�ymbol鍊�
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pEnumSymbol">[IN] 寰呰缃殑鏋氫妇灞炴�ymbol鍊�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetEnumFeatureEntryNum(System.String,System.UInt32@)">
+            <summary>
+            鑾峰彇鏋氫妇灞炴�х殑鍙鏋氫妇鍊肩殑涓暟
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pEntryNum">[OUT] 鏋氫妇灞炴�х殑鍙鏋氫妇鍊肩殑涓暟</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetEnumFeatureEntrys(System.String,MVSDK_Net.IMVDefine.IMV_EnumEntryList@)">
+            <summary>
+            鑾峰彇鏋氫妇灞炴�х殑鍙鏋氫妇鍊煎垪琛�
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pEnumEntryList">[OUT] 鏋氫妇灞炴�х殑鍙鏋氫妇鍊煎垪琛�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_GetStringFeatureValue(System.String,MVSDK_Net.IMVDefine.IMV_String@)">
+            <summary>
+            鑾峰彇瀛楃涓插睘鎬у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pStringValue">[OUT] 瀛楃涓插睘鎬у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SetStringFeatureValue(System.String,System.String)">
+            <summary>
+            璁剧疆瀛楃涓插睘鎬у��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <param name="pStringValue">[IN] 寰呰缃殑瀛楃涓插睘鎬у��</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_ExecuteCommandFeature(System.String)">
+            <summary>
+            鎵ц鍛戒护灞炴��
+            </summary>
+            <param name="pFeatureName">[IN] 灞炴�у悕</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_PixelConvert(MVSDK_Net.IMVDefine.IMV_PixelConvertParam@)">
+            <summary>
+            鍍忕礌鏍煎紡杞崲
+            </summary>
+            <param name="pstPixelConvertParam">[IN][OUT] 鍍忕礌鏍煎紡杞崲鍙傛暟缁撴瀯浣�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            <para>鍙敮鎸佽浆鍖栨垚鐩爣鍍忕礌鏍煎紡gvspPixelRGB8 / gvspPixelBGR8 / gvspPixelMono8 / gvspPixelBGRA8</para>
+            <para>閫氳繃璇ユ帴鍙e皢鍘熷鍥惧儚鏁版嵁杞崲鎴愮敤鎴锋墍闇�鐨勫儚绱犳牸寮忓苟瀛樻斁鍦ㄨ皟鐢ㄨ�呮寚瀹氬唴瀛樹腑銆�</para>
+            <para>鍍忕礌鏍煎紡涓篩UV411Packed鐨勬椂锛屽浘鍍忓椤昏兘琚�4鏁撮櫎</para>
+            <para>鍍忕礌鏍煎紡涓篩UV422Packed鐨勬椂锛屽浘鍍忓椤昏兘琚�2鏁撮櫎</para>
+            <para>鍍忕礌鏍煎紡涓篩UYVPacked鐨勬椂锛屽浘鍍忓椤昏兘琚�2鏁撮櫎</para>
+            <para>杞崲鍚庣殑鍥惧儚:鏁版嵁瀛樺偍鏄粠鏈�涓婇潰绗竴琛屽紑濮嬬殑锛岃繖涓槸鐩告満鏁版嵁鐨勯粯璁ゅ瓨鍌ㄦ柟鍚�</para>
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_FlipImage(MVSDK_Net.IMVDefine.IMV_FlipImageParam@)">
+            <summary>
+            鍥惧儚缈昏浆
+            </summary>
+            <param name="pstFlipImageParam">[IN][OUT] 鍥惧儚缈昏浆鍙傛暟缁撴瀯浣�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            <para>鍙敮鎸佸儚绱犳牸寮廹vspPixelRGB8 / gvspPixelBGR8 / gvspPixelMono8鐨勫浘鍍忕殑鍨傜洿鍜屾按骞崇炕杞��</para>
+            <para>閫氳繃璇ユ帴鍙e皢鍘熷鍥惧儚鏁版嵁缈昏浆鍚庡苟瀛樻斁鍦ㄨ皟鐢ㄨ�呮寚瀹氬唴瀛樹腑銆�</para>
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_RotateImage(MVSDK_Net.IMVDefine.IMV_RotateImageParam@)">
+            <summary>
+            鍥惧儚椤烘椂閽堟棆杞�
+            </summary>
+            <param name="pstRotateImageParam">[IN][OUT] 鍥惧儚鏃嬭浆鍙傛暟缁撴瀯浣�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            <para>鍙敮鎸乬vspPixelRGB8 / gvspPixelBGR8 / gvspPixelMono8鏍煎紡鏁版嵁鐨�90/180/270搴﹂『鏃堕拡鏃嬭浆銆�</para>
+            <para>閫氳繃璇ユ帴鍙e皢鍘熷鍥惧儚鏁版嵁鏃嬭浆鍚庡苟瀛樻斁鍦ㄨ皟鐢ㄨ�呮寚瀹氬唴瀛樹腑銆�</para>
+            </remarks>
+        </member>
+        <member name="M:MVSDK_Net.MyCamera.IMV_SaveImageToFile(MVSDK_Net.IMVDefine.IMV_SaveImageToFileParam@)">
+            <summary>
+            淇濆瓨鍥惧儚鍒版枃浠�
+            </summary>
+            <param name="pstSaveImageToFileParam">[IN] 淇濆瓨鍥剧墖鏂囦欢鍙傛暟缁撴瀯浣�</param>
+            <returns>鎴愬姛锛岃繑鍥濱MV_OK锛涢敊璇紝杩斿洖閿欒鐮�</returns>
+            <remarks>
+            璇ユ帴鍙f敮鎸佷繚瀛楤MP/JPEG/PNG/TIFF,JPEG鏍煎紡鏈�澶ф敮鎸佸楂樹负65500
+            </remarks>
+        </member>
+    </members>
+</doc>
diff --git a/LB_VisionProcesses/ref/MVSDK_Net.dll b/LB_VisionProcesses/ref/MVSDK_Net.dll
new file mode 100644
index 0000000..f75c173
--- /dev/null
+++ b/LB_VisionProcesses/ref/MVSDK_Net.dll
Binary files differ
diff --git a/LB_VisionProcesses/ref/PHM6000.dll b/LB_VisionProcesses/ref/PHM6000.dll
new file mode 100644
index 0000000..63d2d22
--- /dev/null
+++ b/LB_VisionProcesses/ref/PHM6000.dll
Binary files differ
diff --git a/LB_VisionProcesses/ref/PHM6000API.dll b/LB_VisionProcesses/ref/PHM6000API.dll
new file mode 100644
index 0000000..f523ffd
--- /dev/null
+++ b/LB_VisionProcesses/ref/PHM6000API.dll
Binary files differ
diff --git a/LB_VisionProcesses/ref/PHM6000API.lib b/LB_VisionProcesses/ref/PHM6000API.lib
new file mode 100644
index 0000000..1f69ed5
--- /dev/null
+++ b/LB_VisionProcesses/ref/PHM6000API.lib
Binary files differ
diff --git a/LB_VisionProcesses/ref/Pilot2D.dll b/LB_VisionProcesses/ref/Pilot2D.dll
new file mode 100644
index 0000000..8d9ed88
--- /dev/null
+++ b/LB_VisionProcesses/ref/Pilot2D.dll
Binary files differ
diff --git a/LB_VisionProcesses/ref/PointCloud3D.dll b/LB_VisionProcesses/ref/PointCloud3D.dll
new file mode 100644
index 0000000..af08044
--- /dev/null
+++ b/LB_VisionProcesses/ref/PointCloud3D.dll
Binary files differ
diff --git a/LB_VisionProcesses/ref/ThridLibray.dll b/LB_VisionProcesses/ref/ThridLibray.dll
new file mode 100644
index 0000000..896e12c
--- /dev/null
+++ b/LB_VisionProcesses/ref/ThridLibray.dll
Binary files differ
diff --git a/LB_VisionProcesses/ref/halcondotnet.dll b/LB_VisionProcesses/ref/halcondotnet.dll
new file mode 100644
index 0000000..bb41201
--- /dev/null
+++ b/LB_VisionProcesses/ref/halcondotnet.dll
Binary files differ

--
Gitblit v1.9.3