home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / OCCEVENT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  5.9 KB  |  233 lines

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