DllToolCommon.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. #pragma once
  2. #include <QString>
  3. #include <QVector>
  4. #include <QWidget>
  5. #include <QDialog>
  6. #include <QMessageBox>
  7. #include <QCoreApplication>
  8. #include <QBuffer>
  9. #include "DataStructure.h"
  10. #include "Utility.h"
  11. // 使用 utf8 编码
  12. #if _MSC_VER >= 1600
  13. #pragma execution_character_set("utf-8")
  14. #endif
  15. // 自定义警告信息
  16. #define vDebug() qDebug() << "[" << __FUNCTION__ << ":" << __LINE__ << "]"
  17. #define vWarning() qWarning() << "[" << __FUNCTION__ << ":" << __LINE__ << "]"
  18. // dll 通用接口函数名称
  19. // 获取工具函数的指针
  20. #define FUNCTION_GETTOOL ("GetTool")
  21. // 释放工具函数的指针
  22. #define FUNCTION_RELEASETOOL ("ReleaseTool")
  23. //////////////////////////////////////////////
  24. // Dll工具的描述信息
  25. typedef struct _tagDllToolDescription
  26. {
  27. TOOL_TYPE Type; // 工具的类型(工具、控件、跳转指令)
  28. QString strCategory; // 工具的分组
  29. QString strName; // 工具名字
  30. QString strAliasName; // 工具别名(通常为曾用名或者中文名)
  31. QString strVersion; // 工具版本
  32. QString strInfo; // 描述信息
  33. _tagDllToolDescription()
  34. {
  35. Type = TOOL_TYPE::TOOL_TYPE_STANDARD;
  36. }
  37. } DLL_TOOL_DESC, * LPDLL_TOOL_DESC;
  38. ////////////////////////////////////////////////
  39. //// 用于UI、Runtime和Dll同步的消息
  40. //enum class UI_SYNC_MSG: short
  41. //{
  42. // EDIT_TEXT_CHANGED,
  43. // COMBO_SEL_CHANGED,
  44. // LIST_SEL_CHANGED,
  45. // CHECKBOX_CHANGED,
  46. // RADIOBOX_CHANGED,
  47. // VALUE_CHANGED
  48. //
  49. //};
  50. // dll消息向exe同步的回调函数(控件类型,已经废弃,统一和value类型一样采用postEvent了)
  51. // QWidget: 触发消息的控件指针
  52. // MSG: 触发的消息
  53. typedef std::function<void(QWidget*, UI_SYNC_MSG msg)> CONTROL_CALLBACK;
  54. //// dll数值向exe同步的回调函数(数值类型,由于影响Tool的Execute的效率,已经废弃,改为postEvent的方式)
  55. //typedef std::function<void(void* value, VALUE_TYPE type)> VALUE_CALLBACK;
  56. //////////////////////////////////////////////////////////
  57. // 工具中的对话框信息封装类(PORT类型工具没有对话框界面)
  58. class DllToolDialog : public QDialog
  59. {
  60. public:
  61. DllToolDialog(QWidget* parent = nullptr) :
  62. QDialog(parent),
  63. m_pEventTarget(nullptr),
  64. m_pSyncTarget(nullptr),
  65. m_pGvlTarget(nullptr),
  66. m_pDB(nullptr),
  67. controlCallback(nullptr),
  68. m_pPouTarget(nullptr)
  69. {
  70. };
  71. virtual ~DllToolDialog() {};
  72. public:
  73. virtual VPEnum::RETURN_VALUE Execute() { return VPEnum::RETURN_VALUE::Success; };
  74. virtual void Running(bool bRun) { Q_UNUSED(bRun); };
  75. virtual bool updateValue(int nIndex) { Q_UNUSED(nIndex); return true; };
  76. // 设置Event类型工具的事件接收对象(exe中的TaskManager)
  77. virtual void setEventTarget(QObject* pTarget)
  78. {
  79. this->m_pEventTarget = pTarget;
  80. }
  81. // 设置变量和控件同步事件的接收对象(exe中的WindowRunTime)
  82. virtual void setSyncTarget(QObject* pTarget)
  83. {
  84. this->m_pSyncTarget = pTarget;
  85. }
  86. // 设置全局变量操作指针,用于接收变量变动通知消息(exe中GvlManager)
  87. virtual void setGvlTarget(QObject* pTarget)
  88. {
  89. this->m_pGvlTarget = pTarget;
  90. }
  91. // 设置Pou管理者指针,用于接收接口变动通知消息(exe中的WindowAppPouScene)
  92. virtual void setPouTarget(QObject* pTarget)
  93. {
  94. this->m_pPouTarget = pTarget;
  95. }
  96. virtual bool Serialized(QDataStream& ar, bool bIsOut)
  97. {
  98. Q_UNUSED(ar);
  99. Q_UNUSED(bIsOut);
  100. return true;
  101. }
  102. // 设置控件双向同步的回调函数
  103. void setControlCallback(CONTROL_CALLBACK callback)
  104. {
  105. this->controlCallback = callback;
  106. }
  107. // 设置绑定的DB变量(仅硬件工具有可能会用到)
  108. void setBindDB(GVL* pDB)
  109. {
  110. this->m_pDB = pDB;
  111. }
  112. // 解除DB的绑定(仅硬件工具有可能会用到)
  113. void unbindDB()
  114. {
  115. this->m_pDB = nullptr;
  116. }
  117. //// 设置数值变更向UI单向同步的回调函数
  118. //void setValueCallback(VALUE_CALLBACK callback)
  119. //{
  120. // this->valueCallback = callback;
  121. //}
  122. // 变动的硬件数值向UI同步(第一种方式,按接口全名称同步,主要用于硬件组态的接口数值同步,因为硬件组态的数值没有Execute)
  123. void syncHdValueToUi(QString strInstanceName, QString strInfName )
  124. {
  125. if (this->m_pSyncTarget == nullptr)
  126. {
  127. // qDebug() << "ToolDialogImpl::syncValueToUi failed - m_pSyncTarget is nullptr.";
  128. return;
  129. }
  130. // 生成数值同步消息,向UI同步
  131. SyncHdValueEvent* valueEvent = new SyncHdValueEvent();
  132. valueEvent->setGroupName(m_strPouName);
  133. // 保存变动数值信息
  134. valueEvent->m_strInstanceName = strInstanceName;
  135. valueEvent->m_strInfName = strInfName;
  136. // 发送 value 同步 event,event指针会自动释放
  137. QCoreApplication::postEvent(m_pSyncTarget, valueEvent);
  138. }
  139. // 变动的硬件数值向UI同步(第二种方式,按接口指针同步,主要用于硬件组态的接口数值同步,因为硬件组态的数值没有Execute)
  140. void syncHdValueToUi(void* pValue)
  141. {
  142. if (this->m_pSyncTarget == nullptr)
  143. {
  144. // qDebug() << "ToolDialogImpl::syncValueToUi failed - m_pSyncTarget is nullptr.";
  145. return;
  146. }
  147. // 生成数值同步消息,向UI同步
  148. SyncHdValueEvent* valueEvent = new SyncHdValueEvent();
  149. // 保存变动数值信息
  150. valueEvent->m_pSrcValue = pValue;
  151. // 发送 value 同步 event,event指针会自动释放
  152. QCoreApplication::postEvent(m_pSyncTarget, valueEvent);
  153. }
  154. // 变动的控件向UI同步
  155. void syncControlToUi(QWidget* pWidget, UI_SYNC_MSG syncMsg)
  156. {
  157. if (this->m_pSyncTarget == nullptr)
  158. {
  159. qDebug() << "ToolDialogImpl::syncControlToUi failed - m_pSyncTarget is nullptr.";
  160. return;
  161. }
  162. // 生成控件的同步消息,向UI同步
  163. SyncControlEvent* controlEvent = new SyncControlEvent();
  164. // 保存变动数值信息
  165. controlEvent->m_pSrcControl = pWidget;
  166. controlEvent->m_SyncMsg = syncMsg;
  167. // 发送 value 同步 event,event指针会自动释放
  168. QCoreApplication::postEvent(m_pSyncTarget, controlEvent);
  169. }
  170. DebugData GetDebugData()
  171. {
  172. return m_DebugData;
  173. }
  174. void SetDebugData(DebugData data)
  175. {
  176. m_DebugData = data;
  177. }
  178. DebugData* GetDebugDataPtr()
  179. {
  180. return &m_DebugData;
  181. }
  182. void SetToolInfo(QString strPouName, QString strInstanceName)
  183. {
  184. m_strPouName = strPouName;
  185. m_strInstanceName = strInstanceName;
  186. }
  187. void showEvent(QShowEvent* event)
  188. {
  189. Q_UNUSED(event);
  190. // 将本工具的数据备份一下,以便误操作的时候,使用取消按钮恢复数据
  191. try
  192. {
  193. m_BufferBackup.open(QIODevice::WriteOnly);
  194. QDataStream ar(&m_BufferBackup);
  195. this->Serialized(ar, true);
  196. m_BufferBackup.close();
  197. }
  198. catch (HalconCpp::HException& ex)
  199. {
  200. QString hErr = Utility::getHalconErrMessage(ex.ErrorCode());
  201. }
  202. catch (...)
  203. {
  204. qWarning() << "Backup To Buffer Error";
  205. }
  206. }
  207. void closeEvent(QCloseEvent* event)
  208. {
  209. event->ignore();
  210. this->hide();
  211. }
  212. bool RecoverData()
  213. {
  214. try
  215. {
  216. m_BufferBackup.open(QIODevice::ReadOnly);
  217. QDataStream ar(&m_BufferBackup);
  218. this->Serialized(ar, false);
  219. m_BufferBackup.close();
  220. this->hide();
  221. }
  222. catch (...)
  223. {
  224. qWarning() << "Load Frm Buffer Error";
  225. return false;
  226. }
  227. return true;
  228. }
  229. protected:
  230. // Event Target(TaskManager*)
  231. QObject* m_pEventTarget;
  232. // Sync Target(WindowRunTime*)
  233. QObject* m_pSyncTarget;
  234. // 用于接收数值变动通知的指针(GvlManager*)
  235. QObject* m_pGvlTarget;
  236. // 用于接收接口变动通知的指针(WindowAppPouScene*)
  237. QObject* m_pPouTarget;
  238. // 2022-3-1,本工具所绑定的DB变量组指针
  239. GVL* m_pDB;
  240. // 控件用于双向同步的回调函数
  241. CONTROL_CALLBACK controlCallback;
  242. //// 用于数值变更后向界面同步的回调函数
  243. //VALUE_CALLBACK valueCallback;
  244. DebugData m_DebugData;
  245. // 本工具的实例名字
  246. QString m_strInstanceName;
  247. // 本工具所在的Pou名字
  248. QString m_strPouName;
  249. //用于备份数据的buffer
  250. QBuffer m_BufferBackup;
  251. };
  252. //////////////////////////////////////////////////////////
  253. // 工具信息的封装类
  254. class DllTool
  255. {
  256. public:
  257. DllTool()
  258. {
  259. ////ControlCallback = nullptr;
  260. //m_Even.hEvenHandle = nullptr;
  261. //m_Even.nEvenTime = 0;
  262. m_pDlgTool = nullptr;
  263. }
  264. virtual ~DllTool()
  265. {
  266. }
  267. public:
  268. // 执行工具
  269. virtual VPEnum::RETURN_VALUE Execute()
  270. {
  271. if (m_pDlgTool != nullptr)
  272. {
  273. return m_pDlgTool->Execute();
  274. }
  275. return VPEnum::RETURN_VALUE::Error;
  276. }
  277. //系统Run和Stop时调用
  278. virtual void Running(bool bRun)
  279. {
  280. if (m_pDlgTool!= nullptr)
  281. {
  282. m_pDlgTool->Running(bRun);
  283. }
  284. }
  285. //
  286. virtual bool updateValue(int nIndex)
  287. {
  288. if (m_pDlgTool != nullptr)
  289. {
  290. return m_pDlgTool->updateValue(nIndex);
  291. }
  292. return false;
  293. }
  294. // 显示参数设置对话框
  295. virtual void ShowDialog()
  296. {
  297. if (m_pDlgTool != nullptr)
  298. {
  299. m_pDlgTool->show();
  300. m_pDlgTool->setWindowTitle(this->m_strPouName + (" ---> ") + this->m_strInstanceName);
  301. }
  302. }
  303. // 获取调试参数
  304. virtual DebugData GetDebugData()
  305. {
  306. if (m_pDlgTool != nullptr)
  307. {
  308. return m_pDlgTool->GetDebugData();
  309. }
  310. DebugData data;
  311. return data;
  312. }
  313. // 2022-10-4增加,Dll信息中保存一下本Dll对应的全路径,用于后续查询
  314. QString m_strFullPath;
  315. public:
  316. /// <summary>
  317. /// 工具初始化(不带参数)
  318. /// </summary>
  319. virtual int InitTool() = 0;
  320. /// <summary>
  321. /// 纯虚函数,工具初始化
  322. /// </summary>
  323. /// <param name="pWnd">父窗体指针</param>
  324. /// <param name="strPouName">工具所在Pou的名字</param>
  325. /// <param name="strInstanceName">工具生成的实例名字</param>
  326. /// <returns></returns>
  327. virtual int InitTool(QWidget* pWnd, QString strPouName, QString strInstanceName, QObject* pEventTarget = nullptr) = 0;
  328. /// <summary>
  329. /// 获取工具的总体描述信息
  330. /// </summary>
  331. virtual const DLL_TOOL_DESC& Description() = 0;
  332. virtual bool bindValuePtrByName(const QString strName, const int nIndex) = 0;
  333. /// <summary>
  334. /// 获取本工具的名称
  335. /// </summary>
  336. /// <returns></returns>
  337. QString getName()
  338. {
  339. return this->m_strPouName;
  340. }
  341. /// <summary>
  342. /// 获取本工具的实例名称
  343. /// </summary>
  344. /// <returns></returns>
  345. QString getInstanceName()
  346. {
  347. return this->m_strInstanceName;
  348. }
  349. /// <summary>
  350. /// 序列化至文件
  351. /// </summary>
  352. virtual bool SerializedToDoc(QDataStream& out) { Q_UNUSED(out); return true; }
  353. /// <summary>
  354. /// 从文件反序列化
  355. /// </summary>
  356. virtual bool SerializedFromDoc(QDataStream& in) { Q_UNUSED(in); return true;}
  357. // 修改所在的Pou名字
  358. void ModToolPouName(QString strNewPouName)
  359. {
  360. this->m_strPouName = strNewPouName;
  361. if (m_pDlgTool!= nullptr)
  362. {
  363. m_pDlgTool->SetToolInfo(m_strPouName, m_strInstanceName);
  364. }
  365. }
  366. // 修改工具的实例名字
  367. void ModToolInstanceName(QString strNewInstanceName)
  368. {
  369. this->m_strInstanceName = strNewInstanceName;
  370. if (m_pDlgTool != nullptr)
  371. {
  372. m_pDlgTool->SetToolInfo(m_strPouName, m_strInstanceName);
  373. }
  374. }
  375. // 获取指定的接口
  376. DLL_INF& Interface(const int nIndex)
  377. {
  378. return m_Interfaces[nIndex];
  379. }
  380. // 获取工具接口的数量
  381. int GetInterfaceSize()
  382. {
  383. return m_Interfaces.size();
  384. }
  385. // 动态增加接口
  386. virtual void AddInterface(const DLL_INF& dll_inf)
  387. {
  388. m_Interfaces.push_back(dll_inf);
  389. };
  390. // 动态删除接口
  391. virtual bool DelInterface(const QString& infName)
  392. {
  393. bool bFind = false;
  394. for ( int i = 0;i< m_Interfaces.size();i++ )
  395. {
  396. DLL_INF& dllInf = m_Interfaces[i];
  397. if (dllInf.strName == infName)
  398. {
  399. // 只有动态接口才允许删除
  400. if (!dllInf.bDynamic)
  401. {
  402. qDebug() << "DllTool::DelInterface - failed, reason: " << dllInf.strName << " is not dynamic interface.";
  403. return false;
  404. }
  405. m_Interfaces.removeAt(i);
  406. bFind = true;
  407. }
  408. // 后续的接口Index都需要 - 1
  409. else
  410. {
  411. dllInf.nIndex --;
  412. }
  413. }
  414. return bFind;
  415. }
  416. // 获取工具接口的值
  417. template<typename T>
  418. T& Value(const int nIndex)
  419. {
  420. if (m_Interfaces.size() <= nIndex)
  421. {
  422. qWarning() << "DllTool::Value() Error - Inf Size:[" << m_Interfaces.size() << "] Index Vilue: [" << nIndex << "]";
  423. }
  424. return *(T*)m_Interfaces[nIndex].value.Ptr;
  425. }
  426. // 设置Interface的值(默认绑定成员变量,不重新开辟内存)
  427. template<typename T>
  428. void SetValue(const int nIndex, T& t)
  429. {
  430. if (m_Interfaces.size() <= nIndex)
  431. {
  432. qWarning() << "DllTool::SetValue() Error - Inf Size:[" << m_Interfaces.size() << "] Index Vilue: [" << nIndex << "]";
  433. return;
  434. }
  435. this->SetValue(m_Interfaces[nIndex].value, t);
  436. }
  437. // 设置Interface的值(默认绑定成员变量,不重新开辟内存)
  438. template<typename T>
  439. void SetValue(VALUE& value, T& t)
  440. {
  441. value.Ptr = (void**)&t;
  442. }
  443. // 2022-3-17,放弃了重新开辟内存的做法,
  444. //// 设置Interface的值(需要重新开辟内存)
  445. //template<typename T>
  446. //void SetValue(const int nIndex, T& t)
  447. //{
  448. // if (m_Interfaces.size() <= nIndex)
  449. // {
  450. // qWarning() << "DllTool::SetValue() Error - Inf Size:[" << m_Interfaces.size() << "] Index Vilue: [" << nIndex << "]";
  451. // return;
  452. // }
  453. // this->SetValue(m_Interfaces[nIndex].value, t);
  454. //}
  455. //// 设置Interface的值(需要重新开辟内存)
  456. //template<typename T>
  457. //void SetValue(VALUE& value, T& t)
  458. //{
  459. // T* newValue = new T;
  460. // *newValue = t;
  461. // value.Ptr = (void**)newValue;
  462. //}
  463. // 更新Interface的值(已经开辟好了内存,只是做值的更新)
  464. template<typename T>
  465. void UpdateValue(const int nIndex, T& t, VALUE_PASS_MODE passmode = VALUE_PASS_MODE::PASS_BY_VALUE)
  466. {
  467. if (m_Interfaces.size() <= nIndex)
  468. {
  469. qWarning() << "DllTool::UpdateValue() Error - Inf Size:[" << m_Interfaces.size() <<"] Index Vilue: [" << nIndex << "]" ;
  470. return;
  471. }
  472. // 按值
  473. if (passmode == VALUE_PASS_MODE::PASS_BY_VALUE)
  474. {
  475. *(T*)m_Interfaces[nIndex].value.Ptr = t;
  476. }
  477. // 按地址
  478. else
  479. {
  480. *m_Interfaces[nIndex].value.Ptr = &t;
  481. }
  482. }
  483. // 设置Event类型工具的事件接收对象(exe中的TaskManager)
  484. void setEventTarget(QObject* pTarget) const
  485. {
  486. Q_ASSERT(pTarget != nullptr);
  487. if (m_pDlgTool)
  488. {
  489. this->m_pDlgTool->setEventTarget(pTarget);
  490. }
  491. }
  492. // 设置变量和控件同步事件的接收对象(exe中的WindowRuntime*)
  493. void setSyncTarget(QObject* pTarget) const
  494. {
  495. Q_ASSERT(pTarget != nullptr);
  496. if (m_pDlgTool)
  497. {
  498. this->m_pDlgTool->setSyncTarget(pTarget);
  499. }
  500. }
  501. // 设置全局变量操作指针,用于接收变量变动通知消息(exe中GvlManager)
  502. void setGvlTarget(QObject* pTarget)
  503. {
  504. Q_ASSERT(pTarget != nullptr);
  505. if (m_pDlgTool)
  506. {
  507. this->m_pDlgTool->setGvlTarget(pTarget);
  508. }
  509. }
  510. // 设置Pou管理者指针,用于接收接口变动通知消息(exe中的WindowAppPouScene)
  511. void setPouTarget(QObject* pTarget)
  512. {
  513. Q_ASSERT(pTarget != nullptr);
  514. if (m_pDlgTool)
  515. {
  516. this->m_pDlgTool->setPouTarget(pTarget);
  517. }
  518. }
  519. // 设置控件双向同步的回调函数
  520. void setControlCallback(CONTROL_CALLBACK callback)
  521. {
  522. if (m_pDlgTool)
  523. {
  524. this->m_pDlgTool->setControlCallback(callback);
  525. }
  526. }
  527. // 设置绑定的DB变量(仅硬件工具有可能会用到)
  528. void setBindDB(GVL* pDB)
  529. {
  530. Q_ASSERT(pDB != nullptr);
  531. this->m_pDlgTool->setBindDB(pDB);
  532. }
  533. // 解除绑定的DB变量(仅硬件工具有可能会用到)
  534. void unbindDB()
  535. {
  536. this->m_pDlgTool->unbindDB();
  537. }
  538. //// 设置数值向UI同步的回调函数
  539. //void setValueCallback(VALUE_CALLBACK callback)
  540. //{
  541. // this->m_pDlgTool->setValueCallback(callback);
  542. //}
  543. protected:
  544. // 初始化默认的接口描述
  545. virtual void InitDefaultInterfaces( bool withValue = false ) = 0;
  546. protected:
  547. // 本工具的接口
  548. QVector<DLL_INF> m_Interfaces;
  549. // 本工具的对话框
  550. DllToolDialog* m_pDlgTool;
  551. // 本工具的实例名字
  552. QString m_strInstanceName;
  553. // 本工具所在的Pou名字
  554. QString m_strPouName;
  555. };