occevent.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #include "occimpl.h"
  12. #ifdef AFX_OCC_SEG
  13. #pragma code_seg(AFX_OCC_SEG)
  14. #endif
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. #define new DEBUG_NEW
  20. /////////////////////////////////////////////////////////////////////////////
  21. // OLE event sink handler
  22. typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_CHANGED)();
  23. typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_REQUEST)(BOOL*);
  24. typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_DSCNOTIFY)(DSCSTATE, DSCREASON, BOOL*);
  25. typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_CHANGED_RANGE)(UINT);
  26. typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_REQUEST_RANGE)(UINT, BOOL*);
  27. typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_DSCNOTIFY_RANGE)(UINT, DSCSTATE, DSCREASON, BOOL*);
  28. BOOL CCmdTarget::OnEvent(UINT idCtrl, AFX_EVENT* pEvent,
  29. AFX_CMDHANDLERINFO* pHandlerInfo)
  30. {
  31. HRESULT hResult = S_OK;
  32. UINT uArgError = (UINT)-1; // no error yet
  33. const AFX_EVENTSINKMAP_ENTRY* pEntry = GetEventSinkEntry(idCtrl, pEvent);
  34. // no handler for this event
  35. if (pEntry == NULL)
  36. return FALSE;
  37. if (pHandlerInfo != NULL)
  38. {
  39. // just fill in the information, don't do it
  40. pHandlerInfo->pTarget = this;
  41. switch (pEvent->m_eventKind)
  42. {
  43. case AFX_EVENT::event:
  44. case AFX_EVENT::propRequest:
  45. pHandlerInfo->pmf = pEntry->dispEntry.pfn;
  46. break;
  47. case AFX_EVENT::propChanged:
  48. pHandlerInfo->pmf = pEntry->dispEntry.pfnSet;
  49. break;
  50. default:
  51. ASSERT(FALSE); // bogus value for pEvent->m_eventKind
  52. }
  53. return (pHandlerInfo->pmf != NULL);
  54. }
  55. BOOL bRange = (pEntry->nCtrlIDLast != (UINT)-1);
  56. BOOL bHandled = FALSE;
  57. TRY
  58. {
  59. switch (pEvent->m_eventKind)
  60. {
  61. case AFX_EVENT::event:
  62. // do standard method call
  63. VARIANT var;
  64. AfxVariantInit(&var);
  65. DISPPARAMS dispparams;
  66. dispparams.rgvarg = NULL;
  67. if (bRange)
  68. {
  69. memcpy(&dispparams, pEvent->m_pDispParams, sizeof(DISPPARAMS));
  70. dispparams.rgvarg = new VARIANT[++dispparams.cArgs];
  71. memcpy(dispparams.rgvarg, pEvent->m_pDispParams->rgvarg,
  72. sizeof(VARIANT) * (dispparams.cArgs-1));
  73. VARIANT* pvarID = &dispparams.rgvarg[dispparams.cArgs-1];
  74. V_VT(pvarID) = VT_I4;
  75. V_I4(pvarID) = idCtrl;
  76. }
  77. hResult = CallMemberFunc(&pEntry->dispEntry, DISPATCH_METHOD, &var,
  78. (bRange ? &dispparams : pEvent->m_pDispParams), &uArgError);
  79. ASSERT(FAILED(hResult) || (V_VT(&var) == VT_BOOL));
  80. bHandled = V_BOOL(&var);
  81. if (bRange)
  82. delete [] dispparams.rgvarg;
  83. break;
  84. case AFX_EVENT::propChanged:
  85. {
  86. if (bRange)
  87. {
  88. PFN_CHANGED_RANGE pfn = (PFN_CHANGED_RANGE)pEntry->dispEntry.pfnSet;
  89. bHandled = (this->*pfn)(idCtrl);
  90. }
  91. else
  92. {
  93. PFN_CHANGED pfn = (PFN_CHANGED)pEntry->dispEntry.pfnSet;
  94. bHandled = (this->*pfn)();
  95. }
  96. hResult = S_OK;
  97. }
  98. break;
  99. case AFX_EVENT::propRequest:
  100. {
  101. BOOL bAllow = TRUE;
  102. if (bRange)
  103. {
  104. PFN_REQUEST_RANGE pfn = (PFN_REQUEST_RANGE)pEntry->dispEntry.pfn;
  105. bHandled = (this->*pfn)(idCtrl, &bAllow);
  106. }
  107. else
  108. {
  109. PFN_REQUEST pfn = (PFN_REQUEST)pEntry->dispEntry.pfn;
  110. bHandled = (this->*pfn)(&bAllow);
  111. }
  112. hResult = bAllow ? S_OK : S_FALSE;
  113. }
  114. break;
  115. case AFX_EVENT::propDSCNotify:
  116. {
  117. BOOL bAllow = TRUE;
  118. if (bRange)
  119. {
  120. PFN_DSCNOTIFY_RANGE pfn = (PFN_DSCNOTIFY_RANGE)pEntry->dispEntry.pfn;
  121. bHandled = (this->*pfn)(idCtrl, pEvent->m_nDSCState,
  122. pEvent->m_nDSCReason, &bAllow);
  123. }
  124. else
  125. {
  126. PFN_DSCNOTIFY pfn = (PFN_DSCNOTIFY)pEntry->dispEntry.pfn;
  127. bHandled = (this->*pfn)(pEvent->m_nDSCState,
  128. pEvent->m_nDSCReason, &bAllow);
  129. }
  130. hResult = bAllow ? S_OK : S_FALSE;
  131. }
  132. break;
  133. default:
  134. ASSERT(FALSE); // bogus value for pEvent->m_eventKind
  135. }
  136. }
  137. CATCH_ALL(e)
  138. {
  139. if (pEvent->m_pExcepInfo != NULL)
  140. {
  141. // fill exception with translation of MFC exception
  142. COleDispatchException::Process(pEvent->m_pExcepInfo, e);
  143. }
  144. DELETE_EXCEPTION(e);
  145. hResult = DISP_E_EXCEPTION;
  146. }
  147. END_CATCH_ALL
  148. // fill error argument if one is available
  149. if (FAILED(hResult) && pEvent->m_puArgError != NULL && uArgError != -1)
  150. *pEvent->m_puArgError = uArgError;
  151. // fill result code
  152. pEvent->m_hResult = hResult;
  153. return bHandled;
  154. }
  155. /////////////////////////////////////////////////////////////////////////////
  156. // Locate event sink map entry
  157. const AFX_EVENTSINKMAP_ENTRY* PASCAL CCmdTarget::GetEventSinkEntry(
  158. UINT idCtrl, AFX_EVENT* pEvent)
  159. {
  160. const AFX_EVENTSINKMAP* pSinkMap = GetEventSinkMap();
  161. const AFX_EVENTSINKMAP_ENTRY* pEntry;
  162. size_t flag = (pEvent->m_eventKind != AFX_EVENT::event);
  163. while (pSinkMap != NULL)
  164. {
  165. // find matching AFX_EVENTSINKMAP_ENTRY
  166. pEntry = pSinkMap->lpEntries;
  167. while (pEntry->dispEntry.nPropOffset != -1)
  168. {
  169. if ((pEntry->dispEntry.lDispID == pEvent->m_dispid) &&
  170. (pEntry->dispEntry.nPropOffset == flag))
  171. {
  172. if (pEntry->nCtrlIDLast == (UINT)-1)
  173. {
  174. // check for wildcard match or exact match
  175. if ((pEntry->nCtrlIDFirst == (UINT)-1) ||
  176. (pEntry->nCtrlIDFirst == idCtrl))
  177. return pEntry;
  178. }
  179. else
  180. {
  181. // check for range match
  182. if ((pEntry->nCtrlIDFirst <= idCtrl) &&
  183. (idCtrl <= pEntry->nCtrlIDLast))
  184. return pEntry;
  185. }
  186. }
  187. ++pEntry;
  188. }
  189. // check base class
  190. #ifdef _AFXDLL
  191. pSinkMap = (*pSinkMap->pfnGetBaseMap)();
  192. #else
  193. pSinkMap = pSinkMap->pBaseMap;
  194. #endif
  195. }
  196. return NULL; // no matching entry
  197. }