XTPNotifyConnection.h
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:30k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTPNotifyConnection.h: interface for CXTPNotifyConnection and
  2. // CXTPNotifySik classes.
  3. //
  4. // This file is a part of the XTREME TOOLKIT PRO MFC class library.
  5. // (c)1998-2008 Codejock Software, All Rights Reserved.
  6. //
  7. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  8. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  9. // CONSENT OF CODEJOCK SOFTWARE.
  10. //
  11. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  12. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  13. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  14. // SINGLE COMPUTER.
  15. //
  16. // CONTACT INFORMATION:
  17. // support@codejock.com
  18. // http://www.codejock.com
  19. //
  20. /////////////////////////////////////////////////////////////////////////////
  21. //{{AFX_CODEJOCK_PRIVATE
  22. #ifndef _XTPNOTIFYCONNECTION_H__
  23. #define _XTPNOTIFYCONNECTION_H__
  24. //}}AFX_CODEJOCK_PRIVATE
  25. #if _MSC_VER > 1000
  26. #pragma once
  27. #endif // _MSC_VER > 1000
  28. #pragma warning(disable : 4097)
  29. #include <afxmt.h>
  30. #include "XTPVC80Helpers.h"
  31. /////////////////////////////////////////////////////////////////////////////
  32. class CXTPNotifySink;
  33. typedef DWORD_PTR XTP_CONNECTION_ID;
  34. typedef DWORD XTP_NOTIFY_CODE;
  35. //---------------------------------------------------------------------------
  36. // Summary: Defines a base ID for common notifications.
  37. //---------------------------------------------------------------------------
  38. const UINT WM_XTP_COMMON_BASE = (WM_USER + 9550); 
  39. // RANGE for WM_XTP_COMMON_BASE {+ 1 ... + 49}
  40. //
  41. // Next free COMMON ID = (WM_XTP_COMMON_BASE + 2)
  42. //{{AFX_CODEJOCK_PRIVATE
  43. //---------------------------------------------------------------------------
  44. // Defines an ID for Office2007 Images changed notification.
  45. // Sender: CXTPOffice2007Image
  46. // Parameters: wParam, lParam - <Unused>
  47. //---------------------------------------------------------------------------
  48. static const XTP_NOTIFY_CODE   XTP_NC_COMMON_OFFICE2007IMAGES_CHANGED = (WM_XTP_COMMON_BASE + 1);
  49. //}}AFX_CODEJOCK_PRIVATE
  50. //-------------------------------------------------------------------------
  51. // Summary: Notify flags options
  52. //-------------------------------------------------------------------------
  53. enum XTPNotifyFlags
  54. {
  55. xtpNotifyPostMessage                = 0x80000000, // Event will be posted
  56. xtpNotifyGuarantyPost               = 0x40000000, // Used together with nofPostMessage. Event will be guaranty posted. (Wait untill PostMessage returns TRUE)
  57. xtpNotifyDirectCallForOneThread     = 0x20000000  // Event handler will be called directly if sender and receiver are in one thread.
  58. };
  59. //===========================================================================
  60. // Summary:
  61. //     This class is used as implementation of Connection interface in
  62. //     a XTPNotification mechanism. This mechanism consists of
  63. //     Connection object(s) and Sink object(s). The first are used to
  64. //     send notification messages and the second are used to receive
  65. //     these notification. Each notification has unique number
  66. //     (or EventCode or NotificationCode) for a given connection
  67. //     object or for the whole system. This depends on implementation.
  68. //     Using system unique NotificationCodes is a preferred way to avoid
  69. //     potential errors with intersected NotificationCodes.
  70. // See Also: CXTPNotifySink overview,
  71. //           CXTPNotifyConnection overview,
  72. //===========================================================================
  73. class _XTP_EXT_CLASS CXTPNotifyConnection : public CXTPCmdTarget
  74. {
  75. public:
  76. //-----------------------------------------------------------------------
  77. // Summary:
  78. //     Default object constructor.
  79. // See Also: ~CXTPNotifyConnection()
  80. //-----------------------------------------------------------------------
  81. CXTPNotifyConnection();
  82. //-----------------------------------------------------------------------
  83. // Summary:
  84. //     Default object destructor.
  85. // See Also: CXTPNotifyConnection()
  86. //-----------------------------------------------------------------------
  87. virtual ~CXTPNotifyConnection();
  88. public:
  89. //-----------------------------------------------------------------------
  90. // Summary:
  91. //     Establishes a connection between the connection object and
  92. //     a sink object.
  93. // Parameters:
  94. //     dwNotifyCode - EventCode of a Notification.
  95. //     pSink     - Pointer to the Sink object which will receive
  96. //                 events with specified code.
  97. // Remarks:
  98. //     Call this method to establish a connection with the event
  99. //     source and the sink object. pSink->OnEvent(...) method will be
  100. //     called if event with specified EventCode will occur.
  101. //     Use Unadvise() method with returned connection ID to terminate
  102. //     the connection call.
  103. // Returns:
  104. //     The unique connection ID used for Unadvise() method.
  105. // See Also: CXTPNotifySink overview, Unadvise() method.
  106. //-----------------------------------------------------------------------
  107. XTP_CONNECTION_ID Advise(XTP_NOTIFY_CODE dwNotifyCode, CXTPNotifySink* pSink);
  108. //-----------------------------------------------------------------------
  109. // Summary:
  110. //     Terminate a connection between the connection object and
  111. //     a sink object.
  112. // Parameters:
  113. //     ConnectionID - The unique connection ID previously returned
  114. //                    in Advise() call.
  115. // Remarks:
  116. //     Call this method to Terminate a connection with the event
  117. //     source and the sink object.
  118. // See Also: Advise() method.
  119. //-----------------------------------------------------------------------
  120. void Unadvise(XTP_CONNECTION_ID ConnectionID);
  121. //-----------------------------------------------------------------------
  122. // Summary:
  123. //     Remove All connections information.
  124. // Remarks:
  125. //     Call this method to remove all connections added using
  126. //     Advise method.
  127. // See Also: Advise method
  128. //-----------------------------------------------------------------------
  129. void RemoveAll();
  130. //-----------------------------------------------------------------------
  131. // Summary:
  132. //     Send event with specified EventCode.
  133. // Parameters:
  134. //          dwNotifyCode   - EventCode of a Notification.
  135. //          wParam      - First parameter specific for this Notification.
  136. //          lParam      - Second parameter specific for this Notification.
  137. //          dwFlags     - Additional flags. See XTPNotifyFlags.
  138. // Remarks:
  139. //     Call this method to send event with specified EventCode to
  140. //     sinks which where advised to this EventCode using Advise
  141. //     method.
  142. // Returns:
  143. //     TRUE if event was sent to any client (if any client exists),
  144. //     FALSE - otherwise.
  145. // See Also: Advise(), XTPNotifyFlags.
  146. //-----------------------------------------------------------------------
  147. BOOL SendEvent(XTP_NOTIFY_CODE dwNotifyCode, WPARAM wParam , LPARAM lParam, DWORD dwFlags = 0);
  148. protected:
  149. //-----------------------------------------------------------------------
  150. // Summary:
  151. //     Find connection information in the m_arConnections array.
  152. // Parameters:
  153. //     ConnectionID - The unique connection ID.
  154. // Remarks:
  155. //     Call this method to find connection description in the
  156. //     m_arConnections array using specified connection ID.
  157. // Returns:
  158. //     The zero-based index of connection description in the
  159. //     m_arConnections array that matches the requested ConnectionID;
  160. //     -1 if the it is not found.
  161. // See Also: Advise method, CONNECTION_DESCRIPTOR
  162. //-----------------------------------------------------------------------
  163. int FindConnection(XTP_CONNECTION_ID ConnectionID);
  164. //-----------------------------------------------------------------------
  165. // Summary:
  166. //     Get synchronization object to lock internal class data.
  167. // Remarks:
  168. //     This method is used as prototype for derived classes to
  169. //     support multi threaded clients calls. In base
  170. //     implementation pointer to an empty locker object is returned.
  171. // Returns:
  172. //     Pointer to the locker object.
  173. // See Also: CCriticalSection, CSingleLock, CSyncObject.
  174. //-----------------------------------------------------------------------
  175. virtual CSyncObject* GetDataLock();
  176. //===========================================================================
  177. // Summary:
  178. //     This struct is used in the implementation of the
  179. //     class CXTPNotifyConnection to store connection between
  180. //     a Connection object, Notification code and the sink object.
  181. // See Also: CXTPNotifyConnection overview,
  182. //           CXTPNotifySink overview,
  183. //===========================================================================
  184. struct CONNECTION_DESCRIPTOR
  185. {
  186. XTP_NOTIFY_CODE    dwNotifyCode;   // The Notification code.
  187. CXTPNotifySink*    pSink;          // The pointer to the sink object. (with InternalAddRef)
  188. XTP_CONNECTION_ID  dwConnectionID; // The unique connection ID used for Unadvise() method.
  189. };
  190. //===========================================================================
  191. // Summary:
  192. //     This struct is derived from CSyncObject and should be used
  193. //     instead of CCriticalSection to improve performance and
  194. //     to provide compatibility. It just provide CSyncObject
  195. //     interface with empty Lock and Unlock methods.
  196. // See Also: CCriticalSection, CSingleLock, CSyncObject.
  197. //===========================================================================
  198. class CEmptySyncObject : public CSyncObject
  199. {
  200. public:
  201. //-----------------------------------------------------------------------
  202. // Summary:
  203. //     Default object constructor.
  204. //-----------------------------------------------------------------------
  205. CEmptySyncObject();
  206. //-----------------------------------------------------------------------
  207. // Summary:
  208. //     Set object state as locked.
  209. // Parameters:
  210. //     dwTimeout - Specifies the amount of time to wait for the
  211. //                 synchronization object to be available (signaled)
  212. // Remarks:
  213. //     Empty Lock method.
  214. // Returns:
  215. //     TRUE
  216. // See Also: CCriticalSection::Lock, CSingleLock, CSyncObject.
  217. //-----------------------------------------------------------------------
  218. virtual BOOL Lock(DWORD dwTimeout = INFINITE);
  219. //-----------------------------------------------------------------------
  220. // Summary:
  221. //     Set object state as unlocked.
  222. // Parameters:
  223. //     lCount     - Number of accesses to release
  224. //     lPrevCount - Points to a variable to receive the previous count of the synchronization object
  225. // Remarks:
  226. //     Empty Unlock method.
  227. // Returns:
  228. //     TRUE
  229. // See Also: CCriticalSection::Unlock, CSingleLock, CSyncObject.
  230. //-----------------------------------------------------------------------
  231. virtual BOOL Unlock();
  232. virtual BOOL Unlock(LONG lCount, LPLONG lPrevCount = NULL); //<combine CXTPNotifyConnection::CEmptySyncObject::Unlock>
  233. };
  234. protected:
  235. CArray<CONNECTION_DESCRIPTOR*, CONNECTION_DESCRIPTOR*> m_arrConnections; // store connections between a Connection object, Notification code and the sink object.
  236. CArray<CONNECTION_DESCRIPTOR, CONNECTION_DESCRIPTOR&> m_arrSendQueueCache; // used in SendEvent method for safety reason
  237. int m_nSendQueueCacheSize; // used in SendEvent method together with m_arrSendQueueCache.
  238. CEmptySyncObject m_emptyLocker; // Pseudo-locker object
  239. };
  240. //===========================================================================
  241. // Summary:
  242. //     This class is used as thread-safety implementation of Connection
  243. //     interface in a XTPNotification mechanism. This mechanism consists of
  244. //     Connection object(s) and Sink object(s). The first are used to
  245. //     send notification messages and the second are used to receive
  246. //     these notification. Each notification has unique number
  247. //     (or EventCode or NotificationCode) for a given connection
  248. //     object or for the whole system. This depends on implementation.
  249. //     Using system unique NotificationCodes is a preferred way to avoid
  250. //     potential errors with intersected NotificationCodes.
  251. // See Also: CXTPNotifySink, CXTPNotifyConnection
  252. //===========================================================================
  253. class _XTP_EXT_CLASS CXTPNotifyConnectionMT : public CXTPNotifyConnection
  254. {
  255. public:
  256. //-----------------------------------------------------------------------
  257. // Summary:
  258. //     Default object constructor.
  259. //-----------------------------------------------------------------------
  260. CXTPNotifyConnectionMT();
  261. //-----------------------------------------------------------------------
  262. // Summary:
  263. //     Default object destructor.
  264. //-----------------------------------------------------------------------
  265. virtual ~CXTPNotifyConnectionMT();
  266. //-----------------------------------------------------------------------
  267. // Summary:
  268. //     Post event with specified EventCode.
  269. // Parameters:
  270. //          dwNotifyCode  - EventCode of a Notification.
  271. //          wParam  - First parameter specific for this Notification.
  272. //          lParam  - Second parameter specific for this Notification.
  273. //          dwFlags     - Additional flags. See XTPNotifyFlags.
  274. // Remarks:
  275. //          Call this method to post event with specified EventCode to
  276. //          sinks which where advised to this EventCode using Advise
  277. //          method. Event will be posted only to the sinks which
  278. //          implementations support Post event possibility, like standard
  279. //          multithreaded sinks.
  280. //          The sink implementation is responsible for the Post mechanism.
  281. //          For posted event the appropriate bit of dwFlags is set
  282. //          automatically and SendEvent is called.
  283. // Returns:
  284. //          TRUE if event was sent to any client (if any client exists),
  285. //          FALSE - otherwise.
  286. // See Also: Advise(), SendEvent(), XTPNotifyFlags.
  287. //-----------------------------------------------------------------------
  288. BOOL PostEvent(XTP_NOTIFY_CODE dwNotifyCode, WPARAM wParam , LPARAM lParam,
  289. DWORD dwFlags = 0);
  290. protected:
  291. //-----------------------------------------------------------------------
  292. // Summary:
  293. //     Get synchronization object to lock internal class data.
  294. // Remarks:
  295. //     This method is used to support multi threaded clients calls..
  296. // Returns:
  297. //     Pointer to the locker object (CCriticalSection).
  298. // See Also: CCriticalSection, CSingleLock, CSyncObject.
  299. //-----------------------------------------------------------------------
  300. virtual CSyncObject* GetDataLock();
  301. CCriticalSection m_DataLockerCS; // Data locker object
  302. };
  303. //{{AFX_CODEJOCK_PRIVATE
  304. static LPCTSTR XTP_NOTIFICATION_SINK_MT_ON_EVENT_MSG = _T("XTPNotificationSinkMTOnEvent");
  305. const UINT xtp_wm_NotificationSinkMTOnEvent = RegisterWindowMessage(XTP_NOTIFICATION_SINK_MT_ON_EVENT_MSG);
  306. //}}AFX_CODEJOCK_PRIVATE
  307. //===========================================================================
  308. // Summary:
  309. //     This class is used as implementation of Sink interface in
  310. //     a XTPNotification mechanism. This mechanism consists of
  311. //     Connection object(s) and Sink object(s). The first are used to
  312. //     send notification messages and the second are used to receive
  313. //     these notification. Each notification has unique number
  314. //     (or dwNotifyCode or NotificationCode) for a given connection
  315. //     object or for the whole system. This depends on implementation.
  316. //     Using system unique NotificationCodes is a preferred way to avoid
  317. //     potential errors with intersected NotificationCodes.
  318. // See Also: CXTPNotifySink overview, DECLARE_XTPSINK macro,
  319. //           CXTPNotifyConnection overview,
  320. //===========================================================================
  321. class _XTP_EXT_CLASS CXTPNotifySink
  322. {
  323. public:
  324. //-----------------------------------------------------------------------
  325. // Summary:
  326. //     Default object constructor.
  327. // See Also: ~CXTPNotifySink()
  328. //-----------------------------------------------------------------------
  329. CXTPNotifySink();
  330. //-----------------------------------------------------------------------
  331. // Summary:
  332. //     Default object destructor.
  333. // See Also: CXTPNotifySink()
  334. //-----------------------------------------------------------------------
  335. virtual ~CXTPNotifySink();
  336. public:
  337. // -----------------------------------------------------------------------------------------
  338. // Summary:
  339. //     Event with specified dwNotifyCode was occurred.
  340. // Parameters:
  341. //     dwNotifyCode :  EventCode of a Notification.
  342. //     wParam :   First parameter specific for this Notification.
  343. //     lParam :   Second parameter specific for this Notification.
  344. //     dwFlags  :   Additional flags. See XTPNotifyFlags.
  345. // Remarks:
  346. //     This method is called by Connection object to notify advice sink
  347. //     that event with specified EventCode was occurred. It should be
  348. //     override in your derived class to receive notification(s).
  349. // See Also:
  350. //           DECLARE_XTPSINK macro, DECLARE_XTPSINK_MT macro,
  351. //           CXTPNotifyConnection,
  352. //           CXTPNotifyConnection::Advise method
  353. //-----------------------------------------------------------------------
  354. virtual void OnEvent(XTP_NOTIFY_CODE dwNotifyCode, WPARAM wParam,
  355.  LPARAM lParam, DWORD dwFlags) = 0;
  356. public:
  357. //-----------------------------------------------------------------------
  358. // Summary:
  359. //     Terminate all connections between the connection object(s) and
  360. //     this sink object.
  361. // Remarks:
  362. //     Call this method to Terminate all connections with the event
  363. //     source(s) and this sink object.
  364. // See Also: CXTPNotifySink, UnadviseAll method, Advise method,
  365. //           CXTPNotifyConnection,
  366. //           CXTPNotifyConnection::Unadvise method
  367. //-----------------------------------------------------------------------
  368. void UnadviseAll();
  369. //-----------------------------------------------------------------------
  370. // Summary:
  371. //     Terminate a connection between the connection object and
  372. //     this sink object.
  373. // Parameters:
  374. //     id - The unique connection ID previously returned
  375. //          in Advise() call.
  376. // Remarks:
  377. //     Call this method to Terminate a connection with the event
  378. //     source and this sink object.
  379. // See Also: CXTPNotifySink, UnadviseAll method, Advise method,
  380. //           CXTPNotifyConnection,
  381. //           CXTPNotifyConnection::Unadvise method
  382. //-----------------------------------------------------------------------
  383. void Unadvise(XTP_CONNECTION_ID id);
  384. protected:
  385. //-----------------------------------------------------------------------
  386. // Summary:
  387. //     Establishes a connection between the connection object and
  388. //     a sink object.
  389. // Parameters:
  390. //     pConnection  - Pointer to the Connection object.
  391. //     dwNotifyCode - Notify Code of a Notification.
  392. // Remarks:
  393. //     Call this method to establish a connection with the event
  394. //     source and the sink object. OnEvent(...) method will be
  395. //     called if event with specified dwNotifyCode will occur.
  396. //     Use Unadvise() method with returned connection ID to terminate
  397. //     the connection call.
  398. // Returns:
  399. //     The unique connection ID used for Unadvise() method.
  400. // See Also: CXTPNotifySink, Unadvise method, GetParam method,
  401. //           CXTPNotifyConnection,
  402. //           CXTPNotifyConnection::Advise method
  403. //-----------------------------------------------------------------------
  404. XTP_CONNECTION_ID Advise(CXTPNotifyConnection* pConnection, XTP_NOTIFY_CODE dwNotifyCode);
  405. protected:
  406. //===========================================================================
  407. // Summary:
  408. //     This struct is used in to store connection between a Connection
  409. //     object(s), Notification code and the sink object.
  410. // See Also: CXTPNotifySink overview,
  411. //===========================================================================
  412. struct ADVISE_DESCRIPTOR
  413. {
  414. XTP_NOTIFY_CODE        dwNotifyCode;   // The Notification code.
  415. CXTPNotifyConnection*  pConnection;    // The pointer to the connection object. (with InternalAddRef)
  416. XTP_CONNECTION_ID      dwConnectionID; // Original Connection ID returned by pConnection->Advise() method.
  417. };
  418. CMap<XTP_CONNECTION_ID, XTP_CONNECTION_ID&, ADVISE_DESCRIPTOR, ADVISE_DESCRIPTOR&> m_mapAdviseData; // store connections between a Connection objects, Notification code and this sink object.
  419. };
  420. //////////////////////////////////////////////////////////////////////////////
  421. AFX_INLINE BOOL CXTPNotifyConnection::CEmptySyncObject::Lock(DWORD /*dwTimeout*/) {
  422. return TRUE;
  423. }
  424. AFX_INLINE BOOL CXTPNotifyConnection::CEmptySyncObject::Unlock() {
  425. return TRUE;
  426. }
  427. AFX_INLINE BOOL CXTPNotifyConnection::CEmptySyncObject::Unlock(LONG /*lCount*/, LPLONG /*lPrevCount = NULL*/) {
  428. return TRUE;
  429. }
  430. AFX_INLINE CSyncObject* CXTPNotifyConnection::GetDataLock() {
  431. return &m_emptyLocker;
  432. }
  433. AFX_INLINE CSyncObject* CXTPNotifyConnectionMT::GetDataLock() {
  434. return &m_DataLockerCS;
  435. }
  436. AFX_INLINE BOOL CXTPNotifyConnectionMT::PostEvent(XTP_NOTIFY_CODE dwNotifyCode, WPARAM wParam , LPARAM lParam, DWORD dwFlags) {
  437. return SendEvent(dwNotifyCode, wParam, lParam, dwFlags | xtpNotifyPostMessage);
  438. }
  439. //{{AFX_CODEJOCK_PRIVATE
  440. // to avoid warning C4786 MAPHANDLER is used.
  441. #if (_MSC_VER <= 1200)
  442. template<int HandlerSize>
  443. class XTP_MAPHANDLER_T
  444. {
  445. public:
  446. BYTE pfHandler[HandlerSize];
  447. };
  448. template<typename T_pfHandler>
  449. class CXTPNotifyMapCodeToHandler : public CMap<XTP_NOTIFY_CODE, XTP_NOTIFY_CODE, XTP_MAPHANDLER_T<sizeof(T_pfHandler)>, XTP_MAPHANDLER_T<sizeof(T_pfHandler)>&>
  450. {
  451. typedef XTP_MAPHANDLER_T<sizeof(T_pfHandler)> HANDLER;
  452. typedef CMap<XTP_NOTIFY_CODE, XTP_NOTIFY_CODE, HANDLER, HANDLER&> TBase;
  453. public:
  454. AFX_INLINE void SetAt(XTP_NOTIFY_CODE dwNotifyCode, T_pfHandler pfHandler)
  455. {
  456. HANDLER hnd;
  457. MEMCPY_S(&hnd.pfHandler, &pfHandler, sizeof(T_pfHandler));
  458. TBase::SetAt(dwNotifyCode, hnd);
  459. }
  460. AFX_INLINE BOOL Lookup(XTP_NOTIFY_CODE dwNotifyCode, T_pfHandler& rValue)
  461. {
  462. HANDLER hnd;
  463. if (TBase::Lookup(dwNotifyCode, hnd))
  464. {
  465. MEMCPY_S(&rValue, &hnd.pfHandler, sizeof(T_pfHandler));
  466. return TRUE;
  467. }
  468. rValue = 0;
  469. return FALSE;
  470. }
  471. };
  472. #endif
  473. template<class ownerClassName, class _CInformator>
  474. class CXTPNotifySinkImpl : public CXTPNotifySink
  475. {
  476. public:
  477. CXTPNotifySinkImpl() {
  478. m_mapHandlers.InitHashTable(101, FALSE);
  479. }
  480. virtual ~CXTPNotifySinkImpl() {
  481. UnadviseAll();
  482. };
  483. public:
  484. typedef void (ownerClassName::*T_pfHandler) (XTP_NOTIFY_CODE dwNotifyCode, WPARAM wParam , LPARAM lParam);
  485. XTP_CONNECTION_ID Advise(CXTPNotifyConnection* pConnection, XTP_NOTIFY_CODE dwNotifyCode, T_pfHandler pfHandler)
  486. {
  487. m_mapHandlers.SetAt(dwNotifyCode, pfHandler);
  488. return CXTPNotifySink::Advise(pConnection, dwNotifyCode);
  489. }
  490. virtual void OnEvent(XTP_NOTIFY_CODE dwNotifyCode, WPARAM wParam,
  491.  LPARAM lParam, DWORD /*dwFlags*/)
  492. {
  493. ownerClassName* pThis = _CInformator::GetPThis((BYTE*)this);
  494. if (!pThis) {
  495. ASSERT(FALSE);
  496. return;
  497. }
  498. T_pfHandler pfHandler = 0;
  499. if (m_mapHandlers.Lookup(dwNotifyCode, pfHandler) && (pfHandler != NULL))
  500. {
  501. (pThis->*(pfHandler)) (dwNotifyCode, wParam, lParam);
  502. return;
  503. }
  504. //WARNING. no handler found. ???
  505. ASSERT(FALSE);
  506. }
  507. protected:
  508. #if (_MSC_VER <= 1200) // Using Visual C++ 5.0, 6.0
  509. CXTPNotifyMapCodeToHandler<T_pfHandler> m_mapHandlers;
  510. #else
  511. CMap<XTP_NOTIFY_CODE, XTP_NOTIFY_CODE, T_pfHandler, T_pfHandler> m_mapHandlers;
  512. #endif
  513. };
  514. class CXTPNotifySinkImplMTMsgWnd : public CWnd
  515. {
  516. public:
  517. CXTPNotifySinkImplMTMsgWnd();
  518. virtual ~CXTPNotifySinkImplMTMsgWnd();
  519. virtual afx_msg LRESULT OnInterThreadEvent(WPARAM pEventData, LPARAM reserved) = 0;
  520. virtual BOOL CreateWnd();
  521. DECLARE_MESSAGE_MAP()
  522. };
  523. //=== Multithreaded sink implementation =====================================
  524. struct XTP_INTER_THREAD_EVENT_DATA
  525. {
  526. XTP_NOTIFY_CODE dwNotifyCode;
  527. WPARAM wParam;
  528. LPARAM lParam;
  529. DWORD dwFlags;
  530. };
  531. template<class ownerClassName, class _CInformator >
  532. class CXTPNotifySinkImplMT :
  533. public CXTPNotifySinkImpl< ownerClassName, _CInformator >,
  534. protected CXTPNotifySinkImplMTMsgWnd
  535. {
  536. public:
  537. typedef CXTPNotifySinkImpl<ownerClassName, _CInformator> TBaseSink;
  538. CXTPNotifySinkImplMT(BOOL bInitInternal = TRUE)
  539. {
  540. m_dwTraceFlag0 = 0;
  541. m_dwNexDataID = 0;
  542. m_bWndCreated = FALSE;
  543. m_dwOwnerThreadID = ::GetCurrentThreadId();
  544. if (bInitInternal) {
  545. m_bWndCreated = CreateWnd();
  546. }
  547. m_PostedEvents.InitHashTable(199, FALSE);
  548. }
  549. virtual ~CXTPNotifySinkImplMT()
  550. {
  551. UnadviseAll();
  552. DestroyWindow();
  553. m_bWndCreated = FALSE;
  554. }
  555. virtual void OnEvent(XTP_NOTIFY_CODE dwNotifyCode, WPARAM wParam,
  556.  LPARAM lParam, DWORD dwFlags)
  557. {
  558. ASSERT(m_bWndCreated);
  559. if (dwFlags & xtpNotifyDirectCallForOneThread)
  560. {
  561. if (GetCurrentThreadId() == m_dwOwnerThreadID)
  562. {
  563. TBaseSink::OnEvent(dwNotifyCode, wParam, lParam, dwFlags);
  564. return;
  565. }
  566. }
  567. //====================================================================
  568. XTP_INTER_THREAD_EVENT_DATA ithData = {dwNotifyCode, wParam, lParam, dwFlags};
  569. if (dwFlags & xtpNotifyPostMessage)
  570. {
  571. CSingleLock singleLock(&m_DataCS, TRUE);
  572. #ifdef _DEBUG
  573. XTP_INTER_THREAD_EVENT_DATA ithDataTmp;
  574. ASSERT(m_PostedEvents.Lookup(m_dwNexDataID, ithDataTmp) == FALSE);
  575. #endif
  576. DWORD dwDataID = m_dwNexDataID;
  577. m_dwNexDataID++;
  578. BOOL bTrace1 = FALSE;
  579. BOOL bPosted = FALSE;
  580. do
  581. {
  582. bPosted = PostMessage(xtp_wm_NotificationSinkMTOnEvent, NULL, dwDataID);
  583. if (!bPosted && (dwFlags & xtpNotifyGuarantyPost))
  584. {
  585. if (!bTrace1) {
  586. TRACE(_T("WARNING!  CXTPNotifySinkImplMT: PostMessage return FALSE. WAIT and retry. (ThreadID = %x, dataID = %d) n"),
  587.  GetCurrentThreadId(),   dwDataID);
  588. bTrace1 = TRUE;
  589. }
  590. singleLock.Unlock();
  591. Sleep(100);
  592. singleLock.Lock();
  593. }
  594. }
  595. while (!bPosted && (dwFlags & xtpNotifyGuarantyPost));
  596. if (bPosted)
  597. {
  598. m_PostedEvents[dwDataID] = ithData;
  599. if (bTrace1) {
  600. TRACE(_T("WARNING.*  CXTPNotifySinkImplMT: Event is posted! (ThreadID = %x, dataID = %d) n"),
  601. GetCurrentThreadId(),   dwDataID);
  602. }
  603. m_dwTraceFlag0 = 0;
  604. }
  605. else if (!(dwFlags & xtpNotifyGuarantyPost))
  606. {
  607. if (m_dwTraceFlag0 < 3)
  608. {
  609. TRACE(_T("WARNING!  CXTPNotifySinkImplMT: PostMessage return FALSE - Event is skipped! (ThreadID = %x, dataID = %d) n"),
  610. GetCurrentThreadId(),   dwDataID);
  611. TRACE(_T("          Use xtpNotifyGuarantyPost flag for important events. n"));
  612. }
  613. m_dwTraceFlag0++;
  614. }
  615. }
  616. else
  617. {
  618. SendMessage(xtp_wm_NotificationSinkMTOnEvent, (WPARAM)&ithData, 0);
  619. }
  620. };
  621. virtual LRESULT OnInterThreadEvent(WPARAM pEventData, LPARAM dwPostDataID)
  622. {
  623. XTP_INTER_THREAD_EVENT_DATA* pIthData = (XTP_INTER_THREAD_EVENT_DATA*)pEventData;
  624. if (pIthData)
  625. {
  626. TBaseSink::OnEvent(pIthData->dwNotifyCode, pIthData->wParam,
  627. pIthData->lParam, pIthData->dwFlags);
  628. }
  629. else
  630. {
  631. XTP_INTER_THREAD_EVENT_DATA ithData;
  632. CSingleLock singleLock(&m_DataCS, TRUE);
  633. if (m_PostedEvents.Lookup((DWORD)dwPostDataID, ithData))
  634. {
  635. m_PostedEvents.RemoveKey((DWORD)dwPostDataID);
  636. singleLock.Unlock();
  637. TBaseSink::OnEvent(ithData.dwNotifyCode, ithData.wParam,
  638. ithData.lParam, ithData.dwFlags);
  639. }
  640. else
  641. {
  642. ASSERT(FALSE);
  643. }
  644. }
  645. //====================================================================
  646. return 0;
  647. };
  648. protected:
  649. CMap<DWORD, DWORD, XTP_INTER_THREAD_EVENT_DATA, XTP_INTER_THREAD_EVENT_DATA&> m_PostedEvents;
  650. DWORD               m_dwNexDataID;
  651. BOOL                m_bWndCreated;
  652. DWORD               m_dwOwnerThreadID;
  653. CCriticalSection    m_DataCS;
  654. private:
  655. DWORD m_dwTraceFlag0;
  656. };
  657. //}}AFX_CODEJOCK_PRIVATE
  658. //{{AFX_CODEJOCK_PRIVATE
  659. #define DECLARE_XTP_SINKEX(ownerClassName, MemberName, _CSinkClass) 
  660. class C_##MemberName##_Informator 
  661. public: 
  662. static ownerClassName* GetPThis(BYTE* pSink) { 
  663. ownerClassName* pThis = 
  664. ((ownerClassName*)((BYTE*)pSink - offsetof(ownerClassName, MemberName))); 
  665. return pThis; 
  666. }; 
  667. }; 
  668. friend class C_##MemberName##_Informator; 
  669. typedef _CSinkClass<ownerClassName, C_##MemberName##_Informator> T_##MemberName; 
  670. T_##MemberName MemberName;
  671. //}}AFX_CODEJOCK_PRIVATE
  672. //===========================================================================
  673. // Parameters:
  674. //     ownerClassName - Name of the class where DECLARE_XTPSINK macro
  675. //                      is placed.
  676. //     MemberName     - Name of the sink class member.
  677. // Summary:
  678. //     This macro is used as implementation of Sink object in
  679. //     the events receiver class.
  680. // Example: class CMyObjectEventsReceiver : public CXTPCmdTarget
  681. //          {
  682. //          protected:
  683. //              // Declare sink object
  684. //              DECLARE_XTPSINK(CMyObjectEventsReceiver, m_Sink)
  685. //
  686. //              // Declare Event handlers methods
  687. //              void NotificationHandler1(XTP_NOTIFY_CODE Event,
  688. //                                          WPARAM wParam , LPARAM lParam);
  689. //              void NotificationHandler2(XTP_NOTIFY_CODE Event,
  690. //                                          WPARAM wParam , LPARAM lParam);
  691. //              // ...
  692. //          };
  693. // See Also: CXTPNotifySink overview,
  694. //           CXTPNotifyConnection overview,
  695. //===========================================================================
  696. #define DECLARE_XTP_SINK(ownerClassName, MemberName) 
  697. DECLARE_XTP_SINKEX(ownerClassName, MemberName, CXTPNotifySinkImpl) 
  698. friend class CXTPNotifySinkImpl<ownerClassName, C_##MemberName##_Informator>;
  699. // <COMBINE DECLARE_XTP_SINK>
  700. #define DECLARE_XTP_SINK_MT(ownerClassName, MemberName) 
  701. DECLARE_XTP_SINKEX(ownerClassName, MemberName, CXTPNotifySinkImplMT) 
  702. friend class CXTPNotifySinkImplMT<ownerClassName, C_##MemberName##_Informator>; 
  703. friend class CXTPNotifySinkImpl<ownerClassName, C_##MemberName##_Informator>;
  704. #endif // !defined(_XTPNOTIFYCONNECTION_H__)