目录
- 2.3.1 渲染控件:渲染控件上自定义图形的方法
 - 2.3.2 参数控件:参数配置控件绑定模块的方法
 - 2.3.3 控件颜色:控件颜色修改方法
 - 2.3.4 独立控件:二次开发单独显示Group的方法
 - 2.3.5 取流控件:实时取流控件的使用方法
 - 2.3.6 渲染控件:渲染控件绘制ROI的方法
 - 2.3.7 控件语言:控件设置为英文的方法
 - 2.3.8 控件报错:子窗口包含主界面控件及其它控件时报错的解决方法
 - 2.3.9 图像传入:给渲染控件传入图像的方法
 - 2.3.10 主界面控件:主界面控件添加参数修改记录并将记录保存至本地的方法
 - 2.3.11 渲染控件:渲染控件绘制十字方法
 
2.3.1 渲染控件:渲染控件上自定义图形的方法
描述
 环境:VM4.2 + VS2013及以上
 现象:VM4.2如何在渲染控件上自定义图形?
 解答
 VM4.2二次开发相比较VM4.0二次开发,渲染控件上自定义图形有一些更新,除了接口vmRenderControl.DrawShape(),新增加一个接口vmRenderControl.AddShape(),前者是立刻绘制,后者是在下次刷新渲染时自动绘制。所以在VM4.0二次开发回调函数中图像渲染并添加自定义图形时, DrawShape接口函数前需要添加延时,不然回调中的图像渲染还没更新,自定义的图形已经调用DrawShape函数,从而导致自定义图形不能很好的渲染在图像上。在VM4.2二次开发中使用AddShape接口就不要加延时,它会在图像渲染结束后再绘制自定义图形。
 手动添加引用VMControls.WPF.dll、WindowsBase.dll,添加后,引用属性【复制本地】改为false;渲染控件需要先绑定图像,再调用渲染控件的AddShape绘图接口;支持直线、圆形、矩形、文本等图形元素绘制;绘制时机:流程运行结束,在流程结果回调函数中绘制。下面绘制了直线和文本,其它图形依次类推。
C#
//绘制直线
VMControls.WPF.LineEx line = new VMControls.WPF.LineEx(new System.Windows.Point(100, 100), new System.Windows.Point(600, 600), stroke: "#FF0000", strokeThickness: 10);
vmRenderControl1.AddShape(line);
//绘制文本
VMControls.WPF.TextEx text = new VMControls.WPF.TextEx("欢迎使用VM4.2二次开发!", new System.Windows.Point(1000, 1000), fontSize: 20, stroke: "#FF0000");
vmRenderControl1.AddShape(text);
 
问题根因
 不熟悉如何绘制自定义图形。
2.3.2 参数控件:参数配置控件绑定模块的方法
描述
 环境:VM4.2 + VS2013及以上
 现象:如何给参数配置控件绑定指定模块?
 解答
