diff --git a/TestBenchFramework/BenchControl/GenericDevices/IRoi.cs b/TestBenchFramework/BenchControl/GenericDevices/IRoi.cs index d35525729..48110bf87 100644 --- a/TestBenchFramework/BenchControl/GenericDevices/IRoi.cs +++ b/TestBenchFramework/BenchControl/GenericDevices/IRoi.cs @@ -1,14 +1,12 @@ /// /// Copyright (c) 2017 Sensus Metering Systems /// -using Config.Entities; using TBF.BenchControl.Generic; namespace TBF.BenchControl.GenericDevices { - public interface IRoi : IComponent, IRegisterReader + public interface IRoi : IComponent, IRoiForFixedStart { - GenericDevices.ICamera Camera { get; } bool Detected { get; } string DetectedImageName { get; } @@ -21,12 +19,6 @@ namespace TBF.BenchControl.GenericDevices double TimestampStart { get; } /// in s double TimestampEnd { get; } /// in s - /// - /// Watermeter wheel/arrow detection process. - /// - /// Reference to operation object instance - IOperation GrabImageOp(string imageFileName, bool blackAndWhite, bool lowResolution, ImageRotation imageRotation); - /// /// Watermeter wheel/arrow detection process. /// diff --git a/TestBenchFramework/BenchControl/GenericDevices/IRoiForFixedStart.cs b/TestBenchFramework/BenchControl/GenericDevices/IRoiForFixedStart.cs new file mode 100644 index 000000000..d597573cc --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IRoiForFixedStart.cs @@ -0,0 +1,21 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IRoiForFixedStart : IComponent, IRegisterReader + { + GenericDevices.ICamera Camera { get; } + + /// + /// Watermeter wheel/arrow detection process. + /// + /// Reference to operation object instance + IOperation GrabImageOp(string imageFileName, + bool blackAndWhite, + bool lowResolution, + Config.Entities.ImageRotation imageRotation); + } +} diff --git a/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/Factory.cs b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/Factory.cs new file mode 100644 index 000000000..dc4dc6827 --- /dev/null +++ b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/Factory.cs @@ -0,0 +1,26 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Network.Camera.RoiForFixedStart +{ + public class Factory : IComponentFactory + { + public string ClassName { get { return this.GetType().Namespace.Substring(17); } } + + public void ResetStaticProperties() { Roi.ResetStaticProperties(); } + + public IComponent DummyComponent() { return new Roi(); } + + public IComponent GetComponent(IComponentCfg cfg, IList components) { return new Roi(cfg, components); } + + public IComponentCfg DefaultConfig() { return new RoiCfg(this.GetType().Namespace.Substring(17), this); } + + public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component) + { + return ComponentCfgBase.CreateFromDbEntity(RoiCfg.Serializer, component, this); + } + } +} diff --git a/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/ProcedureParams.cs b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/ProcedureParams.cs new file mode 100644 index 000000000..e036f2bf7 --- /dev/null +++ b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/ProcedureParams.cs @@ -0,0 +1,115 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System.IO; +using System.Xml.Serialization; +using Config.Entities; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.Network.Camera.RoiForFixedStart +{ + public class ProcedureParams : ProcedureParamsBase, IParamsProvider, IProcedureParams + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ProcedureParams) })[0]; + protected override XmlSerializer GetSerializer() { return Serializer; } + + public float PulsesPerLtr; /// [l^-1] + + public override void InitializeAll() + { + PulsesPerLtr = 1.0f; + } + + string[] paramNames = new string[] + { + Strings.PulsesPerLtr, + }; + public override string ParamName(int i) { return paramNames[i]; } + public override int ParamsCount() { return paramNames.Length; } + + public override string ToString(int i) + { + switch (i) + { + case 0: return PulsesPerLtr.ToString(); + default: return string.Empty; + } + } + + /// Retrieves parameters from UI controls + public void UpdateParam(int i, string strValue) + { + switch (i) + { + case 0: PulsesPerLtr = Utils.ParseUFloat(strValue); return; + default: return; + } + } + + /// Verifies whether strings in UI controls represent valid parameters + public bool ValidateParam(int i, string strValue, out string message) + { + message = string.Empty; + + float dummy; + int idummy; + switch (i) + { + case 0: + if (Utils.TryParseUFloat(strValue, out dummy)) return true; + break; + default: + message = "Invalid index"; + return false; + } + + message = ParamName(i) + " is invalid"; + return false; + } + + void CopyContentTo(ProcedureParams prms) + { + prms.PulsesPerLtr = this.PulsesPerLtr; + } + + public IParamsProvider Clone() + { + ProcedureParams pars = new ProcedureParams(); + CopyContentTo(pars); + return pars; + } + + public override void UpdateProcedureParams(ComponentProcedure dbEntity) + { + if (dbEntity == null) return; + try + { + ProcedureParams tmp = Serializer.Deserialize(new StringReader(dbEntity.Parameters)) as ProcedureParams; + + procedureParamsEntity = dbEntity; + componentName = dbEntity.CmpntName; + procedure = dbEntity.Procedure; + + if (tmp != null) tmp.CopyContentTo(this); + } + catch + { + } + } + + public ProcedureParams() { } + + public ProcedureParams(bool initialize) + { + if (initialize) InitializeAll(); + } + + public ProcedureParams(ComponentProcedure procedureParamsEntity, string componentName, Procedure procedure) + { + this.procedureParamsEntity = procedureParamsEntity; + this.componentName = componentName; + this.procedure = procedure; + } + } +} diff --git a/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/Roi.cs b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/Roi.cs new file mode 100644 index 000000000..3c70be84a --- /dev/null +++ b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/Roi.cs @@ -0,0 +1,165 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.Collections.Generic; +using System.Text; +using log4net; +using Config.Entities; + +namespace TBF.BenchControl.Network.Camera.RoiForFixedStart +{ + public class Roi : ComponentBase, GenericDevices.IRoiForFixedStart, IOperation + { + /// TODO: Implement support for sharing one camera by multiple ROI-s + + private static readonly ILog log = LogManager.GetLogger(typeof(Roi)); + public override string ToString() + { + return string.Format("{0}({1})", this.GetType().Namespace.Substring(17), Cfg.ToString(1)); + } + + /// + /// Cfg + /// + readonly RoiCfg roiCfg; + + /// + /// Camera and ICamera + /// + public readonly CLP1611.Camera NetCamera; + public GenericDevices.ICamera Camera { get { return NetCamera as GenericDevices.ICamera; } } + + public double PulsesPerLtr { get { return (double)roiCfg.ProcParams.PulsesPerLtr; } } + public double LtrsPerPulse { get { return (PulsesPerLtr <= float.Epsilon) ? 1.0 : (1 / PulsesPerLtr); } } + + + double beginWMState; + public double BeginWMState + { + get { return beginWMState; } + set { beginWMState = value; } + } + + double endWMState; + public double EndWMState + { + get { return endWMState; } + set { endWMState = value; } + } + + public double WMVolume { get { return endWMState - beginWMState; } } + + public int WMPulses { get { return (int)(WMVolume / LtrsPerPulse); } } + + int wmRefPulses; + public int WMRefPulses { get { return wmRefPulses; } } + + + public Roi() + { + } + + public Roi(Generic.IComponentCfg cfg, IList components) + : base(cfg) + { + roiCfg = cfg as RoiCfg; + NetCamera = TbfComponents.FindComponent(cfg.ParentName, components) as CLP1611.Camera; + + Clear(); + + StartChangeHandler(); + + log.Debug(this.ToString()); + } + + + #region Configuration Change Handling + + public static void OnCfgChange(object sender, CfgChangeArgs args) + { + if (CfgChangeHandler == null) return; + try { CfgChangeHandler(sender, args); } + catch (Exception e) { log.Error("CfgChangeHandler(...) failed", e); } + } + + public static event EventHandler CfgChangeHandler; + + public override void StartChangeHandler() + { + CfgChangeHandler += delegate(object sender, CfgChangeArgs args) + { + RoiCfg tmpcfg = args.Cfg as RoiCfg; + if (tmpcfg != null && tmpcfg.Name.Equals(Name)) + { + if (args.Command == CfgChangeCmd.CfgChange) + { + roiCfg.SaveImages = tmpcfg.SaveImages; + } + } + }; + } + + #endregion Configuration Change Handling + + public void Clear() + { + log.DebugFormat("{0}:Clear()", Name); + beginWMState = 0; + endWMState = 0; + wmRefPulses = 0; + } + + public void TestCompleted() + { + log.DebugFormat("{0}:TestCompleted()", Name); + ReadPulses(); + } + + private void ReadPulses() + { + wmRefPulses = (int)StateMachine.ControlBoard.EtPulses(0); + } + + + public IOperation GrabImageOp(string imageFileName, bool blackAndWhite, bool lowResolution, ImageRotation imageRotation) + { + if (NetCamera != null && NetCamera.Telnet != null) + { + /// TODO: Implement support for sharing one camera by multiple ROI-s + return NetCamera.GrabImagesOp(new string[] { imageFileName }, blackAndWhite, lowResolution, imageRotation); + } + else + return null; + } + + + /// + /// Events: Event.ReadRegisterDone + /// + /// ReadWaterMeter instance reference casted to IOperaton + public IOperation ReadRegisterOp() + { + return this; + } + + /// Start this operation + public void Start() + { + ReadPulses(); + } + + /// Run this operation + /// eventDone + public Event Run() + { + ReadPulses(); + return Event.ReadRegisterDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfg.cs b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfg.cs new file mode 100644 index 000000000..62d0f8047 --- /dev/null +++ b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfg.cs @@ -0,0 +1,52 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System.Xml.Serialization; +using Config.Entities; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Network.Camera.RoiForFixedStart +{ + public class RoiCfg : ComponentCfgBase, IChildComponentCfg + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(RoiCfg) })[0]; + protected override XmlSerializer GetSerializer() { return Serializer; } + + public IComponentCfgCtrl GetControl() { return new RoiCfgCtrl(); } + + /// + /// Serialized parameters + /// + public bool SaveImages; + + /// Procedure parameters + [XmlIgnore] + public ProcedureParams ProcParams; + public override IParamsProvider GetProcedureParams() { return ProcParams; } + public override IParamsProvider CreateProcedureParams(Procedure procedure) + { + ProcedureParams procParams = new ProcedureParams(true); + procParams.UpdateProcedureParams(Name, procedure); + return procParams; + } + + /// Private parameterless constructor invoked by all other (public) constructors + RoiCfg() + { + ProcParams = new ProcedureParams(true); + } + + public RoiCfg(string name, IComponentFactory factory) + : this() + { + Name = name; + Factory = factory; + ParentName = "Camera"; + } + + public string ToString(int i) + { + return string.Format("{0} ({1}) {2}", Name, ParentName, (SaveImages ? " save images" : "")); + } + } +} diff --git a/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfgCtrl.cs b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfgCtrl.cs new file mode 100644 index 000000000..bb9db361f --- /dev/null +++ b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfgCtrl.cs @@ -0,0 +1,137 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Network.Camera.RoiForFixedStart +{ + public partial class RoiCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(RoiCfgCtrl)); + + ComponentParametersDlg parent; + + public bool ShowMore { get { return false; } } + + RoiCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as RoiCfg; + Redraw(); + } + } + + public RoiCfgCtrl() + { + InitializeComponent(); + } + + private void PumpCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is TBF.BenchControl.Network.Camera.CLP1611.Factory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + public void Closing() + { + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + saveImagesCheckBox.Checked = config.SaveImages; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + saveImagesCheckBox.Enabled = true; + } + + public CfgUpdateFlags VerifyCfg(ref string message) + { + CfgUpdateFlags flags = CfgUpdateFlags.None; + + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgUpdateFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + + return flags; + } + + public CfgUpdateFlags UpdateCfg() + { + CfgUpdateFlags flags = CfgUpdateFlags.None; + + if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed + + if (config.Name != nameTextBox.Text) + { + config.Name = nameTextBox.Text; + flags |= (CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange); + } + + string newParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + if (config.ParentName != newParentName) + { + config.ParentName = newParentName; + flags |= (CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange); + } + + if (config.SaveImages != saveImagesCheckBox.Checked) + { + config.SaveImages = saveImagesCheckBox.Checked; + flags |= (CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange); + } + + if ((flags & CfgUpdateFlags.InvokeCfgChange) != 0) + { + Roi.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.CfgChange, config)); + } + + return flags; + } + + #region Configuration Change Handling + + public static void OnCmdResponse(object sender, CmdResponseArgs args) + { + if (CmdResponseHandler == null) return; + try { CmdResponseHandler(sender, args); } + catch (Exception e) { log.Error("CmdResponseHandler(...) failed", e); } + } + + public static event EventHandler CmdResponseHandler; + + public void StartResponseHandler() { } + public void StopResponseHandler() { } + + #endregion Configuration Change Handling + } +} diff --git a/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfgCtrl.designer.cs new file mode 100644 index 000000000..54fb7f4b4 --- /dev/null +++ b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfgCtrl.designer.cs @@ -0,0 +1,147 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +namespace TBF.BenchControl.Network.Camera.RoiForFixedStart +{ + partial class RoiCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.parentNameLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.saveImagesCheckBox = new System.Windows.Forms.CheckBox(); + this.SuspendLayout(); + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(13, 62); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 3; + this.parentNameLabel.Text = "Parent Name"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(99, 34); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(174, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(13, 37); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(96, 11); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(114, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComponentClassName"; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(99, 59); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(174, 21); + this.parentNameComboBox.TabIndex = 4; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(-211, -147); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(57, 13); + this.label1.TabIndex = 5; + this.label1.Text = "Arguments"; + // + // textBox1 + // + this.textBox1.Enabled = false; + this.textBox1.Location = new System.Drawing.Point(-125, -150); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(372, 20); + this.textBox1.TabIndex = 6; + // + // saveImagesCheckBox + // + this.saveImagesCheckBox.AutoSize = true; + this.saveImagesCheckBox.Enabled = false; + this.saveImagesCheckBox.Location = new System.Drawing.Point(99, 90); + this.saveImagesCheckBox.Name = "saveImagesCheckBox"; + this.saveImagesCheckBox.Size = new System.Drawing.Size(131, 17); + this.saveImagesCheckBox.TabIndex = 7; + this.saveImagesCheckBox.Text = "Save images (archive)"; + this.saveImagesCheckBox.UseVisualStyleBackColor = true; + // + // RoiCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.saveImagesCheckBox); + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "RoiCfgCtrl"; + this.Size = new System.Drawing.Size(500, 300); + this.Load += new System.EventHandler(this.PumpCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label parentNameLabel; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.ComboBox parentNameComboBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.CheckBox saveImagesCheckBox; + } +} diff --git a/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfgCtrl.resx b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Network/Camera/RoiForFixedStart/RoiCfgCtrl.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/TestBenchFramework/BenchControl/TbfComponents.cs b/TestBenchFramework/BenchControl/TbfComponents.cs index ded0c1822..992c913b2 100644 --- a/TestBenchFramework/BenchControl/TbfComponents.cs +++ b/TestBenchFramework/BenchControl/TbfComponents.cs @@ -84,6 +84,7 @@ namespace TBF.BenchControl Factories.Add(new Network.Camera.CLP1611.Factory()); Factories.Add(new Network.Camera.Display.Factory()); Factories.Add(new Network.Camera.Roi.Factory()); + Factories.Add(new Network.Camera.RoiForFixedStart.Factory()); Factories.Add(new Output.FileWriters.Basic.FactorySingle()); Factories.Add(new Output.FileWriters.Basic.FactoryCompound()); Factories.Add(new Output.FileWriters.Basic.FactoryHeatMeters()); diff --git a/TestBenchFramework/TBF.csproj b/TestBenchFramework/TBF.csproj index 91af05bf9..f8f50cc75 100644 --- a/TestBenchFramework/TBF.csproj +++ b/TestBenchFramework/TBF.csproj @@ -502,6 +502,7 @@ + @@ -663,6 +664,16 @@ DisplayCfgCtrl.cs + + + + + + UserControl + + + RoiCfgCtrl.cs + @@ -2073,6 +2084,9 @@ DisplayCfgCtrl.cs + + RoiCfgCtrl.cs + RoiCfgCtrl.cs