让代码更简单

VisionPro自定义工具教程

重要:本文最后更新于2022-03-21 20:18:17,某些文章具有时效性,若有错误或已失效,请在下方留言或联系代码狗

当你使用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安装在程序文件以外的目录中,示例程序将位于该目录中。

VisionPro自定义工具教程

VisionPro自定义工具教程

编写工具

以SimpleTool示例程序为例。当你编写工具时,你当然会定义适合它的属性和方法。创建一个新的类库项目。你的项目必须包括对 Cognex.VisionProCognex.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文件放在其中即可。

感觉很棒!可以赞赏支持我哟~

3 打赏

评论 (0)

登录后评论
QQ咨询 邮件咨询