前面有一篇文章讲过C++和三菱plc的通讯:https://blog.csdn.net/V_Gogol/article/details/103389983,本文是其拓展。
背景
前面讲过在工程中添加Activex控件,并使用控件创建变量,此对象包含了PLC的多个操作函数。但是在实际项目中遇到了一个问题,就是只能在主对话框放入activex控件,相当于这个对象的作用域仅限于主对话框对应的头文件和源文件,如果要在其他类中对PLC进行操作(例如设置或读取指定端口的值)就会显得比较麻烦。本文讲的是编写一个专门的PLC操作类包含回调函数来实现其他类里也可以方便的对plc进行操作。
实现
直接贴代码:
这个类是为了方便复用和全局范围操作plc编写的,声明了几个回调函数,下面主要讲设置端口值和读取端口值的封装操作。
下面是回调函数,在主对话框初始化函数中注册,就能够实现plc类里进行设置和读取操作时自动执行主对话框中实际的plc操作相关代码
这个是设置和读取端口值函数
以上是声明,下面才是函数实现:
设置和读取差不多,下面以设置值为例对代码进行详细讲解
这个函数在主对话框调用,注册回调函数,相当于通知主对话框,只要调用CFXPlc这个类中的设置端口值函数,就会自动执行主对话框的的对应函数。
////回调--设置指定端口值
BOOL CFXPlc::C_SetPortValue(BOOL(CALLBACK*lpSetPortValue)(CString PortName, long PortValue))
{
m_pSPlcV = lpSetPortValue;
return PLC_NO_ERROR;
}
下面这个是CFXPlc类里的函数,用于判定回调是否有注册,没有注册报警返回
//回调中间函数--设置指定端口值
BOOL CFXPlc::Mid_SetPortValue(CString PortName, long PortValue)
{
if (NULL == m_pSPlcV)
{
AfxMessageBox(L"fx-setportvalue未编写回调函数!");
return PLC_ERROR;
}
else
return(*m_pSPlcV)(PortName, PortValue);
}
最后就是实际的设置端口值函数,包括两个参数,端口名称和想要设定的值,代码如下
//设置指定端口值
int CFXPlc::SetPortValue(CString PortName, long PortValue)
{
if (PLC_ERROR == Mid_SetPortValue(PortName, PortValue))
{
AfxMessageBox(PortName + L"值设置失败!");
return PLC_ERROR;
}
else
return PLC_NO_ERROR;
}
它会调用那个回调中间函数,回调中间函数返回的就是主对话框的注册的回调函数地址,也就是直接执行主对话框的中对应的plc操作函数。
后续任何要使用plc操作的地方,只要包含CFXPlc类,创建对象就可以直接操作plc。
下面将主对话框中要编写的代码:
//回调函数--设置指定端口值
BOOL CALLBACK CB_SetPortValue(CString PortName, long Value)
{
try
{
if (PLC_NO_ERROR != SetPlcPortValue(0, PortName, Value))
return PLC_ERROR;
else
return PLC_NO_ERROR;
}
catch (...)
{
AfxMessageBox(L"设置"+PortName+L"出错!");
return PLC_ERROR;
}
}
上面是主对话框中的回调函数,其中SetPlcPortValue这个函数的具体实现我上篇文章里有源代码。
最后一步,只需要在程序初始化时将CB_SetPortValue的函数地址传给fxplc类中的对应回调函数即可,也就是回调注册,它起的作用是只要调用了fxplc类中SetPortValue这个函数,就会自动主对话框的CB_SetPortValue函数,这样,就可以实现拖入activex控件后整个程序都可操作plc了。
来源:CSDN
作者:V_Gogol
链接:https://blog.csdn.net/V_Gogol/article/details/103770164