From c49c45d6e42402376ec1069d081c6eb289e62380 Mon Sep 17 00:00:00 2001
From: "xhm\\HP" <1173131411@qq.com>
Date: Sun, 16 Mar 2025 13:11:08 +0800
Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E7=95=8C=E9=9D=A2=E6=98=BE?=
=?UTF-8?q?=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
DH.Commons.Devies/Base/VisionEngineBase.cs | 186 +++
DH.Commons.Devies/DH.Commons.Devies.csproj | 15 +-
DH.Commons/DH.Commons.csproj | 16 +-
.../DetectionConfig.cs | 234 +++-
DH.Commons/Enums/SolidMotionCardEnum.cs | 2 +-
DH.Commons/GlobalVar.cs | 2 +-
DH.Commons/Helper/EnumHelper.cs | 771 ++++++++++++
DH.Commons/Helper/HDevEngineTool.cs | 2 +-
DH.Commons/Helper/OpenCVEngineTool.cs | 2 +-
DH.Commons/Helper/UIHelper.cs | 123 ++
DH.Commons/Interface/IShapeElement.cs | 39 +
DH.Devices.Vision/DH.Devices.Vision.csproj | 42 +-
DH.Devices.Vision/GlobalSuppressions.cs | 10 +
DH.Devices.Vision/SimboDetection.cs | 13 +-
.../SimboInstanceSegmentation.cs | 9 +
DH.Devices.Vision/SimboObjectDetection.cs | 9 +
DH.Devices.Vision/SimboVisionDriver.cs | 657 ++++++++++-
DH.Devices.Vision/SimboVisionMLBase.cs | 42 +-
DH.Devices.Vision/SimboVisionModel.cs | 6 +
DH.UI.Model.Winform/Canvas.Designer.cs | 599 ++++++++++
DH.UI.Model.Winform/Canvas.cs | 629 ++++++++++
DH.UI.Model.Winform/Canvas.resx | 120 ++
DH.UI.Model.Winform/CanvasImage.Designer.cs | 33 +
DH.UI.Model.Winform/CanvasImage.cs | 943 +++++++++++++++
DH.UI.Model.Winform/CanvasImage.resx | 120 ++
DH.UI.Model.Winform/Ctrl/GridCtrl.Designer.cs | 109 ++
DH.UI.Model.Winform/Ctrl/GridCtrl.cs | 74 ++
DH.UI.Model.Winform/Ctrl/GridCtrl.resx | 120 ++
DH.UI.Model.Winform/Ctrl/GridCtrlHost.cs | 12 +
.../Ctrl/IOIndicatorCtrl.Designer.cs | 78 ++
DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.cs | 126 ++
DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.resx | 120 ++
.../DH.UI.Model.Winform.csproj | 48 +
DH.UI.Model.Winform/Element/CommonHelper.cs | 199 ++++
DH.UI.Model.Winform/Element/ElementBase.cs | 980 ++++++++++++++++
.../Element/MLResultDisplay.cs | 325 ++++++
DH.UI.Model.Winform/GridCtrl.Designer.cs | 109 ++
DH.UI.Model.Winform/GridCtrl.cs | 74 ++
DH.UI.Model.Winform/GridCtrl.resx | 120 ++
DH.UI.Model.Winform/GridCtrlHost.cs | 12 +
.../IOIndicatorCtrl.Designer.cs | 78 ++
DH.UI.Model.Winform/IOIndicatorCtrl.cs | 126 ++
DH.UI.Model.Winform/IOIndicatorCtrl.resx | 120 ++
DHSoftware.sln | 35 +-
DHSoftware/DHSoftware.csproj | 2 +
DHSoftware/MainWindow.Designer.cs | 23 +-
DHSoftware/MainWindow.cs | 1030 +++++------------
DHSoftware/MainWindow.resx | 4 +-
.../Views/CtrlVisionDisplay.Designer.cs | 196 ++++
DHSoftware/Views/CtrlVisionDisplay.cs | 172 +++
DHSoftware/Views/CtrlVisionDisplay.resx | 123 ++
.../Views/CtrlVisionRunBase.Designer.cs | 174 +++
DHSoftware/Views/CtrlVisionRunBase.cs | 249 ++++
DHSoftware/Views/CtrlVisionRunBase.resx | 120 ++
DHSoftware/Views/DefectRowEdit.Designer.cs | 177 +--
DHSoftware/Views/DefectRowEdit.cs | 5 +-
.../Views/DetectConfigControl.Designer.cs | 351 +++---
DHSoftware/Views/DetectConfigControl.cs | 170 +--
DHSoftware/Views/SettingWindow.cs | 1 +
DHSoftware/Views/UserConfigFrm.cs | 5 +-
DHSoftware/Views/UserDetetion.cs | 5 +-
DHSoftware/productModel.cs | 3 +-
62 files changed, 9095 insertions(+), 1204 deletions(-)
create mode 100644 DH.Commons.Devies/Base/VisionEngineBase.cs
rename {DH.Devices.Vision => DH.Commons}/DetectionConfig.cs (67%)
create mode 100644 DH.Commons/Helper/EnumHelper.cs
create mode 100644 DH.Commons/Helper/UIHelper.cs
create mode 100644 DH.Commons/Interface/IShapeElement.cs
create mode 100644 DH.Devices.Vision/GlobalSuppressions.cs
create mode 100644 DH.UI.Model.Winform/Canvas.Designer.cs
create mode 100644 DH.UI.Model.Winform/Canvas.cs
create mode 100644 DH.UI.Model.Winform/Canvas.resx
create mode 100644 DH.UI.Model.Winform/CanvasImage.Designer.cs
create mode 100644 DH.UI.Model.Winform/CanvasImage.cs
create mode 100644 DH.UI.Model.Winform/CanvasImage.resx
create mode 100644 DH.UI.Model.Winform/Ctrl/GridCtrl.Designer.cs
create mode 100644 DH.UI.Model.Winform/Ctrl/GridCtrl.cs
create mode 100644 DH.UI.Model.Winform/Ctrl/GridCtrl.resx
create mode 100644 DH.UI.Model.Winform/Ctrl/GridCtrlHost.cs
create mode 100644 DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.Designer.cs
create mode 100644 DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.cs
create mode 100644 DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.resx
create mode 100644 DH.UI.Model.Winform/DH.UI.Model.Winform.csproj
create mode 100644 DH.UI.Model.Winform/Element/CommonHelper.cs
create mode 100644 DH.UI.Model.Winform/Element/ElementBase.cs
create mode 100644 DH.UI.Model.Winform/Element/MLResultDisplay.cs
create mode 100644 DH.UI.Model.Winform/GridCtrl.Designer.cs
create mode 100644 DH.UI.Model.Winform/GridCtrl.cs
create mode 100644 DH.UI.Model.Winform/GridCtrl.resx
create mode 100644 DH.UI.Model.Winform/GridCtrlHost.cs
create mode 100644 DH.UI.Model.Winform/IOIndicatorCtrl.Designer.cs
create mode 100644 DH.UI.Model.Winform/IOIndicatorCtrl.cs
create mode 100644 DH.UI.Model.Winform/IOIndicatorCtrl.resx
create mode 100644 DHSoftware/Views/CtrlVisionDisplay.Designer.cs
create mode 100644 DHSoftware/Views/CtrlVisionDisplay.cs
create mode 100644 DHSoftware/Views/CtrlVisionDisplay.resx
create mode 100644 DHSoftware/Views/CtrlVisionRunBase.Designer.cs
create mode 100644 DHSoftware/Views/CtrlVisionRunBase.cs
create mode 100644 DHSoftware/Views/CtrlVisionRunBase.resx
diff --git a/DH.Commons.Devies/Base/VisionEngineBase.cs b/DH.Commons.Devies/Base/VisionEngineBase.cs
new file mode 100644
index 0000000..28f5718
--- /dev/null
+++ b/DH.Commons.Devies/Base/VisionEngineBase.cs
@@ -0,0 +1,186 @@
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Imaging;
+using DH.Commons.Enums;
+using HalconDotNet;
+using OpenCvSharp;
+
+
+
+namespace DH.Devices.Devices
+{
+ ///
+ /// 视觉处理引擎:1.传统视觉 2.深度学习
+ /// CV深度学习 四大领域
+ /// Image Classification 图像分类:判别图中物体是什么,比如是猫还是狗;
+ /// Semantic Segmentation 语义分割:对图像进行像素级分类,预测每个像素属于的类别,不区分个体;
+ /// Object Detection 目标检测:寻找图像中的物体并进行定位;
+ /// Instance Segmentation 实例分割:定位图中每个物体,并进行像素级标注,区分不同个体;
+ ///
+ public abstract class VisionEngineBase
+ {
+ public List DetectionConfigs = new List();
+ #region event
+ public event Action> OnCropParamsOutput;
+ public event Action> OnDetectionDone;
+ public event Action OnDetectionWarningStop;//有无检测 需要报警停机
+ #endregion
+ //public VisionEngineInitialConfigBase IConfig
+ //{
+ // get => InitialConfig as VisionEngineInitialConfigBase;
+ //}
+ // public ImageSaveHelper ImageSaveHelper { get; set; } = new ImageSaveHelper();
+ public string BatchNO { get; set; }
+
+ public HTuple hv_ModelID;
+
+ public abstract DetectStationResult RunInference(Mat originImgSet, string detectionId = null);
+
+ //public abstract void SaveDetectResultAsync(DetectStationResult detectResult);
+
+
+
+ public virtual void DetectionDone(string detectionId, Bitmap image, List detectionResults)
+ {
+ OnDetectionDone?.Invoke(detectionId, image, detectionResults);
+ }
+
+ public virtual void DetectionWarningStop(string detectionDes)
+ {
+ OnDetectionWarningStop?.Invoke(detectionDes);
+ }
+
+ public virtual void SaveImageAsync(string fullname, Bitmap saveMap, ImageFormat imageFormat)
+ {
+ if (saveMap != null)
+ {
+ //ImageSaveSet imageSaveSet = new ImageSaveSet()
+ //{
+ // FullName = fullname,
+ // SaveImage = saveMap.CopyBitmap(),
+ // ImageFormat = imageFormat.DeepSerializeClone()
+ //};
+
+ //ImageSaveHelper.ImageSaveAsync(imageSaveSet);
+ }
+ }
+ }
+ public class CamModuleXY
+ {
+ [Category("图片行")]
+ [DisplayName("行")]
+ [Description("行")]
+ // [TypeConverter(typeof(DeviceIdSelectorConverter))]
+ //[TypeConverter(typeof(CollectionCountConvert))]
+ public int PicRows { get; set; } = 1;
+
+ [Category("图片列")]
+ [DisplayName("列")]
+ [Description("列")]
+ // [TypeConverter(typeof(DeviceIdSelectorConverter))]
+ //[TypeConverter(typeof(CollectionCountConvert))]
+ public int PicCols { get; set; } = 1;
+
+ public string GetDisplayText()
+ {
+ return "行:" + PicRows.ToString() + "列:" + PicCols.ToString();
+ }
+ }
+
+ //public class RelatedCamera
+ //{
+
+ // [Category("关联相机")]
+ // [DisplayName("关联相机")]
+ // [Description("关联相机描述")]
+ // //[TypeConverter(typeof(DeviceIdSelectorConverter))]
+ // //[TypeConverter(typeof(CollectionCountConvert))]
+ // public string CameraSourceId { get; set; } = "";
+
+
+ // //public string GetDisplayText()
+ // //{
+ // // using (var scope = GlobalVar.Container.BeginLifetimeScope())
+ // // {
+ // // List deviceList = scope.Resolve>();
+ // // IDevice CameraDevice = deviceList.FirstOrDefault(dev => dev.Id.Equals(CameraSourceId));
+
+ // // if (CameraDevice != null && CameraDevice is CameraBase)
+ // // {
+ // // return CameraDevice.Name;
+ // // }
+
+ // // }
+ // // return CameraSourceId;
+ // //}
+ //}
+ public class VisionEngineInitialConfigBase //: InitialConfigBase
+ {
+ [Category("深度学习检测配置")]
+ [DisplayName("检测配置集合")]
+ [Description("检测配置集合")]
+ //[TypeConverter(typeof(CollectionCountConvert))]
+ //[Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))]
+ public List DetectionConfigs { get; set; } = new List();
+
+ [Category("深度学习检测配置")]
+ [DisplayName("标签分类")]
+ [Description("标签分类,A_NG,B_TBD...")]
+ // [TypeConverter(typeof(CollectionCountConvert))]
+ // [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))]
+ public List RecongnitionLabelCategoryList { get; set; } = new List();
+
+ [Category("深度学习检测配置")]
+ [DisplayName("检测标签定义集合")]
+ [Description("定义检测标签的集合,例如:Seg/Detection模式:断裂、油污、划伤...;Class模式:ok、ng、上面、下面、套环、正常...")]
+ // [TypeConverter(typeof(CollectionCountConvert))]
+ // [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))]
+ public List RecongnitionLabelList { get; set; } = new List();
+
+ [Category("深度学习检测配置")]
+ [DisplayName("标签置信度")]
+ [Description("标签置信度,过滤小于改置信度的标签,大于该设置的标签才能识别")]
+ public float Score { get; set; } = 0.5f;
+
+ [Category("深度学习检测配置")]
+ [DisplayName("CPU线程数量")]
+ [Description("用于深度学习的CPU线程数量,不要设置太大,会单独占用线程,影响其他程序运行")]
+ public int CPUNums { get; set; } = 1;
+
+ //[Category("深度学习检测配置")]
+ //[DisplayName("检测项GPU指定")]
+ //[Description("将检测项指定到GPU")]
+ // [TypeConverter(typeof(CollectionCountConvert))]
+ // [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))]
+ // public List DetectionGPUList { get; set; } = new List();
+
+ // [Category("数据保存配置")]
+ //[DisplayName("是否保存检测明细CSV")]
+ //[Description("是否保存 检测明细CSV")]
+ //public override bool IsEnableCSV { get; set; } = true;
+
+ //[Category("数据保存配置")]
+ //[DisplayName("是否保存检测图片")]
+ //[Description("是否保存 检测图片,总开关")]
+ //public bool IsSaveImage { get; set; } = true;
+
+ //[Category("数据保存配置")]
+ //[Description("检测图片 保存文件夹")]
+ //[DisplayName("检测图片保存文件夹")]
+ //[Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))]
+ //public string ImageSaveDirectory { get; set; } = "D:\\PROJECTS\\X017\\Images";
+
+ //[Category("数据保存配置")]
+ //[Description("检测明细CSV文件夹")]
+ //[DisplayName("检测明细CSV文件夹")]
+ //[Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))]
+ //public string CSVDataPath { get; set; } = "D:\\PROJECTS\\X017\\Images";
+
+ }
+}
+
+
+
+
+
diff --git a/DH.Commons.Devies/DH.Commons.Devies.csproj b/DH.Commons.Devies/DH.Commons.Devies.csproj
index 37c8091..7f403cc 100644
--- a/DH.Commons.Devies/DH.Commons.Devies.csproj
+++ b/DH.Commons.Devies/DH.Commons.Devies.csproj
@@ -1,11 +1,14 @@
-
+
- net8.0
+ net8.0-windows
enable
enable
- AnyCPU;X64
- True
+ ..\
+ output
+ true
+ true
+ AnyCPU;x64
@@ -19,6 +22,10 @@
+
+
+
+
..\x64\Debug\halcondotnet.dll
diff --git a/DH.Commons/DH.Commons.csproj b/DH.Commons/DH.Commons.csproj
index 1920bc2..fc78210 100644
--- a/DH.Commons/DH.Commons.csproj
+++ b/DH.Commons/DH.Commons.csproj
@@ -1,17 +1,19 @@
-
+
- net8.0
+ net8.0-windows
enable
enable
- AnyCPU;X64
- True
+ ..\
+ output
+ true
+ true
+ AnyCPU;x64
-
-
-
+
+
diff --git a/DH.Devices.Vision/DetectionConfig.cs b/DH.Commons/DetectionConfig.cs
similarity index 67%
rename from DH.Devices.Vision/DetectionConfig.cs
rename to DH.Commons/DetectionConfig.cs
index 90afdb6..e62cd14 100644
--- a/DH.Devices.Vision/DetectionConfig.cs
+++ b/DH.Commons/DetectionConfig.cs
@@ -6,7 +6,7 @@ using System.Text.RegularExpressions;
using System.Text;
using System.Drawing.Design;
-namespace DH.Devices.Vision
+namespace DH.Commons.Enums
{
public enum MLModelType
{
@@ -25,7 +25,9 @@ namespace DH.Devices.Vision
}
public class ModelLabel
{
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string LabelId { get; set; }
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
[Category("模型标签")]
@@ -37,7 +39,9 @@ namespace DH.Devices.Vision
[Category("模型标签")]
[DisplayName("模型标签")]
[Description("模型识别的标签名称")]
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string LabelName { get; set; }
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
@@ -57,7 +61,9 @@ namespace DH.Devices.Vision
public class MLRequest
{
public int ImageChannels = 3;
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public Mat mImage;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public int ResizeWidth;
public int ResizeHeight;
@@ -68,11 +74,17 @@ namespace DH.Devices.Vision
//public int ImageResizeCount;
public bool IsCLDetection;
public int ProCount;
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string in_node_name;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string out_node_name;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string in_lable_path;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public int ResizeImageSize;
public int segmentWidth;
@@ -81,7 +93,9 @@ namespace DH.Devices.Vision
// public List OkClassTxtList;
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public List LabelNames;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
@@ -113,16 +127,22 @@ namespace DH.Devices.Vision
///
public class DetectionResultDetail
{
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string LabelBGR { get; set; }//识别到对象的标签BGR
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public int LabelNo { get; set; } // 识别到对象的标签索引
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string LabelName { get; set; }//识别到对象的标签名称
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public double Score { get; set; }//识别目标结果的可能性、得分
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string LabelDisplay { get; set; }//识别到对象的 显示信息
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public double Area { get; set; }//识别目标的区域面积
@@ -141,8 +161,12 @@ namespace DH.Devices.Vision
public class MLResult
{
public bool IsSuccess = false;
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string ResultMessage;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public Bitmap ResultMap;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public List ResultDetails = new List();
}
public class MLInit
@@ -164,7 +188,11 @@ namespace DH.Devices.Vision
public bool IsGPU;
public int GPUId;
public float Score_thre;
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public MLInit(string modelFile, bool isGPU, int gpuId, float score_thre)
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
{
ModelFile = modelFile;
IsGPU = isGPU;
@@ -186,20 +214,27 @@ namespace DH.Devices.Vision
}
public class DetectStationResult
{
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string Pid { get; set; }
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string TempPid { get; set; }
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
///
/// 检测工位名称
///
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string DetectName { get; set; }
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
///
/// 深度学习 检测结果
///
public List DetectDetails = new List();
+ public List DetectionResultShapes = new List();
///
@@ -237,7 +272,9 @@ namespace DH.Devices.Vision
public int StationDetectElapsed { get; set; }
public static string NormalizeAndClean(string input)
{
+#pragma warning disable CS8603 // 可能返回 null 引用。
if (input == null) return null;
+#pragma warning restore CS8603 // 可能返回 null 引用。
// Step 1: 标准化字符编码为 Form C (规范组合)
string normalizedString = input.Normalize(NormalizationForm.FormC);
@@ -274,6 +311,184 @@ namespace DH.Devices.Vision
CameraSourceId = cameraSourceId;
}
+ }
+ public class CustomizedPoint : INotifyPropertyChanged, IComparable
+ {
+ private double x = 0;
+ [Category("坐标设置")]
+ [Description("X坐标")]
+ public double X
+ {
+ get => x;
+ set
+ {
+ if (value != x)
+ {
+ x = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("X"));
+ }
+ }
+ }
+
+ private double y = 0;
+ [Category("坐标设置")]
+ [Description("Y坐标")]
+ public double Y
+ {
+ get => y;
+ set
+ {
+ if (value != y)
+ {
+ y = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Y"));
+ }
+ }
+ }
+
+ public CustomizedPoint() { }
+
+ public CustomizedPoint(double x, double y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ //public CustomizedPoint(Point p)
+ //{
+ // X = p.X;
+ // Y = p.Y;
+ //}
+
+ public CustomizedPoint(PointF p)
+ {
+ X = p.X;
+ Y = p.Y;
+ }
+
+ public CustomizedPoint(CustomizedPoint p)
+ {
+ X = p.X;
+ Y = p.Y;
+ }
+
+ ///
+ /// 根据PLC的读取数值获取点位坐标
+ ///
+ /// 0:X低位 1:X高位 2:Y低位 3:Y高位
+ //public CustomizedPoint(List plcValues)
+ //{
+ // if (plcValues == null || plcValues.Count != 4)
+ // return;
+
+ // var list = plcValues.ParseUnsignShortListToInt();
+
+ // X = list[0];
+ // Y = list[1];
+ //}
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public static List GetPoints(List Xs, List Ys)
+ {
+ List points = new List();
+ for (int i = 0; i < Xs.Count && i < Ys.Count; i++)
+ {
+ points.Add(new CustomizedPoint(Xs[i], Ys[i]));
+ }
+
+ return points;
+ }
+
+ public static double GetDistance(CustomizedPoint p1, CustomizedPoint p2)
+ {
+ return Math.Sqrt(Math.Pow((p1.X - p2.X), 2) + Math.Pow((p1.Y - p2.Y), 2));
+ }
+
+ public override string ToString()
+ {
+ return GetDisplayText();
+ }
+
+ public virtual string GetDisplayText()
+ {
+ return string.Format("X:{0};Y:{1}", X, Y);
+ }
+
+ public virtual string GetCSVHead()
+ {
+ return "X,Y";
+ }
+
+ public virtual string GetCSVData()
+ {
+ return X.ToString("f3") + ";" + Y.ToString("f3");
+ }
+
+ //public static double GetCustomizedPointDistance(CustomizedPoint startPoint, CustomizedPoint endPoint)
+ //{
+ // return Math.Sqrt(Math.Pow(endPoint.X - startPoint.X, 2) + Math.Pow(endPoint.Y - startPoint.Y, 2));
+ //}
+
+ public CustomizedPoint OffsetClone(CustomizedPoint point)
+ {
+ return new CustomizedPoint(X + point.X, Y + point.Y);
+ }
+
+ public void Offset(CustomizedPoint point)
+ {
+ X += point.X;
+ Y += point.Y;
+ }
+
+ public int CompareTo(CustomizedPoint other)
+ {
+ return (X == other.X && Y == other.Y) ? 0 : 1;
+ }
+
+ public override int GetHashCode()
+ {
+ //return (int)(X * 10 + Y);
+ return (new Tuple(X, Y)).GetHashCode();
+ }
+
+ public static CustomizedPoint operator -(CustomizedPoint p1, CustomizedPoint p2)
+ {
+ return new CustomizedPoint(p1.X - p2.X, p1.Y - p2.Y);
+ }
+
+ public static CustomizedPoint operator +(CustomizedPoint p1, CustomizedPoint p2)
+ {
+ return new CustomizedPoint(p1.X + p2.X, p1.Y + p2.Y);
+ }
+ }
+ public class PreTreatParam
+ {
+
+ ///
+ /// 参数名称
+ ///
+ ///
+ [Category("预处理参数")]
+ [DisplayName("参数名称")]
+ [Description("参数名称")]
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
+ public string Name { get; set; }
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
+
+
+ ///
+ /// 参数值
+ ///
+ ///
+ [Category("预处理参数")]
+ [DisplayName("参数值")]
+ [Description("参数值")]
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
+ public string Value { get; set; }
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
+
+
}
public class DetectionConfig
{
@@ -403,9 +618,14 @@ namespace DH.Devices.Vision
//[Category("深度学习配置")]
//[DisplayName("检测配置标签")]
//[Description("检测配置标签关联")]
-
- //public List DetectConfigLabelList { get; set; } = new List();
+ //public List DetectConfigLabelList { get; set; } = new List();
+ [Category("显示配置")]
+ [DisplayName("显示位置")]
+ [Description("检测信息显示位置。左上角为(1,1),向右向下为正方向")]
+ // [TypeConverter(typeof(ComplexObjectConvert))]
+ // [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
+ public CustomizedPoint ShowLocation { get; set; } = new CustomizedPoint();
public DetectionConfig()
{
@@ -413,7 +633,7 @@ namespace DH.Devices.Vision
}
public DetectionConfig(string name, MLModelType modelType, string modelPath, bool isEnableGPU,string sCameraSourceId)
- {
+ {
ModelPath = modelPath ?? string.Empty;
Name = name;
ModelType = modelType;
@@ -463,7 +683,9 @@ namespace DH.Devices.Vision
[DisplayName("检测项标签")]
[Description("检测标签Id")]
//[TypeConverter(typeof(DetectionLabelConverter))]
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string LabelId { get; set; }
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
[Browsable(false)]
//public string LabelName { get => GetLabelName(); }
@@ -562,11 +784,13 @@ namespace DH.Devices.Vision
[DisplayName("检测标签")]
[Description("检测标签信息")]
//[TypeConverter(typeof(DetectionLabelConverter))]
+
public string LabelId { get; set; }
- // [Browsable(false)]
+
public string LabelName { get; set; }
+
[Category("过滤器基础信息")]
[DisplayName("是否启用过滤器")]
[Description("是否启用过滤器")]
diff --git a/DH.Commons/Enums/SolidMotionCardEnum.cs b/DH.Commons/Enums/SolidMotionCardEnum.cs
index c2387bc..6f424c1 100644
--- a/DH.Commons/Enums/SolidMotionCardEnum.cs
+++ b/DH.Commons/Enums/SolidMotionCardEnum.cs
@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace XKRS.Common.Model.SolidMotionCard
+namespace DH.Commons.Enums
{
diff --git a/DH.Commons/GlobalVar.cs b/DH.Commons/GlobalVar.cs
index ce615fc..8cd5751 100644
--- a/DH.Commons/GlobalVar.cs
+++ b/DH.Commons/GlobalVar.cs
@@ -1,6 +1,6 @@
-namespace XKRS.Common.Model
+namespace DH.Commons.Enums
{
public static class GlobalVar
{
diff --git a/DH.Commons/Helper/EnumHelper.cs b/DH.Commons/Helper/EnumHelper.cs
new file mode 100644
index 0000000..32cc533
--- /dev/null
+++ b/DH.Commons/Helper/EnumHelper.cs
@@ -0,0 +1,771 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Reflection;
+
+namespace DH.Commons.Enums
+{
+ public static class EnumHelper
+ {
+ ///
+ /// 根据枚举的代码名称获取枚举列表信息
+ ///
+ ///
+ ///
+ public static List GetEnumListByName(string enumName, string assemblyName = "Common.Model.Helper.EnumHelper+")
+ {
+ List list = new List();
+
+ string fullName = assemblyName + enumName;
+
+ Type t = typeof(EnumHelper).Assembly.GetType(fullName);
+
+ t.GetEnumNames().ToList().ForEach(e =>
+ {
+ int value = Convert.ToInt32(Enum.Parse(t, e));
+ string desc = ((Enum)Enum.Parse(t, e)).GetEnumDescription();
+ var item = new { Value = value, Desc = desc, Code = e };
+ list.Add(item);
+ });
+
+ return list;
+ }
+
+ ///
+ /// 获取枚举的列表信息,一般供下拉列表使用
+ ///
+ /// 枚举类型
+ /// Desc:中文描述 Value:整形值 Code:枚举值
+ public static List GetEnumListByType(Type enumType)
+ {
+ List list = new List();
+
+ enumType.GetEnumNames().ToList().ForEach(e =>
+ {
+ int value = Convert.ToInt32(Enum.Parse(enumType, e));
+ string desc = ((Enum)Enum.Parse(enumType, e)).GetEnumDescription();
+ var item = new { Value = value, Desc = desc, Code = e };
+ list.Add(item);
+ });
+
+ return list;
+ }
+
+ ///
+ /// 获取具体某一枚举的中文描述
+ ///
+ ///
+ ///
+ public static string GetEnumDescription(this Enum enumObj)
+ {
+ Type t = enumObj.GetType();
+ FieldInfo f = t.GetField(enumObj.ToString());
+ if (f == null)
+ {
+ return enumObj.ToString();
+ }
+ DescriptionAttribute attr = f.GetCustomAttribute();
+ if (attr != null)
+ {
+ return attr.Description;
+ }
+ else
+ {
+ return enumObj.ToString();
+ }
+ }
+
+ //public static System.Windows.Media.Color GetEnumSelectedMediaColor(this Enum enumObj)
+ //{
+ // Type t = enumObj.GetType();
+ // FieldInfo f = t.GetField(enumObj.ToString());
+
+ // ColorSelectAttribute attr = f.GetCustomAttribute();
+ // if (attr != null)
+ // {
+ // var prop = typeof(System.Windows.Media.Colors).GetProperties().FirstOrDefault(p => p.Name == attr.SelectedColor);
+ // if (prop != null)
+ // {
+ // return (System.Windows.Media.Color)prop.GetValue(null);
+ // }
+ // }
+ // return System.Windows.Media.Colors.Transparent;
+ //}
+
+ //public static System.Drawing.Color GetEnumSelectedColor(this Enum enumObj)
+ //{
+ // Type t = enumObj.GetType();
+ // FieldInfo f = t.GetField(enumObj.ToString());
+
+ // ColorSelectAttribute attr = f.GetCustomAttribute();
+ // if (attr != null)
+ // {
+ // return System.Drawing.Color.FromName(attr.SelectedColor);
+ // }
+ // else
+ // {
+ // return System.Drawing.Color.Transparent;
+ // }
+ //}
+
+ //public static System.Drawing.Color GetEnumSelectedFontColor(this Enum enumObj)
+ //{
+ // Type t = enumObj.GetType();
+ // FieldInfo f = t.GetField(enumObj.ToString());
+
+ // var attr = f.GetCustomAttribute();
+ // if (attr != null)
+ // {
+ // return System.Drawing.Color.FromName(attr.SelectedColor);
+ // }
+ // else
+ // {
+ // return System.Drawing.Color.Transparent;
+ // }
+ //}
+
+ //public static string GetEnumSelectedColorString(this Enum enumObj)
+ //{
+ // Type t = enumObj.GetType();
+ // FieldInfo f = t.GetField(enumObj.ToString());
+
+ // ColorSelectAttribute attr = f.GetCustomAttribute();
+ // if (attr != null)
+ // {
+ // return attr.SelectedColor;
+ // }
+ // else
+ // {
+ // return "Transparent";
+ // }
+ //}
+
+
+ ///
+ /// 当枚举牵涉到状态变换,检查现状态是否满足待转换的状态的前置状态要求
+ ///
+ ///
+ ///
+ ///
+ //public static bool CheckPreStateValid(this Enum stateToBe, int currentState)
+ //{
+ // Type t = stateToBe.GetType();
+ // FieldInfo f = t.GetField(stateToBe.ToString());
+
+ // PreStateAttribute attr = f.GetCustomAttribute();
+ // if (attr == null)
+ // {
+ // return true;
+ // }
+ // else
+ // {
+ // return attr.CheckPreStateValid(currentState);
+ // }
+ //}
+
+ ///
+ /// 设备状态定义
+ /// 未初始化和异常状态无前置状态要求
+ /// 初始化操作前置状态必须是未初始化、关闭状态和异常状态
+ /// 打开前置必须是初始化和暂停
+ /// 关闭前置必须是打开和暂停和异常
+ /// 暂停前置必须是打开
+ ///
+ //public enum DeviceState
+ //{
+ // TBD = -1,
+
+ // [ColorSelect("Gray")]
+ // [FontColorSelect("Black")]
+ // [Description("未初始化")]
+ // DSUninit = 1,
+
+ // [ColorSelect("Gold")]
+ // [FontColorSelect("White")]
+ // [PreState(1 + 2 + 4 + 8 + 32)]
+ // [Description("初始化")]
+ // DSInit = 2,
+
+ // [ColorSelect("Lime")]
+ // [FontColorSelect("Black")]
+ // [PreState(2 + 4 + 16)]
+ // [Description("运行中")]
+ // DSOpen = 4,
+
+ // [ColorSelect("Gray")]
+ // [FontColorSelect("White")]
+ // [PreState(1 + 4 + 8 + 16 + 32)]
+ // [Description("关闭")]
+ // DSClose = 8,
+
+ // [ColorSelect("Gold")]
+ // [FontColorSelect("White")]
+ // [PreState(4 + 16)]
+ // [Description("暂停")]
+ // DSPause = 16,
+
+ // [ColorSelect("Red")]
+ // [FontColorSelect("White")]
+ // [Description("异常")]
+ // DSExcept = 32
+ //}
+
+ /////
+ ///// 工序状态
+ /////
+ //public enum RunState
+ //{
+ // [ColorSelect("Gold")]
+ // [Description("空闲")]
+ // Idle = 1,
+ // [ColorSelect("Lime")]
+ // [Description("运行中")]
+ // Running = 2,
+ // [ColorSelect("Gray")]
+ // [Description("停止")]
+ // Stop = 3,
+ // [ColorSelect("Red")]
+ // [Description("宕机")]
+ // Down = 99,
+ //}
+
+ [Flags]
+ public enum DeviceAttributeType
+ {
+ [Description("设备驱动")]
+ Device = 1,
+
+ [Description("初始配置")]
+ InitialConfig = 2,
+ [Description("操作配置")]
+ OperationConfig = 4,
+ [Description("设备配置")]
+ DeviceConfig = 8,
+ [Description("输入配置")]
+ InputConfig = 16,
+
+ [Description("初始配置控件")]
+ InitialConfigCtrl = 32,
+ [Description("操作配置控件")]
+ OperationConfigCtrl = 64,
+ [Description("设备配置控件")]
+ DeviceConfigCtrl = 128,
+ [Description("输入配置控件")]
+ InputConfigCtrl = 256,
+
+ [Description("运行控件")]
+ RunCtrl = 512,
+
+ [Description("操作配置面板")]
+ OperationConfigPanel = 1024,
+ }
+
+ public enum EnableState
+ {
+ [Description("启用")]
+ Enabled = 0,
+ [Description("禁用")]
+ Disabled = 1,
+ }
+
+ public enum EnableStateFilter
+ {
+ [Description("全部")]
+ All = -1,
+ [Description("启用")]
+ Enabled = 0,
+ [Description("禁用")]
+ Disabled = 1,
+ }
+
+ public enum OutputResult
+ {
+ [Description("OK")]
+ OK = 1,
+ [Description("NG")]
+ NG = 2,
+ }
+
+ ///
+ /// PLC项目的值的类型
+ ///
+ public enum PLCItemType
+ {
+ [Description("布尔类型")]
+ Bool = 0,
+ [Description("整型")]
+ Integer = 1,
+ [Description("字符串型")]
+ String = 2,
+ }
+
+ ///
+ /// 对PLC项目的操作类型
+ ///
+ public enum PLCOpType
+ {
+ [Description("读取")]
+ Read = 1,
+ [Description("写入")]
+ Write = 2,
+ [Description("监控")]
+ Monitor = 4,
+
+ ///
+ /// 报警监控 1+8
+ ///
+ [Description("报警监控")]
+ WarningMonitor = 9,
+
+ ///
+ /// CT监控 1+16
+ ///
+ [Description("CT监控")]
+ CTMonitor = 17,
+ }
+
+ ///
+ /// 相机运行模式
+ ///
+ public enum CameraOpMode
+ {
+ [Description("单次拍照")]
+ SingleSnapShot = 1,
+ [Description("连续模式")]
+ ContinuousMode = 2,
+ }
+
+ ///
+ /// 日志类型
+ ///
+ public enum LogType
+ {
+ [Description("警告信息")]
+ Exception_Warning = 1,
+ [Description("错误信息")]
+ Exception_Error = 2,
+ [Description("致命信息")]
+ Exception_Fatal = 3,
+
+ [Description("设备信息")]
+ Info_Device = 11,
+ [Description("工序信息")]
+ Info_Process = 12,
+ [Description("操作信息")]
+ Info_Operation = 13,
+
+ [Description("用户操作信息")]
+ User_Operation = 21,
+
+ [Description("测量结果")]
+ MeasureResult = 31,
+ }
+
+ //public enum CameraDriverType
+ //{
+ // Halcon,
+ // //HalconPlugIn,
+ // Hik,
+ //}
+
+ //public enum ImageType
+ //{
+ // Bmp,
+ // Png,
+ // Jpeg,
+ //}
+
+ //public enum ReplyValue
+ //{
+ // OK = 1,
+ // NG = -1,
+ // IGNORE = -999,
+ //}
+
+ public enum PriorityDirection
+ {
+ X,
+ Y,
+ }
+
+ public enum ElementState
+ {
+ New = 1,
+ MouseHover = 2,
+ MouseInSide = 3,
+ Selected = 4,
+ Moving = 5,
+ Editing = 6,
+
+ Normal = 11,
+
+ Measuring = 21,
+ MeasureDoneOK = 22,
+ MeasureDoneNG = 23,
+
+ CanStretchLeft = 41,
+ CanStretchRight = 42,
+ CanStretchTop = 43,
+ CanStretchBottom = 44,
+
+ CanStretchLeftUpperCorner = 45,
+ CanStretchLeftLowerCorner = 46,
+ CanStretchRightUpperCorner = 47,
+ CanStretchRightLowerCorner = 48,
+
+ StretchingLeft = 31,
+ StretchingRight = 32,
+ StretchingTop = 33,
+ StretchingBottom = 34,
+
+ StretchingLeftUpperCorner = 35,
+ StretchingLeftLowerCorner = 36,
+ StretchingRightUpperCorner = 37,
+ StretchingRightLowerCorner = 38,
+ }
+
+ public enum MouseState
+ {
+ Normal = 1,
+ HoverElement = 2,
+ InSideElement = 3,
+
+ MoveElement = 4,
+
+ StretchingLeft = 11,
+ StretchingRight = 12,
+ StretchingTop = 13,
+ StretchingBottom = 14,
+
+ StretchingLeftUpperCorner = 15,
+ StretchingLeftLowerCorner = 16,
+ StretchingRightUpperCorner = 17,
+ StretchingRightLowerCorner = 18,
+
+ New = 21,
+ Editing = 22,
+ //SelectedElement = 23,
+
+ MovingAll = 31,
+
+ SelectionZone = 41,
+ SelectionZoneDoing = 42,
+ }
+
+ public enum RunMode
+ {
+ [Description("正常运行模式")]
+ NormalMode = 1,
+ [Description("调试模式")]
+ DebugMode = 0,
+ [Description("模拟模式")]
+ DemoMode = 2,
+ }
+
+ public enum MoveType
+ {
+ [Description("绝对运动")]
+ AbsoluteMove = 1,
+ [Description("机器人坐标系相对运动")]
+ RobotRelativeMove = 2,
+ [Description("相对某个基准点位的相对运动")]
+ BasedPointRelativeMove = 3,
+ [Description("回原点")]
+ Origin = 4,
+ [Description("左侧姿势")]
+ LeftPose = 6,
+ [Description("右侧姿势")]
+ RightPose = 5,
+ [Description("前侧姿势")]
+ FrontPose = 7,
+ [Description("相机坐标系相对运动")]
+ CameraRelativeMove = 12,
+ }
+
+ ///
+ /// 马达/运动板卡运行模式
+ ///
+ public enum MotionMode
+ {
+ ///
+ /// 普通点位运动
+ ///
+ [Description("普通点位运动")]
+ P2P = 1,
+
+ ///
+ /// 找正限位运动
+ ///
+ [Description("找正限位运动")]
+ FindPositive = 4,
+
+ ///
+ /// 离开正限位
+ ///
+ [Description("离开正限位")]
+ LeavePositive = 5,
+
+ ///
+ /// 找负限位运动
+ ///
+ [Description("找负限位运动")]
+ FindNegative = 6,
+
+ ///
+ /// 离开负限位
+ ///
+ [Description("离开负限位")]
+ LeaveNegative = 7,
+
+ ///
+ /// 找原点运动
+ ///
+ [Description("回原点运动")]
+ GoHome = 8,
+
+ ///
+ /// Jog模式
+ ///
+ [Description("Jog模式")]
+ Jog = 9,
+
+ /////
+ ///// 读数头找原点方式
+ /////
+ //[Description("找原点inde")]
+ //FindOriIndex = 10,
+
+ /////
+ ///// 插补模式
+ /////
+ //[Description("插补模式")]
+ //Coordinate = 11
+ }
+
+ ///
+ /// IO预定义类型 主要针对输出
+ ///
+ public enum IOPrestatement
+ {
+ [Description("自定义")]
+ Customized = 0,
+
+ [Description("指示灯-黄")]
+ Light_Yellow = 1,
+ [Description("指示灯-绿")]
+ Light_Green = 2,
+ [Description("指示灯-红")]
+ Light_Red = 3,
+ [Description("蜂鸣器")]
+ Beep = 4,
+ [Description("照明灯")]
+ Light = 5,
+
+ [Description("急停")]
+ EmergencyStop = 99,
+ }
+
+ /////
+ ///// GTS运动板卡控制返回控制码
+ /////
+ //public enum GTSRetCode
+ //{
+ // [Description("指令执行成功")]
+ // GRCRunOK = 0, // 指令执行成功
+ // [Description("指令执行错误")]
+ // GRCRunErr = 1, // 指令执行错误
+ // [Description("icense不支持")]
+ // GRCNotSupport = 2, // icense不支持
+ // [Description("指令参数错误")]
+ // GRCInvalidParam = 7, // 指令参数错误
+ // [Description("主机和运动控制器通讯失败")]
+ // GRCCommErr = -1, // 主机和运动控制器通讯失败
+ // [Description("打开控制器失败")]
+ // GRCOpenErr = -6, // 打开控制器失败
+ // [Description("运动控制器没有响应")]
+ // GRCNotAck = -7 // 运动控制器没有响应
+ //}
+
+ ///
+ /// 运动板卡 IO 类型(IN OUT)
+ ///
+ public enum IOType
+ {
+ [Description("INPUT")]
+ INPUT = 0,
+ [Description("OUTPUT")]
+ OUTPUT = 1
+ }
+
+ public enum IOValue
+ {
+ [Description("关闭")]
+ FALSE = 0,
+ [Description("开启")]
+ TRUE = 1,
+ [Description("反转")]
+ REVERSE = 2,
+ }
+
+ ///
+ /// PubSubCenter事件中心的消息类型
+ ///
+ public enum PubSubCenterMessageType
+ {
+ ///
+ /// 运行界面更新产品下拉
+ ///
+ [Description("更新产品下拉")]
+ UpdateProductionCodes,
+
+ ///
+ /// 流程是否关闭
+ ///
+ [Description("流程是否打开")]
+ IsProcessOpened,
+
+ ///
+ /// 清除数据
+ ///
+ [Description("清除数据")]
+ ClearData,
+ ///
+ /// 更新批次信息
+ ///
+ [Description("更新批次信息")]
+ UpdateBatchNO,
+ ///
+ /// 请求批次信息
+ ///
+ [Description("更新批次信息")]
+ RequestBatchNO,
+
+ ///
+ /// 模型检测异常
+ ///
+ [Description("模型检测异常")]
+ MLDetectException,
+ }
+ public enum SizeEnum
+ {
+ [Description("圆形测量")]
+ Circle = 1,
+ [Description("直线测量")]
+ Line = 2,
+ [Description("线线测量")]
+ LineLine = 3,
+ [Description("线圆测量")]
+ LineCircle = 4,
+ [Description("高度测量")]
+ Height = 5,
+ }
+
+ public enum MachineState
+ {
+ Unknown = 0,
+ Ready = 1,
+ Running = 2,
+ Alarm = 3,
+ Pause = 4,
+ Resetting = 5,
+ Closing = 6,
+ ClearProduct = 7,
+ Warning = 8,
+ }
+
+ public enum ResultState
+ {
+ [Description("NA")]
+ NA = -5,
+ [Description("尺寸NG")]
+ SizeNG = -4,
+ [Description("检测NG")]
+ DetectNG = -3,
+
+ //[Description("检测不足TBD")]
+ // ShortageTBD = -2,
+ [Description("检测结果TBD")]
+ ResultTBD = -1,
+ [Description("OK")]
+ OK = 1,
+ // [Description("NG")]
+ // NG = 2,
+ //统计结果
+ [Description("A类NG")]
+ A_NG = 25,
+ [Description("B类NG")]
+ B_NG = 26,
+ [Description("C类NG")]
+ C_NG = 27,
+ }
+ public enum HikCameraType
+ {
+ [Description("HikCamera-Gige")]
+ Gige = 0,
+ [Description("HikCamera-USB")]
+ USB = 1
+ }
+
+ ///
+ /// 光源操作
+ ///
+ public enum LightOperation
+ {
+ [Description("打开")]
+ Open = 1,
+ [Description("关闭")]
+ Close = 2,
+ [Description("写入")]
+ Write = 3,
+ [Description("读取")]
+ Read = 4,
+ [Description("频闪")]
+ Flash = 5,
+ }
+
+ ///
+ /// 监听反馈数据值
+ ///
+ public enum ReturnValue
+ {
+ OKVALUE = 1,
+ NGVALUE = -1,
+ EXCEPTIONVALUE = -2,
+ UNAUTHORIZATION = -10,
+ IGNORE = -999,
+ }
+
+ //public enum LogLevel
+ //{
+ // [Description("详细")]
+ // [ColorSelect("White")]
+ // [FontColorSelect("Green")]
+ // Detail = 2,
+ // [Description("信息")]
+ // [ColorSelect("White")]
+ // [FontColorSelect("Dark")]
+ // Information = 3,
+ // [Description("辅助")]
+ // [ColorSelect("White")]
+ // [FontColorSelect("Blue")]
+ // Assist = 4,
+ // [Description("动作")]
+ // [ColorSelect("DarkGreen")]
+ // [FontColorSelect("Yellow")]
+ // Action = 5,
+ // [Description("错误")]
+ // [ColorSelect("Orange")]
+ // [FontColorSelect("White")]
+ // Error = 6,
+ // [Description("警报")]
+ // [ColorSelect("Brown")]
+ // [FontColorSelect("White")]
+ // Warning = 7,
+ // [Description("异常")]
+ // [ColorSelect("Red")]
+ // [FontColorSelect("White")]
+ // Exception = 8,
+ //}
+ }
+}
diff --git a/DH.Commons/Helper/HDevEngineTool.cs b/DH.Commons/Helper/HDevEngineTool.cs
index bd6f51e..bfe77f2 100644
--- a/DH.Commons/Helper/HDevEngineTool.cs
+++ b/DH.Commons/Helper/HDevEngineTool.cs
@@ -5,7 +5,7 @@ using System.Drawing.Imaging;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
-namespace XKRS.Common.Model
+namespace DH.Commons.Enums
{
public class HDevEngineTool : IDisposable
{
diff --git a/DH.Commons/Helper/OpenCVEngineTool.cs b/DH.Commons/Helper/OpenCVEngineTool.cs
index 86e5aff..5226ecf 100644
--- a/DH.Commons/Helper/OpenCVEngineTool.cs
+++ b/DH.Commons/Helper/OpenCVEngineTool.cs
@@ -9,7 +9,7 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
-namespace XKRS.Common.Model
+namespace DH.Commons.Enums
{
public class OpenCVEngineTool : IDisposable
{
diff --git a/DH.Commons/Helper/UIHelper.cs b/DH.Commons/Helper/UIHelper.cs
new file mode 100644
index 0000000..2ab9f8d
--- /dev/null
+++ b/DH.Commons/Helper/UIHelper.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace DH.Commons.Enums
+{
+ public static class UIHelper
+ {
+ public static void SetCombo(ComboBox cbo, object dataSource, string display, string value)
+ {
+ cbo.DataSource = dataSource;
+ cbo.DisplayMember = display;
+ if (!string.IsNullOrWhiteSpace(value))
+ {
+ cbo.ValueMember = value;
+ }
+ }
+
+ public static void SetCombo(ToolStripComboBox cbo, object dataSource, string display, string value)
+ {
+ cbo.ComboBox.DataSource = dataSource;
+ cbo.ComboBox.DisplayMember = display;
+ if (!string.IsNullOrWhiteSpace(value))
+ {
+ cbo.ComboBox.ValueMember = value;
+ }
+ }
+
+ public static void SetCombo(DataGridViewComboBoxColumn cbo, object dataSource, string display, string value)
+ {
+ cbo.DataSource = dataSource;
+ cbo.DisplayMember = display;
+ if (!string.IsNullOrWhiteSpace(value))
+ {
+ cbo.ValueMember = value;
+ }
+ }
+ }
+
+ #region DataGridView设置列头为复选框
+ public class DataGridViewCheckboxHeaderEventArgs : EventArgs
+ {
+ private bool checkedState = false;
+
+ public bool CheckedState
+ {
+ get { return checkedState; }
+ set { checkedState = value; }
+ }
+ }
+
+ public delegate void DataGridViewCheckboxHeaderEventHander(object sender, DataGridViewCheckboxHeaderEventArgs e);
+ public class DataGridViewCheckboxHeaderCell : DataGridViewColumnHeaderCell
+ {
+ Point checkBoxLocation;
+ Size checkBoxSize;
+ bool _checked = false;
+ Point _cellLocation = new Point();
+ System.Windows.Forms.VisualStyles.CheckBoxState _cbState = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal;
+
+ public event DataGridViewCheckboxHeaderEventHander OnCheckBoxClicked;
+
+ //绘制列头checkbox
+ protected override void Paint(System.Drawing.Graphics graphics,
+ System.Drawing.Rectangle clipBounds,
+ System.Drawing.Rectangle cellBounds,
+ int rowIndex,
+ DataGridViewElementStates dataGridViewElementState,
+ object value,
+ object formattedValue,
+ string errorText,
+ DataGridViewCellStyle cellStyle,
+ DataGridViewAdvancedBorderStyle advancedBorderStyle,
+ DataGridViewPaintParts paintParts)
+ {
+ base.Paint(graphics, clipBounds, cellBounds, rowIndex,
+ dataGridViewElementState, value,
+ formattedValue, errorText, cellStyle,
+ advancedBorderStyle, paintParts);
+
+ Point p = new Point();
+ Size s = CheckBoxRenderer.GetGlyphSize(graphics, System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
+ p.X = cellBounds.Location.X + (cellBounds.Width / 2) - (s.Width / 2) - 1; //列头checkbox的X坐标
+ p.Y = cellBounds.Location.Y + (cellBounds.Height / 2) - (s.Height / 2); //列头checkbox的Y坐标
+ _cellLocation = cellBounds.Location;
+ checkBoxLocation = p;
+ checkBoxSize = s;
+ if (_checked)
+ _cbState = System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal;
+ else
+ _cbState = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal;
+
+ CheckBoxRenderer.DrawCheckBox(graphics, checkBoxLocation, _cbState);
+ }
+
+ ///
+ /// 点击列头checkbox单击事件
+ ///
+ protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
+ {
+ Point p = new Point(e.X + _cellLocation.X, e.Y + _cellLocation.Y);
+ if (p.X >= checkBoxLocation.X && p.X <= checkBoxLocation.X + checkBoxSize.Width
+ && p.Y >= checkBoxLocation.Y && p.Y <= checkBoxLocation.Y + checkBoxSize.Height)
+ {
+ _checked = !_checked;
+
+ //获取列头checkbox的选择状态
+ DataGridViewCheckboxHeaderEventArgs ex = new DataGridViewCheckboxHeaderEventArgs();
+ ex.CheckedState = _checked;
+
+ object sender = new object();//此处不代表选择的列头checkbox,只是作为参数传递。因为列头checkbox是绘制出来的,无法获得它的实例
+
+ if (OnCheckBoxClicked != null)
+ {
+ OnCheckBoxClicked(sender, ex);//触发单击事件
+ DataGridView.InvalidateCell(this);
+ }
+ }
+ base.OnMouseClick(e);
+ }
+ }
+ #endregion
+}
diff --git a/DH.Commons/Interface/IShapeElement.cs b/DH.Commons/Interface/IShapeElement.cs
new file mode 100644
index 0000000..3d39fa1
--- /dev/null
+++ b/DH.Commons/Interface/IShapeElement.cs
@@ -0,0 +1,39 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using static DH.Commons.Enums.EnumHelper;
+
+
+namespace DH.Commons.Enums
+{
+ public interface IShapeElement : INotifyPropertyChanged, ICloneable
+ {
+ string ID { get; set; }
+
+ int Index { get; set; }
+ int GroupIndex { get; set; }
+
+ string Name { get; set; }
+
+ void OnMouseDown(PointF point);
+ void OnMouseUp(PointF point);
+ void OnMouseMove(PointF point);
+ void OnMouseDoubleClick(PointF point);
+ bool IsIntersect(RectangleF rect);
+
+ bool IsEnabled { get; set; }
+ void Draw(Graphics g);
+
+ void Translate(float x, float y);
+
+ ///
+ /// WPF中标识该对象是否已经加入渲染,需要显示
+ ///
+ bool IsShowing { get; set; }
+
+ void Initial();
+ bool IsCreatedDone();
+
+ ElementState State { get; set; }
+ }
+}
diff --git a/DH.Devices.Vision/DH.Devices.Vision.csproj b/DH.Devices.Vision/DH.Devices.Vision.csproj
index 6ca65e5..5c3baff 100644
--- a/DH.Devices.Vision/DH.Devices.Vision.csproj
+++ b/DH.Devices.Vision/DH.Devices.Vision.csproj
@@ -1,15 +1,15 @@
-
+
-
- net8.0-windows
- enable
- enable
- ..\
- output
- true
- true
- AnyCPU;x64
-
+
+ net8.0-windows
+ enable
+ enable
+ ..\
+ output
+ true
+ true
+ AnyCPU;x64
+
@@ -22,4 +22,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\x64\Debug\halcondotnet.dll
+
+
+
diff --git a/DH.Devices.Vision/GlobalSuppressions.cs b/DH.Devices.Vision/GlobalSuppressions.cs
new file mode 100644
index 0000000..8b2c949
--- /dev/null
+++ b/DH.Devices.Vision/GlobalSuppressions.cs
@@ -0,0 +1,10 @@
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Usage", "CA2200:再次引发以保留堆栈详细信息", Justification = "<挂起>", Scope = "member", Target = "~M:DH.Devices.Vision.SimboDetection.Load(DH.Devices.Vision.MLInit)~System.Boolean")]
+[assembly: SuppressMessage("Usage", "CA2200:再次引发以保留堆栈详细信息", Justification = "<挂起>", Scope = "member", Target = "~M:DH.Devices.Vision.SimboInstanceSegmentation.Load(DH.Devices.Vision.MLInit)~System.Boolean")]
+[assembly: SuppressMessage("Usage", "CA2200:再次引发以保留堆栈详细信息", Justification = "<挂起>", Scope = "member", Target = "~M:DH.Devices.Vision.SimboObjectDetection.Load(DH.Devices.Vision.MLInit)~System.Boolean")]
diff --git a/DH.Devices.Vision/SimboDetection.cs b/DH.Devices.Vision/SimboDetection.cs
index d579cf8..7ef52ac 100644
--- a/DH.Devices.Vision/SimboDetection.cs
+++ b/DH.Devices.Vision/SimboDetection.cs
@@ -1,4 +1,4 @@
-#define USE_MULTI_THREAD
+//#define USE_MULTI_THREAD
using OpenCvSharp;
using OpenCvSharp.Extensions;
@@ -13,6 +13,7 @@ using System.Threading.Tasks;
using System.Security.Cryptography.Xml;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
+using DH.Commons.Enums;
@@ -103,14 +104,18 @@ namespace DH.Devices.Vision
// json = "{\"FastDetResult\":[{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654843,\"rect\":[175,99,110,594]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654589,\"rect\":[2608,19,104,661]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654285,\"rect\":[1275,19,104,662]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.620762,\"rect\":[1510,95,107,600]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.617812,\"rect\":[2844,93,106,602]}]}";
//
Console.WriteLine("检测结果JSON:" + json);
+#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
HYoloResult detResult = JsonConvert.DeserializeObject(json);
+#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
if (detResult == null)
{
return;
}
int iNum = detResult.HYolo.Count;
+#pragma warning disable CS0219 // 变量已被赋值,但从未使用过它的值
int IokNum = 0;
+#pragma warning restore CS0219 // 变量已被赋值,但从未使用过它的值
for (int ix = 0; ix < iNum; ix++)
{
var det = detResult.HYolo[ix];
@@ -140,6 +145,7 @@ namespace DH.Devices.Vision
Mat originMat = new Mat();
Mat detectMat = new Mat();
+#pragma warning disable CS0168 // 声明了变量,但从未使用过
try
{
if (req.mImage == null)
@@ -228,15 +234,20 @@ namespace DH.Devices.Vision
{
originMat?.Dispose();
+#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
originMat = null;
+#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
//maskMat?.Dispose();
// maskMat = null;
detectMat?.Dispose();
+#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
detectMat = null;
+#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
// maskWeighted?.Dispose();
// maskWeighted = null;
// GC.Collect();
}
+#pragma warning restore CS0168 // 声明了变量,但从未使用过
}
diff --git a/DH.Devices.Vision/SimboInstanceSegmentation.cs b/DH.Devices.Vision/SimboInstanceSegmentation.cs
index f0a751d..7f7936c 100644
--- a/DH.Devices.Vision/SimboInstanceSegmentation.cs
+++ b/DH.Devices.Vision/SimboInstanceSegmentation.cs
@@ -12,6 +12,7 @@ using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
+using DH.Commons.Enums;
namespace DH.Devices.Vision
@@ -126,14 +127,18 @@ namespace DH.Devices.Vision
// json = "{\"FastDetResult\":[{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654843,\"rect\":[175,99,110,594]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654589,\"rect\":[2608,19,104,661]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654285,\"rect\":[1275,19,104,662]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.620762,\"rect\":[1510,95,107,600]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.617812,\"rect\":[2844,93,106,602]}]}";
//
Console.WriteLine("检测结果JSON:" + json);
+#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
SegResult detResult = JsonConvert.DeserializeObject(json);
+#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
if (detResult == null)
{
return;
}
int iNum = detResult.SegmentResult.Count;
+#pragma warning disable CS0219 // 变量已被赋值,但从未使用过它的值
int IokNum = 0;
+#pragma warning restore CS0219 // 变量已被赋值,但从未使用过它的值
for (int ix = 0; ix < iNum; ix++)
{
var det = detResult.SegmentResult[ix];
@@ -166,6 +171,7 @@ namespace DH.Devices.Vision
Mat originMat = new Mat();
Mat detectMat = new Mat();
+#pragma warning disable CS0168 // 声明了变量,但从未使用过
try
{
if (req.mImage == null)
@@ -253,11 +259,14 @@ namespace DH.Devices.Vision
{
originMat?.Dispose();
+#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
originMat = null;
+#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
// GC.Collect();
}
+#pragma warning restore CS0168 // 声明了变量,但从未使用过
}
}
diff --git a/DH.Devices.Vision/SimboObjectDetection.cs b/DH.Devices.Vision/SimboObjectDetection.cs
index 6e60836..3ad0d60 100644
--- a/DH.Devices.Vision/SimboObjectDetection.cs
+++ b/DH.Devices.Vision/SimboObjectDetection.cs
@@ -13,6 +13,7 @@ using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
using System.Xml;
+using DH.Commons.Enums;
namespace DH.Devices.Vision
@@ -135,7 +136,9 @@ namespace DH.Devices.Vision
// json = "{\"FastDetResult\":[{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654843,\"rect\":[175,99,110,594]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654589,\"rect\":[2608,19,104,661]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654285,\"rect\":[1275,19,104,662]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.620762,\"rect\":[1510,95,107,600]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.617812,\"rect\":[2844,93,106,602]}]}";
//
Console.WriteLine("检测结果JSON:" + json);
+#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
SegResult detResult = JsonConvert.DeserializeObject(json);
+#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
if (detResult == null)
{
return;
@@ -173,6 +176,7 @@ namespace DH.Devices.Vision
MLResult mlResult = new MLResult();
Mat originMat=new Mat() ;
Mat detectMat= new Mat();
+#pragma warning disable CS0168 // 声明了变量,但从未使用过
try
{
if (req.mImage == null)
@@ -263,19 +267,24 @@ namespace DH.Devices.Vision
if (detectMat != null)
{
detectMat.Dispose();
+#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
detectMat = null;
+#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
}
if (originMat != null)
{
originMat.Dispose();
+#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
originMat = null;
+#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
}
// GC.Collect();
}
+#pragma warning restore CS0168 // 声明了变量,但从未使用过
}
diff --git a/DH.Devices.Vision/SimboVisionDriver.cs b/DH.Devices.Vision/SimboVisionDriver.cs
index 378cecf..7d22468 100644
--- a/DH.Devices.Vision/SimboVisionDriver.cs
+++ b/DH.Devices.Vision/SimboVisionDriver.cs
@@ -1,4 +1,9 @@
-using OpenCvSharp;
+using DH.Commons.Enums;
+using DH.Devices.Devices;
+using DH.UI.Model.Winform;
+using HalconDotNet;
+using OpenCvSharp;
+using OpenCvSharp.Extensions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -6,13 +11,659 @@ using System.Linq;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading.Tasks;
+using System.Windows.Forms;
using System.Xml.Linq;
+using XKRS.UI.Model.Winform;
+using static DH.Commons.Enums.EnumHelper;
+using ResultState = DH.Commons.Enums.ResultState;
+
namespace DH.Devices.Vision
{
- public class SimboVisionDriver
+ public class SimboVisionDriver : VisionEngineBase
{
-
+ public Dictionary HalconToolDict = new Dictionary();
+
+ public List SimboStationMLEngineList = new List();
+
+ public void Init()
+ {
+ //InitialQueue();
+ InitialHalconTools();
+ InitialSimboMLEnginesAsync();
+
+ // ImageSaveHelper.OnImageSaveExceptionRaised -= ImageSaveHelper_OnImageSaveExceptionRaised;
+ // ImageSaveHelper.OnImageSaveExceptionRaised += ImageSaveHelper_OnImageSaveExceptionRaised;
+ // base.Init();
+ }
+
+ //private void ImageSaveHelper_OnImageSaveExceptionRaised(DateTime dt, string msg)
+ //{
+ // LogAsync(new LogMsg(dt, LogLevel.Error, msg));
+ //}
+ public override DetectStationResult RunInference(Mat originImgSet, string detectionId = null)
+ {
+ DetectStationResult detectResult = new DetectStationResult();
+ DetectionConfig detectConfig = null;
+ //找到对应的配置
+ if (!string.IsNullOrWhiteSpace(detectionId))
+ {
+ detectConfig = DetectionConfigs.FirstOrDefault(u => u.Id == detectionId);
+ }
+ else
+ {
+ //detectConfig = DetectionConfigs.FirstOrDefault(u => u.CameraSourceId == camera.CameraName);
+ }
+
+ if (detectConfig == null)
+ {
+
+ //未能获得检测配置
+ return detectResult;
+ }
+ #region 1.预处理
+
+ using (Mat PreTMat = originImgSet.Clone())
+ {
+ PreTreated(detectConfig, detectResult, PreTMat);
+ }
+
+
+
+ #endregion
+ if (detectResult.IsPreTreatNG)
+ {
+ detectResult.ResultState = ResultState.DetectNG;
+ detectResult.IsPreTreatDone = true;
+ detectResult.IsMLDetectDone = false;
+ return detectResult;
+
+ }
+
+
+
+ if (!string.IsNullOrWhiteSpace(detectConfig.ModelPath) && detectConfig.IsEnabled)
+ {
+
+
+ SimboStationMLEngineSet mlSet = null;
+ mlSet = SimboStationMLEngineList.FirstOrDefault(t => t.DetectionId == detectConfig.Id);
+ if (mlSet == null)
+ {
+ // LogAsync(DateTime.Now, LogLevel.Exception, $"异常:{detectConfig.Name}未能获取对应配置的模型检测工具");
+ detectResult.IsMLDetectDone = false;
+
+ //HandleDetectDone(detectResult, detectConfig);
+ return detectResult;
+ }
+
+ #region 2.深度学习推理
+ //LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} 模型检测执行");
+
+ if (!string.IsNullOrWhiteSpace(detectConfig.ModelPath))
+ {
+ Stopwatch mlWatch = new Stopwatch();
+ var req = new MLRequest();
+ //之前的检测图片都是相机存储成HImage
+
+
+ req.ResizeWidth = (int)detectConfig.ModelWidth;
+ req.ResizeHeight = (int)detectConfig.ModelHeight;
+ // req.LabelNames = detectConfig.GetLabelNames();
+ // req.Score = IIConfig.Score;
+ req.mImage = originImgSet.Clone();
+
+ req.in_lable_path = detectConfig.in_lable_path;
+
+ req.confThreshold = detectConfig.ModelconfThreshold;
+ req.iouThreshold = 0.3f;
+ req.segmentWidth = 320;
+ req.out_node_name = "output0";
+ switch (detectConfig.ModelType)
+ {
+ case MLModelType.ImageClassification:
+ break;
+ case MLModelType.ObjectDetection:
+
+ break;
+ case MLModelType.SemanticSegmentation:
+ break;
+ case MLModelType.InstanceSegmentation:
+ break;
+ case MLModelType.ObjectGPUDetection:
+
+ break;
+ default:
+ break;
+ }
+
+ // LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} RunInference BEGIN");
+ mlWatch.Start();
+ //20230802改成多线程推理 RunInferenceFixed
+
+ var result = mlSet.StationMLEngine.RunInference(req);
+ // var result = mlSet.StationMLEngine.RunInferenceFixed(req);
+ mlWatch.Stop();
+ // LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} RunInference END");
+
+
+
+
+
+
+ // var req = new MLRequest();
+
+ //req.mImage = inferenceImage;
+
+ //req.ResizeWidth = detectConfig.ModelWidth;
+ //req.ResizeHeight = detectConfig.ModelHeight;
+ //req.confThreshold = detectConfig.ModelconfThreshold;
+ //req.iouThreshold = 0.3f;
+ //req.out_node_name = "output0";
+ //req.in_lable_path = detectConfig.in_lable_path;
+
+ //Stopwatch sw = Stopwatch.StartNew();
+ //var result = Dectection[detectionId].RunInference(req);
+ //sw.Stop();
+ //LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 推理进度1.1,产品{productNumber},耗时{sw.ElapsedMilliseconds}ms");
+
+ //this.BeginInvoke(new MethodInvoker(delegate ()
+ //{
+ // // pictureBox1.Image?.Dispose(); // 释放旧图像
+ // // pictureBox1.Image = result.ResultMap;
+ // richTextBox1.AppendText($"推理成功 {productNumber}, {result.IsSuccess}相机名字{camera.CameraName} 耗时 {mlWatch.ElapsedMilliseconds}ms\n");
+ //}));
+ //req.mImage?.Dispose();
+
+
+
+
+ if (result == null || (result != null && !result.IsSuccess))
+ {
+ detectResult.IsMLDetectDone = false;
+ }
+ if (result != null && result.IsSuccess)
+ {
+ detectResult.DetectDetails = result.ResultDetails;
+ if (detectResult.DetectDetails != null)
+ {
+ }
+ else
+ {
+ detectResult.IsMLDetectDone = false;
+ }
+ }
+ }
+ #endregion
+
+
+
+ #region 3.后处理
+ #endregion
+ //根据那些得分大于阈值的推理结果,判断产品是否成功
+ #region 4.最终过滤(逻辑过滤)
+ detectResult.DetectDetails?.ForEach(d =>
+ {
+
+
+ //当前检测项的 过滤条件
+ //var conditionList = detectConfig.DetectionFilterList
+ // .Where(u => u.IsEnabled && u.LabelName == d.LabelName)
+ // .GroupBy(u => u.ResultState)
+ // .OrderBy(u => u.Key)
+ // .ToList();
+ //当前检测项的 过滤条件
+ var conditionList = detectConfig.DetectionFilterList
+ .Where(u => u.IsEnabled && u.LabelName == d.LabelName)
+ .GroupBy(u => u.ResultState)
+ .OrderBy(u => u.Key)
+ .ToList();
+
+ if (conditionList.Count == 0)
+ {
+
+ d.FinalResult = d.LabelName.ToLower() == "ok"
+ ? ResultState.OK
+ : ResultState.DetectNG;
+ }
+ else
+ {
+ d.FinalResult = detectConfig.IsMixModel
+ ? ResultState.A_NG
+ : ResultState.OK;
+
+
+ }
+
+
+ foreach (IGrouping group in conditionList)
+ {
+ //bool b = group.ToList().Any(f =>
+ //{
+ // return f.FilterOperation(d);
+ //});
+
+
+ //if (b)
+ //{
+ // d.FinalResult = group.Key;
+ // break;
+ //}
+
+ if (group.Any(f => f.FilterOperation(d)))
+ {
+ d.FinalResult = group.Key;
+ break;
+ }
+ //else
+ //{
+ // d.FinalResult = d.InferenceResult = ResultState.OK;
+ //}
+ }
+ });
+ #endregion
+ #region 5.统计缺陷过滤结果或预处理直接NG
+ //if (detectResult.DetectDetails?.Count > 0)
+ //{
+ // detectResult.ResultState = detectResult.DetectDetails.GroupBy(u => u.FinalResult).OrderBy(u => u.Key).First().First().FinalResult;
+ // detectResult.ResultLabel = detectResult.ResultLabel;
+ // detectResult.ResultLabelCategoryId = detectResult.ResultLabel;//TODO:设置优先级
+
+
+ //}
+ detectResult.ResultState = detectResult.DetectDetails?
+ .GroupBy(u => u.FinalResult)
+ .OrderBy(u => u.Key)
+ .FirstOrDefault()?.Key ?? ResultState.OK;
+ detectResult.ResultLabel = detectResult.ResultLabel;
+ detectResult.ResultLabelCategoryId = detectResult.ResultLabel;//TODO:设置优先级
+ #endregion
+
+
+
+
+
+ DisplayDetectionResult(detectResult, originImgSet.Clone(), detectionId);
+
+
+
+
+ }
+ return detectResult;
+
+ }
+ ///
+ /// 初始化深度学习工具
+ ///
+ private bool InitialSimboMLEnginesAsync()
+ {
+ //深度学习 模型加载
+ var resultOK = MLLoadModel();
+ return resultOK;
+ }
+ ///
+ /// 深度学习 模型加载
+ ///
+ ///
+ private bool MLLoadModel()
+ {
+ bool resultOK = false;
+ try
+ {
+ // SimboStationMLEngineList = new List();
+ // _cameraRelatedDetectionDict = IConfig.DetectionConfigs.Select(t => t.ModelPath).Distinct().ToList();
+ DetectionConfigs.ForEach(dc =>
+ //_cameraRelatedDetectionDict.ForEach(dc =>
+ {
+
+ if (dc.IsEnabled && !string.IsNullOrWhiteSpace(dc.ModelPath))
+ {
+ if (dc.IsEnableGPU)
+ {
+ //if (IIConfig.IsLockGPU)
+ //{
+ //foreach (var validGPU in ValidGPUList2)
+ //{
+ // if (validGPU.DetectionIds.Contains(dc.Id))
+ // {
+ var engine = SingleMLLoadModel(dc, true, 0);
+ SimboStationMLEngineList.Add(engine);
+ // }
+ //}
+ //}
+ //else
+ //{
+ // foreach (var validGPU in ValidGPUList)
+ // {
+ // //var validGPU = ValidGPUList.FirstOrDefault(u => u.DetectionIds.Contains(dc.Id));
+ // if (validGPU.DetectionId == dc.Id)
+ // {
+ // var engine = SingleMLLoadModel(dc, true, validGPU.GPUNo);
+ // SimboStationMLEngineList.Add(engine);
+ // }
+ // }
+ //}
+
+ }
+ else
+ {
+ //for (int i = 0; i < IConfig.CPUNums; i++)
+ for (int i = 0; i < 1; i++)
+ {
+ //var engine = SingleMLLoadModel(dc, false, i);
+ var engine = SingleMLLoadModel(dc, false, i);
+ SimboStationMLEngineList.Add(engine);
+ }
+ }
+ }
+ });
+ resultOK = true;
+ }
+ catch (Exception ex)
+ {
+ // LogAsync(DateTime.Now, LogLevel.Exception, $"异常:模型并发加载异常:{ex.GetExceptionMessage()}");
+ resultOK = false;
+ }
+
+ return resultOK;
+ }
+ ///
+ /// 单个模型加载
+ ///
+ ///
+ ///
+ ///
+ private SimboStationMLEngineSet SingleMLLoadModel(DetectionConfig dc, bool isGPU, int coreInx)
+ {
+ SimboStationMLEngineSet mLEngineSet = new SimboStationMLEngineSet();
+ try
+ {
+ mLEngineSet.IsUseGPU = isGPU;
+ if (isGPU)
+ {
+ mLEngineSet.GPUNo = coreInx;
+ }
+ else
+ {
+ mLEngineSet.CPUNo = coreInx;
+ }
+ mLEngineSet.DetectionId = dc.Id;
+ mLEngineSet.DetectionName = dc.Name;
+
+ if (!string.IsNullOrWhiteSpace(dc.ModelPath))
+ {
+ // 根据算法类型创建不同的实例
+ switch (dc.ModelType)
+ {
+ case MLModelType.ImageClassification:
+ break;
+ case MLModelType.ObjectDetection:
+ mLEngineSet.StationMLEngine = new SimboObjectDetection();
+ break;
+ case MLModelType.SemanticSegmentation:
+
+ break;
+ case MLModelType.InstanceSegmentation:
+ mLEngineSet.StationMLEngine = new SimboInstanceSegmentation();
+ break;
+ case MLModelType.ObjectGPUDetection:
+ mLEngineSet.StationMLEngine = new SimboDetection();
+ break;
+ default:
+ break;
+ }
+ MLInit mLInit;
+ string inferenceDevice = "CPU";
+ if (dc.IsEnableGPU)
+ {
+ inferenceDevice = "GPU";
+ mLInit = new MLInit(dc.ModelPath, isGPU, coreInx, dc.ModelconfThreshold);
+ }
+ else
+ {
+ mLInit = new MLInit(dc.ModelPath, "images", inferenceDevice, (int)dc.ModelWidth, (int)dc.ModelHeight);
+
+ }
+
+ bool isSuccess = mLEngineSet.StationMLEngine.Load(mLInit);
+ if (!isSuccess)
+ {
+ // throw new ProcessException("异常:模型加载异常", null);
+ }
+ //LogAsync(DateTime.Now, LogLevel.Information, $"模型加载成功;是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}" + $" {dc.ModelType.GetEnumDescription()}:{dc.ModelPath}");
+ }
+ }
+ catch (Exception ex)
+ {
+ //throw new ProcessException($"异常:是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}模型加载异常:{ex.GetExceptionMessage()}");
+ }
+ return mLEngineSet;
+ }
+ private void InitialHalconTools()
+ {
+ HOperatorSet.SetSystem("parallelize_operators", "true");
+ HOperatorSet.SetSystem("reentrant", "true");
+ HOperatorSet.SetSystem("global_mem_cache", "exclusive");
+
+ HalconToolDict = new Dictionary();
+
+ DetectionConfigs.ForEach(c =>
+ {
+ if (!c.IsEnabled)
+ return;
+
+ if (c.HalconAlgorithemPath_Pre != null)
+ LoadHalconTool(c.HalconAlgorithemPath_Pre);
+
+ });
+ }
+
+ private void LoadHalconTool(string path)
+ {
+ if (!HalconToolDict.ContainsKey(path))
+ {
+
+
+ string algorithemPath = path;
+
+ if (string.IsNullOrWhiteSpace(algorithemPath))
+ return;
+
+ string directoryPath = Path.GetDirectoryName(algorithemPath);
+ string fileName = Path.GetFileNameWithoutExtension(algorithemPath);
+
+ HDevEngineTool tool = new HDevEngineTool(directoryPath);
+ tool.LoadProcedure(fileName);
+
+ HalconToolDict[path] = tool;
+ }
+ }
+
+ ///
+ /// 预处理
+ ///
+ ///
+ ///
+ public void PreTreated(DetectionConfig detectConfig, DetectStationResult detectResult, Mat MhImage)
+ {
+ try
+ {
+ // detectResult.VisionImageSet.DetectionOriginImage = detectResult.VisionImageSet.HImage.ConvertHImageToBitmap();
+ //detectResult.VisionImageSet.PreTreatedBitmap = detectResult.VisionImageSet.HImage.ConvertHImageToBitmap();
+ //detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.PreTreatedBitmap?.CopyBitmap();
+ if (!string.IsNullOrWhiteSpace(detectConfig.HalconAlgorithemPath_Pre))
+ {
+ HObject obj = OpenCVHelper.MatToHImage(MhImage);
+ HImage hImage = HalconHelper.ConvertHObjectToHImage(obj);
+ string toolKey = detectConfig.HalconAlgorithemPath_Pre;
+ if (!HalconToolDict.ContainsKey(toolKey))
+ {
+ // LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}未获取预处理算法");
+ return;
+ }
+ //Mean_Thre Deviation_Thre Mean_standard Deviation_standard
+ var tool = HalconToolDict[toolKey];
+
+ ////tool.InputTupleDic["Mean_Thre"] = 123;
+ for (int i = 0; i < detectConfig.PreTreatParams.Count; i++)
+ {
+ var param = detectConfig.PreTreatParams[i];
+ tool.InputTupleDic[param.Name] = double.Parse(param.Value);
+ }
+
+ // tool.InputTupleDic["fCricularity"] = 200;
+
+ tool.InputImageDic["INPUT_Image"] = hImage;
+
+
+ if (!tool.RunProcedure(out string errorMsg, out _))
+ {
+ // detectResult.PreTreatedFlag = false;
+
+ detectResult.IsPreTreatDone = false;
+
+
+ return;
+ }
+
+ var preTreatRet = tool.GetResultTuple("OUTPUT_Flag").I;
+
+ //var fRCricularity = tool.GetResultTuple("fRCricularity");
+
+
+ // detectResult.IsPreTreatDone = detectResult.VisionImageSet.PreTreatedFlag = preTreatRet == 1;
+ //detectResult.IsPreTreatDone = detectResult.VisionImageSet.PreTreatedFlag = true;
+ // detectResult.VisionImageSet.PreTreatedTime = DateTime.Now;
+
+ for (int i = 0; i < detectConfig.OUTPreTreatParams.Count; i++)
+ {
+ var param = detectConfig.OUTPreTreatParams[i];
+ tool.InputTupleDic[param.Name] = double.Parse(param.Value);
+ }
+
+
+
+
+ // 2023/10/16 新增预处理结果反馈,如果预处理结果为NG,直接返回
+ if (preTreatRet != 0)
+ {
+ detectResult.ResultState = ResultState.DetectNG;
+
+ detectResult.IsPreTreatNG = true;
+
+
+
+ // if (detectResult.VisionImageSet.PreTreatedFlag)
+ {
+ //detectResult.VisionImageSet.MLImage = tool.GetResultObject("OUTPUT_PreTreatedImage");
+ //DetectionResultImage
+ // detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
+
+ }
+
+ }
+ else
+ {
+ // detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
+
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+
+ }
+ finally
+ {
+ //detectResult.VisionImageSet.HImage?.Dispose();
+ //detectResult.VisionImageSet.HImage = null;
+ // MhImage?.Dispose();
+ //MhImage = null;
+ }
+
+ }
+
+ ///
+ /// 显示检测结果
+ ///
+ ///
+ private void DisplayDetectionResult(DetectStationResult detectResult,Mat result,string DetectionId)
+ {
+ //结果显示上传
+ Task.Run(() =>
+ {
+ try
+ {
+
+
+ string displayTxt = detectResult.ResultState.ToString() + "\r\n";
+ if (detectResult.DetectDetails != null && detectResult.DetectDetails?.Count > 0)
+ {
+ detectResult.DetectDetails.ForEach(d =>
+ {
+ displayTxt +=
+ $"{d.LabelName} score:{d.Score.ToString("f2")} area:{d.Area.ToString("f2")}\r\n";
+ });
+ }
+
+ //if (detectResult.realSpecs != null && detectResult.realSpecs?.Count > 0)
+ //{
+ // detectResult.realSpecs.ForEach(d =>
+ // {
+ // displayTxt +=
+ // $"{d.Code} :{d.ActualValue} \r\n";
+ // });
+ //}
+ Bitmap resultMask=result.ToBitmap();
+ //if (detectResult.VisionImageSet.DetectionResultImage == null && detectResult.VisionImageSet.SizeResultImage == null)
+ //{
+ // return;
+ //}
+ //else if (detectResult.VisionImageSet.DetectionResultImage == null && detectResult.VisionImageSet.SizeResultImage != null)
+ //{
+ // detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.SizeResultImage.CopyBitmap();
+ // resultMask = detectResult.VisionImageSet.DetectionResultImage.CopyBitmap();
+ //}
+ //else if (detectResult.VisionImageSet.DetectionResultImage != null && detectResult.VisionImageSet.SizeResultImage != null)
+ //{
+ // Mat img1 = ConvertBitmapToMat(detectResult.VisionImageSet.SizeResultImage.CopyBitmap()); // 第一张图片,已经带框
+ // Mat img2 = ConvertBitmapToMat(detectResult.VisionImageSet.DetectionResultImage.CopyBitmap()); // 第二张图片,已经带框
+
+ // // 合成两张图像:可以选择叠加或拼接
+ // Mat resultImg = new Mat();
+ // Cv2.AddWeighted(img1, 0.5, img2, 0.5, 0, resultImg); // 使用加权平均法合成图像
+
+ // resultMask = resultImg.ToBitmap();
+ //}
+ //else
+ //{
+ // resultMask = detectResult.VisionImageSet.DetectionResultImage.CopyBitmap();
+ //}
+
+ List detectionResultShapes =
+ new List(detectResult.DetectionResultShapes);
+
+ DetectResultDisplay resultDisplay = new DetectResultDisplay(detectResult, resultMask, displayTxt);
+ detectionResultShapes.Add(resultDisplay);
+ List detectionResultShapesClone = new List(detectionResultShapes);
+
+ DetectionDone(DetectionId, resultMask, detectionResultShapes);
+
+ //SaveDetectResultImageAsync(detectResult);
+ // SaveDetectResultCSVAsync(detectResult);
+ }
+ catch (Exception ex)
+ {
+ // LogAsync(DateTime.Now, LogLevel.Exception,
+ // $"{Name}显示{detectResult.DetectName}检测结果异常,{ex.GetExceptionMessage()}");
+ }
+ finally
+ {
+
+
+ }
+ });
+ }
}
}
diff --git a/DH.Devices.Vision/SimboVisionMLBase.cs b/DH.Devices.Vision/SimboVisionMLBase.cs
index 485093e..9d8482a 100644
--- a/DH.Devices.Vision/SimboVisionMLBase.cs
+++ b/DH.Devices.Vision/SimboVisionMLBase.cs
@@ -1,4 +1,5 @@
+using DH.Commons.Enums;
using OpenCvSharp;
using System;
using System.Collections.Generic;
@@ -28,7 +29,7 @@ namespace DH.Devices.Vision
MLGPUEngine.FreePredictor(Model);
}
catch (Exception e) { }
- // MLEngine.FreePredictor(Model);
+ // MLEngine.FreePredictor(Model);
}
public void Dispose2()
{
@@ -41,7 +42,7 @@ namespace DH.Devices.Vision
}
public SimboVisionMLBase()
{
- // ColorMap = OpenCVHelper.GetColorMap(256);//使用3个通道
+ ColorMap = OpenCVHelper.GetColorMap(256);//使用3个通道
// ColorLut = new Mat(1, 256, MatType.CV_8UC3, ColorMap);
}
}
@@ -55,16 +56,22 @@ namespace DH.Devices.Vision
// "rect": [421, 823, 6, 8]
// }]
//}
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public List HYolo;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public class Result
{
public double fScore;
public int classId;
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string classname;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
//public double area;
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public List rect;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
}
@@ -72,45 +79,28 @@ namespace DH.Devices.Vision
}
public class SegResult
{
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public List SegmentResult;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public class Result
{
public double fScore;
public int classId;
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string classname;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public double area;
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public List rect;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
}
}
- public class PreTreatParam
- {
-
- ///
- /// 参数名称
- ///
- ///
- [Category("预处理参数")]
- [DisplayName("参数名称")]
- [Description("参数名称")]
- public string Name { get; set; }
-
-
- ///
- /// 参数值
- ///
- ///
- [Category("预处理参数")]
- [DisplayName("参数值")]
- [Description("参数值")]
- public string Value { get; set; }
-
-
- }
+
public static class MLGPUEngine
{
diff --git a/DH.Devices.Vision/SimboVisionModel.cs b/DH.Devices.Vision/SimboVisionModel.cs
index b07f3e6..9427f3e 100644
--- a/DH.Devices.Vision/SimboVisionModel.cs
+++ b/DH.Devices.Vision/SimboVisionModel.cs
@@ -22,14 +22,20 @@ namespace DH.Devices.Vision
///
/// 检测配置ID
///
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string DetectionId { get; set; }
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string DetectionName { get; set; }
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
///
/// 深度学习模型
///
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public SimboVisionMLBase StationMLEngine { get; set; }
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
}
}
diff --git a/DH.UI.Model.Winform/Canvas.Designer.cs b/DH.UI.Model.Winform/Canvas.Designer.cs
new file mode 100644
index 0000000..d5d2379
--- /dev/null
+++ b/DH.UI.Model.Winform/Canvas.Designer.cs
@@ -0,0 +1,599 @@
+namespace DH.UI.Model.Winform
+{
+ partial class Canvas
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Canvas));
+ this.ctmsElements = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.tsmiResort = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiInitialState = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiClearStandardValue = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiClearActualValue = new System.Windows.Forms.ToolStripMenuItem();
+ this.ctmsKeepElements = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.tsmiUnselectElements = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiKeepSelected = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiKeepUnselected = new System.Windows.Forms.ToolStripMenuItem();
+ this.BottomToolStripPanel = new System.Windows.Forms.ToolStripPanel();
+ this.TopToolStripPanel = new System.Windows.Forms.ToolStripPanel();
+ this.RightToolStripPanel = new System.Windows.Forms.ToolStripPanel();
+ this.LeftToolStripPanel = new System.Windows.Forms.ToolStripPanel();
+ this.ContentPanel = new System.Windows.Forms.ToolStripContentPanel();
+ this.scMain = new System.Windows.Forms.SplitContainer();
+ this.tsROIs = new System.Windows.Forms.ToolStrip();
+ this.tsTool = new System.Windows.Forms.ToolStrip();
+ this.tsBtnLoadImage = new System.Windows.Forms.ToolStripButton();
+ this.tsBtnSaveImage = new System.Windows.Forms.ToolStripButton();
+ this.tsBtnSaveImageWithElements = new System.Windows.Forms.ToolStripButton();
+ this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
+ this.tsBtnMapSize = new System.Windows.Forms.ToolStripButton();
+ this.tsBtnScreenSize = new System.Windows.Forms.ToolStripButton();
+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ this.tsBtnModeNormal = new System.Windows.Forms.ToolStripButton();
+ this.tsBtnModeSelection = new System.Windows.Forms.ToolStripButton();
+ this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ this.chkShowChecked = new System.Windows.Forms.CheckBox();
+ this.dgElements = new System.Windows.Forms.DataGridView();
+ this.colEnableState = new System.Windows.Forms.DataGridViewCheckBoxColumn();
+ this.colId = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.colIndex = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.colName = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.propGridElement = new System.Windows.Forms.PropertyGrid();
+ this.miniToolStrip = new System.Windows.Forms.ToolStrip();
+ this.stsStatus = new System.Windows.Forms.StatusStrip();
+ this.tsslLocation = new System.Windows.Forms.ToolStripStatusLabel();
+ this.tsslMouseState = new System.Windows.Forms.ToolStripStatusLabel();
+ this.dataGridViewCheckBoxColumn1 = new System.Windows.Forms.DataGridViewCheckBoxColumn();
+ this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.ctmsElements.SuspendLayout();
+ this.ctmsKeepElements.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.scMain)).BeginInit();
+ this.scMain.Panel1.SuspendLayout();
+ this.scMain.Panel2.SuspendLayout();
+ this.scMain.SuspendLayout();
+ this.tsTool.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
+ this.splitContainer1.Panel1.SuspendLayout();
+ this.splitContainer1.Panel2.SuspendLayout();
+ this.splitContainer1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.dgElements)).BeginInit();
+ this.stsStatus.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // ctmsElements
+ //
+ this.ctmsElements.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsmiResort,
+ this.tsmiInitialState,
+ this.tsmiClearStandardValue,
+ this.tsmiClearActualValue});
+ this.ctmsElements.Name = "ctmsElements";
+ this.ctmsElements.Size = new System.Drawing.Size(137, 92);
+ //
+ // tsmiResort
+ //
+ this.tsmiResort.Name = "tsmiResort";
+ this.tsmiResort.Size = new System.Drawing.Size(136, 22);
+ this.tsmiResort.Text = "重新排序";
+ this.tsmiResort.Click += new System.EventHandler(this.tsmiResort_Click);
+ //
+ // tsmiInitialState
+ //
+ this.tsmiInitialState.Name = "tsmiInitialState";
+ this.tsmiInitialState.Size = new System.Drawing.Size(136, 22);
+ this.tsmiInitialState.Text = "初始化";
+ this.tsmiInitialState.Click += new System.EventHandler(this.tsmiInitialState_Click);
+ //
+ // tsmiClearStandardValue
+ //
+ this.tsmiClearStandardValue.Name = "tsmiClearStandardValue";
+ this.tsmiClearStandardValue.Size = new System.Drawing.Size(136, 22);
+ this.tsmiClearStandardValue.Text = "清空标准值";
+ this.tsmiClearStandardValue.Click += new System.EventHandler(this.tsmiClearStandardValue_Click);
+ //
+ // tsmiClearActualValue
+ //
+ this.tsmiClearActualValue.Name = "tsmiClearActualValue";
+ this.tsmiClearActualValue.Size = new System.Drawing.Size(136, 22);
+ this.tsmiClearActualValue.Text = "清空测量值";
+ this.tsmiClearActualValue.Click += new System.EventHandler(this.tsmiClearActualValue_Click);
+ //
+ // ctmsKeepElements
+ //
+ this.ctmsKeepElements.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsmiUnselectElements,
+ this.tsmiKeepSelected,
+ this.tsmiKeepUnselected});
+ this.ctmsKeepElements.Name = "ctmsKeepElements";
+ this.ctmsKeepElements.Size = new System.Drawing.Size(173, 70);
+ //
+ // tsmiUnselectElements
+ //
+ this.tsmiUnselectElements.Name = "tsmiUnselectElements";
+ this.tsmiUnselectElements.Size = new System.Drawing.Size(172, 22);
+ this.tsmiUnselectElements.Text = "取消全部基元选择";
+ this.tsmiUnselectElements.Click += new System.EventHandler(this.tsmiUnselectElements_Click);
+ //
+ // tsmiKeepSelected
+ //
+ this.tsmiKeepSelected.Name = "tsmiKeepSelected";
+ this.tsmiKeepSelected.Size = new System.Drawing.Size(172, 22);
+ this.tsmiKeepSelected.Text = "保留选中的基元";
+ this.tsmiKeepSelected.Click += new System.EventHandler(this.tsmiKeepSelected_Click);
+ //
+ // tsmiKeepUnselected
+ //
+ this.tsmiKeepUnselected.Name = "tsmiKeepUnselected";
+ this.tsmiKeepUnselected.Size = new System.Drawing.Size(172, 22);
+ this.tsmiKeepUnselected.Text = "保留未选中的基元";
+ this.tsmiKeepUnselected.Click += new System.EventHandler(this.tsmiKeepUnselected_Click);
+ //
+ // BottomToolStripPanel
+ //
+ this.BottomToolStripPanel.Location = new System.Drawing.Point(0, 0);
+ this.BottomToolStripPanel.Name = "BottomToolStripPanel";
+ this.BottomToolStripPanel.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ this.BottomToolStripPanel.RowMargin = new System.Windows.Forms.Padding(3, 0, 0, 0);
+ this.BottomToolStripPanel.Size = new System.Drawing.Size(0, 0);
+ //
+ // TopToolStripPanel
+ //
+ this.TopToolStripPanel.Location = new System.Drawing.Point(0, 0);
+ this.TopToolStripPanel.Name = "TopToolStripPanel";
+ this.TopToolStripPanel.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ this.TopToolStripPanel.RowMargin = new System.Windows.Forms.Padding(3, 0, 0, 0);
+ this.TopToolStripPanel.Size = new System.Drawing.Size(0, 0);
+ //
+ // RightToolStripPanel
+ //
+ this.RightToolStripPanel.Location = new System.Drawing.Point(0, 0);
+ this.RightToolStripPanel.Name = "RightToolStripPanel";
+ this.RightToolStripPanel.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ this.RightToolStripPanel.RowMargin = new System.Windows.Forms.Padding(3, 0, 0, 0);
+ this.RightToolStripPanel.Size = new System.Drawing.Size(0, 0);
+ //
+ // LeftToolStripPanel
+ //
+ this.LeftToolStripPanel.Location = new System.Drawing.Point(0, 0);
+ this.LeftToolStripPanel.Name = "LeftToolStripPanel";
+ this.LeftToolStripPanel.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ this.LeftToolStripPanel.RowMargin = new System.Windows.Forms.Padding(3, 0, 0, 0);
+ this.LeftToolStripPanel.Size = new System.Drawing.Size(0, 0);
+ //
+ // ContentPanel
+ //
+ this.ContentPanel.Size = new System.Drawing.Size(610, 417);
+ //
+ // scMain
+ //
+ this.scMain.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.scMain.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
+ this.scMain.Location = new System.Drawing.Point(0, 0);
+ this.scMain.Name = "scMain";
+ //
+ // scMain.Panel1
+ //
+ this.scMain.Panel1.Controls.Add(this.tsROIs);
+ this.scMain.Panel1.Controls.Add(this.tsTool);
+ //
+ // scMain.Panel2
+ //
+ this.scMain.Panel2.Controls.Add(this.splitContainer1);
+ this.scMain.Size = new System.Drawing.Size(635, 467);
+ this.scMain.SplitterDistance = 399;
+ this.scMain.TabIndex = 4;
+ //
+ // tsROIs
+ //
+ this.tsROIs.Location = new System.Drawing.Point(29, 0);
+ this.tsROIs.Name = "tsROIs";
+ this.tsROIs.Size = new System.Drawing.Size(370, 25);
+ this.tsROIs.TabIndex = 2;
+ this.tsROIs.Text = "toolStrip1";
+ this.tsROIs.Visible = false;
+ //
+ // tsTool
+ //
+ this.tsTool.Dock = System.Windows.Forms.DockStyle.Left;
+ this.tsTool.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+ this.tsTool.ImageScalingSize = new System.Drawing.Size(24, 24);
+ this.tsTool.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsBtnLoadImage,
+ this.tsBtnSaveImage,
+ this.tsBtnSaveImageWithElements,
+ this.toolStripSeparator4,
+ this.tsBtnMapSize,
+ this.tsBtnScreenSize,
+ this.toolStripSeparator1,
+ this.tsBtnModeNormal,
+ this.tsBtnModeSelection,
+ this.toolStripSeparator2});
+ this.tsTool.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow;
+ this.tsTool.Location = new System.Drawing.Point(0, 0);
+ this.tsTool.Margin = new System.Windows.Forms.Padding(10, 0, 0, 0);
+ this.tsTool.Name = "tsTool";
+ this.tsTool.Size = new System.Drawing.Size(29, 467);
+ this.tsTool.TabIndex = 1;
+ this.tsTool.Text = "toolStrip1";
+ //
+ // tsBtnLoadImage
+ //
+ this.tsBtnLoadImage.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsBtnLoadImage.Image = ((System.Drawing.Image)(resources.GetObject("tsBtnLoadImage.Image")));
+ this.tsBtnLoadImage.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsBtnLoadImage.Name = "tsBtnLoadImage";
+ this.tsBtnLoadImage.Size = new System.Drawing.Size(26, 28);
+ this.tsBtnLoadImage.Text = "LoadImage";
+ this.tsBtnLoadImage.ToolTipText = "Load Image";
+ this.tsBtnLoadImage.Click += new System.EventHandler(this.tsBtnLoadImage_Click);
+ //
+ // tsBtnSaveImage
+ //
+ this.tsBtnSaveImage.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsBtnSaveImage.Image = ((System.Drawing.Image)(resources.GetObject("tsBtnSaveImage.Image")));
+ this.tsBtnSaveImage.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsBtnSaveImage.Name = "tsBtnSaveImage";
+ this.tsBtnSaveImage.Size = new System.Drawing.Size(26, 28);
+ this.tsBtnSaveImage.Text = "SaveImage";
+ this.tsBtnSaveImage.Click += new System.EventHandler(this.tsBtnSaveImage_Click);
+ //
+ // tsBtnSaveImageWithElements
+ //
+ this.tsBtnSaveImageWithElements.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsBtnSaveImageWithElements.Image = ((System.Drawing.Image)(resources.GetObject("tsBtnSaveImageWithElements.Image")));
+ this.tsBtnSaveImageWithElements.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsBtnSaveImageWithElements.Name = "tsBtnSaveImageWithElements";
+ this.tsBtnSaveImageWithElements.Size = new System.Drawing.Size(26, 28);
+ this.tsBtnSaveImageWithElements.Text = "SaveImageWithElements";
+ this.tsBtnSaveImageWithElements.Click += new System.EventHandler(this.tsBtnSaveImageWithElements_Click);
+ //
+ // toolStripSeparator4
+ //
+ this.toolStripSeparator4.Name = "toolStripSeparator4";
+ this.toolStripSeparator4.Size = new System.Drawing.Size(26, 6);
+ //
+ // tsBtnMapSize
+ //
+ this.tsBtnMapSize.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsBtnMapSize.Image = ((System.Drawing.Image)(resources.GetObject("tsBtnMapSize.Image")));
+ this.tsBtnMapSize.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsBtnMapSize.Name = "tsBtnMapSize";
+ this.tsBtnMapSize.Size = new System.Drawing.Size(26, 28);
+ this.tsBtnMapSize.Text = "Original";
+ this.tsBtnMapSize.ToolTipText = "Map Size";
+ this.tsBtnMapSize.Click += new System.EventHandler(this.tsBtnMapSize_Click);
+ //
+ // tsBtnScreenSize
+ //
+ this.tsBtnScreenSize.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsBtnScreenSize.Image = ((System.Drawing.Image)(resources.GetObject("tsBtnScreenSize.Image")));
+ this.tsBtnScreenSize.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsBtnScreenSize.Name = "tsBtnScreenSize";
+ this.tsBtnScreenSize.Size = new System.Drawing.Size(26, 28);
+ this.tsBtnScreenSize.Text = "toolStripButton2";
+ this.tsBtnScreenSize.ToolTipText = "Screen Size";
+ this.tsBtnScreenSize.Click += new System.EventHandler(this.tsBtnScreenSize_Click);
+ //
+ // toolStripSeparator1
+ //
+ this.toolStripSeparator1.Name = "toolStripSeparator1";
+ this.toolStripSeparator1.Size = new System.Drawing.Size(26, 6);
+ //
+ // tsBtnModeNormal
+ //
+ this.tsBtnModeNormal.CheckOnClick = true;
+ this.tsBtnModeNormal.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsBtnModeNormal.Image = ((System.Drawing.Image)(resources.GetObject("tsBtnModeNormal.Image")));
+ this.tsBtnModeNormal.ImageTransparentColor = System.Drawing.SystemColors.Control;
+ this.tsBtnModeNormal.Name = "tsBtnModeNormal";
+ this.tsBtnModeNormal.Size = new System.Drawing.Size(26, 28);
+ this.tsBtnModeNormal.Text = "Normal Mode";
+ this.tsBtnModeNormal.ToolTipText = "Normal Mode";
+ this.tsBtnModeNormal.CheckedChanged += new System.EventHandler(this.tsBtnModeNormal_CheckedChanged);
+ //
+ // tsBtnModeSelection
+ //
+ this.tsBtnModeSelection.CheckOnClick = true;
+ this.tsBtnModeSelection.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsBtnModeSelection.Image = ((System.Drawing.Image)(resources.GetObject("tsBtnModeSelection.Image")));
+ this.tsBtnModeSelection.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsBtnModeSelection.Name = "tsBtnModeSelection";
+ this.tsBtnModeSelection.Size = new System.Drawing.Size(26, 28);
+ this.tsBtnModeSelection.Text = "Selection Mode";
+ this.tsBtnModeSelection.CheckedChanged += new System.EventHandler(this.tsBtnModeNormal_CheckedChanged);
+ //
+ // toolStripSeparator2
+ //
+ this.toolStripSeparator2.Name = "toolStripSeparator2";
+ this.toolStripSeparator2.Size = new System.Drawing.Size(26, 6);
+ //
+ // splitContainer1
+ //
+ this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer1.Location = new System.Drawing.Point(0, 0);
+ this.splitContainer1.Name = "splitContainer1";
+ this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ //
+ // splitContainer1.Panel1
+ //
+ this.splitContainer1.Panel1.Controls.Add(this.chkShowChecked);
+ this.splitContainer1.Panel1.Controls.Add(this.dgElements);
+ //
+ // splitContainer1.Panel2
+ //
+ this.splitContainer1.Panel2.Controls.Add(this.propGridElement);
+ this.splitContainer1.Size = new System.Drawing.Size(232, 467);
+ this.splitContainer1.SplitterDistance = 215;
+ this.splitContainer1.TabIndex = 2;
+ //
+ // chkShowChecked
+ //
+ this.chkShowChecked.AutoSize = true;
+ this.chkShowChecked.Location = new System.Drawing.Point(14, 8);
+ this.chkShowChecked.Name = "chkShowChecked";
+ this.chkShowChecked.Size = new System.Drawing.Size(110, 17);
+ this.chkShowChecked.TabIndex = 1;
+ this.chkShowChecked.Text = "仅显示选中项目";
+ this.chkShowChecked.UseVisualStyleBackColor = true;
+ this.chkShowChecked.CheckedChanged += new System.EventHandler(this.chkShowChecked_CheckedChanged);
+ //
+ // dgElements
+ //
+ this.dgElements.AllowUserToAddRows = false;
+ this.dgElements.AllowUserToDeleteRows = false;
+ this.dgElements.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.dgElements.BackgroundColor = System.Drawing.SystemColors.GradientInactiveCaption;
+ this.dgElements.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ this.dgElements.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+ this.colEnableState,
+ this.colId,
+ this.colIndex,
+ this.colName});
+ this.dgElements.Location = new System.Drawing.Point(0, 30);
+ this.dgElements.MultiSelect = false;
+ this.dgElements.Name = "dgElements";
+ this.dgElements.RowTemplate.Height = 23;
+ this.dgElements.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
+ this.dgElements.Size = new System.Drawing.Size(232, 185);
+ this.dgElements.TabIndex = 0;
+ this.dgElements.CellMouseDoubleClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.dgElements_CellMouseDoubleClick);
+ this.dgElements.SelectionChanged += new System.EventHandler(this.dgElements_SelectionChanged);
+ //
+ // colEnableState
+ //
+ this.colEnableState.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.colEnableState.DataPropertyName = "IsEnabled";
+ this.colEnableState.FillWeight = 41.95804F;
+ this.colEnableState.HeaderText = "";
+ this.colEnableState.MinimumWidth = 30;
+ this.colEnableState.Name = "colEnableState";
+ this.colEnableState.Resizable = System.Windows.Forms.DataGridViewTriState.True;
+ //
+ // colId
+ //
+ this.colId.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.colId.DataPropertyName = "ID";
+ this.colId.HeaderText = "ID";
+ this.colId.MinimumWidth = 30;
+ this.colId.Name = "colId";
+ this.colId.ReadOnly = true;
+ this.colId.Visible = false;
+ //
+ // colIndex
+ //
+ this.colIndex.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
+ this.colIndex.DataPropertyName = "Index";
+ this.colIndex.HeaderText = "序号";
+ this.colIndex.MinimumWidth = 40;
+ this.colIndex.Name = "colIndex";
+ this.colIndex.ReadOnly = true;
+ this.colIndex.Width = 56;
+ //
+ // colName
+ //
+ this.colName.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.colName.DataPropertyName = "Name";
+ this.colName.FillWeight = 158.042F;
+ this.colName.HeaderText = "名称";
+ this.colName.MinimumWidth = 60;
+ this.colName.Name = "colName";
+ this.colName.ReadOnly = true;
+ //
+ // propGridElement
+ //
+ this.propGridElement.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.propGridElement.LargeButtons = true;
+ this.propGridElement.LineColor = System.Drawing.SystemColors.ControlDark;
+ this.propGridElement.Location = new System.Drawing.Point(0, 0);
+ this.propGridElement.Margin = new System.Windows.Forms.Padding(3, 3, 3, 50);
+ this.propGridElement.Name = "propGridElement";
+ this.propGridElement.Size = new System.Drawing.Size(232, 248);
+ this.propGridElement.TabIndex = 0;
+ this.propGridElement.ToolbarVisible = false;
+ this.propGridElement.SelectedObjectsChanged += new System.EventHandler(this.propGridElement_SelectedObjectsChanged);
+ //
+ // miniToolStrip
+ //
+ this.miniToolStrip.AccessibleName = "新项选择";
+ this.miniToolStrip.AccessibleRole = System.Windows.Forms.AccessibleRole.ButtonDropDown;
+ this.miniToolStrip.AutoSize = false;
+ this.miniToolStrip.CanOverflow = false;
+ this.miniToolStrip.Dock = System.Windows.Forms.DockStyle.None;
+ this.miniToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+ this.miniToolStrip.ImageScalingSize = new System.Drawing.Size(24, 24);
+ this.miniToolStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow;
+ this.miniToolStrip.Location = new System.Drawing.Point(0, 235);
+ this.miniToolStrip.Margin = new System.Windows.Forms.Padding(10, 0, 0, 0);
+ this.miniToolStrip.Name = "miniToolStrip";
+ this.miniToolStrip.Size = new System.Drawing.Size(29, 237);
+ this.miniToolStrip.TabIndex = 1;
+ //
+ // stsStatus
+ //
+ this.stsStatus.BackColor = System.Drawing.Color.Transparent;
+ this.stsStatus.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsslLocation,
+ this.tsslMouseState});
+ this.stsStatus.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.Flow;
+ this.stsStatus.Location = new System.Drawing.Point(0, 445);
+ this.stsStatus.Name = "stsStatus";
+ this.stsStatus.Size = new System.Drawing.Size(635, 22);
+ this.stsStatus.TabIndex = 0;
+ this.stsStatus.Text = "statusStrip1";
+ //
+ // tsslLocation
+ //
+ this.tsslLocation.Name = "tsslLocation";
+ this.tsslLocation.Size = new System.Drawing.Size(24, 17);
+ this.tsslLocation.Text = " ";
+ //
+ // tsslMouseState
+ //
+ this.tsslMouseState.Name = "tsslMouseState";
+ this.tsslMouseState.Size = new System.Drawing.Size(52, 17);
+ this.tsslMouseState.Text = " ";
+ //
+ // dataGridViewCheckBoxColumn1
+ //
+ this.dataGridViewCheckBoxColumn1.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.dataGridViewCheckBoxColumn1.DataPropertyName = "IsEnabled";
+ this.dataGridViewCheckBoxColumn1.FillWeight = 41.95804F;
+ this.dataGridViewCheckBoxColumn1.HeaderText = "";
+ this.dataGridViewCheckBoxColumn1.MinimumWidth = 30;
+ this.dataGridViewCheckBoxColumn1.Name = "dataGridViewCheckBoxColumn1";
+ this.dataGridViewCheckBoxColumn1.Resizable = System.Windows.Forms.DataGridViewTriState.True;
+ //
+ // dataGridViewTextBoxColumn1
+ //
+ this.dataGridViewTextBoxColumn1.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.dataGridViewTextBoxColumn1.DataPropertyName = "Id";
+ this.dataGridViewTextBoxColumn1.HeaderText = "ID";
+ this.dataGridViewTextBoxColumn1.MinimumWidth = 30;
+ this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
+ this.dataGridViewTextBoxColumn1.ReadOnly = true;
+ this.dataGridViewTextBoxColumn1.Visible = false;
+ //
+ // dataGridViewTextBoxColumn2
+ //
+ this.dataGridViewTextBoxColumn2.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader;
+ this.dataGridViewTextBoxColumn2.DataPropertyName = "Index";
+ this.dataGridViewTextBoxColumn2.HeaderText = "序号";
+ this.dataGridViewTextBoxColumn2.MinimumWidth = 40;
+ this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
+ this.dataGridViewTextBoxColumn2.ReadOnly = true;
+ //
+ // dataGridViewTextBoxColumn3
+ //
+ this.dataGridViewTextBoxColumn3.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader;
+ this.dataGridViewTextBoxColumn3.DataPropertyName = "Name";
+ this.dataGridViewTextBoxColumn3.FillWeight = 158.042F;
+ this.dataGridViewTextBoxColumn3.HeaderText = "名称";
+ this.dataGridViewTextBoxColumn3.MinimumWidth = 80;
+ this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3";
+ this.dataGridViewTextBoxColumn3.ReadOnly = true;
+ //
+ // Canvas
+ //
+ this.Controls.Add(this.stsStatus);
+ this.Controls.Add(this.scMain);
+ this.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, ((byte)(134)));
+ this.Name = "Canvas";
+ this.Size = new System.Drawing.Size(635, 467);
+ this.ctmsElements.ResumeLayout(false);
+ this.ctmsKeepElements.ResumeLayout(false);
+ this.scMain.Panel1.ResumeLayout(false);
+ this.scMain.Panel1.PerformLayout();
+ this.scMain.Panel2.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.scMain)).EndInit();
+ this.scMain.ResumeLayout(false);
+ this.tsTool.ResumeLayout(false);
+ this.tsTool.PerformLayout();
+ this.splitContainer1.Panel1.ResumeLayout(false);
+ this.splitContainer1.Panel1.PerformLayout();
+ this.splitContainer1.Panel2.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
+ this.splitContainer1.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.dgElements)).EndInit();
+ this.stsStatus.ResumeLayout(false);
+ this.stsStatus.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn2;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn3;
+ private System.Windows.Forms.ContextMenuStrip ctmsElements;
+ private System.Windows.Forms.ToolStripMenuItem tsmiResort;
+ private System.Windows.Forms.ToolStripMenuItem tsmiInitialState;
+ private System.Windows.Forms.ToolStripMenuItem tsmiClearStandardValue;
+ private System.Windows.Forms.ToolStripMenuItem tsmiClearActualValue;
+ private System.Windows.Forms.DataGridViewCheckBoxColumn dataGridViewCheckBoxColumn1;
+ private System.Windows.Forms.ContextMenuStrip ctmsKeepElements;
+ private System.Windows.Forms.ToolStripMenuItem tsmiKeepSelected;
+ private System.Windows.Forms.ToolStripMenuItem tsmiKeepUnselected;
+ private System.Windows.Forms.ToolStripMenuItem tsmiUnselectElements;
+ private System.Windows.Forms.ToolStripPanel BottomToolStripPanel;
+ private System.Windows.Forms.ToolStripPanel TopToolStripPanel;
+ private System.Windows.Forms.ToolStripPanel RightToolStripPanel;
+ private System.Windows.Forms.ToolStripPanel LeftToolStripPanel;
+ private System.Windows.Forms.ToolStripContentPanel ContentPanel;
+ private System.Windows.Forms.SplitContainer scMain;
+ private System.Windows.Forms.StatusStrip stsStatus;
+ private System.Windows.Forms.ToolStripStatusLabel tsslLocation;
+ private System.Windows.Forms.ToolStripStatusLabel tsslMouseState;
+ private System.Windows.Forms.ToolStrip tsTool;
+ private System.Windows.Forms.ToolStripButton tsBtnLoadImage;
+ private System.Windows.Forms.ToolStripButton tsBtnSaveImage;
+ private System.Windows.Forms.ToolStripButton tsBtnSaveImageWithElements;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
+ private System.Windows.Forms.ToolStripButton tsBtnMapSize;
+ private System.Windows.Forms.ToolStripButton tsBtnScreenSize;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ private System.Windows.Forms.ToolStripButton tsBtnModeNormal;
+ private System.Windows.Forms.ToolStripButton tsBtnModeSelection;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ private System.Windows.Forms.CheckBox chkShowChecked;
+ private System.Windows.Forms.DataGridView dgElements;
+ private System.Windows.Forms.DataGridViewCheckBoxColumn colEnableState;
+ private System.Windows.Forms.DataGridViewTextBoxColumn colId;
+ private System.Windows.Forms.DataGridViewTextBoxColumn colIndex;
+ private System.Windows.Forms.DataGridViewTextBoxColumn colName;
+ private System.Windows.Forms.PropertyGrid propGridElement;
+ private System.Windows.Forms.ToolStrip miniToolStrip;
+ private System.Windows.Forms.ToolStrip tsROIs;
+ }
+}
diff --git a/DH.UI.Model.Winform/Canvas.cs b/DH.UI.Model.Winform/Canvas.cs
new file mode 100644
index 0000000..8c95fd2
--- /dev/null
+++ b/DH.UI.Model.Winform/Canvas.cs
@@ -0,0 +1,629 @@
+
+using DH.Commons.Enums;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static DH.Commons.Enums.EnumHelper;
+
+
+
+namespace DH.UI.Model.Winform
+{
+ public partial class Canvas : UserControl
+ {
+ readonly CanvasImage cvImage = new CanvasImage();
+
+ #region Grid
+ readonly GridCtrl gridCtrl = new GridCtrl();
+
+ private void GridValueChanged(int gridValue)
+ {
+ cvImage.GridValue = gridValue;
+ }
+
+ private void ShowGridChanged(bool isShowGrid)
+ {
+ cvImage.ShowGrid = isShowGrid;
+ }
+
+ private void GridColorChanged(Color obj)
+ {
+ cvImage.Pen_Grid.Color = obj;
+ }
+ #endregion
+
+ public Canvas()
+ {
+ InitializeComponent();
+ DoubleBuffered = true;
+ SetStyle(ControlStyles.OptimizedDoubleBuffer |
+ ControlStyles.ResizeRedraw |
+ ControlStyles.AllPaintingInWmPaint, true);
+
+ cvImage.Dock = DockStyle.Fill;
+ scMain.Panel1.Controls.Add(cvImage);
+
+ dgElements.AutoGenerateColumns = false;
+
+ var checkHead = new DataGridViewCheckboxHeaderCell();
+ checkHead.OnCheckBoxClicked += CheckHead_OnCheckBoxClicked;
+ dgElements.Columns[0].HeaderCell = checkHead;
+ dgElements.Columns[0].HeaderCell.Value = string.Empty;
+
+ Elements.CollectionChanged += Elements_CollectionChanged;
+
+ cvImage.OnMouseLocationUpdated = OnMouseLocationUpdated;
+ cvImage.OnMouseStateChanged += OnMouseStateChanged;
+
+ gridCtrl.IsShowGridChanged = ShowGridChanged;
+ gridCtrl.GridValueChanged = GridValueChanged;
+ gridCtrl.GridColorChanged = GridColorChanged;
+ gridCtrl.Padding = new Padding(0, 5, 0, 5);
+ tsTool.Items.Add(new GridCtrlHost(gridCtrl));
+ tsTool.Invalidate();
+
+ _eleCollectionChangedTimer = new System.Threading.Timer(OnElementCollectionChangedBufferTimer, null, -1, -1);
+
+ //tsmiShowStatusBar.Checked = tsmiShowToolBar.Checked = IsShowElementList = IsShowROITool = IsShowStatusBar = IsShowToolBar = false;
+ }
+
+ private void OnMouseStateChanged(MouseState ms)
+ {
+ if (ms != MouseState.SelectionZone && ms != MouseState.SelectionZoneDoing)
+ {
+ if (this.IsHandleCreated)
+ {
+ this.Invoke(new Action(() =>
+ {
+ tsBtnModeSelection.Checked = false;
+ tsBtnModeNormal.Checked = true;
+ }));
+ }
+ }
+ }
+
+ #region 底部状态栏
+ public bool IsShowStatusBar
+ {
+ get => stsStatus.Visible;
+ set => stsStatus.Visible = value;
+ }
+
+ private void OnMouseLocationUpdated(Point screenPoint, PointF imagePoint, string colorDesc)
+ {
+ //await Task.Run(() => tsslLocation.Text = $"屏幕坐标X:{screenPoint.X},Y:{screenPoint.Y} 图片坐标X:{imagePoint.X},Y:{imagePoint.Y} 颜色:{colorDesc}");
+ this.Invoke(new Action(() =>
+ {
+ tsslLocation.Text = $"屏幕坐标X:{screenPoint.X},Y:{screenPoint.Y} 图片坐标X:{imagePoint.X.ToString("f2")},Y:{imagePoint.Y.ToString("f2")} 颜色:{colorDesc}";
+ }));
+ }
+
+ //private void MouseLocationUpdated(Point screenPoint, Point imagePoint, string colorDesc)
+ //{
+ // if (InvokeRequired)
+ // {
+ // Invoke(new Action(MouseLocationUpdated), screenPoint, imagePoint);
+ // }
+ // else
+ // {
+ // tsslLocation.Text = $"屏幕坐标X:{screenPoint.X},Y:{screenPoint.Y} 图片坐标X:{imagePoint.X},Y:{imagePoint.Y} 颜色:{colorDesc}";
+ // }
+ //}
+ #endregion
+
+ #region 属性
+ #region CanvasImage相关
+ //private MouseState mouseState = MouseState.Normal;
+ //public MouseState MouseState
+ //{
+ // get
+ // {
+ // return mouseState;
+ // }
+ // set
+ // {
+ // if (mouseState != value)
+ // {
+ // mouseState = value;
+
+ // tsslMouseState.Text = mouseState.ToString();
+
+ // if (mouseState >= MouseState.SelectionZone)
+ // {
+ // tsBtnModeSelection.Checked = true;
+ // }
+ // else
+ // {
+ // tsBtnModeNormal.Checked = true;
+ // }
+ // }
+ // }
+ //}
+
+ public string ImageFilePath { get; set; }
+
+ public Bitmap MAP
+ {
+ get => cvImage.MAP;
+ set => cvImage.MAP = value;
+ }
+ public Matrix Matrix
+ {
+ get => cvImage.Matrix;
+ set => cvImage.Matrix = value;
+ }
+ public MouseState MouseState
+ {
+ get => cvImage.MouseState;
+ set => cvImage.MouseState = value;
+ }
+ public ObservableCollection Elements
+ {
+ get => cvImage.Elements;
+ }
+ #endregion
+
+ private bool isShowElementList = false;
+ public bool IsShowElementList
+ {
+ get => isShowElementList;
+ set
+ {
+ //if (isShowElementList != value)
+ {
+ isShowElementList = value;
+ scMain.Panel2Collapsed = !value;
+ }
+ }
+ }
+
+ private bool isShowROITool = false;
+ public bool IsShowROITool
+ {
+ get => isShowROITool;
+ set
+ {
+ tsROIs.Visible = isShowROITool = value;
+ }
+ }
+ #endregion
+
+ #region 图片操作
+ ///
+ /// 载入图片
+ ///
+ ///
+ public void LoadImage(Bitmap map)
+ {
+ cvImage.LoadImage(map);
+ OnImageChanged?.Invoke();
+ }
+ public void Clear()
+ {
+ cvImage.Clear();
+ }
+
+ ///
+ /// 设置图片为原始尺寸
+ ///
+ public void SetMapSize()
+ {
+ cvImage.SetMapSize();
+ }
+
+ ///
+ /// 设置图片为适配尺寸
+ ///
+ public void SetScreenSize()
+ {
+ cvImage.SetScreenSize();
+ }
+ #endregion
+
+ #region 基元列表
+ private void chkShowChecked_CheckedChanged(object sender, EventArgs e)
+ {
+ dgElements.DataSource = null;
+
+ if (Elements != null && Elements.Count > 0)
+ {
+ if (chkShowChecked.Checked)
+ {
+ dgElements.DataSource = Elements.Where(u => u.IsEnabled && u.IsShowing).ToList();
+ }
+ else
+ {
+ dgElements.DataSource = Elements.Where(u => u.IsShowing).ToList();
+ }
+ }
+ }
+
+ private void CheckHead_OnCheckBoxClicked(object sender, DataGridViewCheckboxHeaderEventArgs e)
+ {
+ //foreach (IShapeElement ele in Elements)
+ //{
+ // ele.IsEnabled = e.CheckedState;
+ //}
+ for (int i = 0; i < Elements.Count; i++)
+ {
+ Elements[i].IsEnabled = e.CheckedState;
+ }
+ OnElementChanged(null);
+ }
+
+ private void dgElements_SelectionChanged(object sender, EventArgs e)
+ {
+ if (dgElements.SelectedRows.Count > 0)
+ {
+ var ele = Elements.FirstOrDefault(u => u.ID == dgElements.SelectedRows[0].Cells["colID"].Value.ToString());
+ propGridElement.SelectedObject = ele;
+ }
+ }
+
+ private void dgElements_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
+ {
+ if (dgElements.SelectedRows.Count > 0)
+ {
+ var ele = Elements.FirstOrDefault(u => u.ID == dgElements.SelectedRows[0].Cells["colID"].Value.ToString());
+
+ for (int i = 0; i < Elements.Count; i++)
+ {
+ Elements[i].State = ElementState.Normal;
+ }
+
+ ele.State = ElementState.Selected;
+
+ SetDeviceByElement?.Invoke(ele);
+
+ Invalidate();
+ }
+ }
+
+ System.Threading.Timer _eleCollectionChangedTimer = null;
+
+ private void OnElementCollectionChangedBufferTimer(object state)
+ {
+ OnElementChanged(null);
+ for (int i = 0; i < Elements.Count; i++)
+ {
+ Elements[i].PropertyChanged -= Ele_PropertyChanged;
+ Elements[i].PropertyChanged += Ele_PropertyChanged;
+ }
+ //foreach (IShapeElement ele in Elements)
+ //{
+ // ele.PropertyChanged -= Ele_PropertyChanged;
+ // ele.PropertyChanged += Ele_PropertyChanged;
+ //}
+ }
+
+ private void Elements_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+ {
+ //_eleCollectionChangedTimer?.Change(200, -1);
+ OnElementChanged(null);
+ for (int i = 0; i < Elements.Count; i++)
+ {
+ Elements[i].PropertyChanged -= Ele_PropertyChanged;
+ Elements[i].PropertyChanged += Ele_PropertyChanged;
+ }
+ }
+
+ private void Ele_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "IsEnabled")
+ {
+ OnElementChanged(sender as IShapeElement);
+ }
+ else
+ {
+ Invoke(new Action(() =>
+ {
+ cvImage.Invalidate();
+ }));
+ }
+ }
+
+ private void OnElementChanged(IShapeElement ele)
+ {
+ if (ele != null)
+ OnElementChangedHandle?.Invoke(ele);
+
+ if (InvokeRequired)
+ {
+ Invoke(new Action(() => OnElementChanged(ele)));
+ }
+ else
+ {
+ if (isShowElementList)
+ {
+ dgElements.DataSource = null;
+ if (Elements != null && Elements.Count > 0)
+ {
+ if (chkShowChecked.Checked)
+ {
+ dgElements.DataSource = Elements.ToList().Where(u => u.IsEnabled && u.IsShowing).ToList();
+ }
+ else
+ {
+ dgElements.DataSource = Elements.ToList().Where(u => u.IsShowing).ToList();
+ }
+ }
+ Invalidate();
+ }
+ }
+ }
+
+ private void propGridElement_SelectedObjectsChanged(object sender, EventArgs e)
+ {
+ propGridElement.ExpandAllGridItems();
+ }
+
+ #region 基元列表右键菜单
+ private void tsmiResort_Click(object sender, EventArgs e)
+ {
+ //Elements.Sort();
+ }
+
+ private void tsmiClearActualValue_Click(object sender, EventArgs e)
+ {
+ //foreach (IShapeElement ele in Elements)
+ //{
+ // if (ele.IsEnabled)
+ // {
+ // ele.SetActualValue(0.0);
+ // }
+ //}
+ }
+
+ private void tsmiInitialState_Click(object sender, EventArgs e)
+ {
+ //foreach (IShapeElement ele in Elements)
+ //{
+ // if (ele.IsEnabled)
+ // {
+ // ele.State = ElementState.Normal;
+ // ele.InitialMeasureResult();
+ // }
+ //}
+ }
+
+ private void tsmiClearStandardValue_Click(object sender, EventArgs e)
+ {
+ //foreach (IShapeElement ele in Elements)
+ //{
+ // if (ele.IsEnabled)
+ // {
+ // ele.SetStandardValue(0.0);
+ // }
+ //}
+ }
+ #endregion
+ #endregion
+
+ #region 图像区域右键菜单
+ private void tsmiKeepUnselected_Click(object sender, EventArgs e)
+ {
+ KeepElements(false);
+ }
+
+ private void tsmiKeepSelected_Click(object sender, EventArgs e)
+ {
+ KeepElements(true);
+ }
+
+ private void KeepElements(bool isKeepSelected)
+ {
+ for (int i = 0; i < Elements.Count; i++)
+ {
+ var ele = Elements[i];
+ if (ele.IsEnabled)
+ {
+ if (ele.State == ElementState.Selected)
+ {
+ ele.IsEnabled = isKeepSelected;
+ }
+ else
+ {
+ ele.IsEnabled = !isKeepSelected;
+ }
+ }
+ }
+ }
+
+ private void tsmiUnselectElements_Click(object sender, EventArgs e)
+ {
+ //if (MouseState == MouseState.SelectedElement)
+ //{
+ // MouseState = MouseState.Normal;
+
+ // //Elements.ForEach(ele =>
+ // foreach (IShapeElement ele in Elements)
+ // {
+ // ele.State = ElementState.Normal;
+ // }
+ // //);
+ //}
+ }
+ #endregion
+
+ #region 基元的设备属性 运动设置和相机设置
+ public Action SetElementDevicePara;
+
+ public Action SetDeviceByElement;
+ #endregion
+
+ #region 一般操作工具条
+ public bool IsShowToolBar
+ {
+ get => tsTool.Visible;
+ set => tsTool.Visible = value;
+ }
+
+ private void tsBtnLoadImage_Click(object sender, EventArgs e)
+ {
+ Thread InvokeThread = new Thread(new ThreadStart(OpenLoadImage));
+ InvokeThread.SetApartmentState(ApartmentState.STA);
+ InvokeThread.Start();
+ InvokeThread.Join();
+ }
+
+ private void OpenLoadImage()
+ {
+ ImageFilePath = "";
+ OpenFileDialog ofd = new OpenFileDialog();
+ if (ofd.ShowDialog() == DialogResult.OK)
+ {
+ ImageFilePath = ofd.FileName;
+ LoadImage((Bitmap)Bitmap.FromFile(ImageFilePath));
+ }
+ }
+
+ private void tsBtnSaveImage_Click(object sender, EventArgs e)
+ {
+ if (MAP == null)
+ return;
+
+ SaveFileDialog sfd = new SaveFileDialog();
+ sfd.Filter = "JPG文件|*.jpg|BMP文件|*.bmp";
+ if (sfd.ShowDialog() == DialogResult.OK)
+ {
+ string filePath = sfd.FileName;
+ if (filePath.EndsWith("bmp"))
+ {
+ MAP.Save(filePath, ImageFormat.Bmp);
+ }
+ else
+ {
+ MAP.Save(filePath, ImageFormat.Jpeg);
+ }
+ MessageBox.Show("图片保存成功!");
+ }
+ }
+
+ private void tsBtnSaveImageWithElements_Click(object sender, EventArgs e)
+ {
+ if (MAP == null)
+ return;
+
+ SaveFileDialog sfd = new SaveFileDialog();
+ sfd.Filter = "JPG文件|*.jpg|BMP文件|*.bmp";
+ if (sfd.ShowDialog() == DialogResult.OK)
+ {
+ string filePath = sfd.FileName;
+
+ Bitmap bmp = new Bitmap(MAP.Width, MAP.Height, PixelFormat.Format32bppArgb);
+ //Bitmap bmp = new Bitmap(MAP.Width, MAP.Height, MAP.PixelFormat);
+ //Bitmap bmp = new Bitmap(MAP.Width, MAP.Height);
+ using (Graphics g = Graphics.FromImage(bmp))
+ {
+ g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
+ g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
+ g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
+ g.DrawImage(MAP, 0, 0);
+
+ for (int i = 0; i < Elements.Count; i++)
+ {
+ var ele = Elements[i];
+ if (ele.IsEnabled)
+ ele.Draw(g);
+ }
+ }
+
+ if (filePath.EndsWith("bmp"))
+ {
+ bmp.Save(filePath, ImageFormat.Bmp);
+ }
+ else
+ {
+ bmp.Save(filePath, ImageFormat.Jpeg);
+ }
+ MessageBox.Show("带基元图片保存成功!");
+ }
+ }
+
+ private void tsBtnMapSize_Click(object sender, EventArgs e)
+ {
+ SetMapSize();
+ }
+
+ private void tsBtnModeNormal_CheckedChanged(object sender, EventArgs e)
+ {
+ var btn = sender as ToolStripButton;
+ if (btn.Checked)
+ {
+ btn.BackColor = SystemColors.ActiveCaption;
+
+ foreach (ToolStripItem c in tsTool.Items)
+ {
+ if (c is ToolStripButton)
+ {
+ if (c.Name.StartsWith("tsBtnMode") && c.Name != btn.Name)
+ {
+ var temp = c as ToolStripButton;
+ temp.Checked = false;
+ temp.BackColor = SystemColors.Control;
+ }
+ }
+ }
+
+ switch (btn.Name)
+ {
+ case "tsBtnModeNormal":
+ MouseState = MouseState.Normal;
+ break;
+ case "tsBtnModeSelection":
+ MouseState = MouseState.SelectionZone;
+ break;
+ }
+ }
+ }
+
+ private void tsBtnScreenSize_Click(object sender, EventArgs e)
+ {
+ SetScreenSize();
+ }
+ #endregion
+
+ #region 基元工具条
+ //private void LoadElementTools()
+ //{
+ // var eleDict = ElementFactory.GetAllElementsInfo();
+
+ // foreach (KeyValuePair pair in eleDict)
+ // {
+
+ // }
+ //}
+
+ public void SetNewROIType(IShapeElement element)
+ {
+ cvImage.DrawTemplate = element;
+ }
+ #endregion
+
+ #region 事件
+ public event Action OnElementChangedHandle;
+ public event Action OnImageChanged;
+ #endregion
+
+ #region 工具栏显示/隐藏右键菜单
+ private void tsmiShowToolBar_CheckedChanged(object sender, EventArgs e)
+ {
+ //IsShowToolBar = tsmiShowToolBar.Checked;
+ }
+
+ private void tsmiShowStatusBar_CheckedChanged(object sender, EventArgs e)
+ {
+ //IsShowStatusBar = tsmiShowStatusBar.Checked;
+ }
+ #endregion
+ }
+}
diff --git a/DH.UI.Model.Winform/Canvas.resx b/DH.UI.Model.Winform/Canvas.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/DH.UI.Model.Winform/Canvas.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/DH.UI.Model.Winform/CanvasImage.Designer.cs b/DH.UI.Model.Winform/CanvasImage.Designer.cs
new file mode 100644
index 0000000..1e2b61f
--- /dev/null
+++ b/DH.UI.Model.Winform/CanvasImage.Designer.cs
@@ -0,0 +1,33 @@
+namespace DH.UI.Model.Winform
+{
+ partial class CanvasImage
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ //
+ // CanvasImage
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.Name = "CanvasImage";
+ this.Size = new System.Drawing.Size(575, 472);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ }
+}
diff --git a/DH.UI.Model.Winform/CanvasImage.cs b/DH.UI.Model.Winform/CanvasImage.cs
new file mode 100644
index 0000000..e25b9a7
--- /dev/null
+++ b/DH.UI.Model.Winform/CanvasImage.cs
@@ -0,0 +1,943 @@
+
+using DH.Commons.Enums;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.Linq;
+using System.Threading;
+using System.Windows.Forms;
+
+using static DH.Commons.Enums.EnumHelper;
+
+
+namespace DH.UI.Model.Winform
+{
+ public partial class CanvasImage : UserControl
+ {
+ public CanvasImage()
+ {
+ InitializeComponent();
+
+ DoubleBuffered = true;
+ SetStyle(ControlStyles.OptimizedDoubleBuffer |
+ ControlStyles.ResizeRedraw |
+ ControlStyles.AllPaintingInWmPaint, true);
+
+ MouseWheel += Canvas_MouseWheel;
+ KeyDown += OnCanvasKeyDown;
+ KeyPress += OnCanvasKeyPressed;
+ MouseDoubleClick += Canvas_MouseDoubleClick;
+ MouseDown += Canvas_MouseDown;
+ MouseMove += Canvas_MouseMove;
+ MouseUp += Canvas_MouseUp;
+
+ // EventRouter.ChangeElementsMouseState -= OnElementChangeMouseState;
+ // EventRouter.ChangeElementsMouseState += OnElementChangeMouseState;
+
+ //Elements.CollectionChanged += Elements_CollectionChanged;
+ }
+
+ private void Elements_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+ {
+ //this.Invoke(new Action(() =>
+ //{
+ // this.Invalidate();
+ //}));
+ }
+
+ #region Event
+ public Action OnMouseStateChanged;
+ public Action DrawTemplateChanged = null;
+ public Action OnMouseLocationUpdated;
+ #endregion
+
+ private MouseState mouseState = MouseState.Normal;
+ public MouseState MouseState
+ {
+ get
+ {
+ return mouseState;
+ }
+ set
+ {
+ if (mouseState != value)
+ {
+ mouseState = value;
+
+ // OnMouseStateChanged?.BeginInvoke(value, null, null);
+ Task.Run(() => OnMouseStateChanged.Invoke(value));
+ }
+ }
+ }
+
+ #region 属性和字段
+
+ //private Bitmap map = new Bitmap(10, 10);
+ //public Bitmap MAP
+ //{
+ // get
+ // {
+ // _mapLoadHandler.WaitOne();
+ // return map;
+ // }
+ // set
+ // {
+ // map = value;
+ // }
+ //}
+
+ public Bitmap MAP { get; set; } = new Bitmap(10, 10);
+
+ public Matrix Matrix { get; set; } = new Matrix();
+ public ObservableCollection Elements { get; set; } = new ObservableCollection();
+
+ RectangleF _selectionRect = new RectangleF();
+ #endregion
+
+ #region 重绘
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ try
+ {
+ //lock (_mapLoadLock)
+ //{ }
+
+ Rectangle rect = ClientRectangle;
+ Graphics originG = e.Graphics;
+ BufferedGraphicsContext currentContext = BufferedGraphicsManager.Current;
+ BufferedGraphics myBuffer = currentContext.Allocate(originG, rect);
+ Graphics g = myBuffer.Graphics;
+ g.SmoothingMode = SmoothingMode.HighSpeed;
+ g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
+ g.InterpolationMode = InterpolationMode.NearestNeighbor;
+ g.Clear(BackColor);
+
+ g.MultiplyTransform(Matrix);
+
+ if (MAP != null)
+ {
+ try
+ {
+ g.DrawImage(MAP, 0, 0, MAP.Width, MAP.Height);
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+ else
+ {
+ g.Clear(BackColor);
+ }
+
+ DrawTemplate?.Draw(g);
+ foreach (IShapeElement ele in Elements)
+ {
+ if (ele.IsEnabled && ele.IsShowing)
+ {
+ ele.Draw(g);
+ }
+ }
+
+ #region Grid
+ if (MAP != null)
+ {
+ if (ShowGrid)
+ {
+ int baseX = MAP.Width / 2;
+ int baseY = MAP.Height / 2;
+
+ Point[] xPoint = new Point[] { new Point(0, baseY), new Point(MAP.Width, baseY) };
+ Point[] yPoint = new Point[] { new Point(baseX, 0), new Point(baseX, MAP.Height) };
+
+ g.DrawLine(new Pen(Pen_Grid.Color, 5.0f), xPoint[0], xPoint[1]);
+ g.DrawLine(new Pen(Pen_Grid.Color, 5.0f), yPoint[0], yPoint[1]);
+
+ if (GridValue > 0)
+ {
+ int stepX = MAP.Width / 2 / (GridValue * MAP.Width / 2 / _minGridStep / 10);
+ int stepY = MAP.Height / 2 / (GridValue * MAP.Height / 2 / _minGridStep / 10);
+
+ //int stepX = _minGridStep + (10 - GridValue) * (MAP.Width / 2 - _minGridStep) / 10;
+ //int stepY = _minGridStep + (10 - GridValue) * (MAP.Height / 2 - _minGridStep) / 10;
+
+ int yPositive = baseY;
+ do
+ {
+ xPoint = new Point[] { new Point(0, yPositive), new Point(MAP.Width, yPositive) };
+ g.DrawLine(Pen_Grid, xPoint[0], xPoint[1]);
+ yPositive -= stepY;
+ } while (yPositive > 0);
+
+ int yNegative = baseY;
+ do
+ {
+ xPoint = new Point[] { new Point(0, yNegative), new Point(MAP.Width, yNegative) };
+ g.DrawLine(Pen_Grid, xPoint[0], xPoint[1]);
+ yNegative += stepY;
+ } while (yNegative < MAP.Height);
+
+ int xPositive = baseX;
+ do
+ {
+ yPoint = new Point[] { new Point(xPositive, 0), new Point(xPositive, MAP.Height) };
+ g.DrawLine(Pen_Grid, yPoint[0], yPoint[1]);
+ xPositive -= stepX;
+ } while (xPositive > 0);
+
+ int xNegative = baseX;
+ do
+ {
+ yPoint = new Point[] { new Point(xNegative, 0), new Point(xNegative, MAP.Height) };
+ g.DrawLine(Pen_Grid, yPoint[0], yPoint[1]);
+ xNegative += stepX;
+ } while (xNegative < MAP.Width);
+ }
+ }
+ }
+ #endregion
+
+ if (MouseState == MouseState.SelectionZoneDoing)
+ {
+ g.DrawRectangle(Pens.AliceBlue, _selectionRect.X, _selectionRect.Y, _selectionRect.Width, _selectionRect.Height);
+ g.FillRectangle(new SolidBrush(Color.FromArgb(40, 0, 0, 255)), _selectionRect);
+ }
+
+ myBuffer.Render(originG);
+ g.Dispose();
+ myBuffer.Dispose();//释放资源
+ }
+ catch (Exception)
+ {
+ }
+ }
+
+ private void halfTransparent()
+ {
+ }
+ #endregion
+
+ #region 绘制类型
+ private IShapeElement drawTemplate = null;
+ public IShapeElement DrawTemplate
+ {
+ get
+ {
+ return drawTemplate;
+ }
+ set
+ {
+ if (drawTemplate != value)
+ {
+
+ drawTemplate = value;
+
+ //DrawTemplateChanged?.BeginInvoke(value, null, null);
+ Task.Run(() => DrawTemplateChanged.Invoke(value));
+
+ if (value == null)
+ {
+ MouseState = MouseState.Normal;
+ return;
+ }
+
+ MouseState = MouseState.New;
+
+ var existed = Elements.FirstOrDefault(e => e.ID == value.ID);
+ if (existed != null)
+ {
+ Elements.Remove(existed);
+ }
+
+ //if (DrawTemplate != null)
+ //{
+ // DrawTemplate.OnDrawDone += OnElementDrawDone;
+ //}
+ }
+ }
+ }
+
+ string currentElementId = "";
+ string CurrentElementId
+ {
+ get
+ {
+ return currentElementId;
+ }
+ set
+ {
+ if (currentElementId != value)
+ {
+ currentElementId = value;
+ }
+ }
+ }
+
+ private void OnElementDrawDone(IShapeElement ele)
+ {
+ //int maxIndex = 1;
+ //if (Elements.Count > 0)
+ //{
+ // maxIndex = Elements.Max(u => u.Index) + 1;
+ //}
+ //ele.Index = maxIndex;
+ //ele.Name = maxIndex.ToString();
+
+ //#region 获取基元的设备属性,目前包括运动坐标和相机参数
+ //SetElementDevicePara?.Invoke(ele);
+ //#endregion
+
+ //Elements.Add(ele);
+ //DrawTemplate = DrawTemplate?.Clone() as IShapeElement;
+ }
+ #endregion
+
+ #region 状态变换
+ private void OnElementChangeMouseState(IShapeElement ele, ElementState preState, ElementState curState)
+ {
+ if (curState != ElementState.Normal)
+ {
+ switch (curState)
+ {
+ case ElementState.New:
+ MouseState = MouseState.New;
+ break;
+ case ElementState.Selected:
+ CurrentElementId = ele.ID;
+ Cursor = Cursors.Default;
+ break;
+ case ElementState.Moving:
+ MouseState = MouseState.MoveElement;
+ Cursor = Cursors.NoMove2D;
+ break;
+ case ElementState.Editing:
+ MouseState = MouseState.Editing;
+ Cursor = Cursors.Hand;
+ break;
+ case ElementState.MouseInSide:
+ MouseState = MouseState.InSideElement;
+ break;
+ case ElementState.MouseHover:
+ MouseState = MouseState.HoverElement;
+ break;
+ case ElementState.CanStretchLeft:
+ Cursor = Cursors.SizeWE;
+ break;
+ case ElementState.StretchingLeft:
+ MouseState = MouseState.StretchingLeft;
+ Cursor = Cursors.SizeWE;
+ break;
+ case ElementState.CanStretchBottom:
+ Cursor = Cursors.SizeNS;
+ break;
+ case ElementState.StretchingBottom:
+ MouseState = MouseState.StretchingBottom;
+ Cursor = Cursors.SizeNS;
+ break;
+ case ElementState.CanStretchRight:
+ Cursor = Cursors.SizeWE;
+ break;
+ case ElementState.StretchingRight:
+ MouseState = MouseState.StretchingRight;
+ Cursor = Cursors.SizeWE;
+ break;
+ case ElementState.CanStretchTop:
+ Cursor = Cursors.SizeNS;
+ break;
+ case ElementState.StretchingTop:
+ MouseState = MouseState.StretchingTop;
+ Cursor = Cursors.SizeNS;
+ break;
+
+ case ElementState.CanStretchLeftLowerCorner:
+ Cursor = Cursors.SizeNESW;
+ break;
+ case ElementState.StretchingLeftLowerCorner:
+ MouseState = MouseState.StretchingLeftLowerCorner;
+ Cursor = Cursors.SizeNESW;
+ break;
+ case ElementState.CanStretchLeftUpperCorner:
+ Cursor = Cursors.SizeNWSE;
+ break;
+ case ElementState.StretchingLeftUpperCorner:
+ MouseState = MouseState.StretchingLeftUpperCorner;
+ Cursor = Cursors.SizeNWSE;
+ break;
+ case ElementState.CanStretchRightLowerCorner:
+ Cursor = Cursors.SizeNWSE;
+ break;
+ case ElementState.StretchingRightLowerCorner:
+ MouseState = MouseState.StretchingRightLowerCorner;
+ Cursor = Cursors.SizeNWSE;
+ break;
+ case ElementState.CanStretchRightUpperCorner:
+ Cursor = Cursors.SizeNESW;
+ break;
+ case ElementState.StretchingRightUpperCorner:
+ MouseState = MouseState.StretchingRightUpperCorner;
+ Cursor = Cursors.SizeNESW;
+ break;
+ default:
+ //MouseState = MouseState.Normal;
+ break;
+ }
+ }
+ else
+ {
+ if (Elements.All(e => e.State == ElementState.Normal))
+ {
+ CurrentElementId = null;
+
+ if (preState == ElementState.Selected)
+ {
+ DrawTemplate = null;
+ }
+ else if (DrawTemplate != null)
+ {
+ MouseState = MouseState.New;
+ return;
+ }
+
+ //MouseState = MouseState.Normal;
+ }
+ }
+
+ this.Invalidate();
+ }
+ #endregion
+
+ #region 鼠标动作
+ private void Canvas_MouseWheel(object sender, MouseEventArgs e)
+ {
+ PointF prePoint = ToMapPoint(e.Location);
+
+ //先缩放
+ if (e.Delta > 0)
+ {
+ Matrix.Scale((float)1.1, (float)1.1);
+ }
+ else
+ {
+ Matrix.Scale((float)0.9, (float)0.9);
+ }
+
+ PointF afterPoint = ToMapPoint(e.Location);
+
+ //后平移
+ Matrix.Translate(afterPoint.X - prePoint.X, afterPoint.Y - prePoint.Y);
+
+ Invalidate();
+ }
+
+ PointF startPoint, currentPoint;
+ bool _isMouseBtnPressing = false;
+
+ private void Canvas_MouseDown(object sender, MouseEventArgs e)
+ {
+ PointF p = ToMapPoint(e.Location);
+
+ if (e.Button == MouseButtons.Left)
+ {
+ _isMouseBtnPressing = true;
+
+ switch (MouseState)
+ {
+ case MouseState.Normal:
+ startPoint = e.Location;
+ break;
+ case MouseState.StretchingLeft:
+ break;
+ case MouseState.StretchingRight:
+ break;
+ case MouseState.StretchingTop:
+ break;
+ case MouseState.StretchingBottom:
+ break;
+ case MouseState.MoveElement:
+ break;
+ case MouseState.HoverElement:
+ case MouseState.InSideElement:
+ case MouseState.New:
+ DrawTemplate?.OnMouseDown(p);
+ break;
+ case MouseState.Editing:
+ break;
+ case MouseState.SelectionZone:
+ MouseState = MouseState.SelectionZoneDoing;
+ startPoint = p;
+ break;
+ }
+
+ foreach (IShapeElement ele in Elements)
+ {
+ ele.OnMouseDown(p);
+ }
+ }
+ else if (e.Button == MouseButtons.Right)
+ {
+ if (DrawTemplate != null && DrawTemplate.State == ElementState.New && DrawTemplate.IsCreatedDone())
+ {
+ IShapeElement ele = DrawTemplate.Clone() as IShapeElement;
+ ele.State = ElementState.Normal;
+ Elements.Add(ele);
+
+ // (DrawTemplate as ElementBase).Initial();
+ }
+ }
+ }
+
+ private void Canvas_MouseUp(object sender, MouseEventArgs e)
+ {
+ if (e.Button != MouseButtons.Left)
+ return;
+
+ _isMouseBtnPressing = false;
+ switch (MouseState)
+ {
+ case MouseState.Normal:
+ break;
+ case MouseState.HoverElement:
+ break;
+ case MouseState.InSideElement:
+ break;
+ case MouseState.StretchingLeft:
+ break;
+ case MouseState.StretchingRight:
+ break;
+ case MouseState.StretchingTop:
+ break;
+ case MouseState.StretchingBottom:
+ break;
+ case MouseState.MoveElement:
+ //MouseState = MouseState.SelectedElement;
+ break;
+ case MouseState.New:
+ break;
+ case MouseState.Editing:
+ break;
+ case MouseState.MovingAll:
+ MouseState = MouseState.Normal;
+ break;
+ case MouseState.SelectionZone:
+ break;
+ case MouseState.SelectionZoneDoing:
+ MouseState = MouseState.SelectionZone;
+
+ foreach (IShapeElement ele in Elements)
+ {
+ ele.State = ElementState.Normal;
+ if (ele.IsIntersect(_selectionRect))
+ {
+ ele.State = ElementState.Selected;
+ }
+ }
+
+ break;
+ }
+
+ Cursor = Cursors.Default;
+
+ if (MouseState != MouseState.SelectionZone)
+ {
+ PointF p = ToMapPoint(e.Location);
+ DrawTemplate?.OnMouseUp(p);
+ foreach (IShapeElement ele in Elements)
+ {
+ ele.OnMouseUp(p);
+ }
+ }
+ }
+
+ private void Canvas_MouseMove(object sender, MouseEventArgs e)
+ {
+ PointF p = ToMapPoint(e.Location);
+
+ switch (MouseState)
+ {
+ case MouseState.Normal:
+ {
+ if (_isMouseBtnPressing)
+ {
+ currentPoint = e.Location;
+ PointF p1 = ToMapPoint(startPoint);
+ PointF p2 = ToMapPoint(currentPoint);
+ Matrix.Translate(p2.X - p1.X, p2.Y - p1.Y);
+ startPoint = e.Location;
+ }
+ }
+ break;
+ case MouseState.StretchingLeft:
+ break;
+ case MouseState.StretchingRight:
+ break;
+ case MouseState.StretchingTop:
+ break;
+ case MouseState.StretchingBottom:
+ break;
+ case MouseState.MoveElement:
+ break;
+ case MouseState.HoverElement:
+ case MouseState.InSideElement:
+ case MouseState.New:
+ DrawTemplate?.OnMouseMove(p);
+ break;
+ case MouseState.Editing:
+ break;
+ case MouseState.MovingAll:
+ break;
+ case MouseState.SelectionZoneDoing:
+ {
+ currentPoint = p;
+
+ float[] x2 = new float[2] { startPoint.X, currentPoint.X };
+ float[] y2 = new float[2] { startPoint.Y, currentPoint.Y };
+
+ float xMin = x2.Min();
+ float xMax = x2.Max();
+ float yMin = y2.Min();
+ float yMax = y2.Max();
+
+ _selectionRect = new RectangleF(xMin, yMin, xMax - xMin, yMax - yMin);
+ }
+ break;
+ }
+
+ PointF mapPoint = ToMapPoint(e.Location);
+ Color color = Color.Transparent;
+ if (MAP != null && mapPoint.X > 0 && mapPoint.X < MAP.Width && mapPoint.Y > 0 && mapPoint.Y < MAP.Height)
+ {
+ color = MAP.GetPixel((int)mapPoint.X, (int)mapPoint.Y);
+ }
+
+ // OnMouseLocationUpdated?.BeginInvoke(e.Location, mapPoint, color.Name, null, null);
+ Task.Run(() => OnMouseLocationUpdated?.Invoke(e.Location, mapPoint, color.Name));
+
+ if (MouseState != MouseState.SelectionZoneDoing)
+ {
+ Elements.ToList().ForEach(ele => ele?.OnMouseMove(p));
+ }
+
+ Invalidate();
+ }
+
+ private void Canvas_MouseDoubleClick(object sender, MouseEventArgs e)
+ {
+ PointF p = ToMapPoint(e.Location);
+
+ if (e.Button == MouseButtons.Left)
+ {
+ switch (MouseState)
+ {
+ //case MouseState.SelectedElement:
+ case MouseState.HoverElement:
+ case MouseState.InSideElement:
+ case MouseState.MoveElement:
+ case MouseState.Normal:
+ //Elements.ForEach(ele =>
+ foreach (IShapeElement ele in Elements)
+ {
+ ele.OnMouseDoubleClick(p);
+ }
+ //);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ //if (MouseState == MouseState.SelectedElement)
+ {
+ MouseState = MouseState.Normal;
+
+ //Elements.ForEach(ele =>
+ foreach (IShapeElement ele in Elements)
+ {
+ ele.State = ElementState.Normal;
+ }
+ //);
+ }
+ }
+ }
+ #endregion
+
+ #region 图片操作
+ bool _firstLoad = true;
+ object _mapLoadLock = new object();
+ ManualResetEvent _mapLoadHandler = new ManualResetEvent(true);
+ ManualResetEvent _mapUsingHandler = new ManualResetEvent(false);
+
+ ///
+ /// 载入图片
+ ///
+ ///
+ public void LoadImage(Bitmap bitmap)
+ {
+ if (bitmap == null)
+ return;
+
+ ////lock (_mapLoadLock)
+ ////_mapUsingHandler.WaitOne();
+ //_mapLoadHandler.Reset();
+ //{
+ // map?.Dispose();
+ // map = null;
+ // map = bitmap;
+ //}
+ //_mapLoadHandler.Set();
+
+ MAP = bitmap;
+
+ if (_firstLoad)
+ {
+ SetScreenSize();
+ _firstLoad = false;
+ }
+ Invalidate();
+ }
+
+ public void Clear()
+ {
+ MAP = null;
+ Elements.Clear();
+
+ Invalidate();
+ }
+
+ ///
+ /// 设置图片为原始尺寸
+ ///
+ public void SetMapSize()
+ {
+ Matrix = new Matrix();
+ Invalidate();
+ }
+
+ ///
+ /// 设置图片为适配尺寸
+ ///
+ public void SetScreenSize()
+ {
+ try
+ {
+ if (MAP == null)
+ return;
+
+ Matrix = new Matrix();
+
+ //先缩放
+ List ratios = new List() { MAP.Width / (float)Width, MAP.Height / (float)Height };
+ float ratio = 1 / ratios.Max();
+ Matrix.Scale(ratio, ratio);
+
+ //再平移
+ //将plMain的中心转换为图片坐标
+ PointF screenCenter = new PointF(Width / 2.0f, Height / 2.0f);
+ PointF mapPoint = ToMapPoint(screenCenter);
+
+ //目标坐标减去当前坐标
+ Matrix.Translate(-MAP.Width / 2.0f + mapPoint.X, -MAP.Height / 2.0f + mapPoint.Y);
+
+ Invalidate();
+ }
+ catch (Exception ex)
+ {
+ //Trace.TraceError(ex.GetExceptionMessage());
+ }
+ }
+ #endregion
+
+ #region 私有方法
+ //private void DisplayMouseLocation(Point location)
+ //{
+ // string screenPoint = string.Format("屏幕坐标X:{0};Y:{1}", location.X, location.Y);
+
+ // Point mapPoint = ToMapPoint(location);
+ // string mapPointStr = string.Format("图片坐标X:{0};Y:{1}", mapPoint.X, mapPoint.Y);
+
+ // tsslLocation.Text = screenPoint + " " + mapPointStr;
+ //}
+
+ private PointF ToMapPoint(PointF p)
+ {
+ PointF[] ps = new PointF[] { p };
+ Matrix invertMatrix = Matrix.Clone();
+ invertMatrix.Invert();
+ invertMatrix.TransformPoints(ps);
+
+ return ps[0];
+ }
+
+ private Point ToScreenPoint(Point p)
+ {
+ Point[] ps = new Point[] { p };
+ Matrix.TransformPoints(ps);
+
+ return ps[0];
+ }
+
+ #endregion
+
+ #region 按键操作
+ public void OnCanvasKeyPressed(object sender, KeyPressEventArgs e)
+ {
+ //if (e.KeyChar == 27) //Esc
+ //{
+ // //if (MouseState == MouseState.SelectedElement)
+ // {
+ // MouseState = MouseState.Normal;
+
+ // //Elements.ForEach(ele =>
+ // foreach (IShapeElement ele in Elements)
+ // {
+ // ele.State = ElementState.Normal;
+ // }
+ // //);
+ // }
+ //}
+
+ //Invalidate();
+ }
+
+ public void OnCanvasKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Delete) //delete键
+ {
+ Elements.Remove(Elements.FirstOrDefault(u => u.ID == CurrentElementId));
+ }
+
+ if (e.KeyData == Keys.Escape) //Esc
+ {
+ if (DrawTemplate != null /*&& (DrawTemplate as ElementBase).CreatePoints.Count > 0*/)
+ {
+ DrawTemplate.Initial();
+ }
+ else
+ {
+ DrawTemplate = null;
+
+ if (MouseState != MouseState.Normal)
+ {
+ MouseState = MouseState.Normal;
+ }
+ else
+ {
+ Elements.ToList().ForEach(u => u.State = ElementState.Normal);
+ }
+ }
+ }
+
+ //if (e.KeyData == Keys.Up)
+ //{
+ // Elements.ToList().ForEach(u =>
+ // {
+ // if (u.State == ElementState.Selected)
+ // {
+ // u.Translate(0, -1);
+ // }
+ // });
+ //}
+
+ //if (e.KeyData == Keys.Down)
+ //{
+ // Elements.ToList().ForEach(u =>
+ // {
+ // if (u.State == ElementState.Selected)
+ // {
+ // u.Translate(0, 1);
+ // }
+ // });
+ //}
+
+ //if (e.KeyData == Keys.Left)
+ //{
+ // Elements.ToList().ForEach(u =>
+ // {
+ // if (u.State == ElementState.Selected)
+ // {
+ // u.Translate(-1, 0);
+ // }
+ // });
+ //}
+
+ //if (e.KeyData == Keys.Right)
+ //{
+ // Elements.ToList().ForEach(u =>
+ // {
+ // if (u.State == ElementState.Selected)
+ // {
+ // u.Translate(1, 0);
+ // }
+ // });
+ //}
+
+ Invalidate();
+ }
+ #endregion
+
+ #region 基元的设备属性 运动设置和相机设置
+ public Action SetElementDevicePara;
+
+ public Action SetDeviceByElement;
+ #endregion
+
+ #region Grid
+ private bool showGrid = false;
+ public bool ShowGrid
+ {
+ get => showGrid;
+ set
+ {
+ showGrid = value;
+ Invalidate();
+ }
+ }
+
+ private int gridValue = 0;
+ public int GridValue
+ {
+ get => gridValue;
+ set
+ {
+ gridValue = value;
+ Invalidate();
+ }
+ }
+
+ private Pen penGrid = new Pen(Color.FromArgb(120, Color.Red), 1.0f);
+ public Pen Pen_Grid
+ {
+ get => penGrid;
+ set
+ {
+ penGrid = value;
+ Invalidate();
+ }
+ }
+
+ readonly int _minGridStep = 10;
+ #endregion
+
+ #region Dispose
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ MAP?.Dispose();
+ Matrix?.Dispose();
+ penGrid?.Dispose();
+
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+ #endregion
+ }
+}
diff --git a/DH.UI.Model.Winform/CanvasImage.resx b/DH.UI.Model.Winform/CanvasImage.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/DH.UI.Model.Winform/CanvasImage.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/DH.UI.Model.Winform/Ctrl/GridCtrl.Designer.cs b/DH.UI.Model.Winform/Ctrl/GridCtrl.Designer.cs
new file mode 100644
index 0000000..1b26268
--- /dev/null
+++ b/DH.UI.Model.Winform/Ctrl/GridCtrl.Designer.cs
@@ -0,0 +1,109 @@
+namespace DH.UI.Model.Winform
+{
+ partial class GridCtrl
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.chkShowGrid = new System.Windows.Forms.CheckBox();
+ this.tbGridValue = new System.Windows.Forms.TrackBar();
+ this.panel1 = new System.Windows.Forms.Panel();
+ this.colorDialog1 = new System.Windows.Forms.ColorDialog();
+ this.btnColor = new System.Windows.Forms.Button();
+ ((System.ComponentModel.ISupportInitialize)(this.tbGridValue)).BeginInit();
+ this.panel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // chkShowGrid
+ //
+ this.chkShowGrid.Appearance = System.Windows.Forms.Appearance.Button;
+ //this.chkShowGrid.BackgroundImage = global::XKRS.UI.Model.Winform.Properties.Resources.grid;
+ this.chkShowGrid.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
+ this.chkShowGrid.Dock = System.Windows.Forms.DockStyle.Top;
+ this.chkShowGrid.Location = new System.Drawing.Point(0, 0);
+ this.chkShowGrid.Name = "chkShowGrid";
+ this.chkShowGrid.Size = new System.Drawing.Size(32, 30);
+ this.chkShowGrid.TabIndex = 0;
+ this.chkShowGrid.UseVisualStyleBackColor = true;
+ this.chkShowGrid.CheckedChanged += new System.EventHandler(this.chkShowGrid_CheckedChanged);
+ //
+ // tbGridValue
+ //
+ this.tbGridValue.AutoSize = false;
+ this.tbGridValue.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.tbGridValue.Location = new System.Drawing.Point(0, 21);
+ this.tbGridValue.Name = "tbGridValue";
+ this.tbGridValue.Orientation = System.Windows.Forms.Orientation.Vertical;
+ this.tbGridValue.Size = new System.Drawing.Size(32, 121);
+ this.tbGridValue.TabIndex = 1;
+ this.tbGridValue.TickStyle = System.Windows.Forms.TickStyle.Both;
+ this.tbGridValue.ValueChanged += new System.EventHandler(this.tbGridValue_ValueChanged);
+ //
+ // panel1
+ //
+ this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.panel1.Controls.Add(this.chkShowGrid);
+ this.panel1.Controls.Add(this.tbGridValue);
+ this.panel1.Location = new System.Drawing.Point(1, 1);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(32, 142);
+ this.panel1.TabIndex = 2;
+ //
+ // btnColor
+ //
+ this.btnColor.BackColor = System.Drawing.Color.Red;
+ this.btnColor.Location = new System.Drawing.Point(4, 150);
+ this.btnColor.Name = "btnColor";
+ this.btnColor.Size = new System.Drawing.Size(25, 23);
+ this.btnColor.TabIndex = 3;
+ this.btnColor.Text = " ";
+ this.btnColor.UseVisualStyleBackColor = false;
+ this.btnColor.Click += new System.EventHandler(this.btnColor_Click);
+ //
+ // GridCtrl
+ //
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+ this.Controls.Add(this.btnColor);
+ this.Controls.Add(this.panel1);
+ this.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, ((byte)(134)));
+ this.Name = "GridCtrl";
+ this.Size = new System.Drawing.Size(32, 192);
+ ((System.ComponentModel.ISupportInitialize)(this.tbGridValue)).EndInit();
+ this.panel1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.CheckBox chkShowGrid;
+ private System.Windows.Forms.TrackBar tbGridValue;
+ private System.Windows.Forms.Panel panel1;
+ private System.Windows.Forms.ColorDialog colorDialog1;
+ private System.Windows.Forms.Button btnColor;
+ }
+}
diff --git a/DH.UI.Model.Winform/Ctrl/GridCtrl.cs b/DH.UI.Model.Winform/Ctrl/GridCtrl.cs
new file mode 100644
index 0000000..0eec2c4
--- /dev/null
+++ b/DH.UI.Model.Winform/Ctrl/GridCtrl.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace DH.UI.Model.Winform
+{
+ public partial class GridCtrl : UserControl
+ {
+ public Action IsShowGridChanged { get; set; }
+
+ public Action GridValueChanged { get; set; }
+
+ public Action GridColorChanged { get; set; }
+
+ public GridCtrl()
+ {
+ InitializeComponent();
+
+ IsChecked = chkShowGrid.Checked;
+ GridValue = tbGridValue.Value;
+ }
+
+ bool isChecked = false;
+ bool IsChecked
+ {
+ get => isChecked;
+ set
+ {
+ if (isChecked != value)
+ {
+ // IsShowGridChanged?.BeginInvoke(value, null, null);
+ Task.Run(() => IsShowGridChanged.Invoke(value));
+ }
+
+ isChecked = value;
+ }
+ }
+
+ int gridValue = 0;
+ int GridValue
+ {
+ get => gridValue;
+ set
+ {
+ if (gridValue != value)
+ {
+ // GridValueChanged?.BeginInvoke(value, null, null);
+ Task.Run(() => GridValueChanged.Invoke(value));
+ }
+
+ gridValue = value;
+ }
+ }
+ private void chkShowGrid_CheckedChanged(object sender, EventArgs e)
+ {
+ IsChecked = chkShowGrid.Checked;
+ }
+
+ private void tbGridValue_ValueChanged(object sender, EventArgs e)
+ {
+ GridValue = tbGridValue.Value;
+ }
+
+ private void btnColor_Click(object sender, EventArgs e)
+ {
+ if (colorDialog1.ShowDialog() == DialogResult.OK)
+ {
+ btnColor.BackColor = colorDialog1.Color;
+ // GridColorChanged?.BeginInvoke(btnColor.BackColor, null, null);
+ Task.Run(() => GridColorChanged.Invoke(btnColor.BackColor));
+ }
+ }
+ }
+}
diff --git a/DH.UI.Model.Winform/Ctrl/GridCtrl.resx b/DH.UI.Model.Winform/Ctrl/GridCtrl.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/DH.UI.Model.Winform/Ctrl/GridCtrl.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/DH.UI.Model.Winform/Ctrl/GridCtrlHost.cs b/DH.UI.Model.Winform/Ctrl/GridCtrlHost.cs
new file mode 100644
index 0000000..c999dff
--- /dev/null
+++ b/DH.UI.Model.Winform/Ctrl/GridCtrlHost.cs
@@ -0,0 +1,12 @@
+using System.Windows.Forms;
+
+namespace DH.UI.Model.Winform
+{
+ public class GridCtrlHost : ToolStripControlHost
+ {
+ public GridCtrlHost(GridCtrl grid) : base(grid)
+ {
+ //Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, 134);
+ }
+ }
+}
diff --git a/DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.Designer.cs b/DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.Designer.cs
new file mode 100644
index 0000000..f082d76
--- /dev/null
+++ b/DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.Designer.cs
@@ -0,0 +1,78 @@
+namespace DH.UI.Model.Winform
+{
+ partial class IOIndicatorCtrl
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ plStatus = new Panel();
+ lblDesc = new Label();
+ SuspendLayout();
+ //
+ // plStatus
+ //
+ plStatus.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left;
+ plStatus.Location = new Point(0, 0);
+ plStatus.Margin = new Padding(4);
+ plStatus.Name = "plStatus";
+ plStatus.Size = new Size(28, 34);
+ plStatus.TabIndex = 0;
+ plStatus.Paint += plStatus_Paint;
+ plStatus.DoubleClick += plStatus_DoubleClick;
+ //
+ // lblDesc
+ //
+ lblDesc.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
+ lblDesc.AutoSize = true;
+ lblDesc.Font = new Font("Tahoma", 11F, FontStyle.Regular, GraphicsUnit.World);
+ lblDesc.Location = new Point(36, 11);
+ lblDesc.Margin = new Padding(4, 0, 4, 0);
+ lblDesc.Name = "lblDesc";
+ lblDesc.Size = new Size(31, 13);
+ lblDesc.TabIndex = 1;
+ lblDesc.Text = "XXXX";
+ lblDesc.TextAlign = ContentAlignment.MiddleLeft;
+ lblDesc.DoubleClick += lblDesc_DoubleClick;
+ //
+ // IOIndicatorCtrl
+ //
+ AutoScaleDimensions = new SizeF(7F, 17F);
+ AutoScaleMode = AutoScaleMode.Font;
+ Controls.Add(lblDesc);
+ Controls.Add(plStatus);
+ Margin = new Padding(4);
+ Name = "IOIndicatorCtrl";
+ Size = new Size(138, 34);
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Panel plStatus;
+ private Label lblDesc;
+ }
+}
diff --git a/DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.cs b/DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.cs
new file mode 100644
index 0000000..7821132
--- /dev/null
+++ b/DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace DH.UI.Model.Winform
+{
+ public partial class IOIndicatorCtrl : UserControl
+ {
+ public IOIndicatorCtrl()
+ {
+ InitializeComponent();
+ }
+
+ private bool isON = false;
+
+ public bool IsOn
+ {
+ get => isON;
+ set
+ {
+ bool? temp = isON;
+ isON = value;
+
+ if (temp != isON)
+ {
+ RefreshStatus();
+ }
+ }
+ }
+
+ private void RefreshStatus()
+ {
+ if (InvokeRequired)
+ {
+ Invoke(new Action(() => RefreshStatus()));
+ }
+ else
+ {
+ plStatus.Invalidate();
+ }
+ }
+
+ private string desc = "";
+ public string Desc
+ {
+ get => desc;
+ set
+ {
+ desc = value;
+
+ DisplayDesc();
+ }
+ }
+
+ public int Index { get; set; }
+
+ private void DisplayDesc()
+ {
+ if (InvokeRequired)
+ {
+ Invoke(new Action(() => DisplayDesc()));
+ }
+ else
+ {
+ lblDesc.Text = Desc;
+ }
+ }
+
+ readonly PointF[] regionBlink = new PointF[]
+ {
+ new PointF(5,10),
+ new PointF(10,13),
+ new PointF(12,7),
+ new PointF(10,5)
+ };
+
+ public IOIndicatorCtrl(bool _isOn, string _desc, int index = 0)
+ {
+ InitializeComponent();
+
+ IsOn = _isOn;
+ Desc = _desc;
+ Index = index;
+ }
+
+ ///
+ /// 更新绘制图标
+ ///
+ ///
+ ///
+ private void plStatus_Paint(object sender, PaintEventArgs e)
+ {
+ Panel pl = sender as Panel;
+
+ Graphics g = e.Graphics;
+
+ g.Clear(SystemColors.Control);
+
+
+ if (IsOn)
+ {
+ g.FillEllipse(Brushes.LightGreen, pl.ClientRectangle);
+ }
+ else
+ {
+ g.FillEllipse(Brushes.Gray, pl.ClientRectangle);
+ }
+
+ g.FillPolygon(Brushes.White, regionBlink);
+
+ }
+
+ public event Action OnIODoubleClick;
+
+
+ private void lblDesc_DoubleClick(object sender, EventArgs e)
+ {
+ OnIODoubleClick?.Invoke(Name, IsOn, Index);
+ }
+
+ private void plStatus_DoubleClick(object sender, EventArgs e)
+ {
+ OnIODoubleClick?.Invoke(Name, IsOn, Index);
+ }
+ }
+}
diff --git a/DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.resx b/DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.resx
new file mode 100644
index 0000000..a395bff
--- /dev/null
+++ b/DH.UI.Model.Winform/Ctrl/IOIndicatorCtrl.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/DH.UI.Model.Winform/DH.UI.Model.Winform.csproj b/DH.UI.Model.Winform/DH.UI.Model.Winform.csproj
new file mode 100644
index 0000000..f2d0ff7
--- /dev/null
+++ b/DH.UI.Model.Winform/DH.UI.Model.Winform.csproj
@@ -0,0 +1,48 @@
+
+
+
+ net8.0-windows
+ enable
+ enable
+ ..\
+ output
+ true
+ AnyCPU;x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+
+
+
+ Settings.Designer.cs
+ SettingsSingleFileGenerator
+
+
+
+
\ No newline at end of file
diff --git a/DH.UI.Model.Winform/Element/CommonHelper.cs b/DH.UI.Model.Winform/Element/CommonHelper.cs
new file mode 100644
index 0000000..7f50ccd
--- /dev/null
+++ b/DH.UI.Model.Winform/Element/CommonHelper.cs
@@ -0,0 +1,199 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using static DH.Commons.Enums.EnumHelper;
+
+
+namespace DH.UI.Model.Winform
+{
+ //public static class AOIEnumHelper
+ //{
+ // public enum ElementState
+ // {
+ // New = 1,
+ // MouseHover = 2,
+ // MouseInSide = 3,
+ // Selected = 4,
+ // Moving = 5,
+
+ // Normal = 11,
+
+ // Measuring = 21,
+ // MeasureDoneOK = 22,
+ // MeasureDoneNG = 23,
+ // }
+
+ // public enum MouseState
+ // {
+ // Normal = 1,
+ // HoverElement = 2,
+ // InSideElement = 3,
+
+ // StretchingLeft = 11,
+ // StretchingRight = 12,
+ // StretchingUp = 13,
+ // StretchingDown = 14,
+ // MoveElement = 15,
+
+ // New = 21,
+ // Editing = 22,
+ // SelectedElement = 23,
+
+ // MovingAll = 31,
+
+ // SelectionZone = 41,
+ // SelectionZoneDoing = 42,
+ // }
+
+ // public enum RunMode
+ // {
+ // [Description("设置模式")]
+ // SetMode = 0,
+ // [Description("运行模式")]
+ // RunMode = 1,
+ // }
+ //}
+
+ public static class EventRouter
+ {
+ ///
+ /// ElementBase 基元
+ /// 1st MouseState 初始状态
+ /// 2nd MouseState 变化状态
+ ///
+ public static event Action ChangeElementsMouseState;
+
+ public static void TriggerElementsMouseStateChanged(ElementBase ele, ElementState preState, ElementState curState)
+ {
+ ChangeElementsMouseState?.Invoke(ele, preState, curState);
+ }
+ }
+
+ public class NoticedPoints : List
+ {
+ public Action OnItemChanged;
+
+ public NoticedPoints() { }
+
+ public NoticedPoints(List points)
+ {
+ AddRange(points);
+ }
+
+ public new PointF this[int index]
+ {
+ get
+ {
+ if (index >= 0 && index < Count)
+ {
+ return base[index];
+ }
+ else
+ {
+ return new Point();
+ }
+
+ }
+ set
+ {
+ if (base[index] != value)
+ {
+ base[index] = value;
+ OnItemChanged?.Invoke();
+ }
+ }
+ }
+
+ public new void Add(PointF item)
+ {
+ lock (this)
+ {
+ base.Add(item);
+ OnItemChanged?.Invoke();
+ }
+ }
+
+ public new void AddRange(IEnumerable collection)
+ {
+ lock (this)
+ {
+ base.AddRange(collection);
+ OnItemChanged?.Invoke();
+ }
+ }
+
+ public new void Clear()
+ {
+ lock (this)
+ {
+ base.Clear();
+ OnItemChanged?.Invoke();
+ }
+ }
+
+ public new void Insert(int index, PointF item)
+ {
+ lock (this)
+ {
+ base.Insert(index, item);
+ OnItemChanged?.Invoke();
+ }
+ }
+
+ public new void InsertRange(int index, IEnumerable collection)
+ {
+ lock (this)
+ {
+ base.InsertRange(index, collection);
+ OnItemChanged?.Invoke();
+ }
+ }
+
+ public new bool Remove(PointF item)
+ {
+ lock (this)
+ {
+ bool flag = base.Remove(item);
+
+ if (flag)
+ {
+ OnItemChanged?.Invoke();
+ }
+
+ return flag;
+ }
+ }
+
+ public new int RemoveAll(Predicate match)
+ {
+ lock (this)
+ {
+ int i = base.RemoveAll(match);
+ if (i > 0)
+ {
+ OnItemChanged?.Invoke();
+ }
+
+ return i;
+ }
+ }
+
+ public new void RemoveAt(int index)
+ {
+ lock (this)
+ {
+ base.RemoveAt(index);
+ OnItemChanged?.Invoke();
+ }
+ }
+
+ public new void RemoveRange(int index, int count)
+ {
+ lock (this)
+ {
+ base.RemoveRange(index, count);
+ OnItemChanged?.Invoke();
+ }
+ }
+ }
+}
diff --git a/DH.UI.Model.Winform/Element/ElementBase.cs b/DH.UI.Model.Winform/Element/ElementBase.cs
new file mode 100644
index 0000000..0b529b4
--- /dev/null
+++ b/DH.UI.Model.Winform/Element/ElementBase.cs
@@ -0,0 +1,980 @@
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+using System.Text.Json.Serialization;
+using DH.Commons.Enums;
+using static DH.Commons.Enums.EnumHelper;
+
+
+namespace DH.UI.Model.Winform
+{
+ [Serializable]
+ public abstract class ElementBase : IShapeElement, IEventHandle, ICloneable, IComparable, IDisposable
+ {
+ #region 常量
+ protected int _mouseIntersectDistance = 4;
+ #endregion
+
+ #region 标识符
+ ///
+ /// ID,采用GUID
+ ///
+ [ReadOnly(true)]
+ [Category("\t通用标识")]
+ [Description("GUID")]
+ public virtual string ID { get; set; } = Guid.NewGuid().ToString().ToUpper();
+
+ ///
+ /// 序号
+ ///
+ [Category("\t通用标识")]
+ [Description("序号")]
+ public virtual int Index { get; set; } = 0;
+
+ [Browsable(false)]
+ public virtual int GroupIndex { get; set; } = 0;
+
+ private string name = "";
+ ///
+ /// 名称
+ ///
+ [Category("\t通用标识")]
+ [Description("名称")]
+ public virtual string Name
+ {
+ get
+ {
+ if (string.IsNullOrWhiteSpace(name))
+ {
+ return GetDisplayText();
+ }
+ else
+ {
+ return name;
+ }
+ }
+ set => name = value;
+ }
+ #endregion
+
+ #region 启用状态
+ private bool isEnabled = true;
+
+ //[Browsable(false)]
+ public virtual bool IsEnabled
+ {
+ get
+ {
+ return isEnabled;
+ }
+ set
+ {
+ //if (isEnabled != value)
+ //{
+ // isEnabled = value;
+
+ // PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs("IsEnabled"), null, null);
+ //}
+
+ Set(ref isEnabled, value);
+ }
+ }
+
+ [Browsable(false)]
+ public virtual bool IsShowing { get; set; } = true;
+
+ private bool showList = true;
+ [Browsable(false)]
+ public virtual bool ShowList
+ {
+ get => showList;
+ set => Set(ref showList, value);
+ }
+ #endregion
+
+ #region 字段
+ [JsonIgnore]
+ protected PointF _startPoint, _currentPoint;
+ #endregion
+
+ #region 绘图特性
+ [Browsable(false)]
+ public NoticedPoints CreatePoints { get; set; } = new NoticedPoints();
+
+ public virtual bool IsCreatedDone()
+ {
+ return CreatePoints.Count >= 2;
+ }
+
+ //protected Region Region { get; set; }
+
+ #region 画笔相关
+ #region 绘图画笔
+ [JsonIgnore]
+ [Browsable(false)]
+ protected Pen Pen { get; set; } = new Pen(Color.Red, 1);
+
+ protected virtual void SetNewStatePen()
+ {
+ Pen = new Pen(Color.Red, 3);
+ }
+
+ protected virtual void SetNormalPen()
+ {
+ Pen = new Pen(Color.Red, 1);
+ }
+
+ protected virtual void SetHoverPen()
+ {
+ Pen = new Pen(Color.BlueViolet, 3);
+ }
+
+ protected virtual void SetInSidePen()
+ {
+ Pen = new Pen(Color.YellowGreen, 3);
+ }
+
+ protected virtual void SetSelectedPen()
+ {
+ Pen = new Pen(Color.Pink, 3);
+ }
+
+ protected virtual void SetMeasureDoneOKPen()
+ {
+ Pen = new Pen(Color.Green, 2);
+ }
+
+ protected virtual void SetMeasureDoneNGPen()
+ {
+ Pen = new Pen(Color.Red, 2);
+ }
+
+ protected virtual void SetMeasuringPen()
+ {
+ Pen = new Pen(Color.Yellow, 3);
+ }
+ #endregion
+
+ #region 文字画笔
+ //[JsonIgnore]
+ //protected Pen PenText = new Pen(Color.Black, 1);
+ //[JsonIgnore]
+ //protected Pen PenTextOK = new Pen(Color.Green, 1.5f);
+ //[JsonIgnore]
+ //protected Pen PenTextNG = new Pen(Color.Red, 2);
+
+ /////
+ ///// 字体大小
+ /////
+ //[Category("显示属性")]
+ //[Description("字体大小")]
+ ////[Browsable(false)]
+ //public virtual float FontSize { get; set; } = 15;
+ ///
+ /// 字体大小
+ ///
+ [Category("显示属性")]
+ [Description("字体设置")]
+ [Browsable(false)]
+ public virtual Font Font { get; set; } = new Font(new FontFamily("Tahoma"), 15, GraphicsUnit.World);
+
+ ///
+ /// 字体和基元的距离
+ ///
+ [Category("显示属性")]
+ [Description("字体和基元的距离")]
+ [Browsable(false)]
+ public virtual int FontDistance { get; set; } = 15;
+
+ [Category("显示属性")]
+ [Description("显示字符说明")]
+ [Browsable(false)]
+ public virtual bool IsShowRemark { get; set; } = true;
+
+ #endregion
+ #endregion
+
+ //public Graphics Graphics { get; set; }
+ public abstract void Draw(Graphics g);
+ protected abstract void DrawResult(Graphics g);
+ #endregion
+
+ #region 状态
+ private ElementState state = ElementState.New;
+ [JsonIgnore]
+ [Browsable(false)]
+ public ElementState State
+ {
+ get
+ {
+ return state;
+ }
+ set
+ {
+ if (state != value)
+ {
+ ElementState preState = state;
+ Set(ref state, value);
+ EventRouter.TriggerElementsMouseStateChanged(this, preState, state);
+ switch (state)
+ {
+ case ElementState.MouseHover:
+ SetHoverPen();
+ break;
+ case ElementState.MouseInSide:
+ SetInSidePen();
+ break;
+ case ElementState.Selected:
+ SetSelectedPen();
+ break;
+ case ElementState.Normal:
+ SetNormalPen();
+ break;
+ case ElementState.Measuring:
+ SetMeasuringPen();
+ break;
+ case ElementState.MeasureDoneOK:
+ SetMeasureDoneOKPen();
+ break;
+ case ElementState.MeasureDoneNG:
+ SetMeasureDoneNGPen();
+ break;
+ case ElementState.New:
+ SetNewStatePen();
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// 是否是运行模式
+ ///
+ [Browsable(false)]
+ public RunMode RunMode { get; set; } = RunMode.NormalMode;
+ #endregion
+
+ #region 复制
+ public abstract object Clone();
+
+ public virtual void Initial()
+ {
+ State = ElementState.New;
+ CreatePoints = new NoticedPoints();
+ }
+ #endregion
+
+ #region IMouseEvent
+ public virtual void OnMouseDoubleClick(PointF p)
+ {
+ if (State == ElementState.MeasureDoneNG || State == ElementState.MeasureDoneOK)
+ return;
+
+ //if (State == ElementState.MouseInSide)
+ //{
+ // State = ElementState.Selected;
+ //}
+ //else if (State == ElementState.Selected || State == ElementState.Moving)
+ //{
+ // if (IsMouseInSide(p))
+ // {
+ // State = ElementState.MouseInSide;
+ // }
+ //}
+ if (IsMouseInSide(p))
+ {
+ State = ElementState.Selected;
+ }
+ }
+
+ public abstract void OnKeyDown(object sender, KeyEventArgs e);
+
+ public abstract void OnKeyUp(object sender, KeyEventArgs e);
+
+ public virtual void OnMouseDown(PointF p)
+ {
+ //switch (State)
+ //{
+ // case ElementState.New:
+ // OnMouseDownWhenNew(p);
+ // break;
+ // case ElementState.MouseHover:
+ // break;
+ // case ElementState.MouseInSide:
+ // State = ElementState.Selected;
+ // break;
+ // case ElementState.Selected:
+ // _startPoint = p;
+ // State = ElementState.Moving;
+ // break;
+ // case ElementState.Normal:
+ // break;
+ //}
+ if (State == ElementState.New)
+ {
+ OnMouseDownWhenNew(p);
+ }
+ else if (IsMouseCanMoveElement(p) && State == ElementState.Selected)
+ {
+ State = ElementState.Moving;
+ }
+ else if (IsMouseCanStretchBottom(p) && State == ElementState.CanStretchBottom)
+ {
+ State = ElementState.StretchingBottom;
+ }
+ else if (IsMouseCanStretchTop(p) && State == ElementState.CanStretchTop)
+ {
+ State = ElementState.StretchingTop;
+ }
+ else if (IsMouseCanStretchLeft(p) && State == ElementState.CanStretchLeft)
+ {
+ State = ElementState.StretchingLeft;
+ }
+ else if (IsMouseCanStretchRight(p) && State == ElementState.CanStretchRight)
+ {
+ State = ElementState.StretchingRight;
+ }
+ else if (IsMouseCanStretchLeftLowerCorner(p) && State == ElementState.CanStretchLeftLowerCorner)
+ {
+ State = ElementState.StretchingLeftLowerCorner;
+ }
+ else if (IsMouseCanStretchLeftUpperCorner(p) && State == ElementState.CanStretchLeftUpperCorner)
+ {
+ State = ElementState.StretchingLeftUpperCorner;
+ }
+ else if (IsMouseCanStretchRightLowerCorner(p) && State == ElementState.CanStretchRightLowerCorner)
+ {
+ State = ElementState.StretchingRightLowerCorner;
+ }
+ else if (IsMouseCanStretchRightUpperCorner(p) && State == ElementState.CanStretchRightUpperCorner)
+ {
+ State = ElementState.StretchingRightUpperCorner;
+ }
+ }
+
+ public virtual void OnMouseMove(PointF p)
+ {
+ switch (State)
+ {
+ case ElementState.New:
+ OnMouseMoveWhenNew(p);
+ break;
+ case ElementState.Selected:
+ {
+ if (IsMouseCanStretchLeft(p))
+ {
+ State = ElementState.CanStretchLeft;
+ }
+ else if (IsMouseCanStretchRight(p))
+ {
+ State = ElementState.CanStretchRight;
+ }
+ else if (IsMouseCanStretchTop(p))
+ {
+ State = ElementState.CanStretchTop;
+ }
+ else if (IsMouseCanStretchBottom(p))
+ {
+ State = ElementState.CanStretchBottom;
+ }
+ else if (IsMouseCanStretchLeftLowerCorner(p))
+ {
+ State = ElementState.CanStretchLeftLowerCorner;
+ }
+ else if (IsMouseCanStretchLeftUpperCorner(p))
+ {
+ State = ElementState.CanStretchLeftUpperCorner;
+ }
+ else if (IsMouseCanStretchRightLowerCorner(p))
+ {
+ State = ElementState.CanStretchRightLowerCorner;
+ }
+ else if (IsMouseCanStretchRightUpperCorner(p))
+ {
+ State = ElementState.CanStretchRightUpperCorner;
+ }
+
+ break;
+ }
+ case ElementState.Moving:
+ _currentPoint = p;
+ //Translate(_currentPoint.X - _startPoint.X, _currentPoint.Y - _startPoint.Y);
+ //_startPoint = _currentPoint;
+ Relocate(p);
+ break;
+ case ElementState.MouseHover:
+ case ElementState.MouseInSide:
+ case ElementState.Normal:
+ //if (IsMouseInSide(p))
+ //{
+ // State = ElementState.MouseInSide;
+ //}
+ //else if (IsMouseHover(p))
+ //{
+ // State = ElementState.MouseHover;
+ //}
+ //else
+ //{
+ // State = ElementState.Normal;
+ //}
+ break;
+ case ElementState.CanStretchBottom:
+ if (!IsMouseCanStretchBottom(p))
+ {
+ State = ElementState.Selected;
+ }
+ break;
+ case ElementState.CanStretchTop:
+ if (!IsMouseCanStretchTop(p))
+ {
+ State = ElementState.Selected;
+ }
+ break;
+ case ElementState.CanStretchLeft:
+ if (!IsMouseCanStretchLeft(p))
+ {
+ State = ElementState.Selected;
+ }
+ break;
+ case ElementState.CanStretchRight:
+ if (!IsMouseCanStretchRight(p))
+ {
+ State = ElementState.Selected;
+ }
+ break;
+ case ElementState.CanStretchLeftUpperCorner:
+ if (!IsMouseCanStretchLeftUpperCorner(p))
+ {
+ State = ElementState.Selected;
+ }
+ break;
+ case ElementState.CanStretchLeftLowerCorner:
+ if (!IsMouseCanStretchLeftLowerCorner(p))
+ {
+ State = ElementState.Selected;
+ }
+ break;
+ case ElementState.CanStretchRightLowerCorner:
+ if (!IsMouseCanStretchRightLowerCorner(p))
+ {
+ State = ElementState.Selected;
+ }
+ break;
+ case ElementState.CanStretchRightUpperCorner:
+ if (!IsMouseCanStretchRightUpperCorner(p))
+ {
+ State = ElementState.Selected;
+ }
+ break;
+ case ElementState.StretchingTop:
+ StretchTop(p);
+ break;
+ case ElementState.StretchingBottom:
+ StretchBottom(p);
+ break;
+ case ElementState.StretchingLeft:
+ StretchLeft(p);
+ break;
+ case ElementState.StretchingRight:
+ StretchRight(p);
+ break;
+ case ElementState.StretchingLeftLowerCorner:
+ StretchLeftLowerCorner(p);
+ break;
+ case ElementState.StretchingLeftUpperCorner:
+ StretchLeftUpperCorner(p);
+ break;
+ case ElementState.StretchingRightLowerCorner:
+ StretchRightLowerCorner(p);
+ break;
+ case ElementState.StretchingRightUpperCorner:
+ StretchRightUpperCorner(p);
+ break;
+ }
+ }
+
+ public virtual void OnMouseUp(PointF p)
+ {
+ switch (State)
+ {
+ case ElementState.New:
+ OnMouseUpWhenNew(p);
+ break;
+ case ElementState.Moving:
+ State = ElementState.Selected;
+ break;
+ case ElementState.Selected:
+ if (!IsMouseInSide(p))
+ {
+ State = ElementState.Normal;
+ }
+ break;
+ case ElementState.StretchingBottom:
+ State = ElementState.CanStretchBottom;
+ break;
+ case ElementState.StretchingLeft:
+ State = ElementState.CanStretchLeft;
+ break;
+ case ElementState.StretchingRight:
+ State = ElementState.CanStretchRight;
+ break;
+ case ElementState.StretchingTop:
+ State = ElementState.CanStretchTop;
+ break;
+ case ElementState.StretchingLeftLowerCorner:
+ State = ElementState.CanStretchLeftLowerCorner;
+ break;
+ case ElementState.StretchingLeftUpperCorner:
+ State = ElementState.CanStretchLeftUpperCorner;
+ break;
+ case ElementState.StretchingRightUpperCorner:
+ State = ElementState.CanStretchRightUpperCorner;
+ break;
+ case ElementState.StretchingRightLowerCorner:
+ State = ElementState.CanStretchRightLowerCorner;
+ break;
+ default:
+ State = ElementState.Normal;
+ break;
+ }
+
+ AfterTranformOp();
+ }
+
+ public virtual void AfterTranformOp()
+ {
+ }
+
+ #region 当基元状态为新建或可编辑时的鼠标操作动作
+ ///
+ /// 当状态为New时的鼠标按下操作
+ ///
+ ///
+ public abstract void OnMouseDownWhenNew(PointF p);
+
+ public abstract void OnMouseMoveWhenNew(PointF p);
+
+ public abstract void OnMouseUpWhenNew(PointF p);
+ #endregion
+
+ #endregion
+
+ #region 委托事件
+ [JsonIgnore]
+ public Action OnDrawDone;
+ [JsonIgnore]
+ public Action OnMeasureDone;
+ [JsonIgnore]
+ public Action OnElementEnableChanged;
+ #endregion
+
+ #region 几何特性
+ ///
+ /// 基类基础的Rectangle 用于计算MouseHover和Inside等
+ ///
+ [Browsable(false)]
+ public Rectangle BaseRectangle { get; set; }
+ EnumHelper.ElementState IShapeElement.State { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public abstract bool IsMouseHover(PointF p);
+
+ public abstract bool IsMouseInSide(PointF p);
+
+ public abstract bool IsIntersect(RectangleF rect);
+ #region Move & Stretch & Move Anchor
+ public virtual bool IsMouseCanMoveElement(PointF p)
+ {
+ return false;
+ }
+
+ public virtual bool IsMouseCanStretchLeft(PointF p)
+ {
+ return false;
+ }
+
+ public virtual bool IsMouseCanStretchRight(PointF p)
+ {
+ return false;
+ }
+
+ public virtual bool IsMouseCanStretchTop(PointF p)
+ {
+ return false;
+ }
+
+ public virtual bool IsMouseCanStretchBottom(PointF p)
+ {
+ return false;
+ }
+
+ public virtual void StretchLeft(PointF p)
+ {
+ }
+
+ public virtual void StretchRight(PointF p)
+ {
+ }
+
+ public virtual void StretchTop(PointF p)
+ {
+ }
+
+ public virtual void StretchBottom(PointF p)
+ {
+ }
+
+ public virtual bool IsMouseCanStretchLeftUpperCorner(PointF p)
+ {
+ return false;
+ }
+
+ public virtual bool IsMouseCanStretchRightUpperCorner(PointF p)
+ {
+ return false;
+ }
+
+ public virtual bool IsMouseCanStretchLeftLowerCorner(PointF p)
+ {
+ return false;
+ }
+
+ public virtual bool IsMouseCanStretchRightLowerCorner(PointF p)
+ {
+ return false;
+ }
+
+ public virtual void StretchLeftUpperCorner(PointF p)
+ {
+ }
+
+ public virtual void StretchRightUpperCorner(PointF p)
+ {
+ }
+
+ public virtual void StretchLeftLowerCorner(PointF p)
+ {
+ }
+
+ public virtual void StretchRightLowerCorner(PointF p)
+ {
+ }
+
+ public virtual bool IsMouseCanMoveAnchor(PointF p)
+ {
+ return false;
+ }
+ #endregion
+
+ #endregion
+
+ #region 变形操作
+ public abstract void Translate(float x, float y);
+
+ public virtual void Relocate(PointF point) { }
+
+ //public abstract void RotateAt(int x, int y, float degree);
+ #endregion
+
+ #region 运动
+ //[Browsable(false)]
+ //public PlanPoint MovePoint { get; set; }
+ #endregion
+
+ #region 相机
+ //[Browsable(false)]
+ //public CameraOperationConfigBase CameraOpConfig { get; set; }
+ #endregion
+
+ #region 光源
+ #endregion
+
+ #region 算法
+ ///
+ /// 算法
+ ///
+ /// 计算参数
+ public virtual void Calculate(Bitmap image) { }
+
+ public virtual void Calculate(IntPtr imagePtr, int ptrSize, int imageWidth, int imageHeight) { }
+
+ public virtual void Calculate(string imagePath) { }
+ #endregion
+
+ #region 图片保存
+ //[Description("图片保存方式")]
+ //public ImageSaveMode ImageSaveMode { get; set; } = ImageSaveMode.NoSave;
+
+ //public virtual void SaveImage(Bitmap image)
+ //{
+ // if (string.IsNullOrWhiteSpace(AOIMeasure.GlobalVar.ImageSaveDirectory) || ImageSaveMode == ImageSaveMode.NoSave)
+ // {
+ // return;
+ // }
+
+ // DirectoryInfo dir = new DirectoryInfo(GlobalVar.ImageSaveDirectory);
+ // if (!dir.Exists)
+ // {
+ // dir.Create();
+ // }
+
+ // string imgPath = Path.Combine(AOIMeasure.GlobalVar.ImageSaveDirectory, Name + "_" + DateTime.Now.ToString("MMdd_HHmmss") + ".bmp");
+ // switch (ImageSaveMode)
+ // {
+ // case ImageSaveMode.SaveImage:
+ // image.Save(imgPath);
+ // break;
+ // case ImageSaveMode.SaveImageWithElement:
+ // Bitmap bmp = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb);
+ // using (Graphics g = Graphics.FromImage(bmp))
+ // {
+ // g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
+ // g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
+ // g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
+ // g.DrawImage(image, 0, 0, image.Width, image.Height);
+
+ // Draw(g);
+ // }
+
+ // bmp.Save(imgPath);
+ // break;
+ // }
+ //}
+
+ //public virtual void SaveImage(IntPtr imagePtr, int ptrSize)
+ //{
+ // Bitmap map = null;
+ // unsafe
+ // {
+ // byte* pArray = (byte*)imagePtr;
+ // byte[] array = new byte[ptrSize];
+ // Marshal.Copy(imagePtr, array, 0, ptrSize);
+ // using (MemoryStream ms = new MemoryStream(array))
+ // {
+ // map = (Bitmap)Image.FromStream(ms);
+ // }
+ // }
+
+ // SaveImage(map);
+ //}
+
+ //public virtual void SaveImage(string imagePath)
+ //{
+ // using (Bitmap map = Image.FromFile(imagePath) as Bitmap)
+ // {
+ // SaveImage(map);
+ // }
+ //}
+ #endregion
+
+ #region 值设置
+ public virtual void InitialMeasureResult()
+ {
+ //PropertyInfo[] prop = this.GetType().GetProperties();
+ //Array.ForEach(prop, p =>
+ //{
+ // if ((p.PropertyType.Name == typeof(MeasureSpec).Name) && p.CanRead && p.CanWrite)
+ // {
+ // MeasureSpec spec = p.GetValue(this) as MeasureSpec;
+ // spec.Result = MeasureResult.NotYet;
+ // p.SetValue(this, spec);
+ // }
+ //});
+ }
+
+ public virtual void SetActualValue(double v)
+ {
+ //PropertyInfo[] prop = this.GetType().GetProperties();
+ //Array.ForEach(prop, p =>
+ // {
+ // if ((p.PropertyType.Name == typeof(MeasureSpec).Name) && p.CanRead && p.CanWrite)
+ // {
+ // MeasureSpec spec = p.GetValue(this) as MeasureSpec;
+ // spec.ActualValue = (float)v;
+ // p.SetValue(this, spec);
+ // }
+ // });
+ }
+
+ public virtual void SetStandardValue(double v)
+ {
+ //PropertyInfo[] prop = this.GetType().GetProperties();
+ //Array.ForEach(prop, p =>
+ //{
+ // if ((p.PropertyType.Name == typeof(MeasureSpec).Name) && p.CanRead && p.CanWrite)
+ // {
+ // MeasureSpec spec = p.GetValue(this) as MeasureSpec;
+ // spec.StandardValue = (float)v;
+ // p.SetValue(this, spec);
+ // }
+ //});
+ }
+ #endregion
+
+ #region IPropertyChanged
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public virtual void Set(ref T field, T newValue, [CallerMemberName] string propName = null)
+ {
+ if (!field.Equals(newValue))
+ {
+ field = newValue;
+ //PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs(propName), null, null);
+ RaisePropertyChanged(propName);
+ }
+ }
+
+ public virtual void RaisePropertyChanged(string propName = "")
+ {
+ //PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs(propName), null, null);
+
+ //Task.Run(() =>
+ //{
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
+ //});
+ }
+ #endregion
+
+ public override string ToString()
+ {
+ return GetDisplayText();
+ }
+
+ public abstract string GetDisplayText();
+
+ #region IComparable
+ public virtual int CompareTo(ElementBase other)
+ {
+ //throw new NotImplementedException();
+ return Index - other.Index;
+ }
+ #endregion
+
+ #region IDisposable Support
+ private bool disposedValue = false; // 要检测冗余调用
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ // 释放托管状态(托管对象)。
+ Pen?.Dispose();
+ }
+
+ // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
+ // TODO: 将大型字段设置为 null。
+
+ disposedValue = true;
+ }
+ }
+
+ // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
+ // ~ElementBase()
+ // {
+ // // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
+ // Dispose(false);
+ // }
+
+ // 添加此代码以正确实现可处置模式。
+ public void Dispose()
+ {
+ // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
+ Dispose(true);
+ // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
+ // GC.SuppressFinalize(this);
+ }
+ #endregion
+ }
+
+ [Serializable]
+ public abstract class DisplayElementBase : ElementBase
+ {
+ //public override object Clone()
+ //{
+ // throw new NotImplementedException();
+ //}
+
+ //public override void Draw(Graphics g)
+ //{
+ // throw new NotImplementedException();
+ //}
+
+ //public override string GetDisplayText()
+ //{
+ // throw new NotImplementedException();
+ //}
+
+ //public override bool IsIntersect(Rectangle rect)
+ //{
+ // throw new NotImplementedException();
+ //}
+
+ public override bool IsMouseHover(PointF p)
+ {
+ return false;
+ }
+
+ //public override bool IsMouseInSide(Point p)
+ //{
+ // throw new NotImplementedException();
+ //}
+
+ public override void OnKeyDown(object sender, KeyEventArgs e)
+ {
+ }
+
+ public override void OnKeyUp(object sender, KeyEventArgs e)
+ {
+ }
+
+ public override void OnMouseDownWhenNew(PointF p)
+ {
+ }
+
+ public override void OnMouseMoveWhenNew(PointF p)
+ {
+ }
+
+ public override void OnMouseUpWhenNew(PointF p)
+ {
+ }
+
+ public override void Translate(float x, float y)
+ {
+ }
+
+ protected override void DrawResult(Graphics g)
+ {
+ }
+ }
+
+ public interface IEventHandle
+ {
+ void OnMouseMove(PointF p);
+
+ void OnMouseDown(PointF p);
+
+ void OnMouseUp(PointF p);
+
+ void OnMouseDoubleClick(PointF p);
+
+ void OnKeyDown(object sender, KeyEventArgs e);
+
+ void OnKeyUp(object sender, KeyEventArgs e);
+ }
+
+ public class ElementIndexCompare : IComparer
+ {
+ public int Compare(ElementBase x, ElementBase y)
+ {
+ return x.Index - y.Index;
+ }
+ }
+}
diff --git a/DH.UI.Model.Winform/Element/MLResultDisplay.cs b/DH.UI.Model.Winform/Element/MLResultDisplay.cs
new file mode 100644
index 0000000..61dab98
--- /dev/null
+++ b/DH.UI.Model.Winform/Element/MLResultDisplay.cs
@@ -0,0 +1,325 @@
+
+using DH.Commons.Enums;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+
+namespace DH.UI.Model.Winform
+{
+ public class DetectResultDisplay : ElementBase
+ {
+ //深度学习 显示结果
+ private List mlResultList = null;
+ public List MLResultList
+ {
+ get => mlResultList;
+ set
+ {
+ if (mlResultList != value)
+ {
+ mlResultList = value;
+ }
+ }
+ }
+
+ //测量结果
+ //private List specResultList = null;
+ //public List SpecResultList
+ //{
+ // get => specResultList;
+ // set
+ // {
+ // if (specResultList != value)
+ // {
+ // specResultList = value;
+
+ // string specDisplay = "";
+ // if (specResultList != null && specResultList.Count > 0)
+ // {
+ // specResultList.ForEach(s =>
+ // {
+ // specDisplay += $"{s.Code}:{(s.ActualValue ?? 0).ToString("f2")}\r\n";
+ // });
+ // }
+
+ // if (!string.IsNullOrWhiteSpace(specDisplay))
+ // {
+ // DisplayTxt += specDisplay;
+ // }
+ // }
+ // }
+ //}
+
+ ResultState ResultState = ResultState.DetectNG;
+
+ string DisplayTxt = "";
+ Bitmap ResultImage = null;
+ PointF StartPoint = new PointF();
+ Brush FontBrush = new SolidBrush(Color.Green);
+ Pen DetectResultRectPen = new Pen(new SolidBrush(Color.Green));
+ Font DetectResultFont = new Font(new FontFamily("Tahoma"), 15, GraphicsUnit.World);
+
+ public int ImageWidth { get; set; }
+ public int ImageHeight { get; set; }
+ public DetectResultDisplay() { }
+
+ //public DetectResultDisplay(NetResult result, List specs, ResultState resultState, int imageWidth)
+ //{
+ // ImageWidth = imageWidth;
+
+ // ResultState = resultState;
+
+ // displayTxt = resultState.ToString() + "\r\n";
+ // if (resultState != ResultState.OK)
+ // {
+ // fontBrush = new SolidBrush(Color.Red);
+ // }
+
+ // NetResult = result;
+ // SpecList = specs;
+
+ // Font = new Font(new FontFamily("Tahoma"), 35 * ImageWidth / 1400, GraphicsUnit.World);
+ // startPoint = new PointF(150 * ImageWidth / 1400, 150 * ImageWidth / 1400);
+ //}
+
+ public DetectResultDisplay(DetectStationResult detectResult, Bitmap resultImage, string displayTxt)
+ {
+ ImageWidth = resultImage.Width;
+ ImageHeight = resultImage.Height;
+ var longSide = ImageWidth > ImageHeight ? ImageWidth : ImageHeight;
+
+ MLResultList = detectResult.DetectDetails;
+ // SpecResultList = detectResult.Specs;
+ ResultState = detectResult.ResultState;
+ ResultImage = resultImage;
+ DisplayTxt = displayTxt;
+ if (ResultState != ResultState.OK)
+ {
+ FontBrush = new SolidBrush(Color.Red);
+ DetectResultRectPen = new Pen(new SolidBrush(Color.Red));
+ }
+ Font = new Font(new FontFamily("Tahoma"), 35 * longSide / 1400, GraphicsUnit.World);
+ DetectResultFont = new Font(new FontFamily("Tahoma"), 25 * longSide / 1400, GraphicsUnit.World);
+ StartPoint = new PointF(100 * ImageWidth / 1400, 100 * ImageHeight / 1400);
+ }
+
+ public override object Clone()
+ {
+ return null;
+ }
+
+
+ public override void Draw(Graphics g)
+ {
+ //画检测结果图
+ if (ResultImage != null && ResultState != ResultState.OK)
+ {
+ g.DrawImage(ResultImage, new Point(0, 0));
+ }
+ //画文字
+ if (!string.IsNullOrWhiteSpace(DisplayTxt))
+ {
+ g.DrawString(DisplayTxt, Font, FontBrush, StartPoint);
+ }
+ //画外接矩形+label 深度学习
+ if (MLResultList != null && MLResultList.Count > 0)
+ {
+ MLResultList.ForEach(d =>
+ {
+ g.DrawRectangle(DetectResultRectPen, d.Rect);
+
+ string locationTxt = $"{d.LabelDisplay}";
+ var locationX = d.Rect.X;
+ var locationY = d.Rect.Y <= 20 ? d.Rect.Y + 20 : d.Rect.Y - 20;
+ g.DrawString(locationTxt, DetectResultFont, FontBrush, locationX, locationY);
+ });
+ }
+ //画spec信息
+
+ //if (DetectResult != null && DetectResult.NetResult?.DetectDetails?.Count > 0)
+ //{
+ // DetectResult.NetResult?.DetectDetails.ForEach(d =>
+ // {
+ // g.DrawRectangle(defectRectPen, d.Rect);
+
+ // string locationTxt = $"{d.Rect.X},{d.Rect.Y}";
+ // g.DrawString(locationTxt, defectFont, fontBrush, d.Rect.X, d.Rect.Y - 5);
+ // });
+ //}
+
+ //float fontHeight = g.MeasureString(displayTxt, Font).Height;
+ //startPoint.Y += fontHeight * 1.2f;
+
+ //var defects = DetectResult.NetResult?.DetectDetails;
+ //if (defects != null && defects.Count > 0)
+ //{
+ // defects.ForEach(d =>
+ // {
+ // g.DrawString($"{d.ClassName} X:{d.Rect.X.ToString("f2")} Y:{d.Rect.Y.ToString("f2")} S:{d.Area}", Font, d.FinalResult == EnumHelper.ResultState.OK ? fontBrushOK : fontBrushNG, startPoint);
+
+ // startPoint.Y += fontHeight;
+ // });
+ //}
+
+ //DetectResult.Specs.ForEach(s =>
+ //{
+ // g.DrawString($"{s.Code}:{(s.ActualValue ?? 0).ToString("f2")}", Font, s.MeasureResult ?? false == true ? fontBrushOK : fontBrushNG, startPoint);
+
+ // startPoint.Y += fontHeight;
+ //});
+ }
+
+ public override string GetDisplayText()
+ {
+ return "";
+ }
+
+ public override bool IsIntersect(RectangleF rect)
+ {
+ return false;
+ }
+
+ public override bool IsMouseHover(PointF p)
+ {
+ return false;
+ }
+
+ public override bool IsMouseInSide(PointF p)
+ {
+ return false;
+ }
+
+ public override void OnKeyDown(object sender, KeyEventArgs e)
+ {
+ }
+
+ public override void OnKeyUp(object sender, KeyEventArgs e)
+ {
+ }
+
+ protected override void DrawResult(Graphics g)
+ {
+ }
+
+ public override void OnMouseDownWhenNew(PointF p)
+ {
+ }
+
+ public override void OnMouseMoveWhenNew(PointF p)
+ {
+ }
+
+ public override void OnMouseUpWhenNew(PointF p)
+ {
+ }
+
+ public override void Translate(float x, float y)
+ {
+ }
+ }
+
+ public class RectResultDisplay : ElementBase
+ {
+ ResultState ResultState = ResultState.DetectNG;
+ public string DisplayTxt = "";
+ Color FillColor = Color.Lime;
+ int FontSize = 15;
+ RectangleF Rect = new RectangleF();
+ bool IsFilled = false;
+
+ public RectResultDisplay() { }
+
+ public RectResultDisplay(ResultState _resultState, RectangleF _rect, string _displayTxt, Color _fillColor, bool _isFilled, int _fontSize)
+ {
+ ResultState = _resultState;
+ Rect = _rect;
+ DisplayTxt = _displayTxt;
+ FillColor = _fillColor;
+ IsFilled = _isFilled;
+ FontSize = _fontSize;
+ }
+
+ public override object Clone()
+ {
+ RectResultDisplay rect = new RectResultDisplay();
+
+ rect.ResultState = ResultState;
+ rect.Rect = Rect;
+ rect.DisplayTxt = DisplayTxt;
+ rect.FillColor = FillColor;
+ rect.FontSize = FontSize;
+ rect.IsFilled = IsFilled;
+
+ return rect;
+ }
+
+ public override void Draw(Graphics g)
+ {
+ g.DrawRectangle(new Pen(FillColor, 1), Rect.X, Rect.Y, Rect.Width, Rect.Height);
+
+ if (IsFilled)
+ {
+ g.FillRectangle(new SolidBrush(Color.FromArgb(20, FillColor)), Rect);
+ }
+
+ Font font = new Font("Tahoma", FontSize);
+ var txtSize = g.MeasureString(DisplayTxt, font);
+
+ g.DrawString(DisplayTxt, font, new SolidBrush(FillColor), (float)(Rect.X + Rect.Width / 2.0 - txtSize.Width / 2.0), Rect.Y + Rect.Height + 5);
+ }
+
+ public override string GetDisplayText()
+ {
+ return $"{ResultState} {DisplayTxt} ({Rect.X},{Rect.Y},{Rect.Width},{Rect.Height})";
+ }
+
+ public override bool IsIntersect(RectangleF rect)
+ {
+ return rect.IntersectsWith(Rect);
+ }
+
+ public override bool IsMouseHover(PointF p)
+ {
+ return false;
+ }
+
+ public override bool IsMouseInSide(PointF p)
+ {
+ return Rect.Contains(p);
+ }
+
+ public override void OnKeyDown(object sender, KeyEventArgs e)
+ {
+ }
+
+ public override void OnKeyUp(object sender, KeyEventArgs e)
+ {
+ }
+
+ public override void OnMouseDownWhenNew(PointF p)
+ {
+ }
+
+ public override void OnMouseMoveWhenNew(PointF p)
+ {
+ }
+
+ public override void OnMouseUpWhenNew(PointF p)
+ {
+ }
+
+ public override void Translate(float x, float y)
+ {
+ Rect.Offset(new PointF(x, y));
+ }
+
+ protected override void DrawResult(Graphics g)
+ {
+ }
+ }
+}
diff --git a/DH.UI.Model.Winform/GridCtrl.Designer.cs b/DH.UI.Model.Winform/GridCtrl.Designer.cs
new file mode 100644
index 0000000..bfc50ad
--- /dev/null
+++ b/DH.UI.Model.Winform/GridCtrl.Designer.cs
@@ -0,0 +1,109 @@
+namespace XKRS.UI.Model.Winform
+{
+ partial class GridCtrl
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.chkShowGrid = new System.Windows.Forms.CheckBox();
+ this.tbGridValue = new System.Windows.Forms.TrackBar();
+ this.panel1 = new System.Windows.Forms.Panel();
+ this.colorDialog1 = new System.Windows.Forms.ColorDialog();
+ this.btnColor = new System.Windows.Forms.Button();
+ ((System.ComponentModel.ISupportInitialize)(this.tbGridValue)).BeginInit();
+ this.panel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // chkShowGrid
+ //
+ this.chkShowGrid.Appearance = System.Windows.Forms.Appearance.Button;
+ // this.chkShowGrid.BackgroundImage = global::XKRS.UI.Model.Winform.Properties.Resources.grid;
+ this.chkShowGrid.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
+ this.chkShowGrid.Dock = System.Windows.Forms.DockStyle.Top;
+ this.chkShowGrid.Location = new System.Drawing.Point(0, 0);
+ this.chkShowGrid.Name = "chkShowGrid";
+ this.chkShowGrid.Size = new System.Drawing.Size(32, 30);
+ this.chkShowGrid.TabIndex = 0;
+ this.chkShowGrid.UseVisualStyleBackColor = true;
+ this.chkShowGrid.CheckedChanged += new System.EventHandler(this.chkShowGrid_CheckedChanged);
+ //
+ // tbGridValue
+ //
+ this.tbGridValue.AutoSize = false;
+ this.tbGridValue.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.tbGridValue.Location = new System.Drawing.Point(0, 21);
+ this.tbGridValue.Name = "tbGridValue";
+ this.tbGridValue.Orientation = System.Windows.Forms.Orientation.Vertical;
+ this.tbGridValue.Size = new System.Drawing.Size(32, 121);
+ this.tbGridValue.TabIndex = 1;
+ this.tbGridValue.TickStyle = System.Windows.Forms.TickStyle.Both;
+ this.tbGridValue.ValueChanged += new System.EventHandler(this.tbGridValue_ValueChanged);
+ //
+ // panel1
+ //
+ this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.panel1.Controls.Add(this.chkShowGrid);
+ this.panel1.Controls.Add(this.tbGridValue);
+ this.panel1.Location = new System.Drawing.Point(1, 1);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(32, 142);
+ this.panel1.TabIndex = 2;
+ //
+ // btnColor
+ //
+ this.btnColor.BackColor = System.Drawing.Color.Red;
+ this.btnColor.Location = new System.Drawing.Point(4, 150);
+ this.btnColor.Name = "btnColor";
+ this.btnColor.Size = new System.Drawing.Size(25, 23);
+ this.btnColor.TabIndex = 3;
+ this.btnColor.Text = " ";
+ this.btnColor.UseVisualStyleBackColor = false;
+ this.btnColor.Click += new System.EventHandler(this.btnColor_Click);
+ //
+ // GridCtrl
+ //
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+ this.Controls.Add(this.btnColor);
+ this.Controls.Add(this.panel1);
+ this.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, ((byte)(134)));
+ this.Name = "GridCtrl";
+ this.Size = new System.Drawing.Size(32, 192);
+ ((System.ComponentModel.ISupportInitialize)(this.tbGridValue)).EndInit();
+ this.panel1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.CheckBox chkShowGrid;
+ private System.Windows.Forms.TrackBar tbGridValue;
+ private System.Windows.Forms.Panel panel1;
+ private System.Windows.Forms.ColorDialog colorDialog1;
+ private System.Windows.Forms.Button btnColor;
+ }
+}
diff --git a/DH.UI.Model.Winform/GridCtrl.cs b/DH.UI.Model.Winform/GridCtrl.cs
new file mode 100644
index 0000000..dace442
--- /dev/null
+++ b/DH.UI.Model.Winform/GridCtrl.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace XKRS.UI.Model.Winform
+{
+ public partial class GridCtrl : UserControl
+ {
+ public Action IsShowGridChanged { get; set; }
+
+ public Action GridValueChanged { get; set; }
+
+ public Action GridColorChanged { get; set; }
+
+ public GridCtrl()
+ {
+ InitializeComponent();
+
+ IsChecked = chkShowGrid.Checked;
+ GridValue = tbGridValue.Value;
+ }
+
+ bool isChecked = false;
+ bool IsChecked
+ {
+ get => isChecked;
+ set
+ {
+ if (isChecked != value)
+ {
+ // IsShowGridChanged?.BeginInvoke(value, null, null);
+ Task.Run(() => IsShowGridChanged.Invoke(value));
+ }
+
+ isChecked = value;
+ }
+ }
+
+ int gridValue = 0;
+ int GridValue
+ {
+ get => gridValue;
+ set
+ {
+ if (gridValue != value)
+ {
+ // GridValueChanged?.BeginInvoke(value, null, null);
+ Task.Run(() => GridValueChanged.Invoke(value));
+ }
+
+ gridValue = value;
+ }
+ }
+ private void chkShowGrid_CheckedChanged(object sender, EventArgs e)
+ {
+ IsChecked = chkShowGrid.Checked;
+ }
+
+ private void tbGridValue_ValueChanged(object sender, EventArgs e)
+ {
+ GridValue = tbGridValue.Value;
+ }
+
+ private void btnColor_Click(object sender, EventArgs e)
+ {
+ if (colorDialog1.ShowDialog() == DialogResult.OK)
+ {
+ btnColor.BackColor = colorDialog1.Color;
+ // GridColorChanged?.BeginInvoke(btnColor.BackColor, null, null);
+ Task.Run(() => GridColorChanged.Invoke(btnColor.BackColor));
+ }
+ }
+ }
+}
diff --git a/DH.UI.Model.Winform/GridCtrl.resx b/DH.UI.Model.Winform/GridCtrl.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/DH.UI.Model.Winform/GridCtrl.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/DH.UI.Model.Winform/GridCtrlHost.cs b/DH.UI.Model.Winform/GridCtrlHost.cs
new file mode 100644
index 0000000..2f7f79e
--- /dev/null
+++ b/DH.UI.Model.Winform/GridCtrlHost.cs
@@ -0,0 +1,12 @@
+using System.Windows.Forms;
+
+namespace XKRS.UI.Model.Winform
+{
+ public class GridCtrlHost : ToolStripControlHost
+ {
+ public GridCtrlHost(GridCtrl grid) : base(grid)
+ {
+ //Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, 134);
+ }
+ }
+}
diff --git a/DH.UI.Model.Winform/IOIndicatorCtrl.Designer.cs b/DH.UI.Model.Winform/IOIndicatorCtrl.Designer.cs
new file mode 100644
index 0000000..6d83432
--- /dev/null
+++ b/DH.UI.Model.Winform/IOIndicatorCtrl.Designer.cs
@@ -0,0 +1,78 @@
+namespace XKRS.UI.Model.Winform
+{
+ partial class IOIndicatorCtrl
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ plStatus = new Panel();
+ lblDesc = new Label();
+ SuspendLayout();
+ //
+ // plStatus
+ //
+ plStatus.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left;
+ plStatus.Location = new Point(0, 0);
+ plStatus.Margin = new Padding(4);
+ plStatus.Name = "plStatus";
+ plStatus.Size = new Size(28, 34);
+ plStatus.TabIndex = 0;
+ plStatus.Paint += plStatus_Paint;
+ plStatus.DoubleClick += plStatus_DoubleClick;
+ //
+ // lblDesc
+ //
+ lblDesc.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
+ lblDesc.AutoSize = true;
+ lblDesc.Font = new Font("Tahoma", 11F, FontStyle.Regular, GraphicsUnit.World);
+ lblDesc.Location = new Point(36, 11);
+ lblDesc.Margin = new Padding(4, 0, 4, 0);
+ lblDesc.Name = "lblDesc";
+ lblDesc.Size = new Size(31, 13);
+ lblDesc.TabIndex = 1;
+ lblDesc.Text = "XXXX";
+ lblDesc.TextAlign = ContentAlignment.MiddleLeft;
+ lblDesc.DoubleClick += lblDesc_DoubleClick;
+ //
+ // IOIndicatorCtrl
+ //
+ AutoScaleDimensions = new SizeF(7F, 17F);
+ AutoScaleMode = AutoScaleMode.Font;
+ Controls.Add(lblDesc);
+ Controls.Add(plStatus);
+ Margin = new Padding(4);
+ Name = "IOIndicatorCtrl";
+ Size = new Size(138, 34);
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Panel plStatus;
+ private Label lblDesc;
+ }
+}
diff --git a/DH.UI.Model.Winform/IOIndicatorCtrl.cs b/DH.UI.Model.Winform/IOIndicatorCtrl.cs
new file mode 100644
index 0000000..bc40ed4
--- /dev/null
+++ b/DH.UI.Model.Winform/IOIndicatorCtrl.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace XKRS.UI.Model.Winform
+{
+ public partial class IOIndicatorCtrl : UserControl
+ {
+ public IOIndicatorCtrl()
+ {
+ InitializeComponent();
+ }
+
+ private bool isON = false;
+
+ public bool IsOn
+ {
+ get => isON;
+ set
+ {
+ bool? temp = isON;
+ isON = value;
+
+ if (temp != isON)
+ {
+ RefreshStatus();
+ }
+ }
+ }
+
+ private void RefreshStatus()
+ {
+ if (InvokeRequired)
+ {
+ Invoke(new Action(() => RefreshStatus()));
+ }
+ else
+ {
+ plStatus.Invalidate();
+ }
+ }
+
+ private string desc = "";
+ public string Desc
+ {
+ get => desc;
+ set
+ {
+ desc = value;
+
+ DisplayDesc();
+ }
+ }
+
+ public int Index { get; set; }
+
+ private void DisplayDesc()
+ {
+ if (InvokeRequired)
+ {
+ Invoke(new Action(() => DisplayDesc()));
+ }
+ else
+ {
+ lblDesc.Text = Desc;
+ }
+ }
+
+ readonly PointF[] regionBlink = new PointF[]
+ {
+ new PointF(5,10),
+ new PointF(10,13),
+ new PointF(12,7),
+ new PointF(10,5)
+ };
+
+ public IOIndicatorCtrl(bool _isOn, string _desc, int index = 0)
+ {
+ InitializeComponent();
+
+ IsOn = _isOn;
+ Desc = _desc;
+ Index = index;
+ }
+
+ ///
+ /// 更新绘制图标
+ ///
+ ///
+ ///
+ private void plStatus_Paint(object sender, PaintEventArgs e)
+ {
+ Panel pl = sender as Panel;
+
+ Graphics g = e.Graphics;
+
+ g.Clear(SystemColors.Control);
+
+
+ if (IsOn)
+ {
+ g.FillEllipse(Brushes.LightGreen, pl.ClientRectangle);
+ }
+ else
+ {
+ g.FillEllipse(Brushes.Gray, pl.ClientRectangle);
+ }
+
+ g.FillPolygon(Brushes.White, regionBlink);
+
+ }
+
+ public event Action OnIODoubleClick;
+
+
+ private void lblDesc_DoubleClick(object sender, EventArgs e)
+ {
+ OnIODoubleClick?.Invoke(Name, IsOn, Index);
+ }
+
+ private void plStatus_DoubleClick(object sender, EventArgs e)
+ {
+ OnIODoubleClick?.Invoke(Name, IsOn, Index);
+ }
+ }
+}
diff --git a/DH.UI.Model.Winform/IOIndicatorCtrl.resx b/DH.UI.Model.Winform/IOIndicatorCtrl.resx
new file mode 100644
index 0000000..a395bff
--- /dev/null
+++ b/DH.UI.Model.Winform/IOIndicatorCtrl.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/DHSoftware.sln b/DHSoftware.sln
index 54646c2..a4155f0 100644
--- a/DHSoftware.sln
+++ b/DHSoftware.sln
@@ -17,8 +17,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Commons", "Commons", "{0AB4
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Commons", "DH.Commons\DH.Commons.csproj", "{027373EC-C5CB-4161-8D43-AB6009371FDE}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Devices.Vision", "DH.Devices.Vision\DH.Devices.Vision.csproj", "{97B55FCF-54A3-449E-8437-735E65C35291}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Devices.Camera", "DH.Devices.Camera\DH.Devices.Camera.csproj", "{1378A932-1C25-40EF-BA31-A3463B23F4E5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Devices.PLC", "DH.Devices.PLC\DH.Devices.PLC.csproj", "{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}"
@@ -29,6 +27,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Devices.Motion", "DH.Dev
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Commons.Devies", "DH.Commons.Devies\DH.Commons.Devies.csproj", "{A33108B6-2740-4D28-AD22-B280372980BE}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{3EAF3D9C-D3F9-4B6E-89DE-58F129CD1F4C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.UI.Model.Winform", "DH.UI.Model.Winform\DH.UI.Model.Winform.csproj", "{12CB9041-B1B1-41AE-B308-AABDACAA580E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Devices.Vision", "DH.Devices.Vision\DH.Devices.Vision.csproj", "{5AD3A29E-149A-4C37-9548-7638A36C8175}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -53,14 +57,6 @@ Global
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Release|Any CPU.Build.0 = Release|Any CPU
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Release|x64.ActiveCfg = Release|x64
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Release|x64.Build.0 = Release|x64
- {97B55FCF-54A3-449E-8437-735E65C35291}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {97B55FCF-54A3-449E-8437-735E65C35291}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {97B55FCF-54A3-449E-8437-735E65C35291}.Debug|x64.ActiveCfg = Debug|x64
- {97B55FCF-54A3-449E-8437-735E65C35291}.Debug|x64.Build.0 = Debug|x64
- {97B55FCF-54A3-449E-8437-735E65C35291}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {97B55FCF-54A3-449E-8437-735E65C35291}.Release|Any CPU.Build.0 = Release|Any CPU
- {97B55FCF-54A3-449E-8437-735E65C35291}.Release|x64.ActiveCfg = Release|x64
- {97B55FCF-54A3-449E-8437-735E65C35291}.Release|x64.Build.0 = Release|x64
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Debug|x64.ActiveCfg = Debug|x64
@@ -93,6 +89,22 @@ Global
{A33108B6-2740-4D28-AD22-B280372980BE}.Release|Any CPU.Build.0 = Release|Any CPU
{A33108B6-2740-4D28-AD22-B280372980BE}.Release|x64.ActiveCfg = Release|X64
{A33108B6-2740-4D28-AD22-B280372980BE}.Release|x64.Build.0 = Release|X64
+ {12CB9041-B1B1-41AE-B308-AABDACAA580E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {12CB9041-B1B1-41AE-B308-AABDACAA580E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {12CB9041-B1B1-41AE-B308-AABDACAA580E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {12CB9041-B1B1-41AE-B308-AABDACAA580E}.Debug|x64.Build.0 = Debug|Any CPU
+ {12CB9041-B1B1-41AE-B308-AABDACAA580E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {12CB9041-B1B1-41AE-B308-AABDACAA580E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {12CB9041-B1B1-41AE-B308-AABDACAA580E}.Release|x64.ActiveCfg = Release|Any CPU
+ {12CB9041-B1B1-41AE-B308-AABDACAA580E}.Release|x64.Build.0 = Release|Any CPU
+ {5AD3A29E-149A-4C37-9548-7638A36C8175}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5AD3A29E-149A-4C37-9548-7638A36C8175}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5AD3A29E-149A-4C37-9548-7638A36C8175}.Debug|x64.ActiveCfg = Debug|x64
+ {5AD3A29E-149A-4C37-9548-7638A36C8175}.Debug|x64.Build.0 = Debug|x64
+ {5AD3A29E-149A-4C37-9548-7638A36C8175}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5AD3A29E-149A-4C37-9548-7638A36C8175}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5AD3A29E-149A-4C37-9548-7638A36C8175}.Release|x64.ActiveCfg = Release|x64
+ {5AD3A29E-149A-4C37-9548-7638A36C8175}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -102,12 +114,13 @@ Global
{1591B03B-0015-42FC-B784-0D9F740E2A23} = {8EC33C16-65CE-4C12-9C8D-DB2425F9F7C0}
{F77AF94C-280D-44C5-B7C0-FC86AA9EC504} = {8EC33C16-65CE-4C12-9C8D-DB2425F9F7C0}
{027373EC-C5CB-4161-8D43-AB6009371FDE} = {0AB4BB9A-A861-4F80-B549-CD331490942B}
- {97B55FCF-54A3-449E-8437-735E65C35291} = {F77AF94C-280D-44C5-B7C0-FC86AA9EC504}
{1378A932-1C25-40EF-BA31-A3463B23F4E5} = {1591B03B-0015-42FC-B784-0D9F740E2A23}
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D} = {2560C5A5-0CA2-48AD-B606-6C55BEFD8109}
{5C8472C6-EB6A-4D89-B519-7073BBF6A5D2} = {8EC33C16-65CE-4C12-9C8D-DB2425F9F7C0}
{144E3775-0BD7-4528-9FB0-A0F4ADC74313} = {5C8472C6-EB6A-4D89-B519-7073BBF6A5D2}
{A33108B6-2740-4D28-AD22-B280372980BE} = {0AB4BB9A-A861-4F80-B549-CD331490942B}
+ {12CB9041-B1B1-41AE-B308-AABDACAA580E} = {3EAF3D9C-D3F9-4B6E-89DE-58F129CD1F4C}
+ {5AD3A29E-149A-4C37-9548-7638A36C8175} = {F77AF94C-280D-44C5-B7C0-FC86AA9EC504}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6FC1A8DF-636E-434C-981E-10F20FAD723B}
diff --git a/DHSoftware/DHSoftware.csproj b/DHSoftware/DHSoftware.csproj
index ebca883..730d9ee 100644
--- a/DHSoftware/DHSoftware.csproj
+++ b/DHSoftware/DHSoftware.csproj
@@ -21,6 +21,7 @@
+
@@ -31,6 +32,7 @@
+
diff --git a/DHSoftware/MainWindow.Designer.cs b/DHSoftware/MainWindow.Designer.cs
index b2b9275..b6f3a2e 100644
--- a/DHSoftware/MainWindow.Designer.cs
+++ b/DHSoftware/MainWindow.Designer.cs
@@ -50,7 +50,7 @@
splitContainer1 = new SplitContainer();
splitContainer2 = new SplitContainer();
tabImgDisplay = new AntdUI.Tabs();
- tabPage1 = new AntdUI.TabPage();
+ tabMain = new AntdUI.TabPage();
tabsStas = new AntdUI.Tabs();
tabPage3 = new AntdUI.TabPage();
richTextBox1 = new RichTextBox();
@@ -124,6 +124,7 @@
buttonSZ.Radius = 0;
buttonSZ.Size = new Size(50, 40);
buttonSZ.TabIndex = 0;
+ buttonSZ.Visible = false;
buttonSZ.WaveSize = 0;
//
// pageHeader1
@@ -142,7 +143,7 @@
// label1
//
label1.AutoSize = true;
- label1.Location = new Point(709, 10);
+ label1.Location = new Point(979, 10);
label1.Name = "label1";
label1.Size = new Size(64, 21);
label1.TabIndex = 1;
@@ -240,23 +241,23 @@
//
// tabImgDisplay
//
- tabImgDisplay.Controls.Add(tabPage1);
+ tabImgDisplay.Controls.Add(tabMain);
tabImgDisplay.Dock = DockStyle.Fill;
tabImgDisplay.Location = new Point(0, 0);
tabImgDisplay.Name = "tabImgDisplay";
- tabImgDisplay.Pages.Add(tabPage1);
+ tabImgDisplay.Pages.Add(tabMain);
tabImgDisplay.Size = new Size(580, 320);
tabImgDisplay.Style = styleCard1;
tabImgDisplay.TabIndex = 1;
tabImgDisplay.Text = "tabs1";
//
- // tabPage1
+ // tabMain
//
- tabPage1.Location = new Point(3, 28);
- tabPage1.Name = "tabPage1";
- tabPage1.Size = new Size(574, 289);
- tabPage1.TabIndex = 0;
- tabPage1.Text = "检测";
+ tabMain.Location = new Point(3, 28);
+ tabMain.Name = "tabMain";
+ tabMain.Size = new Size(574, 289);
+ tabMain.TabIndex = 0;
+ tabMain.Text = "检测";
//
// tabsStas
//
@@ -452,7 +453,7 @@
private SplitContainer splitContainer1;
private SplitContainer splitContainer2;
private AntdUI.Tabs tabImgDisplay;
- private AntdUI.TabPage tabPage1;
+ private AntdUI.TabPage tabMain;
private AntdUI.Tabs tabsStas;
private AntdUI.TabPage tabPage3;
private RichTextBox richTextBox1;
diff --git a/DHSoftware/MainWindow.cs b/DHSoftware/MainWindow.cs
index e42539b..92a919d 100644
--- a/DHSoftware/MainWindow.cs
+++ b/DHSoftware/MainWindow.cs
@@ -26,7 +26,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
-using XKRS.Common.Model;
+using XKRS.UI.Device.Winform;
using static AntdUI.Math3D;
using Camera = DHSoftware.Models.Camera;
@@ -60,8 +60,7 @@ namespace DHSoftware
//绑定事件
BindEventHandler();
UserConfigFrm userControlFrm = new UserConfigFrm();
- // tabImgDisplay.Pages.Clear();
- // tabPage2.Controls.Clear();
+
userControlFrm.Window = this;
userControlFrm.Dock = DockStyle.Fill;
tabPage2.Controls.Add(userControlFrm);
@@ -278,6 +277,7 @@ namespace DHSoftware
public volatile int ProductNum_Total = 0;
public volatile int ProductNum_OK = 0;
private readonly object _cameraSummaryLock = new object();
+ public SimboVisionDriver? _visionEngine = null;
List DetectionConfigs = new List();
List SimboStationMLEngineList = new List();
Dictionary HalconToolDict = new Dictionary();
@@ -286,6 +286,8 @@ namespace DHSoftware
private void HandleStartButton()
{
CurrentMachine = true;
+
+ //_visionEngine.Start();
//[Category("深度学习检测配置")]
//[DisplayName("检测标签定义集合")]
//[Description("定义检测标签的集合,例如:Seg/Detection模式:断裂、油污、划伤...;Class模式:ok、ng、上面、下面、套环、正常...")]
@@ -349,6 +351,8 @@ namespace DHSoftware
det1.ModelHeight = 640;
det1.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam1.txt";
det1.IsEnabled = true;
+ det1.ShowLocation.X = 1;
+ det1.ShowLocation.Y = 1;
det2.CameraCollects = CameraCollects2;
det2.ModelconfThreshold = Conf;
@@ -356,6 +360,8 @@ namespace DHSoftware
det2.ModelHeight = 640;
det2.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam2.txt";
det2.IsEnabled = true;
+ det2.ShowLocation.X = 2;
+ det2.ShowLocation.Y = 1;
det3.CameraCollects = CameraCollects3;
det3.ModelconfThreshold = Conf;
@@ -363,6 +369,8 @@ namespace DHSoftware
det3.ModelHeight = 640;
det3.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam3.txt";
det3.IsEnabled = true;
+ det3.ShowLocation.X = 3;
+ det3.ShowLocation.Y = 1;
det4.CameraCollects = CameraCollects4;
det4.ModelconfThreshold = Conf;
@@ -370,6 +378,8 @@ namespace DHSoftware
det4.ModelHeight = 640;
det4.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam4.txt";
det4.IsEnabled = true;
+ det4.ShowLocation.X = 4;
+ det4.ShowLocation.Y = 1;
@@ -379,6 +389,8 @@ namespace DHSoftware
det5.ModelHeight = 640;
det5.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam5.txt";
det5.IsEnabled = true;
+ det5.ShowLocation.X = 1;
+ det5.ShowLocation.Y = 2;
det6.CameraCollects = CameraCollects6;
det6.ModelconfThreshold = Conf;
@@ -386,6 +398,8 @@ namespace DHSoftware
det6.ModelHeight = 640;
det6.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam6.txt";
det6.IsEnabled = true;
+ det6.ShowLocation.X = 2;
+ det6.ShowLocation.Y = 2;
det7.CameraCollects = CameraCollects7;
det7.ModelconfThreshold = Conf;
@@ -393,6 +407,8 @@ namespace DHSoftware
det7.ModelHeight = 640;
det7.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam7.txt";
det7.IsEnabled = true;
+ det7.ShowLocation.X = 3;
+ det7.ShowLocation.Y = 2;
det8.CameraCollects = CameraCollects8;
det8.ModelconfThreshold = Conf;
@@ -400,6 +416,8 @@ namespace DHSoftware
det8.ModelHeight = 640;
det8.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam8.txt";
det8.IsEnabled = true;
+ det8.ShowLocation.X = 4;
+ det8.ShowLocation.Y = 2;
DetectionConfigs.Add(det1);
DetectionConfigs.Add(det2);
@@ -452,7 +470,7 @@ namespace DHSoftware
cam.CameraName = $"Cam{i}";
Cameras.Add(cam);
cam.CameraConnect();
- // cam.OnHImageOutput += OnCameraHImageOutput;
+ cam.OnHImageOutput += OnCameraHImageOutput;
}
@@ -485,20 +503,25 @@ namespace DHSoftware
+ _visionEngine = new SimboVisionDriver();
+ _visionEngine.DetectionConfigs = DetectionConfigs;
+ _visionEngine.Init();
+ CtrlVisionRunBase ctrlVisionRun = new CtrlVisionRunBase(_visionEngine);
+ tabImgDisplay.Controls.Add(ctrlVisionRun);
//Add the code for the "启动" button click here
- //初始化Halcon工具
- InitialHalconTools();
+ ////初始化Halcon工具
+ //InitialHalconTools();
- //深度学习模型加载
- bool resultOK = InitialSimboMLEnginesAsync();
- if (resultOK)
- {
- //初始化失败
- // return;
- }
+ ////深度学习模型加载
+ //bool resultOK = InitialSimboMLEnginesAsync();
+ //if (resultOK)
+ //{
+ // //初始化失败
+ // // return;
+ //}
//位置比较卡
sLDMotion.AxisSettings = new List();
@@ -658,788 +681,261 @@ namespace DHSoftware
});
}
///
- /// 初始化深度学习工具
- ///
- private bool InitialSimboMLEnginesAsync()
- {
- //深度学习 模型加载
- var resultOK = MLLoadModel();
- return resultOK;
- }
- ///
- /// 深度学习 模型加载
- ///
- ///
- private bool MLLoadModel()
- {
- bool resultOK = false;
- try
- {
- SimboStationMLEngineList = new List();
- // _cameraRelatedDetectionDict = IConfig.DetectionConfigs.Select(t => t.ModelPath).Distinct().ToList();
- DetectionConfigs.ForEach(dc =>
- //_cameraRelatedDetectionDict.ForEach(dc =>
- {
-
- if (dc.IsEnabled && !string.IsNullOrWhiteSpace(dc.ModelPath))
- {
- if (dc.IsEnableGPU)
- {
- //if (IIConfig.IsLockGPU)
- //{
- //foreach (var validGPU in ValidGPUList2)
- //{
- // if (validGPU.DetectionIds.Contains(dc.Id))
- // {
- var engine = SingleMLLoadModel(dc, true, 0);
- SimboStationMLEngineList.Add(engine);
- // }
- //}
- //}
- //else
- //{
- // foreach (var validGPU in ValidGPUList)
- // {
- // //var validGPU = ValidGPUList.FirstOrDefault(u => u.DetectionIds.Contains(dc.Id));
- // if (validGPU.DetectionId == dc.Id)
- // {
- // var engine = SingleMLLoadModel(dc, true, validGPU.GPUNo);
- // SimboStationMLEngineList.Add(engine);
- // }
- // }
- //}
-
- }
- else
- {
- //for (int i = 0; i < IConfig.CPUNums; i++)
- for (int i = 0; i < 1; i++)
- {
- //var engine = SingleMLLoadModel(dc, false, i);
- var engine = SingleMLLoadModel(dc, false, i);
- SimboStationMLEngineList.Add(engine);
- }
- }
- }
- });
- resultOK = true;
- }
- catch (Exception ex)
- {
- // LogAsync(DateTime.Now, LogLevel.Exception, $"异常:模型并发加载异常:{ex.GetExceptionMessage()}");
- resultOK = false;
- }
-
- return resultOK;
- }
- ///
- /// 单个模型加载
- ///
- ///
- ///
- ///
- private SimboStationMLEngineSet SingleMLLoadModel(DetectionConfig dc, bool isGPU, int coreInx)
- {
- SimboStationMLEngineSet mLEngineSet = new SimboStationMLEngineSet();
- try
- {
- mLEngineSet.IsUseGPU = isGPU;
- if (isGPU)
- {
- mLEngineSet.GPUNo = coreInx;
- }
- else
- {
- mLEngineSet.CPUNo = coreInx;
- }
- mLEngineSet.DetectionId = dc.Id;
- mLEngineSet.DetectionName = dc.Name;
-
- if (!string.IsNullOrWhiteSpace(dc.ModelPath))
- {
- // 根据算法类型创建不同的实例
- switch (dc.ModelType)
- {
- case MLModelType.ImageClassification:
- break;
- case MLModelType.ObjectDetection:
- mLEngineSet.StationMLEngine = new SimboObjectDetection();
- break;
- case MLModelType.SemanticSegmentation:
-
- break;
- case MLModelType.InstanceSegmentation:
- mLEngineSet.StationMLEngine = new SimboInstanceSegmentation();
- break;
- case MLModelType.ObjectGPUDetection:
- mLEngineSet.StationMLEngine = new SimboDetection();
- break;
- default:
- break;
- }
- MLInit mLInit;
- string inferenceDevice = "CPU";
- if (dc.IsEnableGPU)
- {
- inferenceDevice = "GPU";
- mLInit = new MLInit(dc.ModelPath, isGPU, coreInx, dc.ModelconfThreshold);
- }
- else
- {
- mLInit = new MLInit(dc.ModelPath, "images", inferenceDevice, (int)dc.ModelWidth, (int)dc.ModelHeight);
-
- }
-
- bool isSuccess = mLEngineSet.StationMLEngine.Load(mLInit);
- if (!isSuccess)
- {
- // throw new ProcessException("异常:模型加载异常", null);
- }
- //LogAsync(DateTime.Now, LogLevel.Information, $"模型加载成功;是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}" + $" {dc.ModelType.GetEnumDescription()}:{dc.ModelPath}");
- }
- }
- catch (Exception ex)
- {
- //throw new ProcessException($"异常:是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}模型加载异常:{ex.GetExceptionMessage()}");
- }
- return mLEngineSet;
- }
- private void InitialHalconTools()
- {
- HOperatorSet.SetSystem("parallelize_operators", "true");
- HOperatorSet.SetSystem("reentrant", "true");
- HOperatorSet.SetSystem("global_mem_cache", "exclusive");
-
- HalconToolDict = new Dictionary();
-
- DetectionConfigs.ForEach(c =>
- {
- if (!c.IsEnabled)
- return;
-
- if (c.HalconAlgorithemPath_Pre != null)
- LoadHalconTool(c.HalconAlgorithemPath_Pre);
-
- });
- }
-
- private void LoadHalconTool(string path)
- {
- if (!HalconToolDict.ContainsKey(path))
- {
-
-
- string algorithemPath = path;
-
- if (string.IsNullOrWhiteSpace(algorithemPath))
- return;
-
- string directoryPath = Path.GetDirectoryName(algorithemPath);
- string fileName = Path.GetFileNameWithoutExtension(algorithemPath);
-
- HDevEngineTool tool = new HDevEngineTool(directoryPath);
- tool.LoadProcedure(fileName);
-
- HalconToolDict[path] = tool;
- }
- }
-
- ///
- /// 预处理
- ///
- ///
- ///
- public void PreTreated(DetectionConfig detectConfig, DetectStationResult detectResult, Mat MhImage)
- {
- try
- {
- // detectResult.VisionImageSet.DetectionOriginImage = detectResult.VisionImageSet.HImage.ConvertHImageToBitmap();
- //detectResult.VisionImageSet.PreTreatedBitmap = detectResult.VisionImageSet.HImage.ConvertHImageToBitmap();
- //detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.PreTreatedBitmap?.CopyBitmap();
- if (!string.IsNullOrWhiteSpace(detectConfig.HalconAlgorithemPath_Pre))
- {
- HObject obj = OpenCVHelper.MatToHImage(MhImage);
- HImage hImage = HalconHelper.ConvertHObjectToHImage(obj);
- string toolKey = detectConfig.HalconAlgorithemPath_Pre;
- if (!HalconToolDict.ContainsKey(toolKey))
- {
- // LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}未获取预处理算法");
- return;
- }
- //Mean_Thre Deviation_Thre Mean_standard Deviation_standard
- var tool = HalconToolDict[toolKey];
-
- ////tool.InputTupleDic["Mean_Thre"] = 123;
- for (int i = 0; i < detectConfig.PreTreatParams.Count; i++)
- {
- var param = detectConfig.PreTreatParams[i];
- tool.InputTupleDic[param.Name] = double.Parse(param.Value);
- }
-
- // tool.InputTupleDic["fCricularity"] = 200;
-
- tool.InputImageDic["INPUT_Image"] = hImage;
-
-
- if (!tool.RunProcedure(out string errorMsg, out _))
- {
- // detectResult.PreTreatedFlag = false;
-
- detectResult.IsPreTreatDone = false;
-
-
- return;
- }
-
- var preTreatRet = tool.GetResultTuple("OUTPUT_Flag").I;
-
- //var fRCricularity = tool.GetResultTuple("fRCricularity");
-
-
- // detectResult.IsPreTreatDone = detectResult.VisionImageSet.PreTreatedFlag = preTreatRet == 1;
- //detectResult.IsPreTreatDone = detectResult.VisionImageSet.PreTreatedFlag = true;
- // detectResult.VisionImageSet.PreTreatedTime = DateTime.Now;
-
- for (int i = 0; i < detectConfig.OUTPreTreatParams.Count; i++)
- {
- var param = detectConfig.OUTPreTreatParams[i];
- tool.InputTupleDic[param.Name] = double.Parse(param.Value);
- }
-
-
-
-
- // 2023/10/16 新增预处理结果反馈,如果预处理结果为NG,直接返回
- if (preTreatRet != 0)
- {
- detectResult.ResultState = ResultState.DetectNG;
-
- detectResult.IsPreTreatNG = true;
-
-
-
- // if (detectResult.VisionImageSet.PreTreatedFlag)
- {
- //detectResult.VisionImageSet.MLImage = tool.GetResultObject("OUTPUT_PreTreatedImage");
- //DetectionResultImage
- // detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
-
- }
-
- }
- else
- {
- // detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
-
- }
- }
- }
- catch (Exception ex)
- {
-
- }
- finally
- {
- //detectResult.VisionImageSet.HImage?.Dispose();
- //detectResult.VisionImageSet.HImage = null;
- // MhImage?.Dispose();
- //MhImage = null;
- }
-
- }
- ///
/// 相机回调
///
///
///
///
- //private void OnCameraHImageOutput(DateTime dt, CameraBase camera, Mat imageSet)
- //{
-
- // //if (camera.CameraName.Equals("cam1", StringComparison.OrdinalIgnoreCase))
- // //{
- // // Console.WriteLine();
- // //}
- // //if (camera.CameraName.Equals("cam2", StringComparison.OrdinalIgnoreCase))
- // //{
- // // Console.WriteLine();
- // //}
-
- // // 获取该相机的拍照计数
- // uint productNumber = (uint)camera.SnapshotCount;
-
- // Task.Run(async () =>
- // {
- // using (Mat localImageSet = imageSet.Clone()) // 复制 Mat 避免并发问题
- // {
- // // imageSet?.Dispose();
- // // 拍照计数与物件编号一致,查找对应的产品
- // ProductData product = null;
- // //内外壁模组多个相机的处理方法
- // //计算队列的方法不变
- // int index = PieceNumberToIndex(productNumber);
- // // 找到产品存放在哪个队列里
- // ConcurrentDictionary tmpDic = _productLists[index];
-
- // try
- // {
- // int retryTimes = 100;
- // while (product == null && retryTimes > 0)
- // {
- // if (tmpDic.ContainsKey(productNumber))
- // {
- // product = tmpDic[productNumber];
- // }
- // else
- // {
- // // Thread.Sleep(20);
- // await Task.Delay(20);
- // }
- // retryTimes--;
- // }
- // // 如果产品为空,则销毁图片,提示错误
- // if (null == product)
- // {
- // List pnList = tmpDic.Keys.ToList();
-
- // string pnStr = "";
- // if (pnList != null && pnList.Count > 0)
- // {
- // pnStr = string.Join(",", pnList);
- // }
-
- // //LogAsync(DateTime.Now, LogLevel.Error, $"{camera.Name} 未找到产品,编号:{productNumber},队列{index}数量:{tmpDic.Count},列表:{pnStr}");
- // localImageSet.Dispose();
- // this.BeginInvoke(new MethodInvoker(delegate ()
- // {
-
- // int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
-
- // richTextBox1.AppendText(productNumber + "提前推出" + camera.CameraName);
-
- // // 设置回原来的滚动位置
- // richTextBox1.SelectionStart = richTextBox1.TextLength;
- // richTextBox1.ScrollToCaret();
- // }));
- // //重新生成实例 销毁之前的实例
-
- // using (StreamWriter sw = new StreamWriter("D://123log.txt", true, Encoding.UTF8))
- // {
- // sw.WriteLine(productNumber + "提前推出" + camera.CameraName);
- // }
- // return;
- // }
-
- // // LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 找到产品{productNumber},队列{index}数量:{tmpDic.Count}");
-
- // if (!_cameraRelatedDetectionDict.ContainsKey(camera.CameraName))
- // {
-
- // localImageSet.Dispose();
- // this.BeginInvoke(new MethodInvoker(delegate ()
- // {
-
- // int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
-
- // richTextBox1.AppendText(productNumber + "提前推出" + camera.CameraName);
-
- // // 设置回原来的滚动位置
- // richTextBox1.SelectionStart = richTextBox1.TextLength;
- // richTextBox1.ScrollToCaret();
- // }));
- // //重新生成实例 销毁之前的实例
-
- // using (StreamWriter sw = new StreamWriter("D://123log.txt", true, Encoding.UTF8))
- // {
- // sw.WriteLine(productNumber + "提前推出" + camera.CameraName);
- // }
- // // LogAsync(DateTime.Now, LogLevel.Warning, $"{camera.Name} 找到产品{productNumber},但是没有推理1");
-
- // return;
- // }
-
-
- // double totalTime = 0.0;
- // List resultStates = new List();
- // List? detectionDict = _cameraRelatedDetectionDict[camera.CameraName];
-
-
- // for (int i = 0; i < detectionDict.Count; i++)
- // {
- // string detectionId = detectionDict[i];
-
- // DetectionConfig detectConfig = null;
- // //找到对应的配置
- // if (!string.IsNullOrWhiteSpace(detectionId))
- // {
- // detectConfig = DetectionConfigs.FirstOrDefault(u => u.Id == detectionId);
- // }
- // else
- // {
- // detectConfig = DetectionConfigs.FirstOrDefault(u => u.CameraSourceId == camera.CameraName);
- // }
+ private void OnCameraHImageOutput(DateTime dt, CameraBase camera, Mat imageSet)
+ {
+
+ //if (camera.CameraName.Equals("cam1", StringComparison.OrdinalIgnoreCase))
+ //{
+ // Console.WriteLine();
+ //}
+ //if (camera.CameraName.Equals("cam2", StringComparison.OrdinalIgnoreCase))
+ //{
+ // Console.WriteLine();
+ //}
+
+ // 获取该相机的拍照计数
+ uint productNumber = (uint)camera.SnapshotCount;
+
+ Task.Run(async () =>
+ {
+ using (Mat localImageSet = imageSet.Clone()) // 复制 Mat 避免并发问题
+ {
+ // imageSet?.Dispose();
+ // 拍照计数与物件编号一致,查找对应的产品
+ ProductData product = null;
+ //内外壁模组多个相机的处理方法
+ //计算队列的方法不变
+ int index = PieceNumberToIndex(productNumber);
+ // 找到产品存放在哪个队列里
+ ConcurrentDictionary tmpDic = _productLists[index];
+
+ try
+ {
+ int retryTimes = 100;
+ while (product == null && retryTimes > 0)
+ {
+ if (tmpDic.ContainsKey(productNumber))
+ {
+ product = tmpDic[productNumber];
+ }
+ else
+ {
+ // Thread.Sleep(20);
+ await Task.Delay(20);
+ }
+ retryTimes--;
+ }
+ // 如果产品为空,则销毁图片,提示错误
+ if (null == product)
+ {
+ List pnList = tmpDic.Keys.ToList();
+
+ string pnStr = "";
+ if (pnList != null && pnList.Count > 0)
+ {
+ pnStr = string.Join(",", pnList);
+ }
+
+ //LogAsync(DateTime.Now, LogLevel.Error, $"{camera.Name} 未找到产品,编号:{productNumber},队列{index}数量:{tmpDic.Count},列表:{pnStr}");
+ localImageSet.Dispose();
+ this.BeginInvoke(new MethodInvoker(delegate ()
+ {
+
+ int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
+
+ richTextBox1.AppendText(productNumber + "提前推出" + camera.CameraName);
+
+ // 设置回原来的滚动位置
+ richTextBox1.SelectionStart = richTextBox1.TextLength;
+ richTextBox1.ScrollToCaret();
+ }));
+ //重新生成实例 销毁之前的实例
- // if (detectConfig == null)
- // {
+ using (StreamWriter sw = new StreamWriter("D://123log.txt", true, Encoding.UTF8))
+ {
+ sw.WriteLine(productNumber + "提前推出" + camera.CameraName);
+ }
+ return;
+ }
- // //未能获得检测配置
- // return;
- // }
+ // LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 找到产品{productNumber},队列{index}数量:{tmpDic.Count}");
- // // 1. 预处理
- // using (Mat inferenceImage = localImageSet.Clone()) // 仅在此处克隆,确保推理过程中 Mat 有独立副本
- // {
- // DetectStationResult detectResult = new DetectStationResult();
- // #region 1.预处理
+ if (!_cameraRelatedDetectionDict.ContainsKey(camera.CameraName))
+ {
- // using (Mat PreTMat = inferenceImage.Clone())
- // {
- // PreTreated(detectConfig, detectResult, PreTMat);
- // }
+ localImageSet.Dispose();
+ this.BeginInvoke(new MethodInvoker(delegate ()
+ {
+
+ int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
+
+ richTextBox1.AppendText(productNumber + "提前推出" + camera.CameraName);
+
+ // 设置回原来的滚动位置
+ richTextBox1.SelectionStart = richTextBox1.TextLength;
+ richTextBox1.ScrollToCaret();
+ }));
+ //重新生成实例 销毁之前的实例
+
+ using (StreamWriter sw = new StreamWriter("D://123log.txt", true, Encoding.UTF8))
+ {
+ sw.WriteLine(productNumber + "提前推出" + camera.CameraName);
+ }
+ // LogAsync(DateTime.Now, LogLevel.Warning, $"{camera.Name} 找到产品{productNumber},但是没有推理1");
+
+ return;
+ }
+
+
+ double totalTime = 0.0;
+ List resultStates = new List();
+ List? detectionDict = _cameraRelatedDetectionDict[camera.CameraName];
+
+
+ for (int i = 0; i < detectionDict.Count; i++)
+ {
+ string detectionId = detectionDict[i];
+
+
+
+
+
+ // 1. 预处理
+ using (Mat inferenceImage = localImageSet.Clone()) // 仅在此处克隆,确保推理过程中 Mat 有独立副本
+ {
+ DetectStationResult temp1=_visionEngine.RunInference(inferenceImage, detectionId);
+
+ resultStates.Add(temp1.ResultState);
+
+ product.ResultCollection.Add(temp1);
+
+
+ }
+
+
+ }
+
+ product.InferenceOne();
+
+ // LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 推理完成,产品{productNumber}");
+
+ if (!product.InferenceFinished())
+ {
+ return;
+ }
+ ProductNum_Total++;
+ CalculateOEE();
+ this.BeginInvoke(new MethodInvoker(delegate ()
+ {
+ int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
- // #endregion
- // if (detectResult.IsPreTreatNG)
- // {
- // detectResult.ResultState = ResultState.DetectNG;
- // detectResult.IsPreTreatDone = true;
- // detectResult.IsMLDetectDone = false;
+ richTextBox1.AppendText($"统计结果成功,{productNumber} 吹气!\n");
- // }
+ // 设置回原来的滚动位置
+ richTextBox1.SelectionStart = richTextBox1.TextLength;
+ richTextBox1.ScrollToCaret();
+ }));
+ #region 6. 统计产品结果
+ product.ProductResult = product.ResultCollection.Any(u => u.ResultState != ResultState.OK)
+ ? ResultState.B_NG
+ : ResultState.OK;
+ product.ProductLabelCategory = product.ProductResult.GetEnumDescription();
+ product.ProductLabel = product.ProductResult.GetEnumDescription();
+ #endregion
+ #region 7.产品吹气
+ #endregion
- // if (!string.IsNullOrWhiteSpace(detectConfig.ModelPath) && detectConfig.IsEnabled)
- // {
- // SimboStationMLEngineSet mlSet = null;
- // mlSet = SimboStationMLEngineList.FirstOrDefault(t => t.DetectionId == detectConfig.Id);
- // if (mlSet == null)
- // {
- // // LogAsync(DateTime.Now, LogLevel.Exception, $"异常:{detectConfig.Name}未能获取对应配置的模型检测工具");
- // detectResult.IsMLDetectDone = false;
- // //HandleDetectDone(detectResult, detectConfig);
- // return;
- // }
+ // 出列
+ ProductData temp = null;
- // #region 2.深度学习推理
- // //LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} 模型检测执行");
+ int tryTimes = 10;
+ while (temp == null && tryTimes > 0)
+ {
+ if (tmpDic.TryRemove(productNumber, out temp))
+ {
+ break;
+ }
- // if (!string.IsNullOrWhiteSpace(detectConfig.ModelPath))
- // {
- // Stopwatch mlWatch = new Stopwatch();
- // var req = new MLRequest();
- // //之前的检测图片都是相机存储成HImage
+ tryTimes--;
+ Thread.Sleep(5);
+ }
+ if (temp == null)
+ {
+ string logStr = $"{DateTime.Now}产品{productNumber}出列失败:true," +
+ $"当前队列产品数量:{tmpDic.Count}";
+ this.BeginInvoke(new MethodInvoker(delegate ()
+ {
+ int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
- // req.ResizeWidth = (int)detectConfig.ModelWidth;
- // req.ResizeHeight = (int)detectConfig.ModelHeight;
- // // req.LabelNames = detectConfig.GetLabelNames();
- // // req.Score = IIConfig.Score;
- // req.mImage = inferenceImage.Clone();
+ richTextBox1.AppendText(logStr);
- // req.in_lable_path = detectConfig.in_lable_path;
+ // 设置回原来的滚动位置
+ richTextBox1.SelectionStart = richTextBox1.TextLength;
+ richTextBox1.ScrollToCaret();
+ }));
+ }
+ else
+ {
+ try
+ {
+ string logStr = $"{DateTime.Now}产品{productNumber}出列成功:true," +
+ $"产品结果:{temp.ProductResult.GetEnumDescription()}," +
+ $"当前队列产品数量:{tmpDic.Count}";
+ this.BeginInvoke(new MethodInvoker(delegate ()
+ {
- // req.confThreshold = detectConfig.ModelconfThreshold;
- // req.iouThreshold = 0.3f;
- // req.segmentWidth = 320;
- // req.out_node_name = "output0";
- // switch (detectConfig.ModelType)
- // {
- // case MLModelType.ImageClassification:
- // break;
- // case MLModelType.ObjectDetection:
+ int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
- // break;
- // case MLModelType.SemanticSegmentation:
- // break;
- // case MLModelType.InstanceSegmentation:
- // break;
- // case MLModelType.ObjectGPUDetection:
-
- // break;
- // default:
- // break;
- // }
+ richTextBox1.AppendText(logStr);
- // // LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} RunInference BEGIN");
- // mlWatch.Start();
- // //20230802改成多线程推理 RunInferenceFixed
-
- // var result = mlSet.StationMLEngine.RunInference(req);
- // // var result = mlSet.StationMLEngine.RunInferenceFixed(req);
- // mlWatch.Stop();
- // // LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} RunInference END");
+ // 设置回原来的滚动位置
+ richTextBox1.SelectionStart = richTextBox1.TextLength;
+ richTextBox1.ScrollToCaret();
+ }));
+ //重新生成实例 销毁之前的实例
+ var saveData = temp.GetProductData();
+ using (StreamWriter sw = new StreamWriter("D://123log.txt", true, Encoding.UTF8))
+ {
+ sw.WriteLine(logStr);
+ }
-
-
-
-
-
- // // var req = new MLRequest();
-
- // //req.mImage = inferenceImage;
-
- // //req.ResizeWidth = detectConfig.ModelWidth;
- // //req.ResizeHeight = detectConfig.ModelHeight;
- // //req.confThreshold = detectConfig.ModelconfThreshold;
- // //req.iouThreshold = 0.3f;
- // //req.out_node_name = "output0";
- // //req.in_lable_path = detectConfig.in_lable_path;
-
- // //Stopwatch sw = Stopwatch.StartNew();
- // //var result = Dectection[detectionId].RunInference(req);
- // //sw.Stop();
- // //LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 推理进度1.1,产品{productNumber},耗时{sw.ElapsedMilliseconds}ms");
-
- // this.BeginInvoke(new MethodInvoker(delegate ()
- // {
- // // pictureBox1.Image?.Dispose(); // 释放旧图像
- // // pictureBox1.Image = result.ResultMap;
- // richTextBox1.AppendText($"推理成功 {productNumber}, {result.IsSuccess}相机名字{camera.CameraName} 耗时 {mlWatch.ElapsedMilliseconds}ms\n");
- // }));
- // req.mImage?.Dispose();
-
-
-
-
- // if (result == null || (result != null && !result.IsSuccess))
- // {
- // detectResult.IsMLDetectDone = false;
- // }
- // if (result != null && result.IsSuccess)
- // {
- // detectResult.DetectDetails = result.ResultDetails;
- // if (detectResult.DetectDetails != null)
- // {
- // }
- // else
- // {
- // detectResult.IsMLDetectDone = false;
- // }
- // }
- // }
- // #endregion
-
-
-
- // #region 3.后处理
- // #endregion
- // //根据那些得分大于阈值的推理结果,判断产品是否成功
- // #region 4.最终过滤(逻辑过滤)
- // detectResult.DetectDetails?.ForEach(d =>
- // {
-
-
- // //当前检测项的 过滤条件
- // //var conditionList = detectConfig.DetectionFilterList
- // // .Where(u => u.IsEnabled && u.LabelName == d.LabelName)
- // // .GroupBy(u => u.ResultState)
- // // .OrderBy(u => u.Key)
- // // .ToList();
- // //当前检测项的 过滤条件
- // var conditionList = detectConfig.DetectionFilterList
- // .Where(u => u.IsEnabled && u.LabelName == d.LabelName)
- // .GroupBy(u => u.ResultState)
- // .OrderBy(u => u.Key)
- // .ToList();
-
- // if (conditionList.Count == 0)
- // {
-
- // d.FinalResult = d.LabelName.ToLower() == "ok"
- // ? ResultState.OK
- // : ResultState.DetectNG;
- // }
- // else
- // {
- // d.FinalResult = detectConfig.IsMixModel
- // ? ResultState.A_NG
- // : ResultState.OK;
-
-
- // }
-
-
- // foreach (IGrouping group in conditionList)
- // {
- // //bool b = group.ToList().Any(f =>
- // //{
- // // return f.FilterOperation(d);
- // //});
-
-
- // //if (b)
- // //{
- // // d.FinalResult = group.Key;
- // // break;
- // //}
-
- // if (group.Any(f => f.FilterOperation(d)))
- // {
- // d.FinalResult = group.Key;
- // break;
- // }
- // //else
- // //{
- // // d.FinalResult = d.InferenceResult = ResultState.OK;
- // //}
- // }
- // });
- // #endregion
- // #region 5.统计缺陷过滤结果或预处理直接NG
- // //if (detectResult.DetectDetails?.Count > 0)
- // //{
- // // detectResult.ResultState = detectResult.DetectDetails.GroupBy(u => u.FinalResult).OrderBy(u => u.Key).First().First().FinalResult;
- // // detectResult.ResultLabel = detectResult.ResultLabel;
- // // detectResult.ResultLabelCategoryId = detectResult.ResultLabel;//TODO:设置优先级
-
-
- // //}
- // detectResult.ResultState = detectResult.DetectDetails?
- // .GroupBy(u => u.FinalResult)
- // .OrderBy(u => u.Key)
- // .FirstOrDefault()?.Key ?? ResultState.OK;
- // detectResult.ResultLabel = detectResult.ResultLabel;
- // detectResult.ResultLabelCategoryId = detectResult.ResultLabel;//TODO:设置优先级
- // #endregion
-
- // resultStates.Add(detectResult.ResultState);
-
- // product.ResultCollection.Add(detectResult);
-
-
-
-
-
-
- // }
-
-
- // }
-
-
- // }
-
- // product.InferenceOne();
-
- // // LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 推理完成,产品{productNumber}");
-
- // if (!product.InferenceFinished())
- // {
-
- // return;
- // }
- // ProductNum_Total++;
- // CalculateOEE();
- // this.BeginInvoke(new MethodInvoker(delegate ()
- // {
-
- // int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
-
- // richTextBox1.AppendText($"统计结果成功,{productNumber} 吹气!\n");
-
- // // 设置回原来的滚动位置
- // richTextBox1.SelectionStart = richTextBox1.TextLength;
- // richTextBox1.ScrollToCaret();
- // }));
- // #region 6. 统计产品结果
- // product.ProductResult = product.ResultCollection.Any(u => u.ResultState != ResultState.OK)
- // ? ResultState.B_NG
- // : ResultState.OK;
- // product.ProductLabelCategory = product.ProductResult.GetEnumDescription();
- // product.ProductLabel = product.ProductResult.GetEnumDescription();
- // #endregion
- // #region 7.产品吹气
-
- // #endregion
-
-
-
-
-
- // // 出列
- // ProductData temp = null;
-
- // int tryTimes = 10;
- // while (temp == null && tryTimes > 0)
- // {
- // if (tmpDic.TryRemove(productNumber, out temp))
- // {
- // break;
- // }
-
- // tryTimes--;
- // Thread.Sleep(5);
- // }
- // if (temp == null)
- // {
- // string logStr = $"{DateTime.Now}产品{productNumber}出列失败:true," +
- // $"当前队列产品数量:{tmpDic.Count}";
- // this.BeginInvoke(new MethodInvoker(delegate ()
- // {
-
- // int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
-
- // richTextBox1.AppendText(logStr);
-
- // // 设置回原来的滚动位置
- // richTextBox1.SelectionStart = richTextBox1.TextLength;
- // richTextBox1.ScrollToCaret();
- // }));
- // }
- // else
- // {
- // try
- // {
- // string logStr = $"{DateTime.Now}产品{productNumber}出列成功:true," +
- // $"产品结果:{temp.ProductResult.GetEnumDescription()}," +
- // $"当前队列产品数量:{tmpDic.Count}";
- // this.BeginInvoke(new MethodInvoker(delegate ()
- // {
-
- // int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
-
- // richTextBox1.AppendText(logStr);
-
- // // 设置回原来的滚动位置
- // richTextBox1.SelectionStart = richTextBox1.TextLength;
- // richTextBox1.ScrollToCaret();
- // }));
- // //重新生成实例 销毁之前的实例
- // var saveData = temp.GetProductData();
- // using (StreamWriter sw = new StreamWriter("D://123log.txt", true, Encoding.UTF8))
- // {
- // sw.WriteLine(logStr);
- // }
-
- // }
- // catch (Exception) { }
- // finally
- // {
- // // temp.Dispose();
- // temp = null;
- // }
- // }
-
- // // UpdateCT((float)(dtNow - _ctTime).TotalSeconds);
- // //_ctTime = dtNow;
- // // });
-
-
- // }
- // catch (Exception ex)
- // {
- // //LogAsync(DateTime.Now, LogLevel.Error, $"流程检测未捕获的异常:{ex.GetExceptionMessage()}");
- // product?.Dispose();
- // }
- // }
-
- // });
- //}
+ }
+ catch (Exception) { }
+ finally
+ {
+ // temp.Dispose();
+ temp = null;
+ }
+ }
+
+ // UpdateCT((float)(dtNow - _ctTime).TotalSeconds);
+ //_ctTime = dtNow;
+ // });
+
+
+ }
+ catch (Exception ex)
+ {
+ //LogAsync(DateTime.Now, LogLevel.Error, $"流程检测未捕获的异常:{ex.GetExceptionMessage()}");
+ product?.Dispose();
+ }
+ }
+
+ });
+ }
public void SetResult()
diff --git a/DHSoftware/MainWindow.resx b/DHSoftware/MainWindow.resx
index 3511979..1e30dff 100644
--- a/DHSoftware/MainWindow.resx
+++ b/DHSoftware/MainWindow.resx
@@ -1,7 +1,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 44, 19
+
+
\ No newline at end of file
diff --git a/DHSoftware/Views/CtrlVisionRunBase.Designer.cs b/DHSoftware/Views/CtrlVisionRunBase.Designer.cs
new file mode 100644
index 0000000..409aba4
--- /dev/null
+++ b/DHSoftware/Views/CtrlVisionRunBase.Designer.cs
@@ -0,0 +1,174 @@
+
+namespace XKRS.UI.Device.Winform
+{
+ partial class CtrlVisionRunBase
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.tableDisplay = new System.Windows.Forms.TableLayoutPanel();
+ this.tlpOpConfig = new System.Windows.Forms.TableLayoutPanel();
+ this.propOpConfig = new System.Windows.Forms.PropertyGrid();
+ this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
+ this.btnExecuteOpConfig = new System.Windows.Forms.Button();
+ this.btnBatchRun = new System.Windows.Forms.Button();
+ this.splitCMain = new System.Windows.Forms.SplitContainer();
+ this.tlpOpConfig.SuspendLayout();
+ this.flowLayoutPanel1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.splitCMain)).BeginInit();
+ this.splitCMain.Panel1.SuspendLayout();
+ this.splitCMain.Panel2.SuspendLayout();
+ this.splitCMain.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // tableDisplay
+ //
+ this.tableDisplay.ColumnCount = 2;
+ this.tableDisplay.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ this.tableDisplay.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ this.tableDisplay.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableDisplay.Location = new System.Drawing.Point(0, 0);
+ this.tableDisplay.Name = "tableDisplay";
+ this.tableDisplay.RowCount = 2;
+ this.tableDisplay.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ this.tableDisplay.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ this.tableDisplay.Size = new System.Drawing.Size(769, 251);
+ this.tableDisplay.TabIndex = 0;
+ //
+ // tlpOpConfig
+ //
+ this.tlpOpConfig.ColumnCount = 1;
+ this.tlpOpConfig.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.tlpOpConfig.Controls.Add(this.propOpConfig, 0, 1);
+ this.tlpOpConfig.Controls.Add(this.flowLayoutPanel1, 0, 0);
+ this.tlpOpConfig.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tlpOpConfig.Location = new System.Drawing.Point(0, 0);
+ this.tlpOpConfig.Name = "tlpOpConfig";
+ this.tlpOpConfig.RowCount = 2;
+ this.tlpOpConfig.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 35F));
+ this.tlpOpConfig.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.tlpOpConfig.Size = new System.Drawing.Size(769, 247);
+ this.tlpOpConfig.TabIndex = 0;
+ //
+ // propOpConfig
+ //
+ this.propOpConfig.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.propOpConfig.Location = new System.Drawing.Point(3, 38);
+ this.propOpConfig.Name = "propOpConfig";
+ this.propOpConfig.Size = new System.Drawing.Size(763, 206);
+ this.propOpConfig.TabIndex = 1;
+ this.propOpConfig.ToolbarVisible = false;
+ //
+ // flowLayoutPanel1
+ //
+ this.flowLayoutPanel1.Controls.Add(this.btnExecuteOpConfig);
+ this.flowLayoutPanel1.Controls.Add(this.btnBatchRun);
+ this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;
+ this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+ this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
+ this.flowLayoutPanel1.Name = "flowLayoutPanel1";
+ this.flowLayoutPanel1.Size = new System.Drawing.Size(769, 35);
+ this.flowLayoutPanel1.TabIndex = 2;
+ //
+ // btnExecuteOpConfig
+ //
+ this.btnExecuteOpConfig.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnExecuteOpConfig.BackColor = System.Drawing.SystemColors.GradientActiveCaption;
+ this.btnExecuteOpConfig.Cursor = System.Windows.Forms.Cursors.Hand;
+ this.btnExecuteOpConfig.Font = new System.Drawing.Font("微软雅黑", 12F);
+ this.btnExecuteOpConfig.Location = new System.Drawing.Point(598, 3);
+ this.btnExecuteOpConfig.Margin = new System.Windows.Forms.Padding(5, 3, 5, 3);
+ this.btnExecuteOpConfig.MinimumSize = new System.Drawing.Size(1, 1);
+ this.btnExecuteOpConfig.Name = "btnExecuteOpConfig";
+ this.btnExecuteOpConfig.Size = new System.Drawing.Size(166, 30);
+ this.btnExecuteOpConfig.TabIndex = 0;
+ this.btnExecuteOpConfig.Text = "执行当前配置操作";
+ this.btnExecuteOpConfig.UseVisualStyleBackColor = false;
+ // this.btnExecuteOpConfig.Click += new System.EventHandler(this.btnExecuteOpConfig_Click);
+ //
+ // btnBatchRun
+ //
+ this.btnBatchRun.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnBatchRun.BackColor = System.Drawing.SystemColors.Info;
+ this.btnBatchRun.Cursor = System.Windows.Forms.Cursors.Hand;
+ this.btnBatchRun.Font = new System.Drawing.Font("微软雅黑", 12F);
+ this.btnBatchRun.Location = new System.Drawing.Point(488, 3);
+ this.btnBatchRun.Margin = new System.Windows.Forms.Padding(5, 3, 5, 3);
+ this.btnBatchRun.MinimumSize = new System.Drawing.Size(1, 1);
+ this.btnBatchRun.Name = "btnBatchRun";
+ this.btnBatchRun.Size = new System.Drawing.Size(100, 30);
+ this.btnBatchRun.TabIndex = 0;
+ this.btnBatchRun.Text = "批量检测";
+ this.btnBatchRun.UseVisualStyleBackColor = false;
+ // this.btnBatchRun.Click += new System.EventHandler(this.btnBatchRun_Click);
+ //
+ // splitCMain
+ //
+ this.splitCMain.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitCMain.Location = new System.Drawing.Point(0, 0);
+ this.splitCMain.Name = "splitCMain";
+ this.splitCMain.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ //
+ // splitCMain.Panel1
+ //
+ this.splitCMain.Panel1.Controls.Add(this.tableDisplay);
+ //
+ // splitCMain.Panel2
+ //
+ this.splitCMain.Panel2.Controls.Add(this.tlpOpConfig);
+ this.splitCMain.Size = new System.Drawing.Size(769, 502);
+ this.splitCMain.SplitterDistance = 251;
+ this.splitCMain.TabIndex = 2;
+ //
+ // CtrlVisionRunBase
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.splitCMain);
+ this.Name = "CtrlVisionRunBase";
+ this.Size = new System.Drawing.Size(769, 502);
+ this.tlpOpConfig.ResumeLayout(false);
+ this.flowLayoutPanel1.ResumeLayout(false);
+ this.splitCMain.Panel1.ResumeLayout(false);
+ this.splitCMain.Panel2.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.splitCMain)).EndInit();
+ this.splitCMain.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TableLayoutPanel tableDisplay;
+ private System.Windows.Forms.TableLayoutPanel tlpOpConfig;
+ private System.Windows.Forms.Button btnExecuteOpConfig;
+ private System.Windows.Forms.PropertyGrid propOpConfig;
+ private System.Windows.Forms.SplitContainer splitCMain;
+ private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
+ private System.Windows.Forms.Button btnBatchRun;
+ }
+}
diff --git a/DHSoftware/Views/CtrlVisionRunBase.cs b/DHSoftware/Views/CtrlVisionRunBase.cs
new file mode 100644
index 0000000..f762271
--- /dev/null
+++ b/DHSoftware/Views/CtrlVisionRunBase.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+using System.IO;
+using DH.Commons.Enums;
+using DH.Devices.Devices;
+
+
+namespace XKRS.UI.Device.Winform
+{
+ public partial class CtrlVisionRunBase : UserControl
+ {
+
+ private DateTime LastDisplayTime = DateTime.MinValue;
+
+
+ //public CtrlVisionRunBase()
+ //{
+ // InitializeComponent();
+ //}
+
+ //private object OnUpdateBatchNO(ISubscriber arg1, object arg2, object arg3)
+ //{
+ // //获取BatchNO
+ // if (arg2 is string batchNo)
+ // {
+ // ML.BatchNO = string.IsNullOrEmpty(batchNo) ? "OFFline_" + DateTime.Now.ToString("yyyyMMdd") : batchNo;
+ // }
+ // return null;
+ //}
+
+ public CtrlVisionRunBase(VisionEngineBase device)
+ {
+ InitializeComponent();
+
+ Device = device;
+ InitialLayout();
+
+ this.Load += (s, e) =>
+ {
+ ML.OnDetectionDone -= ML_OnDetectionDone;
+ ML.OnDetectionDone += ML_OnDetectionDone;
+ };
+
+ // PubSubCenter.GetInstance().RemoveSubscribers(PubSubCenterMessageType.UpdateBatchNO.ToString());
+ // PubSubCenter.GetInstance().Subscribe(PubSubCenterMessageType.UpdateBatchNO.ToString(), OnUpdateBatchNO);
+ }
+
+
+
+
+ private async void ML_OnDetectionDone(string detectionId, Bitmap image, List detectionResults)
+ {
+
+ await Task.Run(() =>
+ {
+ if (!this.IsHandleCreated)
+ return;
+
+ this.Invoke(new Action(() =>
+ {
+ if (this.IsDisposed)
+ return;
+ var display = displayList.FirstOrDefault(u => u.DetectionId == detectionId);
+ if (display != null)
+ {
+ display.RefreshDetectionResult(image, detectionResults);
+ }
+ }));
+ });
+ }
+
+ public VisionEngineBase Device { get; set; }
+
+ protected VisionEngineBase ML
+ {
+ get => Device as VisionEngineBase;
+ }
+
+ //VisionEngineInitialConfigBase IConfig => ML?.InitialConfig as VisionEngineInitialConfigBase;
+
+ //VisionEngineOperationConfigBase OpConfig = new VisionEngineOperationConfigBase();
+
+ //private void btnExecuteOpConfig_Click(object sender, EventArgs e)
+ //{
+ // try
+ // {
+ // PubSubCenter.GetInstance().Publish(PubSubCenterMessageType.RequestBatchNO.ToString(), null, null);
+ // var msg = ML.RunWrap(OpConfig);
+
+ // if (msg.Result != 1)
+ // {
+ // MessageBox.Show(msg.Message);
+ // }
+ // }
+ // catch (Exception ex)
+ // {
+ // MessageBox.Show(ex.GetExceptionMessage());
+ // }
+ //}
+
+ #region Layout
+ int rows = 1;
+ int cols = 1;
+
+ public int Rows
+ {
+ get => rows;
+ set
+ {
+ if (value <= 1)
+ {
+ rows = 1;
+ }
+ else
+ {
+ rows = value;
+ }
+ }
+ }
+
+ public int Cols
+ {
+ get => cols;
+ set
+ {
+ if (value <= 1)
+ {
+ cols = 1;
+ }
+ else
+ {
+ cols = value;
+ }
+ }
+ }
+
+ List displayList = null;
+
+ private void InitialLayout()
+ {
+ if (ML.DetectionConfigs.Count == 0)
+ {
+ return;
+ }
+
+ var locations = ML.DetectionConfigs.Select(u => u.ShowLocation).ToList();
+
+ if (locations.Count > 0)
+ {
+ Rows = (int)locations.Max(u => u.Y);
+ Cols = (int)locations.Max(u => u.X);
+ }
+
+
+ tableDisplay.ColumnCount = Cols;
+ tableDisplay.RowCount = Rows;
+
+ tableDisplay.ColumnStyles.Clear();
+ for (int i = 0; i < Cols; i++)
+ {
+ ColumnStyle colStyle = new ColumnStyle();
+ colStyle.SizeType = SizeType.Percent;
+ colStyle.Width = 1.0f / (float)Cols;
+
+ tableDisplay.ColumnStyles.Add(colStyle);
+ }
+
+ tableDisplay.RowStyles.Clear();
+ for (int i = 0; i < Rows; i++)
+ {
+ RowStyle rowStyle = new RowStyle();
+ rowStyle.SizeType = SizeType.Percent;
+ rowStyle.Height = 1.0f / (float)Rows;
+
+ tableDisplay.RowStyles.Add(rowStyle);
+ }
+
+ tableDisplay.Controls.Clear();
+ displayList = new List();
+
+ ML.DetectionConfigs.ForEach(d =>
+ {
+ //if (!d.IsShowInUI)
+ // return;
+
+ CtrlVisionDisplay display = new CtrlVisionDisplay();
+ display.DetectionId = d.Id;
+ display.DetectionName = d.Name;
+ display.RowIndex = (int)d.ShowLocation.Y - 1;
+ display.ColIndex = (int)d.ShowLocation.X - 1;
+ //display.RowIndex = (int)count%row;
+ //display.ColIndex = (int)count / row;
+
+ display.Dock = DockStyle.Fill;
+
+ display.OnShowOpConfigMenuStateChanged -= Display_OnShowOpConfigMenuStateChanged;
+ display.OnShowOpConfigMenuStateChanged += Display_OnShowOpConfigMenuStateChanged;
+
+ displayList.Add(display);
+ tableDisplay.Controls.Add(display);
+ tableDisplay.SetCellPosition(display, new TableLayoutPanelCellPosition(display.ColIndex, display.RowIndex));
+ });
+
+ splitCMain.Panel2Collapsed = true;
+
+ // propOpConfig.SelectedObject = OpConfig;
+ }
+
+ private void Display_OnShowOpConfigMenuStateChanged(bool isVisible)
+ {
+ IsShowOpConfig = isVisible;
+ }
+
+ public bool IsShowOpConfig
+ {
+ get => !splitCMain.Panel2Collapsed;
+ set
+ {
+ if (splitCMain.Panel2Collapsed == value)
+ {
+ splitCMain.Panel2Collapsed = !value;
+
+ displayList.ForEach(d => d.IsShowOpConfig = value);
+ }
+ }
+ }
+ #endregion
+
+ //private void btnBatchRun_Click(object sender, EventArgs e)
+ //{
+ // FrmMLBatchRun frmMLBatchRun = new FrmMLBatchRun(Device);
+
+ // frmMLBatchRun.MdiParent = (this.Parent as DeviceRunFrmBase).MdiParent;
+ // frmMLBatchRun.DockPanel = (this.Parent as DeviceRunFrmBase).DockPanel;
+ // frmMLBatchRun.DockState = DockState.Document;
+ // frmMLBatchRun.Text = $"{Device.Name}_批量检测";
+
+ // frmMLBatchRun.Show();
+ //}
+ }
+}
diff --git a/DHSoftware/Views/CtrlVisionRunBase.resx b/DHSoftware/Views/CtrlVisionRunBase.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/DHSoftware/Views/CtrlVisionRunBase.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/DHSoftware/Views/DefectRowEdit.Designer.cs b/DHSoftware/Views/DefectRowEdit.Designer.cs
index e422d73..70f3f22 100644
--- a/DHSoftware/Views/DefectRowEdit.Designer.cs
+++ b/DHSoftware/Views/DefectRowEdit.Designer.cs
@@ -29,6 +29,13 @@
private void InitializeComponent()
{
panel1 = new AntdUI.Panel();
+ select_Result = new AntdUI.Select();
+ label5 = new AntdUI.Label();
+ input_maxArea = new AntdUI.InputNumber();
+ label3 = new AntdUI.Label();
+ input_minArea = new AntdUI.InputNumber();
+ label4 = new AntdUI.Label();
+ input_maxScore = new AntdUI.InputNumber();
label2 = new AntdUI.Label();
input_minScore = new AntdUI.InputNumber();
label1 = new AntdUI.Label();
@@ -38,13 +45,6 @@
stackPanel1 = new AntdUI.StackPanel();
button_cancel = new AntdUI.Button();
button_ok = new AntdUI.Button();
- input_maxScore = new AntdUI.InputNumber();
- input_maxArea = new AntdUI.InputNumber();
- label3 = new AntdUI.Label();
- input_minArea = new AntdUI.InputNumber();
- label4 = new AntdUI.Label();
- label5 = new AntdUI.Label();
- select_Result = new AntdUI.Select();
panel1.SuspendLayout();
stackPanel1.SuspendLayout();
SuspendLayout();
@@ -74,6 +74,87 @@
panel1.TabIndex = 0;
panel1.Text = "panel1";
//
+ // select_Result
+ //
+ select_Result.Dock = DockStyle.Top;
+ select_Result.Location = new Point(18, 408);
+ select_Result.Name = "select_Result";
+ select_Result.Size = new Size(464, 41);
+ select_Result.TabIndex = 27;
+ select_Result.Text = "select1";
+ //
+ // label5
+ //
+ label5.Dock = DockStyle.Top;
+ label5.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+ label5.Location = new Point(18, 384);
+ label5.Name = "label5";
+ label5.Size = new Size(464, 24);
+ label5.TabIndex = 25;
+ label5.Text = "标签结果";
+ //
+ // input_maxArea
+ //
+ input_maxArea.Dock = DockStyle.Top;
+ input_maxArea.Font = new Font("Microsoft YaHei UI", 9F);
+ input_maxArea.Increment = new decimal(new int[] { 10, 0, 0, 0 });
+ input_maxArea.Location = new Point(18, 346);
+ input_maxArea.Maximum = new decimal(new int[] { 999999999, 0, 0, 0 });
+ input_maxArea.Minimum = new decimal(new int[] { 0, 0, 0, 0 });
+ input_maxArea.Name = "input_maxArea";
+ input_maxArea.Radius = 3;
+ input_maxArea.Size = new Size(464, 38);
+ input_maxArea.TabIndex = 24;
+ input_maxArea.Text = "0";
+ //
+ // label3
+ //
+ label3.Dock = DockStyle.Top;
+ label3.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+ label3.Location = new Point(18, 322);
+ label3.Name = "label3";
+ label3.Size = new Size(464, 24);
+ label3.TabIndex = 23;
+ label3.Text = "最大面积";
+ //
+ // input_minArea
+ //
+ input_minArea.Dock = DockStyle.Top;
+ input_minArea.Font = new Font("Microsoft YaHei UI", 9F);
+ input_minArea.Increment = new decimal(new int[] { 10, 0, 0, 0 });
+ input_minArea.Location = new Point(18, 284);
+ input_minArea.Maximum = new decimal(new int[] { 999999999, 0, 0, 0 });
+ input_minArea.Minimum = new decimal(new int[] { 0, 0, 0, 0 });
+ input_minArea.Name = "input_minArea";
+ input_minArea.Radius = 3;
+ input_minArea.Size = new Size(464, 38);
+ input_minArea.TabIndex = 22;
+ input_minArea.Text = "0";
+ //
+ // label4
+ //
+ label4.Dock = DockStyle.Top;
+ label4.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+ label4.Location = new Point(18, 260);
+ label4.Name = "label4";
+ label4.Size = new Size(464, 24);
+ label4.TabIndex = 21;
+ label4.Text = "最小面积";
+ //
+ // input_maxScore
+ //
+ input_maxScore.Dock = DockStyle.Top;
+ input_maxScore.Font = new Font("Microsoft YaHei UI", 9F);
+ input_maxScore.Increment = new decimal(new int[] { 1, 0, 0, 65536 });
+ input_maxScore.Location = new Point(18, 222);
+ input_maxScore.Maximum = new decimal(new int[] { 1, 0, 0, 0 });
+ input_maxScore.Minimum = new decimal(new int[] { 0, 0, 0, 0 });
+ input_maxScore.Name = "input_maxScore";
+ input_maxScore.Radius = 3;
+ input_maxScore.Size = new Size(464, 38);
+ input_maxScore.TabIndex = 20;
+ input_maxScore.Text = "0";
+ //
// label2
//
label2.Dock = DockStyle.Top;
@@ -96,7 +177,7 @@
input_minScore.Radius = 3;
input_minScore.Size = new Size(464, 38);
input_minScore.TabIndex = 18;
- input_minScore.Text = "0.3";
+ input_minScore.Text = "0";
//
// label1
//
@@ -169,86 +250,6 @@
button_ok.Text = "Submit";
button_ok.Type = AntdUI.TTypeMini.Primary;
//
- // input_maxScore
- //
- input_maxScore.Dock = DockStyle.Top;
- input_maxScore.Font = new Font("Microsoft YaHei UI", 9F);
- input_maxScore.Increment = new decimal(new int[] { 1, 0, 0, 65536 });
- input_maxScore.Location = new Point(18, 222);
- input_maxScore.Maximum = new decimal(new int[] { 1, 0, 0, 0 });
- input_maxScore.Minimum = new decimal(new int[] { 0, 0, 0, 0 });
- input_maxScore.Name = "input_maxScore";
- input_maxScore.Radius = 3;
- input_maxScore.Size = new Size(464, 38);
- input_maxScore.TabIndex = 20;
- input_maxScore.Text = "0";
- //
- // input_maxArea
- //
- input_maxArea.Dock = DockStyle.Top;
- input_maxArea.Font = new Font("Microsoft YaHei UI", 9F);
- input_maxArea.Increment = new decimal(new int[] { 10, 0, 0, 0 });
- input_maxArea.Location = new Point(18, 346);
- input_maxArea.Maximum = new decimal(new int[] { 999999999, 0, 0, 0 });
- input_maxArea.Minimum = new decimal(new int[] { 0, 0, 0, 0 });
- input_maxArea.Name = "input_maxArea";
- input_maxArea.Radius = 3;
- input_maxArea.Size = new Size(464, 38);
- input_maxArea.TabIndex = 24;
- input_maxArea.Text = "0";
- //
- // label3
- //
- label3.Dock = DockStyle.Top;
- label3.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
- label3.Location = new Point(18, 322);
- label3.Name = "label3";
- label3.Size = new Size(464, 24);
- label3.TabIndex = 23;
- label3.Text = "最大面积";
- //
- // input_minArea
- //
- input_minArea.Dock = DockStyle.Top;
- input_minArea.Font = new Font("Microsoft YaHei UI", 9F);
- input_minArea.Increment = new decimal(new int[] { 10, 0, 0, 0 });
- input_minArea.Location = new Point(18, 284);
- input_minArea.Maximum = new decimal(new int[] { 999999999, 0, 0, 0 });
- input_minArea.Minimum = new decimal(new int[] { 0, 0, 0, 0 });
- input_minArea.Name = "input_minArea";
- input_minArea.Radius = 3;
- input_minArea.Size = new Size(464, 38);
- input_minArea.TabIndex = 22;
- input_minArea.Text = "0";
- //
- // label4
- //
- label4.Dock = DockStyle.Top;
- label4.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
- label4.Location = new Point(18, 260);
- label4.Name = "label4";
- label4.Size = new Size(464, 24);
- label4.TabIndex = 21;
- label4.Text = "最小面积";
- //
- // label5
- //
- label5.Dock = DockStyle.Top;
- label5.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
- label5.Location = new Point(18, 384);
- label5.Name = "label5";
- label5.Size = new Size(464, 24);
- label5.TabIndex = 25;
- label5.Text = "标签结果";
- //
- // select_Result
- //
- select_Result.Location = new Point(21, 414);
- select_Result.Name = "select_Result";
- select_Result.Size = new Size(458, 41);
- select_Result.TabIndex = 27;
- select_Result.Text = "select1";
- //
// DefectRowEdit
//
Controls.Add(panel1);
diff --git a/DHSoftware/Views/DefectRowEdit.cs b/DHSoftware/Views/DefectRowEdit.cs
index 72b885d..b83f6a7 100644
--- a/DHSoftware/Views/DefectRowEdit.cs
+++ b/DHSoftware/Views/DefectRowEdit.cs
@@ -42,7 +42,7 @@ namespace AntdUIDemo.Views.Table
if (String.IsNullOrEmpty(input_name.Text))
{
input_name.Status = AntdUI.TType.Error;
- AntdUI.Message.warn(window, "姓名不能为空!", autoClose: 3);
+ AntdUI.Message.warn(window, "标签不能为空!", autoClose: 3);
return;
}
user.LabelDescription = input_name.Text;
@@ -57,6 +57,9 @@ namespace AntdUIDemo.Views.Table
input_name.Text = user.LabelDescription;
// input_addr.Text = user.Address;
input_minScore.Value =(decimal) user.ScoreMinValue;
+ input_maxScore.Value =(decimal) user.ScoreMaxValue;
+ input_minArea.Value =(decimal) user.ScoreMaxValue;
+ input_maxScore.Value =(decimal) user.ScoreMaxValue;
}
}
}
diff --git a/DHSoftware/Views/DetectConfigControl.Designer.cs b/DHSoftware/Views/DetectConfigControl.Designer.cs
index bcccd74..b0fbaff 100644
--- a/DHSoftware/Views/DetectConfigControl.Designer.cs
+++ b/DHSoftware/Views/DetectConfigControl.Designer.cs
@@ -29,90 +29,211 @@
private void InitializeComponent()
{
panel1 = new Panel();
+ panel3 = new Panel();
+ label6 = new AntdUI.Label();
+ cbxDetectType = new AntdUI.Select();
+ label1 = new AntdUI.Label();
+ tbDetectName = new AntdUI.Input();
+ btnPreOpen = new AntdUI.Button();
+ tbModelpath = new AntdUI.Input();
button3 = new AntdUI.Button();
+ switchEnable = new AntdUI.Switch();
+ label8 = new AntdUI.Label();
+ label10 = new AntdUI.Label();
+ sthPic = new AntdUI.Switch();
+ sthSaveNGPic = new AntdUI.Switch();
+ label7 = new AntdUI.Label();
+ label9 = new AntdUI.Label();
+ swSaveOKPic = new AntdUI.Switch();
panel2 = new Panel();
- label2 = new Label();
+ label2 = new AntdUI.Label();
buttonDEL = new AntdUI.Button();
table_base = new AntdUI.Table();
buttonADD = new AntdUI.Button();
- label10 = new AntdUI.Label();
- sthSaveNGPic = new AntdUI.Switch();
- label9 = new AntdUI.Label();
- swSaveOKPic = new AntdUI.Switch();
- label7 = new AntdUI.Label();
- sthPic = new AntdUI.Switch();
- label8 = new AntdUI.Label();
- switchEnable = new AntdUI.Switch();
- tbDetectName = new TextBox();
- label6 = new AntdUI.Label();
- cbxDetectType = new ComboBox();
- label5 = new AntdUI.Label();
- btnPreOpen = new AntdUI.Button();
- tbModelpath = new TextBox();
- label1 = new AntdUI.Label();
panel1.SuspendLayout();
+ panel3.SuspendLayout();
panel2.SuspendLayout();
SuspendLayout();
//
// panel1
//
panel1.BorderStyle = BorderStyle.FixedSingle;
- panel1.Controls.Add(button3);
+ panel1.Controls.Add(panel3);
panel1.Controls.Add(panel2);
- panel1.Controls.Add(label10);
- panel1.Controls.Add(sthSaveNGPic);
- panel1.Controls.Add(label9);
- panel1.Controls.Add(swSaveOKPic);
- panel1.Controls.Add(label7);
- panel1.Controls.Add(sthPic);
- panel1.Controls.Add(label8);
- panel1.Controls.Add(switchEnable);
- panel1.Controls.Add(tbDetectName);
- panel1.Controls.Add(label6);
- panel1.Controls.Add(cbxDetectType);
- panel1.Controls.Add(label5);
- panel1.Controls.Add(btnPreOpen);
- panel1.Controls.Add(tbModelpath);
- panel1.Controls.Add(label1);
panel1.Dock = DockStyle.Fill;
panel1.Location = new Point(0, 0);
panel1.Name = "panel1";
- panel1.Size = new Size(683, 445);
+ panel1.Size = new Size(600, 445);
panel1.TabIndex = 0;
//
+ // panel3
+ //
+ panel3.Controls.Add(label6);
+ panel3.Controls.Add(cbxDetectType);
+ panel3.Controls.Add(label1);
+ panel3.Controls.Add(tbDetectName);
+ panel3.Controls.Add(btnPreOpen);
+ panel3.Controls.Add(tbModelpath);
+ panel3.Controls.Add(button3);
+ panel3.Controls.Add(switchEnable);
+ panel3.Controls.Add(label8);
+ panel3.Controls.Add(label10);
+ panel3.Controls.Add(sthPic);
+ panel3.Controls.Add(sthSaveNGPic);
+ panel3.Controls.Add(label7);
+ panel3.Controls.Add(label9);
+ panel3.Controls.Add(swSaveOKPic);
+ panel3.Dock = DockStyle.Fill;
+ panel3.Location = new Point(0, 0);
+ panel3.Name = "panel3";
+ panel3.Size = new Size(598, 206);
+ panel3.TabIndex = 41;
+ //
+ // label6
+ //
+ label6.Location = new Point(3, 15);
+ label6.Name = "label6";
+ label6.Size = new Size(58, 23);
+ label6.TabIndex = 25;
+ label6.Text = "检测名称";
+ //
+ // cbxDetectType
+ //
+ cbxDetectType.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+ cbxDetectType.Location = new Point(341, 7);
+ cbxDetectType.Name = "cbxDetectType";
+ cbxDetectType.Size = new Size(226, 31);
+ cbxDetectType.TabIndex = 40;
+ //
+ // label1
+ //
+ label1.Location = new Point(3, 44);
+ label1.Name = "label1";
+ label1.Size = new Size(73, 23);
+ label1.TabIndex = 9;
+ label1.Text = "模型路径";
+ //
+ // tbDetectName
+ //
+ tbDetectName.Location = new Point(82, 7);
+ tbDetectName.Name = "tbDetectName";
+ tbDetectName.Size = new Size(249, 31);
+ tbDetectName.TabIndex = 39;
+ //
+ // btnPreOpen
+ //
+ btnPreOpen.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+ btnPreOpen.Location = new Point(507, 36);
+ btnPreOpen.MinimumSize = new Size(20, 0);
+ btnPreOpen.Name = "btnPreOpen";
+ btnPreOpen.Size = new Size(60, 31);
+ btnPreOpen.TabIndex = 22;
+ btnPreOpen.Text = "...";
+ //
+ // tbModelpath
+ //
+ tbModelpath.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
+ tbModelpath.Location = new Point(82, 36);
+ tbModelpath.Name = "tbModelpath";
+ tbModelpath.Size = new Size(415, 31);
+ tbModelpath.TabIndex = 38;
+ //
// button3
//
- button3.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
- button3.Location = new Point(538, 70);
+ button3.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+ button3.Location = new Point(385, 73);
button3.Name = "button3";
- button3.Size = new Size(115, 34);
+ button3.Size = new Size(182, 34);
button3.TabIndex = 37;
button3.Text = "查看文件夹";
//
+ // switchEnable
+ //
+ switchEnable.Location = new Point(82, 84);
+ switchEnable.Name = "switchEnable";
+ switchEnable.Size = new Size(60, 23);
+ switchEnable.TabIndex = 27;
+ switchEnable.Text = "switch1";
+ //
+ // label8
+ //
+ label8.Location = new Point(3, 84);
+ label8.Name = "label8";
+ label8.Size = new Size(58, 23);
+ label8.TabIndex = 28;
+ label8.Text = "模型启用";
+ //
+ // label10
+ //
+ label10.Location = new Point(176, 113);
+ label10.Name = "label10";
+ label10.Size = new Size(73, 23);
+ label10.TabIndex = 34;
+ label10.Text = "保存NG原图";
+ //
+ // sthPic
+ //
+ sthPic.Location = new Point(263, 84);
+ sthPic.Name = "sthPic";
+ sthPic.Size = new Size(60, 23);
+ sthPic.TabIndex = 29;
+ sthPic.Text = "switch2";
+ //
+ // sthSaveNGPic
+ //
+ sthSaveNGPic.Location = new Point(263, 113);
+ sthSaveNGPic.Name = "sthSaveNGPic";
+ sthSaveNGPic.Size = new Size(60, 23);
+ sthSaveNGPic.TabIndex = 33;
+ sthSaveNGPic.Text = "switch4";
+ //
+ // label7
+ //
+ label7.Location = new Point(184, 84);
+ label7.Name = "label7";
+ label7.Size = new Size(58, 23);
+ label7.TabIndex = 30;
+ label7.Text = "数据保存";
+ //
+ // label9
+ //
+ label9.Location = new Point(3, 113);
+ label9.Name = "label9";
+ label9.Size = new Size(73, 23);
+ label9.TabIndex = 32;
+ label9.Text = "保存OK原图";
+ //
+ // swSaveOKPic
+ //
+ swSaveOKPic.Location = new Point(82, 113);
+ swSaveOKPic.Name = "swSaveOKPic";
+ swSaveOKPic.Size = new Size(60, 23);
+ swSaveOKPic.TabIndex = 31;
+ swSaveOKPic.Text = "switch3";
+ //
// panel2
//
- panel2.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
panel2.Controls.Add(label2);
panel2.Controls.Add(buttonDEL);
panel2.Controls.Add(table_base);
panel2.Controls.Add(buttonADD);
- panel2.Location = new Point(17, 141);
+ panel2.Dock = DockStyle.Bottom;
+ panel2.Location = new Point(0, 206);
panel2.Name = "panel2";
- panel2.Size = new Size(639, 286);
+ panel2.Size = new Size(598, 237);
panel2.TabIndex = 35;
//
// label2
//
- label2.AutoSize = true;
- label2.Location = new Point(3, 5);
+ label2.Location = new Point(3, 3);
label2.Name = "label2";
- label2.Size = new Size(56, 17);
- label2.TabIndex = 25;
+ label2.Size = new Size(58, 23);
+ label2.TabIndex = 29;
label2.Text = "模型参数";
//
// buttonDEL
//
- buttonDEL.Location = new Point(93, 25);
+ buttonDEL.Location = new Point(93, 28);
buttonDEL.Name = "buttonDEL";
buttonDEL.Size = new Size(84, 34);
buttonDEL.TabIndex = 24;
@@ -121,152 +242,30 @@
// table_base
//
table_base.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
- table_base.Location = new Point(3, 65);
+ table_base.Location = new Point(0, 68);
table_base.Name = "table_base";
- table_base.Size = new Size(633, 218);
+ table_base.Size = new Size(598, 169);
table_base.TabIndex = 22;
table_base.Text = "table1";
//
// buttonADD
//
- buttonADD.Location = new Point(3, 25);
+ buttonADD.Location = new Point(3, 28);
buttonADD.Name = "buttonADD";
buttonADD.Size = new Size(84, 34);
buttonADD.TabIndex = 23;
buttonADD.Text = "新增";
//
- // label10
- //
- label10.Location = new Point(171, 99);
- label10.Name = "label10";
- label10.Size = new Size(73, 23);
- label10.TabIndex = 34;
- label10.Text = "保存NG原图";
- //
- // sthSaveNGPic
- //
- sthSaveNGPic.Location = new Point(258, 99);
- sthSaveNGPic.Name = "sthSaveNGPic";
- sthSaveNGPic.Size = new Size(57, 23);
- sthSaveNGPic.TabIndex = 33;
- sthSaveNGPic.Text = "switch4";
- //
- // label9
- //
- label9.Location = new Point(17, 99);
- label9.Name = "label9";
- label9.Size = new Size(73, 23);
- label9.TabIndex = 32;
- label9.Text = "保存OK原图";
- //
- // swSaveOKPic
- //
- swSaveOKPic.Location = new Point(96, 99);
- swSaveOKPic.Name = "swSaveOKPic";
- swSaveOKPic.Size = new Size(57, 23);
- swSaveOKPic.TabIndex = 31;
- swSaveOKPic.Text = "switch3";
- //
- // label7
- //
- label7.Location = new Point(179, 70);
- label7.Name = "label7";
- label7.Size = new Size(58, 23);
- label7.TabIndex = 30;
- label7.Text = "数据保存";
- //
- // sthPic
- //
- sthPic.Location = new Point(258, 70);
- sthPic.Name = "sthPic";
- sthPic.Size = new Size(57, 23);
- sthPic.TabIndex = 29;
- sthPic.Text = "switch2";
- //
- // label8
- //
- label8.Location = new Point(17, 70);
- label8.Name = "label8";
- label8.Size = new Size(58, 23);
- label8.TabIndex = 28;
- label8.Text = "模型启用";
- //
- // switchEnable
- //
- switchEnable.Location = new Point(96, 70);
- switchEnable.Name = "switchEnable";
- switchEnable.Size = new Size(57, 23);
- switchEnable.TabIndex = 27;
- switchEnable.Text = "switch1";
- //
- // tbDetectName
- //
- tbDetectName.Location = new Point(96, 12);
- tbDetectName.Name = "tbDetectName";
- tbDetectName.Size = new Size(211, 23);
- tbDetectName.TabIndex = 26;
- //
- // label6
- //
- label6.Location = new Point(17, 12);
- label6.Name = "label6";
- label6.Size = new Size(58, 23);
- label6.TabIndex = 25;
- label6.Text = "检测名称";
- //
- // cbxDetectType
- //
- cbxDetectType.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
- cbxDetectType.DropDownStyle = ComboBoxStyle.DropDownList;
- cbxDetectType.FormattingEnabled = true;
- cbxDetectType.Location = new Point(402, 10);
- cbxDetectType.Name = "cbxDetectType";
- cbxDetectType.Size = new Size(254, 25);
- cbxDetectType.TabIndex = 24;
- //
- // label5
- //
- label5.Location = new Point(333, 12);
- label5.Name = "label5";
- label5.Size = new Size(73, 23);
- label5.TabIndex = 23;
- label5.Text = "目标类型";
- //
- // btnPreOpen
- //
- btnPreOpen.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
- btnPreOpen.Location = new Point(613, 41);
- btnPreOpen.Name = "btnPreOpen";
- btnPreOpen.Size = new Size(43, 23);
- btnPreOpen.TabIndex = 22;
- btnPreOpen.Text = "...";
- //
- // tbModelpath
- //
- tbModelpath.Location = new Point(96, 41);
- tbModelpath.Name = "tbModelpath";
- tbModelpath.Size = new Size(511, 23);
- tbModelpath.TabIndex = 17;
- //
- // label1
- //
- label1.Location = new Point(17, 41);
- label1.Name = "label1";
- label1.Size = new Size(73, 23);
- label1.TabIndex = 9;
- label1.Text = "模型路径";
- //
// DetectConfigControl
//
AutoScaleDimensions = new SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
Controls.Add(panel1);
Name = "DetectConfigControl";
- Size = new Size(683, 445);
+ Size = new Size(600, 445);
panel1.ResumeLayout(false);
- panel1.PerformLayout();
+ panel3.ResumeLayout(false);
panel2.ResumeLayout(false);
- panel2.PerformLayout();
ResumeLayout(false);
}
@@ -274,11 +273,7 @@
private Panel panel1;
private AntdUI.Label label1;
- private TextBox tbModelpath;
- private TextBox tbDetectName;
private AntdUI.Label label6;
- private ComboBox cbxDetectType;
- private AntdUI.Label label5;
private AntdUI.Button btnPreOpen;
private AntdUI.Label label7;
private AntdUI.Switch sthPic;
@@ -289,10 +284,14 @@
private AntdUI.Label label9;
private AntdUI.Switch swSaveOKPic;
private Panel panel2;
- private Label label2;
private AntdUI.Button buttonDEL;
private AntdUI.Table table_base;
private AntdUI.Button buttonADD;
private AntdUI.Button button3;
+ private AntdUI.Input tbDetectName;
+ private AntdUI.Input tbModelpath;
+ private AntdUI.Label label2;
+ private AntdUI.Select cbxDetectType;
+ private Panel panel3;
}
}
diff --git a/DHSoftware/Views/DetectConfigControl.cs b/DHSoftware/Views/DetectConfigControl.cs
index 09828ae..4d6f27f 100644
--- a/DHSoftware/Views/DetectConfigControl.cs
+++ b/DHSoftware/Views/DetectConfigControl.cs
@@ -1,5 +1,6 @@
using AntdUI;
using AntdUIDemo.Views.Table;
+using DH.Commons.Enums;
using DH.Devices.Vision;
using DHSoftware.Models;
using System;
@@ -148,12 +149,12 @@ namespace DHSoftware.Views
},
new ColumnSwitch("IsEnable", "是否启用", ColumnAlign.Center){
//支持点击回调
- Call= (value,record, i_row, i_col) =>{
- //执行耗时操作
- Thread.Sleep(1000);
- // AntdUI.Message.info(window, value.ToString(),autoClose:1);
- return value;
- }
+ //Call= (value,record, i_row, i_col) =>{
+ // //执行耗时操作
+ // Thread.Sleep(10);
+ // // AntdUI.Message.info(window, value.ToString(),autoClose:1);
+ // return value;
+ //}
},
new Column("ScoreMinValue", "最小得分",ColumnAlign.Center),
new Column("ScoreMaxValue", "最大得分",ColumnAlign.Center),
@@ -222,7 +223,12 @@ namespace DHSoftware.Views
{
DefectRow useradd = new DefectRow()
{
- LabelDescription="xinquexian"
+ LabelDescription="xinquexian",
+ IsEnable=true,
+ ScoreMinValue=0.3,
+ ScoreMaxValue=1,
+ AreaMinValue=1,
+ AreaMaxValue=999999999,
};
var form = new DefectRowEdit(_window, useradd) { Size = new Size(700, 500) };
@@ -361,87 +367,87 @@ namespace DHSoftware.Views
//表格内部按钮事件
private void Table_base_CellButtonClick(object sender, TableButtonEventArgs e)
{
- //var buttontext = e.Btn.Text;
+ var buttontext = e.Btn.Text;
- //if (e.Record is User user)
- //{
- // curUser = user;
- // switch (buttontext)
- // {
- // //暂不支持进入整行编辑,只支持指定单元格编辑,推荐使用弹窗或抽屉编辑整行数据
- // case "编辑":
- // var form = new UserEdit(window, user) { Size = new Size(500, 300) };
- // AntdUI.Drawer.open(new AntdUI.Drawer.Config(window, form)
- // {
- // OnLoad = () =>
- // {
- // AntdUI.Message.info(window, "进入编辑", autoClose: 1);
- // },
- // OnClose = () =>
- // {
- // AntdUI.Message.info(window, "结束编辑", autoClose: 1);
- // }
- // });
- // break;
- // case "删除":
- // var result = Modal.open(window, "删除警告!", "确认要删除选择的数据吗?", TType.Warn);
- // if (result == DialogResult.OK)
- // antList.Remove(user);
- // break;
- // case "AntdUI":
- // //超链接内容
- // AntdUI.Message.info(window, user.CellLinks.FirstOrDefault().Id, autoClose: 1);
- // break;
- // case "查看图片":
- // //使用clone可以防止table中的image被修改
- // Preview.open(new Preview.Config(window, (Image)curUser.CellImages[0].Image.Clone()));
- // break;
- // }
- //}
+ if (e.Record is DefectRow user)
+ {
+ curUser = user;
+ switch (buttontext)
+ {
+ //暂不支持进入整行编辑,只支持指定单元格编辑,推荐使用弹窗或抽屉编辑整行数据
+ case "编辑":
+ var form = new DefectRowEdit(_window, user) { Size = new Size(500, 300) };
+ AntdUI.Drawer.open(new AntdUI.Drawer.Config(_window, form)
+ {
+ OnLoad = () =>
+ {
+ AntdUI.Message.info(_window, "进入编辑", autoClose: 1);
+ },
+ OnClose = () =>
+ {
+ AntdUI.Message.info(_window, "结束编辑", autoClose: 1);
+ }
+ });
+ break;
+ case "删除":
+ var result = Modal.open(_window, "删除警告!", "确认要删除选择的数据吗?", TType.Warn);
+ if (result == DialogResult.OK)
+ antList.Remove(user);
+ break;
+ case "AntdUI":
+ //超链接内容
+ // AntdUI.Message.info(_window, user.CellLinks.FirstOrDefault().Id, autoClose: 1);
+ break;
+ case "查看图片":
+ //使用clone可以防止table中的image被修改
+ // Preview.open(new Preview.Config(window, (Image)curUser.CellImages[0].Image.Clone()));
+ break;
+ }
+ }
}
private void ButtonDEL_Click(object sender, EventArgs e)
{
- //if (antList.Count == 0 || !antList.Any(x => x.Selected))
- //{
- // bool isSubSelected = false;
- // // 判断子元素是否勾选
- // for (int i = 0; i < antList.Count; i++)
- // {
- // if (antList[i].Users != null && antList[i].Users.Any(x => x.Selected))
- // {
- // isSubSelected = true;
- // break;
- // }
- // }
- // if (!isSubSelected)
- // {
- // AntdUI.Message.warn(window, "请选择要删除的行!", autoClose: 3);
- // return;
- // }
- //}
+ if (antList.Count == 0 || !antList.Any(x => x.Selected))
+ {
+ bool isSubSelected = false;
+ //// 判断子元素是否勾选
+ //for (int i = 0; i < antList.Count; i++)
+ //{
+ // if (antList[i].Users != null && antList[i].Users.Any(x => x.Selected))
+ // {
+ // isSubSelected = true;
+ // break;
+ // }
+ //}
+ if (!isSubSelected)
+ {
+ AntdUI.Message.warn(_window, "请选择要删除的行!", autoClose: 3);
+ return;
+ }
+ }
- //var result = Modal.open(window, "删除警告!", "确认要删除选择的数据吗?", TType.Warn);
- //if (result == DialogResult.OK)
- //{
- // // 使用反转for循环删除主列表中选中的项
- // for (int i = antList.Count - 1; i >= 0; i--)
- // {
- // // 删除选中的主列表项
- // if (antList[i].Selected)
- // {
- // antList.RemoveAt(i);
- // }
- // else
- // {
- // // 删除子列表中选中的项
- // antList[i].Users = antList[i].Users?.Where(user => !user.Selected).ToArray();
- // }
- // }
- // // 提示删除完成
- // // AntdUI.Message.success(this.w, "删除成功!", autoClose: 3);
- // MessageBox.Show("删除成功!");
- //}
+ var result = Modal.open(_window, "删除警告!", "确认要删除选择的数据吗?", TType.Warn);
+ if (result == DialogResult.OK)
+ {
+ // 使用反转for循环删除主列表中选中的项
+ for (int i = antList.Count - 1; i >= 0; i--)
+ {
+ // 删除选中的主列表项
+ if (antList[i].Selected)
+ {
+ antList.RemoveAt(i);
+ }
+ else
+ {
+ // 删除子列表中选中的项
+ // antList[i].Users = antList[i].Users?.Where(user => !user.Selected).ToArray();
+ }
+ }
+ // 提示删除完成
+ // AntdUI.Message.success(this.w, "删除成功!", autoClose: 3);
+ MessageBox.Show("删除成功!");
+ }
}
diff --git a/DHSoftware/Views/SettingWindow.cs b/DHSoftware/Views/SettingWindow.cs
index d754de3..0837eb9 100644
--- a/DHSoftware/Views/SettingWindow.cs
+++ b/DHSoftware/Views/SettingWindow.cs
@@ -8,6 +8,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using AntdUI;
+using DH.Commons.Enums;
using DH.Devices.Devices;
using DH.Devices.Vision;
diff --git a/DHSoftware/Views/UserConfigFrm.cs b/DHSoftware/Views/UserConfigFrm.cs
index 26ee30b..ba477d5 100644
--- a/DHSoftware/Views/UserConfigFrm.cs
+++ b/DHSoftware/Views/UserConfigFrm.cs
@@ -1,5 +1,6 @@
using AntdUI;
using AntdUIDemo.Models;
+using DH.Commons.Enums;
using DH.Devices.Devices;
using DH.Devices.Vision;
using System;
@@ -198,8 +199,8 @@ namespace DHSoftware.Views
int width = tabs.Width;
int height = tabs.Height;
// 创建新 TabPage
- UserDetetion control = new UserDetetion(width, height);
- control._windows = Window;
+ UserDetetion control = new UserDetetion(Window,width, height);
+ // control._windows = Window;
switch (name)
{
case "工位1":
diff --git a/DHSoftware/Views/UserDetetion.cs b/DHSoftware/Views/UserDetetion.cs
index 2a70177..4b6c3a2 100644
--- a/DHSoftware/Views/UserDetetion.cs
+++ b/DHSoftware/Views/UserDetetion.cs
@@ -17,9 +17,10 @@ namespace DHSoftware.Views
private StackPanel panel, panel2, panel3, panel4;
public Window _windows;
//根据检测配置 将对应的相机配置、中处理预处理、尺寸测量
- public UserDetetion(int parentWidth, int parentHeight)
+ public UserDetetion(Window windows,int parentWidth, int parentHeight)
{
InitializeComponent();
+ _windows = windows;
AntdUI.CollapseItem group1 = new CollapseItem();
group1.Height = parentHeight / 4;
group1.Text = "相机配置";
@@ -214,7 +215,7 @@ namespace DHSoftware.Views
// 遍历 panel 的 Controls,找到最后一个 CameraConfigControl 并移除
for (int i = panel3.Controls.Count - 1; i >= 0; i--)
{
- if (panel3.Controls[i] is CameraConfigControl)
+ if (panel3.Controls[i] is DetectConfigControl)
{
panel3.Controls.RemoveAt(i);
break; // 只删除一个
diff --git a/DHSoftware/productModel.cs b/DHSoftware/productModel.cs
index 4fc7d20..cae60b3 100644
--- a/DHSoftware/productModel.cs
+++ b/DHSoftware/productModel.cs
@@ -1,4 +1,5 @@
-using DH.Devices.Vision;
+using DH.Commons.Enums;
+using DH.Devices.Vision;
using System;
using System.Collections.Generic;
using System.Linq;