using HalconDotNet; using OpenCvSharp; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Collections.Concurrent; using LB_VisionControl; using LB_SmartVision.ProcessRun; using LB_VisionProcesses; using LB_VisionProcesses.Cameras; using LB_VisionProcesses.Communicators; namespace LB_SmartVision.Forms.Pages.ProcessPage { public partial class ProcessPage : UserControl { /// /// 运行步骤(object为IProces或者object为ICamera) /// public ProcessRunBll ProcessRunBll { get; set; } public Action LogInfo; private UserHSmartWindowControl UserHSmartWindowControl = new UserHSmartWindowControl(); public ProcessPage() { InitializeComponent(); } public ProcessPage(string Name, ProcessRunBll ProcessRunBll) { InitializeComponent(); this.Text = "ProcessPage"; this.Name = Name; this.ProcessRunBll = ProcessRunBll; Name = ProcessRunBll.Name; Text = ProcessRunBll.Name; this.splitContainer1.Panel1.Controls.Add(UserHSmartWindowControl); UserHSmartWindowControl.Dock = DockStyle.Fill; this.panel1.Controls.Add(ProcessRunBll.nodesControl); ProcessRunBll.nodesControl.Location = new System.Drawing.Point(0, 0); ProcessRunBll.nodesControl.Size = new System.Drawing.Size(5000, 5000); RemoveAllHandler(); ProcessRunBll.nodesControl.AddNodeAction += AddProcess; ProcessRunBll.nodesControl.RenameNodeAction += RenameProcess; ProcessRunBll.nodesControl.InAndOutNodeAction += InAndOutProcess; ProcessRunBll.nodesControl.DeleteNodeAction += DeleteProcess; ProcessRunBll.nodesControl.EditNodeAction += EditProcess; ProcessRunBll.nodesControl.AddBranchAction += AddBranch; ProcessRunBll.nodesControl.DeleteBranchAction += DeleteBranch; } private void ProcessPage_Paint(object sender, PaintEventArgs e) { if (ProcessRunBll.Result) btn_Run.ButtonType = ReaLTaiizor.Util.HopeButtonType.Success; else btn_Run.ButtonType = ReaLTaiizor.Util.HopeButtonType.Danger; if (ProcessRunBll.GetImage(out _, out HObject RecordImage)) UserHSmartWindowControl.ShowHoImage(RecordImage); } public void RemoveAllHandler() { ProcessRunBll.nodesControl.AddNodeAction -= AddProcess; ProcessRunBll.nodesControl.RenameNodeAction -= RenameProcess; ProcessRunBll.nodesControl.InAndOutNodeAction -= InAndOutProcess; ProcessRunBll.nodesControl.DeleteNodeAction -= DeleteProcess; ProcessRunBll.nodesControl.EditNodeAction -= EditProcess; ProcessRunBll.nodesControl.AddBranchAction -= AddBranch; ProcessRunBll.nodesControl.DeleteBranchAction -= DeleteBranch; } private void btn_Run_Click(object sender, EventArgs e) { this.BeginInvoke(new Action(() => { UserHSmartWindowControl.ClearObj(); LogInfo?.Invoke(string.Format("流程[{0}]开始运行", this.ProcessRunBll.Name), LogInfoType.INFO); bool result = this.ProcessRunBll.Run(); string msg = ProcessRunBll.Msg; LogInfo?.Invoke(string.Format("流程[{0}]运行完成,结果:{1}", this.ProcessRunBll.Name, msg) , result ? LogInfoType.PASS : LogInfoType.ERROR); if (ProcessRunBll.GetImage(out _, out HObject RecordImage)) UserHSmartWindowControl.ShowHoImage(RecordImage); if (result) btn_Run.ButtonType = ReaLTaiizor.Util.HopeButtonType.Success; else btn_Run.ButtonType = ReaLTaiizor.Util.HopeButtonType.Danger; })); } public void AddProcess(string ProcessName, string Descript) { string ClassName = ProcessRunBll.Node2ToolClassName(Descript); string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json"; if (ProcessRunBll.AddStep(ProcessRunBll.Name, ProcessName, ClassName, ProcessPath)) { ProcessRunBll.SaveInputs(); ProcessRunBll.SaveOutputs(); ProcessRunBll.CompileMappings(); } else LogInfo?.Invoke(string.Format("流程[{0}]添加步骤\"{1}\"失败", this.Text, ProcessName), LogInfoType.ERROR); } private void InAndOutProcess(string ProcessName) { var dicSteps = ProcessRunBll.GetSteps(); if (!dicSteps.ContainsKey(ProcessName)) return; ProcessInputsSelectForm inputsSelectForm = new ProcessInputsSelectForm(ProcessName, ProcessRunBll); inputsSelectForm.Text = ProcessName; inputsSelectForm.ShowDialog(); ProcessRunBll.SaveInputs(); ProcessRunBll.SaveOutputs(); ProcessRunBll.CompileMappings(); //string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json"; //((IProcess)dicSteps[ProcessName]).Load(ProcessPath); } public void DeleteProcess(string ProcessName) { try { var dicSteps = ProcessRunBll.GetSteps(); if (!dicSteps.ContainsKey(ProcessName)) return; string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json"; if (string.IsNullOrEmpty(ProcessName) || string.IsNullOrEmpty(ProcessPath)) return; // 获取所有文件(不管后缀名是什么)并进行遍历 string directoryPath = Path.GetDirectoryName(ProcessPath); string[] files = Directory.GetFiles(directoryPath, ProcessName + ".*"); // 匹配所有名称为aa的文件,后缀不限 foreach (var file in files) { try { if (File.Exists(file)) File.Delete(file); } catch (Exception ex) { Debug.WriteLine($"删除文件 {file} 时出错: {ex.Message}"); LogInfo?.Invoke(string.Format("流程[{0}]移除步骤\"{1}\"失败,原因是{2}", this.Text, ProcessName, ex.Message), LogInfoType.ERROR); return; } } if (Directory.Exists(directoryPath + "\\" + ProcessName)) Directory.Delete(directoryPath + "\\" + ProcessName, true); if (!ProcessRunBll.Remove(ProcessName)) LogInfo?.Invoke(string.Format("流程[{0}]移除步骤\"{1}\"失败", this.Text, ProcessName), LogInfoType.ERROR); } catch (Exception ex) { Debug.WriteLine(ex.Message); } } private void RenameProcess(string ProcessName, string newProcessName) { ConcurrentDictionary dicSteps = ProcessRunBll.GetSteps(); if (!dicSteps.ContainsKey(ProcessName)) return; ProcessRenameEvent(ProcessName, newProcessName); } private void ProcessRenameEvent(string oriName, string newName) { ConcurrentDictionary dicSteps = ProcessRunBll.GetSteps(); //更新后的步骤名仍然需要是唯一 if (dicSteps.ContainsKey(newName)) { MessageBox.Show(string.Format("重命名失败,步骤名称[{0}]已存在!", newName), "异常"); return; } if (dicSteps.ContainsKey(oriName)) { string oriPath = GlobalVar.allProcessPath + this.Text + "\\" + oriName + ".json"; string newPath = GlobalVar.allProcessPath + this.Text + "\\" + newName + ".json"; string directoryPath = Path.GetDirectoryName(oriPath); string[] files = new string[] { }; // 重命名当前文件夹 files = Directory.GetFiles(directoryPath, oriName + ".*"); // 匹配所有名称为oriName的文件,后缀不限 foreach (var file in files) { try { // 获取文件的扩展名 string extension = Path.GetExtension(file); // 构造新文件名 string newFileName = Path.Combine(directoryPath, newName + extension); if (!File.Exists(newFileName)) { // 重命名文件 File.Move(file, newFileName); Debug.WriteLine($"文件已重命名: {file} -> {newFileName}"); } else { LogInfo?.Invoke(string.Format("流程[{0}]重命名步骤\"{1}\"为\"{2}\"失败,原因是{3}", this.Text, oriName, newName, "命名重复"), LogInfoType.ERROR); return; } } catch (Exception ex) { Debug.WriteLine($"重命名文件 {file} 时出错: {ex.Message}"); LogInfo?.Invoke(string.Format("流程[{0}]重命名步骤\"{1}\"为\"{2}\"失败,原因是{3}", this.Text, oriName, newName, ex.Message), LogInfoType.ERROR); return; } } // 重命名当前文件夹 if (Directory.Exists(directoryPath + "\\" + oriName)) { Directory.Move(directoryPath + "\\" + oriName, directoryPath + "\\" + newName); // 重命名子文件夹 string newParentDirectory = Path.GetDirectoryName(GlobalVar.allProcessPath + this.Text + "\\" + newName + "\\" + oriName + ".json"); files = Directory.GetFiles(newParentDirectory, oriName + ".*"); // 匹配子文件夹内所有名称为oriName的文件,后缀不限(一般只有一个) foreach (var file in files) { try { // 获取文件的扩展名 string extension = Path.GetExtension(file); // 构造新文件名 string newFileName = Path.Combine(newParentDirectory, newName + extension); if (!File.Exists(newFileName)) { if (!Directory.Exists(newParentDirectory)) Directory.CreateDirectory(newParentDirectory); // 重命名文件 File.Move(file, newFileName); Debug.WriteLine($"文件已重命名: {file} -> {newFileName}"); } else { LogInfo?.Invoke(string.Format("流程[{0}]重命名步骤\"{1}\"为\"{2}\"失败,原因是{3}", this.Text, oriName, newName, "命名重复"), LogInfoType.ERROR); return; } } catch (Exception ex) { Debug.WriteLine($"重命名文件 {file} 时出错: {ex.Message}"); LogInfo?.Invoke(string.Format("流程[{0}]重命名步骤\"{1}\"为\"{2}\"失败,原因是{3}", this.Text, oriName, newName, ex.Message), LogInfoType.ERROR); return; } } } ProcessRunBll.Rename(oriName, newName); LogInfo?.Invoke(string.Format("流程[{0}]重命名步骤\"{1}\"为\"{2}\"成功", this.Text, oriName, newName), LogInfoType.PASS); //if (dicSteps[newName] is VisionProTool && Tool.ContainsChinese(newName)) // MessageBox.Show($"VisionPro工具不支持命名为中文:{newName}", "异常"); } } private void EditProcess(string ProcessName) { try { ConcurrentDictionary dicSteps = ProcessRunBll.GetSteps(); if (!dicSteps.ContainsKey(ProcessName)) return; string ClassName = dicSteps[ProcessName].GetType().ToString(); string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json"; if (string.IsNullOrEmpty(ProcessName) || string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(ProcessPath)) return; //利用反射创建实例 Type type = IProcess.GetExecutingAssembly().GetType(ClassName); if (type == null) { LogInfo?.Invoke(string.Format("流程[{0}]步骤\"{1}\"打开失败了,类[{2}]不存在", this.Text, ProcessName, ClassName), LogInfoType.ERROR); return; } IProcess process = ((IProcess)dicSteps[ProcessName]).Clone() as IProcess; Object InputImage = new Object(); if (process.InputImage != null) { if (process.InputImage is HObject ho_image && ho_image.IsInitialized()) InputImage = ho_image.CopyObj(1, -1); else if (process.InputImage is Mat mat && !mat.Empty()) InputImage = mat.Clone(); else if (process.InputImage is Bitmap bitmap) InputImage = bitmap.Clone(); } if (ClassName.Contains("CameraConfig") && process is CameraConfig) { LB_VisionProcesses.Cameras.CameraForm cameraForm = new LB_VisionProcesses.Cameras.CameraForm(GlobalVar.dicCameras.Items, (CameraConfig)process, ProcessPath); cameraForm.ShowDialog(); if (!(process.Load(ProcessPath))) LogInfo?.Invoke(string.Format("流程[{0}]步骤\"{1}\"加载失败了", this.Text, ProcessName), LogInfoType.ERROR); process.strProcessName = ProcessName; } else if (ClassName.Contains("CommunicatorConfig") && process is CommunicatorConfig) { LB_VisionProcesses.Communicators.CommunicatorForm communicatorForm = new LB_VisionProcesses.Communicators.CommunicatorForm(GlobalVar.dicCommunicators.Items, (CommunicatorConfig)process, ProcessPath); communicatorForm.ShowDialog(); if (!(process.Load(ProcessPath))) LogInfo?.Invoke(string.Format("流程[{0}]步骤\"{1}\"加载失败了", this.Text, ProcessName), LogInfoType.ERROR); process.strProcessName = ProcessName; } else { ProcessEditForm processEditForm = new ProcessEditForm(process, ProcessPath); processEditForm.ShowDialog(); //重新加载更新后的步骤 if (processEditForm.hasChanged) LogInfo?.Invoke(string.Format("流程[{0}]步骤\"{1}\"更新了", this.Text, ProcessName), LogInfoType.WARN); if (!(process.Load(ProcessPath))) LogInfo?.Invoke(string.Format("流程[{0}]步骤\"{1}\"加载失败了", this.Text, ProcessName), LogInfoType.ERROR); process.strProcessName = ProcessName; } if (InputImage != null) { if (InputImage is HObject ho_image && ho_image.IsInitialized()) process.InputImage = ho_image.CopyObj(1, -1); else if (InputImage is Mat mat && !mat.Empty()) process.InputImage = mat.Clone(); else if (InputImage is Bitmap bitmap) process.InputImage = bitmap.Clone(); } dicSteps[ProcessName] = process; ProcessRunBll.UpdataInputsAndOutputs(ProcessName, process); } catch (Exception ex) { Debug.WriteLine(ex.Message); } } private void AddBranch(string ProcessName) { var dicSteps = ProcessRunBll.GetSteps(); if (!dicSteps.ContainsKey(ProcessName)) return; // 多分支的本质为脚本工具,根据branchIndex来走对应的分支 if (dicSteps[ProcessName] is LB_VisionProcesses.Processes.ScriptTool.ScriptTool ScriptTool) { ScriptTool.Params.Outputs.Add($"Branch{ScriptTool.Params.Outputs.Count}", false); Debug.WriteLine($"脚本工具[{ProcessName}]增加了Branch{ScriptTool.Params.Outputs.Count - 1}"); } } private void DeleteBranch(string ProcessName) { var dicSteps = ProcessRunBll.GetSteps(); if (!dicSteps.ContainsKey(ProcessName)) return; // 多分支的本质为脚本工具,根据branchIndex来走对应的分支 if (dicSteps[ProcessName] is LB_VisionProcesses.Processes.ScriptTool.ScriptTool ScriptTool && ScriptTool.Params.Outputs.Remove($"Branch{ScriptTool.Params.Outputs.Count}")) { Debug.WriteLine($"脚本工具[{ProcessName}]移除了Branch{ScriptTool.Params.Outputs.Count + 1}"); } } } }