公司的业务是机器人的系统集成,需要在halcon机器视觉软件处理后,用winform与上位机进行串口的通讯。
这次winform采用了MVC的架构。原来我一直以为MVC都是用在ASP.NET上的,这次看到它在Winform上也能大展身手。
下图是框架结构图:
可以看到有Controller, Model和Viewer文件夹。但是Model文件夹是空的,也就是说这次没有使用Model文件。
先看Controller文件夹,里面是MainController.cs
它是主业务逻辑:
// 主业务逻辑
public class MainController : IReceiveImage
{
private static MainController _controller;
public static MainController GetController()
{
if (_controller == null)
{
_controller = new MainController();
}
return _controller;
}
private ProgramParam _programParam;
private ImageGrabber _imageGrabber;
private FormMain _formMain;
private HDevelopExport _halcon;
private ProgramParam _param;
private SerialUnit _serial;
...
private MainController()
{
_programParam = ProgramParam.Load();
_imageGrabber = new ImageGrabber();
_halcon = new HDevelopExport();
_serial = SerialUnit.GetInstance();
_serial.OnReceived += SerialReceiveHandler;
_param = ProgramParam.Load();
q = new Queue();
mQ = new Queue();
message = "";
backInstruct = "";
UpLeftX = _programParam.UpLeftX;
UpLeftY = _programParam.UpLeftY;
DownRightX = _programParam.DownRightX;
DownRightY = _programParam.DownRightY;
Grayscale = _programParam.GrayValue;
Area1 = _programParam.AreaFrom;
Area2 = _programParam.AreaTo;
Crevice = _programParam.Crevice;
}
MainController的构造函数采用了单例模式,也就是不能随便调用Controller,它一次只能生成一个对象。
下面这段代码是说明调用FormMain作为显示端。
public void SetViewer(FormMain main)
{
_formMain = main;
}
下面代码是连接摄像头和com口
// 连接设备
public void ConnectDevice()
{
var message = "";
try
{
_imageGrabber.OpenGrabber(_programParam.VisionInterfaceName,
_programParam.VisionCameraType, _programParam.VisionDeviceName);
}
catch (Exception e)
{
message = string.Format("连接相机失败:{0}。", e.Message);
if (mQ.Count >= 10)
{
mQ.Dequeue();
mQ.Enqueue(message);
}
else
{
mQ.Enqueue(message);
}
LogHelper.WriteLog(message);
_formMain.DisplayImageMessage();
}
//后台打开串口
var s = _serial.Connect(out string error);
if (s)
{
message = string.Format("打开串口成功: {0}", _param.SerialName);
if (mQ.Count >= 10)
{
mQ.Dequeue();
mQ.Enqueue(message);
}
else
{
mQ.Enqueue(message);
}
LogHelper.WriteLog(message);
_formMain.DisplayImageMessage();
}
else
{
message = string.Format("打开串口失败:{0}" , error);
if (mQ.Count >= 10)
{
mQ.Dequeue();
mQ.Enqueue(message);
}
else
{
mQ.Enqueue(message);
}
LogHelper.WriteLog(message);
_formMain.DisplayImageMessage();
}
LogHelper.WriteLog(message);
}
下面是连续采集图像,接受图像。接受图像后就dispose它,否则大量的图片会积压起来。
// 连续采集图像
public void StartGrabImage()
{
_imageGrabber.Subscribe(this);
_imageGrabber.StartGrab();
}
// 停止采集图像
public void StopGrabImage()
{
_imageGrabber.StopGrab();
_imageGrabber.Unsubscribe(this);
}
// 接收图像
public void ReceiveImage(HImage image)
{
_formMain.DisplayImage(image);
q = Test1(image);
_formMain.DisplayImageMessage();
image.Dispose();
}
private void FormMain_Shown(object sender, System.EventArgs e)
{
_mainController.ConnectDevice();
_mainController.StartGrabImage();
}
再看Viewer端:
public partial class FormMain : Form
{
private MainController _mainController;
private ProgramParam _param;
private SerialUnit _serial;
private HDevelopExport _halcon;
public FormMain()
{
InitializeComponent();
Init();
}
private void Init()
{
_mainController = MainController.GetController();
_mainController.SetViewer(this);
_halcon = new HDevelopExport();
// 设置 Halcon 窗口字体样式
HOperatorSet.SetFont(hSmartWindowControlMain.HalconWindow, "Consolas-Normal-20");
_screenMessage = new List<string>();
}
...
public void DisplayImage(HImage image)
{
hSmartWindowControlMain.HalconWindow.DispImage(image);
hSmartWindowControlMain.HalconWindow.SetPart(0, 0, -2, -2);
_halcon.Find_Nail(image, _mainController.UpLeftX, _mainController.UpLeftY, _mainController.DownRightX, _mainController.DownRightY, _mainController.Grayscale, _mainController.Area1, _mainController.Area2, _mainController.Crevice, out HTuple width, out HTuple height);
for (int i = 0; i < width.Length; i++)
{
hSmartWindowControlMain.HalconWindow.SetColor("green");
hSmartWindowControlMain.HalconWindow.DispCross((double)width[i], (double)height[i], 300.0, 0.0);
}
}
DisplayImage用来显示图像。
Formain其实用的是Halcon的专门显示控件,它作为第三方控件嵌入到Winform中,所以对于它要使用专门的命令来进行显示。
以上就是这次采用MVC框架的主要内容。