- 参数配置控件绑定模块方法(C#),示例代码如下。
 
C#
// 参数配置控件模块绑定
private void button3_Click(object sender, EventArgs e)
{
    try
    {
        //参数配置
        var blobTool = (VMControls.Interface.IVmModule)VmSolution.Instance["流程1.BLOB分析1"];
        //参数配置控件
        vmParamsConfigControl1.ModuleSource=blobTool;
        //参数配置控件带渲染
        vmParamsConfigWithRenderControl1.ModuleSource = blobTool;
    }
    catch (VmException ex)
    {
        MessageBox.Show(Convert.ToString(ex.errorCode, 16));
    }
}
 
2.参数配置控件绑定模块方法(C++),代码如下。
C++
//参数设置
void CMFCApplication5Dlg::OnBnClickedButton4()
{
	// TODO: 在此添加控件通知处理程序代码
	try
	{
		auto pObject = (CModuParamsBase*)(*m_pVmSol)[“流程1.圆查找1”];
		m_ParamsRender.SetParamsInfo(pObject, "");
	}
	catch (CVmException ex)
	{
		CString strTemp;
		strTemp.Format(_T("%d"), ex.GetErrorCode());
	}
}
 
3.绑定效果
 
问题根因
 不熟悉控件的资源绑定方法。
2.3.3 控件颜色:控件颜色修改方法
描述
 环境:VM4.2 + VS2013及以上
 现象:如何修改控件颜色?
 解答
- 修改控件背景色,示例代码(C#)如下。注意:渲染控件颜色修改的前提是渲染控件已经绘制到窗口中。
当通过拖拉渲染控件到窗口中时,控件颜色修改只能写在窗口初始化之后,如Load事件中或按钮事件中;
当通过动态定义渲染控件到窗口中时,控件颜色修改只能写在窗口Add渲染控件之后,如this.Controls.Add(vmRenderControl1)之后。 
C#
private void button16_Click(object sender, EventArgs e)
{
    string str = "#DD22AA";//十六进制颜色码
    vmRenderControl1.SetBackground(str);
}
 
2.修改控件背景色,示例代码(C++)如下。
C++
//修改控件背景色
int CMFCApplication5Dlg::SetBackGroundColor()
{
	// TODO: 在此处添加实现代码.
	CString str("#DD22AA");//十六进制颜色码
	m_RenderCtr.SetBackground(str.GetBuffer());
	return 0;
}
 
3.修改效果
 
问题根因
 不熟悉控件接口。
2.3.4 独立控件:二次开发单独显示Group的方法
描述
 环境:VM4.2 + VS2013及以上
 现象:如何单独显示Group(.gro后缀)文件?
 解答
- 首先需要在界面上拖拽SingleModuleSetConfigControl控件,该控件专门用于显示Group。
2.加载Group文件并绑定到该控件的ModuleSource属性,代码如下。 
C#
private void button16_Click(object sender, EventArgs e)
{
    vmSingleModuleSetConfigControl1.ModuleSource = VmSolution.LoadIndependentGroup("D://Files//test.gro");
}
 
3.显示效果
 
问题根因
 不熟悉控件的资源绑定方法。
2.3.5 取流控件:实时取流控件的使用方法
描述
 环境:VM4.2 + VS2013及以上
 现象:VM4.2新增了一个控件,实时取流控件。
 解答
 1.在工具箱添加控件后,就可以拖拽实时取流控件VmRealTimeAcqControl到窗体中进行使用。
 2.拖拉控件后,还需要将全局相机与控件进行绑定,代码如下所示:
C#
GlobalCameraModuleCs.GlobalCameraModuleTool cameraModu=(GlobalCameraModuleCs.GlobalCameraModuleTool)VmSolution.Instance["全局相机1"];
vmRealTimeAcqControl1.ModuleSource = cameraModu;
vmRealTimeAcqControl1.StartGrabbing();//开始采集
vmRealTimeAcqControl1.Stop Grabbing();//停止采集
 
问题根因
 不熟悉实时取流控件的使用。
2.3.6 渲染控件:渲染控件绘制ROI的方法
描述
 环境:VM4.2.0 + VS2013及以上
 现象:VM二次开发,如何在渲染控件上绘制ROI,以实现界面快速建模、调整模块ROI?
 解答
 安装20220914及后续补丁包,注册GAC后,在二次开发软件中注册ROI绘制事件。示例代码如下:
C#
using VMControls.RenderInterface;
using VMControls.Interface;
using VMControls.Winform.Release;
// 注册ROI绘制事件
vmRenderControl1.IsShowCustomROIMenu = true;
vmRenderControl1.OnCustomRoiAddEvent -= VmRenderControl1_OnCustomRoiAddEvent;
vmRenderControl1.OnCustomRoiAddEvent += VmRenderControl1_OnCustomRoiAddEvent;
// ROI绘制事件
private void VmRenderControl1_OnCustomRoiAddEvent(object sender, VMControls.RenderInterface.RoiEventArgs e)
{
	roi = e.Roi;
	roi.DataChangedCommand = new DelegateCommand<IROI>(OnDataChangedCommandExcute);
    if (roi is IRectROI rect)  // 绘制的ROI为矩形
	{
	// Avoid表示ROI类型为屏蔽区
	if (!(rect.UseType == ROIUseType.Avoid)) { // To Do Code }
	// To Do Code 例如设置模块ROI、例如模板匹配建模等
	}
}
// ROI修改事件
private void OnDataChangedCommandExcute(IROI obj)
{
	if (roi is IRectROI rect)  // 绘制的ROI为矩形
	{ 
	if (!(rect.UseType == ROIUseType.Avoid)) //屏蔽区
	{ // To Do Code }
	// To Do Code 例如设置模块ROI、例如模板匹配建模等
	}
}
 
问题根因
 不熟悉渲染控件的相关事件。
2.3.7 控件语言:控件设置为英文的方法
描述
 环境:VM4.2+VS2013及以上
 现象:如何设置控件为英文?
 解答
 在VM4.0的二次开发中,控件设置为英文的相关配置文件在debug路径中LangCFG文件中,修改配置文件LanguageSet.cfg。在VM4.2的二次开发中,因为debug中没有进行拷贝操作,所以修改配置文件路径如下图所示,zh-cn表示中文,英文则用en-us。
 
上图中是手动打开配置文件直接进行修改,也可以通过代码来修改配置文件:
C#
///修改对应cfg文件内容,切换中文
string path2 =Path+ "Development\\V4.x\\ComControls\\Assembly\\LangCFG\\LanguageSet.cfg";
string[] filelines = File.ReadAllLines(path2);
filelines[2] = "  <LangSet>zh-cn</LangSet>";
File.WriteAllLines(path2, filelines);
///修改对应文件内容,切换英文
string path2 =Path+ "Development\\V4.x\\ComControls\\Assembly\\LangCFG\\LanguageSet.cfg";
string[] filelines = File.ReadAllLines(path2);
filelines[2] = "  <LangSet>en-us</LangSet>";
File.WriteAllLines(path2, filelines);
 
注意:切换后VM二次开发需要重新启动才会生效
 问题根因
 不熟悉如何修改VM4.2二次开发控件的语言
2.3.8 控件报错:子窗口包含主界面控件及其它控件时报错的解决方法
描述
 环境:VM4.0及以上 + VS2013及以上
 现象:子窗口包含主界面控件(VmMainViewConfigControl)及其它控件时,打开子窗口报错如下所示。
 
解答
 将子窗口中的VM控件的属性【TopStop】都改为false即可。
 
问题根因
 主界面控件机制问题,VM4.3将会改善。
2.3.9 图像传入:给渲染控件传入图像的方法
描述
 环境:VM4.0及以上 + VS2013及以上
 现象:VM二次开发如何将在渲染控件上显示本地图像?
 解答
 1.可以通过模块的方式,再将渲染控件绑定模块或流程来显示本地图像,也可以通过VmRnderControl控件的ImageSource属性来设置图像。
 2.首先需要继承IImaageData接口实现图像数据类。示例代码如下:
C#
public class ImageSource : VMControls.RenderInterface.IImageData
{
    public ImageSource(int width, int height, byte[] buffer, VMPixelFormat pixelformat)
    {
        Width = width;
        Height = height;
        PixelFormat = pixelformat == VMPixelFormat.VM_PIXEL_MONO_08 ? "Gray8" : "Rgb24";
        int channels = pixelformat == VMPixelFormat.VM_PIXEL_MONO_08 ? 1 : 3;
        if (buffer.Length != width * height * channels)
            throw new Exception("buffer is error");
        Buffer = new byte[buffer.Length];
        Array.Copy(buffer, Buffer, buffer.Length);
    }
    public int Width { get; set; }
    public int Height { get; set; }
    public byte[] Buffer { get; set; }
    public string MemoryAddress
    {
        get
        {
            GCHandle gCHandle = GCHandle.Alloc(Buffer, GCHandleType.WeakTrackResurrection);
            IntPtr bufferAddress = GCHandle.ToIntPtr(gCHandle);
            return bufferAddress.ToString();
        }
    }
    public string PixelFormat { get; }
}
 
3.使用OpenCV等接口获取本地图像数据流并转换成ImageSource类型显示,示例代码如下:
C#
private void button1_Click(object sender, EventArgs e)
{
    OpenFileDialog openFile = new OpenFileDialog();
    if (openFile.ShowDialog() == DialogResult.OK)
    {
        pictureBox1.Image = Image.FromFile(openFile.FileName);
        var mat = Cv2.ImRead(openFile.FileName);
        byte[] imageByte = new byte[mat.Width * mat.Height * mat.Channels()];
        ImageSource imageSource = null;
        if (mat.Channels() == 1)
        {
            imageSource = new ImageSource(mat.Width, mat.Height, imageByte, VMPixelFormat.VM_PIXEL_MONO_08);
        }
        else
        {
            //OpenCV为BGR VM 为RGB通道
            Cv2.CvtColor(mat,mat,ColorConversionCodes.BGR2RGB);
            Marshal.Copy(mat.Data, imageByte, 0, imageByte.Length);
            imageSource = new ImageSource(mat.Width, mat.Height, imageByte, VMPixelFormat.VM_PIXEL_RGB24_C3);
        }
        if(imageSource!=null)
        vmRenderControl1.ImageSource = imageSource;
   }
}
 
注意事项:灰度图读取到的如果是三通道需先转成单通道图像,彩色图需要交换下R和G通道,即用Cv2.CvtColor转换一下。
 问题根因
 不熟ImageSource属性及接口。
2.3.10 主界面控件:主界面控件添加参数修改记录并将记录保存至本地的方法
描述
 环境:VM4.2 + VS2013及以上
 现象:在VisionMaster软件里,修改模块参数值时,右下角的状态栏会显示修改记录并且记录至本地日志,而在VM二次开发里不会显示修改和记录日志。
 
解答
 当前VM二次开发默认不支持,要支持需手动添加代码Apps.XmlParser.ParamTab.NameValueItem.logManager = new Apps.XmlUI.UILogManager(false);加载到程序初始化函数里。其中,添加引用集Apps.XmlParser.dll和Apps.XmlUI.dll在VM安装路径“VisionMaster4.2.0\Development\V4.x\ComControls\Assembly”下。
 示例代码如下:
C# 
public Form1()
{
InitializeComponent();
Apps.XmlParser.ParamTab.NameValueItem.logManager = new Apps.XmlUI.UILogManager(false);
}
 
添加后,控件日志显示如下:
 
并且,在二次开发应用程序exe同级下的log/UI/SystemLog.log就会记录模块参数修改的日志。
 注:若没有该log,请将VisionMaster路径“VisionMaster4.2.0\Development\V4.x
 \ComControls\Assembly”下的第一个文件夹“3rdLib”拷贝替换至二次开发应用程序exe同级路径下。
 问题根因
 某些功能接口不对外开放,需手动添加。
2.3.11 渲染控件:渲染控件绘制十字方法
描述
 环境:VM4.2 + VS2013及以上
 现象:如何在vmRenderControl控件上显示十字线?
 解答
- 使用控件AddShape()接口显示十字线(渲染控件渲染时机为流程执行结束回调,适合静态显示),示例代码如下;
 
C#
/// <summary>
/// 流程工作状态回调
/// </summary>
/// <param name="workStatusInfo"></param>
private void VmSolution_OnWorkStatusEvent(VM.PlatformSDKCS.ImvsSdkDefine.IMVS_MODULE_WORK_STAUS workStatusInfo)
{
    if (workStatusInfo.nWorkStatus == 0 && workStatusInfo.nProcessID == 10000)//流程空闲且为流程1
    {
        if (vmRenderControl1.ImageSource != null)
        {
            var width = vmRenderControl1.ImageSource.Width;
            var height = vmRenderControl1.ImageSource.Height;
            var lineY = new LineEx(new System.Windows.Point(width / 2, 0), new System.Windows.Point(width / 2, height), stroke: "#4400FF");
            var lineX = new LineEx(new System.Windows.Point(0, height / 2), new System.Windows.Point(width, height / 2), stroke: "#4400FF");
            renderControl.vmRenderControl1.AddShape(lineX);
            renderControl.vmRenderControl1.AddShape(lineY);
        }
    }
}
 
- 使用几何创建模块生成直线的方式创建十字线(推荐);


 
最终二次开发渲染控件显示效果如图所示:
 
问题根因
 不熟悉渲染控件的使用。


















![【群智能算法】一种改进的哈里斯鹰优化算法 IHHO算法[1]【Matlab代码#17】](https://img-blog.csdnimg.cn/cb50fe5045ea40ea85e0a17860ae65aa.png)
