当你使用C#与visionpro做项目做多了,就会发现很多功能可以做成工具,像visionpro一样拖拽完成,省掉很多代码。VisionPro允许你构建自己的工具和工具编辑控件,这些控件将在QuickBuild中工作。编写自己的VisionPro工具有三个主要步骤:
- 编写工具
- 编写编辑控件
- 将该工具与QuickBuild集成
VisionPro安装程序在C:/Program Files/Cognex/VisionPro/Samples/Programming/UserTools中放置了两个用户编写的工具示例。第一个是SimpleTool,它将输入图像复制到输出图像。第二个是CogColorConversionTool,它将三个平面的RGB图像转换为单独的R、G和B平面或单独的H、S和I平面。示例工具是用C#和Visual Basic编写的。
注意:如果将VisionPro安装在程序文件以外的目录中,示例程序将位于该目录中。
编写工具
以SimpleTool示例程序为例。当你编写工具时,你当然会定义适合它的属性和方法。创建一个新的类库项目。你的项目必须包括对 Cognex.VisionPro
和 Cognex.VisionPro.Core
的引用。
你的工具必须派生自CogToolBase,它提供了基本的工具功能:序列化、更改的事件、运行状态和计时信息。
public class SimpleTool : Cognex.VisionPro.Implementation.CogToolBase { .... }
接下来用构造函数和克隆方法填充类。
public class SimpleTool : Cognex.VisionPro.Implementation.CogToolBase { public SimpleTool() { } public SimpleTool(SimpleTool otherTool) { _InputImage = otherTool._InputImage; _OutputImage = otherTool._OutputImage; _CopyTwice = otherTool._CopyTwice; } private SimpleTool(SerializationInfo info, StreamingContext context) : base(info, context) { } protected override object Clone() {return new SimpleTool(this);} ... }
你将需要一些特定于工具的专用字段。简单的工具示例使用输入图像、输出图像和自定义字段。稍后,你将使用属性公开这些字段。
public class SimpleTool : Cognex.VisionPro.Implementation.CogToolBase { // constructors and clone methods ... // private fields private Cognex.VisionPro.CogImage8Grey _InputImage; private Cognex.VisionPro.CogImage8Grey _OutputImage; // CopyTwice is a field that will be modifiable in the edit control. private bool _CopyTwice = false; }
状态标志让已更改的事件处理程序知道哪些属性已更改。按照惯例,为每个类定义的第一个状态标志命名为Sf0,并设置为基类的SfNextSf。通常为类公开的每个属性定义一个状态标志。每个状态标志都设置为从Sf0移位的值位。按照惯例,最后一个州的国旗是SfNextSf。从类派生的任何类都可以使用该值,这样其状态标志就不会重叠。
状态标志的名称必须与它们用Sf前缀表示的属性相同。例如,如果工具具有Region属性,则相应的状态标志必须命名为SfRegion。
public class SimpleTool : Cognex.VisionPro.Implementation.CogToolBase { // constructors and clone methods ... // private fields ... // state flags private const long Sf0 = Cognex.VisionPro.Implementation.CogToolBase.SfNextSf; public const long SfInputImage = Sf0 << 0; public const long SfOutputImage = Sf0 << 1; public const long SfCopyTwice = Sf0 << 2; protected new const long SfNextSf = Sf0 << 3; }
接下来,定义访问专用字段的属性。要确保字段值更改时触发changed事件,必须调用OnChanged。
public class SimpleTool : Cognex.VisionPro.Implementation.CogToolBase { // constructors and clone methods ... // private fields ... // state flags ... // properties public Cognex.VisionPro.CogImage8Grey InputImage { get {return _InputImage;} set { if ((_InputImage == null) || (!_InputImage.Equals(value))) { _InputImage = value; // Note that the state flags also indicate that the current run record // has changed. This is because the input image is part of the current run // record. SfCreateCurrentRecord is provided by CogToolBase OnChanged(SfInputImage | SfCreateCurrentRecord); } } } public Cognex.VisionPro.CogImage8Grey OutputImage { // This property has no setter since it is an output of the tool. get {return _OutputImage;} } public bool CopyTwice { get {return _CopyTwice;} set { if (_CopyTwice != value) { _CopyTwice = value; // Fire CopyTwice changed event OnChanged(SfCopyTwice); } } } }
最后,必须重写以下CogToolBasemethods:
- InternalRun
以编程方式或从编辑控件调用工具时执行。 - InternalCreateCurrentRecord
设置要在工具运行前显示在编辑控件中的图像;通常是输入图像。如果工具使用某个区域,通常也会包含该区域。 - InternalCreateLastRunRecord
设置要在工具运行后显示的图像。通常包括输出图像。如果该工具提供了结果图形,它们也包括在这里。
public class SimpleTool : Cognex.VisionPro.Implementation.CogToolBase { // constructors and clone methods ... // private fields ... // state flags ... // properties ... // CogToolBase overrides /// This method creates the CurrentRunRecord. Run records consist of /// one or more CogRecords. If a CogRecord contains an ICogImage, it will be shown /// on the display of the Tool's edit control. It the ICogImage record contains a /// graphics subrecord, the graphics will appear on the ICogImage. For this tool, /// the CurrentRunRecord includes the InputImage. protected override void InternalCreateCurrentRecord(Cognex.VisionPro.ICogRecord newRecord, int mycurrentRecordEnable) { Cognex.VisionPro.Implementation.CogRecord InputImageRecord; InputImageRecord = new Cognex.VisionPro.Implementation.CogRecord("InputImage", typeof(Cognex.VisionPro.CogImage8Grey), Cognex.VisionPro.CogRecordUsageConstants.Input, false, _InputImage, "InputImage"); newRecord.SubRecords.Add(InputImageRecord); } /// This method creates the LastRunRecord. Run records consist of /// one or more CogRecords. If a CogRecord contains an ICogImage, it will be shown /// on the display of the Tool's edit control. It the ICogImage record contains a /// graphics subrecord, the graphics will appear on the ICogImage. For this tool, /// the LastRunRecord is the OutputImage protected override void InternalCreateLastRunRecord(Cognex.VisionPro.ICogRecord newRecord, int lastRunRecordEnable, int lastRunRecordDiagEnable) { newRecord.SubRecords.Add(new Cognex.VisionPro.Implementation.CogRecord("OutputImage", typeof(Cognex.VisionPro.CogImage8Grey), Cognex.VisionPro.CogRecordUsageConstants.Result, false, _OutputImage, "OutputImage")); } /// This method is the "Run" method for the tool. It generates changed events for /// the OutputImage and CreateLastRunRecord (since the LastRunRecord contains the /// OutputImage). protected override Cognex.VisionPro.CogToolResultConstants InternalRun(ref string message) { if (_InputImage == null) { throw new CogSimpleToolException("No input image specified"); } _OutputImage = _InputImage.Copy(Cognex.VisionPro.CogImageCopyModeConstants.CopyPixels); if (_CopyTwice) _OutputImage = _InputImage.Copy(Cognex.VisionPro.CogImageCopyModeConstants.CopyPixels); OnChanged(SfOutputImage|SfCreateLastRunRecord); return Cognex.VisionPro.CogToolResultConstants.Accept; } }
编写工具控件
作为vision工具项目的一部分,创建一个新的用户控件。你的项目必须包括对Cognex.VisionPro.Controls
的引用。
编辑控件必须派生自CogToolEditControlBaseV2,它为控件提供了通用框架,包括工具按钮和工具显示。从系统更改用户控件的基类System.Windows.Forms.UserControl
到CogToolEditControlBaseV2。
将编辑器属性添加到你编写的工具类中,以将其与工具编辑控件关联。你需要添加一些using语句,如图所示。
using System.ComponentModel; // needed for Editor attribute using System.Windows.Forms; // needed for Editor attribute [Serializable] [Editor(typeof(SimpleToolEditV2), typeof(Control))] public class SimpleTool : CogToolBase { … }
在工具编辑控件的代码中,可以使用CogToolEditControlBaseV2类的线程安全功能来创建一个控件,该控件为图形用户提供对工具属性的访问,同时在工具在非GUI线程中运行时安全地阻止对这些属性的访问。这里的关键概念是围绕基类的主观性属性展开的。此布尔属性指示何时可以安全地访问主题工具——通常是在工具未从非GUI线程执行其Run方法时。在QuickBuild中的作业中运行工具时,基础CogJobManager将根据需要设置并清除SubjectInUse属性。如果使用编辑控件创建多线程应用程序,应用程序可以显式设置和清除主观性。
为控件建立基类后,使用设计器添加控件需要的任何按钮、复选框或类似子控件。通常,在特定的子控制和工具的特定属性之间会有一对一的对应关系。
为编辑控件类创建构造函数。
public SimpleToolEditV2() : base(false) // base(bool hasFloatingResults) { InitializeComponent(); // required by designer … }
创建主题属性,包括getter和setter。对象是vision工具的实例,其状态将通过此控件公开。请注意,如果在主观性为true时调用setter,基类将有效地对其进行排队调用——这将在主观性为false时立即处理。
[Browsable(false)][DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]public SimpleTool Subject{get { return base.GetSubject() as SimpleTool; }set { base.SetSubject(value); }}
重写基类的InitializeFromSubject方法。在主题被替换后的第一个线程安全机会调用此方法。控件应使用此方法使用来自新主题的值(重新)初始化自身。
protected override void InitializeFromSubject() { base.InitializeFromSubject(); SetupSettingsTab(); // a helper method that we’ll define further on }
重写基类的SubjectValuesChanged方法。每当主题引发已更改的事件时,都会调用此方法。此函数始终在GUI线程上执行。在这里,你可以更新其关联工具属性值可能已更改的任何子控件,如所提供的已更改事件参数的状态标志所示。
Protected override void SubjectValuesChanged( object sender, CogChangedEventArgs e) { base.SubjectValuesChanged(sender, e); if ((e.StateFlags & SimpleTool.SfCopyTwice) != 0) { SetupSettingsTab(); // helper method, copies from tool to ctrl } }
重写基类的SubjectInUseChanged方法。每当SubjectInUse属性发生更改时,就会调用此方法。这是启用或禁用子控制的好地方。
protected override void SubjectInUseChanged() { base.SubjectInUseChanged(); bool bEnabled = false; if (Subject != null) if (! SubjectInUse) bEnabled = true; chkCopyTwice.Enabled = bEnabled; }
创建一个private helper方法来设置放置在控件上的任何子控件的值。这不是严格要求的,但实现一个私有助手方法通常很方便,该方法基于工具属性的值设置任何子控件的值和状态。这个helper方法假定在主观性为false时调用它。
private void SetuSettingsTab() { AssertSafe(); // ensures SubjectInUse is false bool bChecked = false; If (Subject != null) If (Subject.CopyTwice) bChecked = true; chkCopyTwice.Checked = bChecked; bool bEnabled = false; If (Subject != null) bEnabled = true; chkCopyTwice.Enabled = bEnabled; }
添加事件处理程序以响应来自每个子控件的用户输入。请注意,因为我们在不安全的时间(当工具从非GUI线程运行时)禁用来自子控件的输入,所以从这些事件处理程序中访问工具应该是安全的。
private void chkCopyTwice_CheckedChanged( object sender, EventArgs e) { if (Subject == null) // It should be safe, but check anyway … return; if (SubjectInUse) return; Subject.CopyTwice = chkCopyTwice.Checked; }
使用自定义工具
将编译好的工具dll文件在新C#窗体程序中引用,并通过CogSerializer.SaveObjectToFile
方法将其序列化成vtt文件。到此,我们得到了一个工具的dll文件,以及一个工具的vtt文件。想要visionpro识别你的工具,你还需要一个16X16大小的ico图标文件。将以上三种文件以你的工具名命名,然后按照下列关系复制过去就能在visionpro中看到你的自定义工具了。
ico与dll文件全部复制到/Program Files/Cognex/VisionPro/bin目录,具体参考你的visionpro安装路径。
vtt文件复制到/Program Files/Cognex/VisionPro/bin/Templates/Tools,如果你想给自定义工具单独分组,请在该路径下新建文件夹,并将vtt文件放在其中即可。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/iot/242137.html