VisionPlusTool.h 13 KB

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