#pragma once #include #include #include #include #include #include #include #include "DataStructure.h" #include "Utility.h" // 使用 utf8 编码 #if _MSC_VER >= 1600 #pragma execution_character_set("utf-8") #endif // 自定义警告信息 #define vDebug() qDebug() << "[" << __FUNCTION__ << ":" << __LINE__ << "]" #define vWarning() qWarning() << "[" << __FUNCTION__ << ":" << __LINE__ << "]" // dll 通用接口函数名称 // 获取工具函数的指针 #define FUNCTION_GETTOOL ("GetTool") // 释放工具函数的指针 #define FUNCTION_RELEASETOOL ("ReleaseTool") ////////////////////////////////////////////// // Dll工具的描述信息 typedef struct _tagDllToolDescription { TOOL_TYPE Type; // 工具的类型(工具、控件、跳转指令) QString strCategory; // 工具的分组 QString strName; // 工具名字 QString strAliasName; // 工具别名(通常为曾用名或者中文名) QString strVersion; // 工具版本 QString strInfo; // 描述信息 _tagDllToolDescription() { Type = TOOL_TYPE::TOOL_TYPE_STANDARD; } } DLL_TOOL_DESC, * LPDLL_TOOL_DESC; //////////////////////////////////////////////// //// 用于UI、Runtime和Dll同步的消息 //enum class UI_SYNC_MSG: short //{ // EDIT_TEXT_CHANGED, // COMBO_SEL_CHANGED, // LIST_SEL_CHANGED, // CHECKBOX_CHANGED, // RADIOBOX_CHANGED, // VALUE_CHANGED // //}; // dll消息向exe同步的回调函数(控件类型,已经废弃,统一和value类型一样采用postEvent了) // QWidget: 触发消息的控件指针 // MSG: 触发的消息 typedef std::function CONTROL_CALLBACK; //// dll数值向exe同步的回调函数(数值类型,由于影响Tool的Execute的效率,已经废弃,改为postEvent的方式) //typedef std::function VALUE_CALLBACK; ////////////////////////////////////////////////////////// // 工具中的对话框信息封装类(PORT类型工具没有对话框界面) class DllToolDialog : public QDialog { public: DllToolDialog(QWidget* parent = nullptr) : QDialog(parent), m_pEventTarget(nullptr), m_pSyncTarget(nullptr), m_pGvlTarget(nullptr), m_pDB(nullptr), controlCallback(nullptr), m_pPouTarget(nullptr) { }; virtual ~DllToolDialog() {}; public: virtual VPEnum::RETURN_VALUE Execute() { return VPEnum::RETURN_VALUE::Success; }; virtual void Running(bool bRun) { Q_UNUSED(bRun); }; virtual bool updateValue(int nIndex) { Q_UNUSED(nIndex); return true; }; // 设置Event类型工具的事件接收对象(exe中的TaskManager) virtual void setEventTarget(QObject* pTarget) { this->m_pEventTarget = pTarget; } // 设置变量和控件同步事件的接收对象(exe中的WindowRunTime) virtual void setSyncTarget(QObject* pTarget) { this->m_pSyncTarget = pTarget; } // 设置全局变量操作指针,用于接收变量变动通知消息(exe中GvlManager) virtual void setGvlTarget(QObject* pTarget) { this->m_pGvlTarget = pTarget; } // 设置Pou管理者指针,用于接收接口变动通知消息(exe中的WindowAppPouScene) virtual void setPouTarget(QObject* pTarget) { this->m_pPouTarget = pTarget; } virtual bool Serialized(QDataStream& ar, bool bIsOut) { Q_UNUSED(ar); Q_UNUSED(bIsOut); return true; } // 设置控件双向同步的回调函数 void setControlCallback(CONTROL_CALLBACK callback) { this->controlCallback = callback; } // 设置绑定的DB变量(仅硬件工具有可能会用到) void setBindDB(GVL* pDB) { this->m_pDB = pDB; } // 解除DB的绑定(仅硬件工具有可能会用到) void unbindDB() { this->m_pDB = nullptr; } //// 设置数值变更向UI单向同步的回调函数 //void setValueCallback(VALUE_CALLBACK callback) //{ // this->valueCallback = callback; //} // 变动的硬件数值向UI同步(第一种方式,按接口全名称同步,主要用于硬件组态的接口数值同步,因为硬件组态的数值没有Execute) void syncHdValueToUi(QString strInstanceName, QString strInfName ) { if (this->m_pSyncTarget == nullptr) { // qDebug() << "ToolDialogImpl::syncValueToUi failed - m_pSyncTarget is nullptr."; return; } // 生成数值同步消息,向UI同步 SyncHdValueEvent* valueEvent = new SyncHdValueEvent(); valueEvent->setGroupName(m_strPouName); // 保存变动数值信息 valueEvent->m_strInstanceName = strInstanceName; valueEvent->m_strInfName = strInfName; // 发送 value 同步 event,event指针会自动释放 QCoreApplication::postEvent(m_pSyncTarget, valueEvent); } // 变动的硬件数值向UI同步(第二种方式,按接口指针同步,主要用于硬件组态的接口数值同步,因为硬件组态的数值没有Execute) void syncHdValueToUi(void* pValue) { if (this->m_pSyncTarget == nullptr) { // qDebug() << "ToolDialogImpl::syncValueToUi failed - m_pSyncTarget is nullptr."; return; } // 生成数值同步消息,向UI同步 SyncHdValueEvent* valueEvent = new SyncHdValueEvent(); // 保存变动数值信息 valueEvent->m_pSrcValue = pValue; // 发送 value 同步 event,event指针会自动释放 QCoreApplication::postEvent(m_pSyncTarget, valueEvent); } // 变动的控件向UI同步 void syncControlToUi(QWidget* pWidget, UI_SYNC_MSG syncMsg) { if (this->m_pSyncTarget == nullptr) { qDebug() << "ToolDialogImpl::syncControlToUi failed - m_pSyncTarget is nullptr."; return; } // 生成控件的同步消息,向UI同步 SyncControlEvent* controlEvent = new SyncControlEvent(); // 保存变动数值信息 controlEvent->m_pSrcControl = pWidget; controlEvent->m_SyncMsg = syncMsg; // 发送 value 同步 event,event指针会自动释放 QCoreApplication::postEvent(m_pSyncTarget, controlEvent); } DebugData GetDebugData() { return m_DebugData; } void SetDebugData(DebugData data) { m_DebugData = data; } DebugData* GetDebugDataPtr() { return &m_DebugData; } void SetToolInfo(QString strPouName, QString strInstanceName) { m_strPouName = strPouName; m_strInstanceName = strInstanceName; } void showEvent(QShowEvent* event) { Q_UNUSED(event); // 将本工具的数据备份一下,以便误操作的时候,使用取消按钮恢复数据 try { m_BufferBackup.open(QIODevice::WriteOnly); QDataStream ar(&m_BufferBackup); this->Serialized(ar, true); m_BufferBackup.close(); } catch (HalconCpp::HException& ex) { QString hErr = Utility::getHalconErrMessage(ex.ErrorCode()); } catch (...) { qWarning() << "Backup To Buffer Error"; } } void closeEvent(QCloseEvent* event) { event->ignore(); this->hide(); } bool RecoverData() { try { m_BufferBackup.open(QIODevice::ReadOnly); QDataStream ar(&m_BufferBackup); this->Serialized(ar, false); m_BufferBackup.close(); this->hide(); } catch (...) { qWarning() << "Load Frm Buffer Error"; return false; } return true; } protected: // Event Target(TaskManager*) QObject* m_pEventTarget; // Sync Target(WindowRunTime*) QObject* m_pSyncTarget; // 用于接收数值变动通知的指针(GvlManager*) QObject* m_pGvlTarget; // 用于接收接口变动通知的指针(WindowAppPouScene*) QObject* m_pPouTarget; // 2022-3-1,本工具所绑定的DB变量组指针 GVL* m_pDB; // 控件用于双向同步的回调函数 CONTROL_CALLBACK controlCallback; //// 用于数值变更后向界面同步的回调函数 //VALUE_CALLBACK valueCallback; DebugData m_DebugData; // 本工具的实例名字 QString m_strInstanceName; // 本工具所在的Pou名字 QString m_strPouName; //用于备份数据的buffer QBuffer m_BufferBackup; }; ////////////////////////////////////////////////////////// // 工具信息的封装类 class DllTool { public: DllTool() { ////ControlCallback = nullptr; //m_Even.hEvenHandle = nullptr; //m_Even.nEvenTime = 0; m_pDlgTool = nullptr; } virtual ~DllTool() { } public: // 执行工具 virtual VPEnum::RETURN_VALUE Execute() { if (m_pDlgTool != nullptr) { return m_pDlgTool->Execute(); } return VPEnum::RETURN_VALUE::Error; } //系统Run和Stop时调用 virtual void Running(bool bRun) { if (m_pDlgTool!= nullptr) { m_pDlgTool->Running(bRun); } } // virtual bool updateValue(int nIndex) { if (m_pDlgTool != nullptr) { return m_pDlgTool->updateValue(nIndex); } return false; } // 显示参数设置对话框 virtual void ShowDialog() { if (m_pDlgTool != nullptr) { m_pDlgTool->show(); m_pDlgTool->setWindowTitle(this->m_strPouName + (" ---> ") + this->m_strInstanceName); } } // 获取调试参数 virtual DebugData GetDebugData() { if (m_pDlgTool != nullptr) { return m_pDlgTool->GetDebugData(); } DebugData data; return data; } // 2022-10-4增加,Dll信息中保存一下本Dll对应的全路径,用于后续查询 QString m_strFullPath; public: /// /// 工具初始化(不带参数) /// virtual int InitTool() = 0; /// /// 纯虚函数,工具初始化 /// /// 父窗体指针 /// 工具所在Pou的名字 /// 工具生成的实例名字 /// virtual int InitTool(QWidget* pWnd, QString strPouName, QString strInstanceName, QObject* pEventTarget = nullptr) = 0; /// /// 获取工具的总体描述信息 /// virtual const DLL_TOOL_DESC& Description() = 0; virtual bool bindValuePtrByName(const QString strName, const int nIndex) = 0; /// /// 获取本工具的名称 /// /// QString getName() { return this->m_strPouName; } /// /// 获取本工具的实例名称 /// /// QString getInstanceName() { return this->m_strInstanceName; } /// /// 序列化至文件 /// virtual bool SerializedToDoc(QDataStream& out) { Q_UNUSED(out); return true; } /// /// 从文件反序列化 /// virtual bool SerializedFromDoc(QDataStream& in) { Q_UNUSED(in); return true;} // 修改所在的Pou名字 void ModToolPouName(QString strNewPouName) { this->m_strPouName = strNewPouName; if (m_pDlgTool!= nullptr) { m_pDlgTool->SetToolInfo(m_strPouName, m_strInstanceName); } } // 修改工具的实例名字 void ModToolInstanceName(QString strNewInstanceName) { this->m_strInstanceName = strNewInstanceName; if (m_pDlgTool != nullptr) { m_pDlgTool->SetToolInfo(m_strPouName, m_strInstanceName); } } // 获取指定的接口 DLL_INF& Interface(const int nIndex) { return m_Interfaces[nIndex]; } // 获取工具接口的数量 int GetInterfaceSize() { return m_Interfaces.size(); } // 动态增加接口 virtual void AddInterface(const DLL_INF& dll_inf) { m_Interfaces.push_back(dll_inf); }; // 动态删除接口 virtual bool DelInterface(const QString& infName) { bool bFind = false; for ( int i = 0;i< m_Interfaces.size();i++ ) { DLL_INF& dllInf = m_Interfaces[i]; if (dllInf.strName == infName) { // 只有动态接口才允许删除 if (!dllInf.bDynamic) { qDebug() << "DllTool::DelInterface - failed, reason: " << dllInf.strName << " is not dynamic interface."; return false; } m_Interfaces.removeAt(i); bFind = true; } // 后续的接口Index都需要 - 1 else { dllInf.nIndex --; } } return bFind; } // 获取工具接口的值 template T& Value(const int nIndex) { if (m_Interfaces.size() <= nIndex) { qWarning() << "DllTool::Value() Error - Inf Size:[" << m_Interfaces.size() << "] Index Vilue: [" << nIndex << "]"; } return *(T*)m_Interfaces[nIndex].value.Ptr; } // 设置Interface的值(默认绑定成员变量,不重新开辟内存) template void SetValue(const int nIndex, T& t) { if (m_Interfaces.size() <= nIndex) { qWarning() << "DllTool::SetValue() Error - Inf Size:[" << m_Interfaces.size() << "] Index Vilue: [" << nIndex << "]"; return; } this->SetValue(m_Interfaces[nIndex].value, t); } // 设置Interface的值(默认绑定成员变量,不重新开辟内存) template void SetValue(VALUE& value, T& t) { value.Ptr = (void**)&t; } // 2022-3-17,放弃了重新开辟内存的做法, //// 设置Interface的值(需要重新开辟内存) //template //void SetValue(const int nIndex, T& t) //{ // if (m_Interfaces.size() <= nIndex) // { // qWarning() << "DllTool::SetValue() Error - Inf Size:[" << m_Interfaces.size() << "] Index Vilue: [" << nIndex << "]"; // return; // } // this->SetValue(m_Interfaces[nIndex].value, t); //} //// 设置Interface的值(需要重新开辟内存) //template //void SetValue(VALUE& value, T& t) //{ // T* newValue = new T; // *newValue = t; // value.Ptr = (void**)newValue; //} // 更新Interface的值(已经开辟好了内存,只是做值的更新) template void UpdateValue(const int nIndex, T& t, VALUE_PASS_MODE passmode = VALUE_PASS_MODE::PASS_BY_VALUE) { if (m_Interfaces.size() <= nIndex) { qWarning() << "DllTool::UpdateValue() Error - Inf Size:[" << m_Interfaces.size() <<"] Index Vilue: [" << nIndex << "]" ; return; } // 按值 if (passmode == VALUE_PASS_MODE::PASS_BY_VALUE) { *(T*)m_Interfaces[nIndex].value.Ptr = t; } // 按地址 else { *m_Interfaces[nIndex].value.Ptr = &t; } } // 设置Event类型工具的事件接收对象(exe中的TaskManager) void setEventTarget(QObject* pTarget) const { Q_ASSERT(pTarget != nullptr); if (m_pDlgTool) { this->m_pDlgTool->setEventTarget(pTarget); } } // 设置变量和控件同步事件的接收对象(exe中的WindowRuntime*) void setSyncTarget(QObject* pTarget) const { Q_ASSERT(pTarget != nullptr); if (m_pDlgTool) { this->m_pDlgTool->setSyncTarget(pTarget); } } // 设置全局变量操作指针,用于接收变量变动通知消息(exe中GvlManager) void setGvlTarget(QObject* pTarget) { Q_ASSERT(pTarget != nullptr); if (m_pDlgTool) { this->m_pDlgTool->setGvlTarget(pTarget); } } // 设置Pou管理者指针,用于接收接口变动通知消息(exe中的WindowAppPouScene) void setPouTarget(QObject* pTarget) { Q_ASSERT(pTarget != nullptr); if (m_pDlgTool) { this->m_pDlgTool->setPouTarget(pTarget); } } // 设置控件双向同步的回调函数 void setControlCallback(CONTROL_CALLBACK callback) { if (m_pDlgTool) { this->m_pDlgTool->setControlCallback(callback); } } // 设置绑定的DB变量(仅硬件工具有可能会用到) void setBindDB(GVL* pDB) { Q_ASSERT(pDB != nullptr); this->m_pDlgTool->setBindDB(pDB); } // 解除绑定的DB变量(仅硬件工具有可能会用到) void unbindDB() { this->m_pDlgTool->unbindDB(); } //// 设置数值向UI同步的回调函数 //void setValueCallback(VALUE_CALLBACK callback) //{ // this->m_pDlgTool->setValueCallback(callback); //} protected: // 初始化默认的接口描述 virtual void InitDefaultInterfaces( bool withValue = false ) = 0; protected: // 本工具的接口 QVector m_Interfaces; // 本工具的对话框 DllToolDialog* m_pDlgTool; // 本工具的实例名字 QString m_strInstanceName; // 本工具所在的Pou名字 QString m_strPouName; };