| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- #include "stdafx.h"
- #include "occimpl.h"
- #ifdef AFX_OCC_SEG
- #pragma code_seg(AFX_OCC_SEG)
- #endif
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- #define new DEBUG_NEW
- /////////////////////////////////////////////////////////////////////////////
- // OLE event sink handler
- typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_CHANGED)();
- typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_REQUEST)(BOOL*);
- typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_DSCNOTIFY)(DSCSTATE, DSCREASON, BOOL*);
- typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_CHANGED_RANGE)(UINT);
- typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_REQUEST_RANGE)(UINT, BOOL*);
- typedef BOOL (AFX_MSG_CALL CCmdTarget::*PFN_DSCNOTIFY_RANGE)(UINT, DSCSTATE, DSCREASON, BOOL*);
- BOOL CCmdTarget::OnEvent(UINT idCtrl, AFX_EVENT* pEvent,
- AFX_CMDHANDLERINFO* pHandlerInfo)
- {
- HRESULT hResult = S_OK;
- UINT uArgError = (UINT)-1; // no error yet
- const AFX_EVENTSINKMAP_ENTRY* pEntry = GetEventSinkEntry(idCtrl, pEvent);
- // no handler for this event
- if (pEntry == NULL)
- return FALSE;
- if (pHandlerInfo != NULL)
- {
- // just fill in the information, don't do it
- pHandlerInfo->pTarget = this;
- switch (pEvent->m_eventKind)
- {
- case AFX_EVENT::event:
- case AFX_EVENT::propRequest:
- pHandlerInfo->pmf = pEntry->dispEntry.pfn;
- break;
- case AFX_EVENT::propChanged:
- pHandlerInfo->pmf = pEntry->dispEntry.pfnSet;
- break;
- default:
- ASSERT(FALSE); // bogus value for pEvent->m_eventKind
- }
- return (pHandlerInfo->pmf != NULL);
- }
- BOOL bRange = (pEntry->nCtrlIDLast != (UINT)-1);
- BOOL bHandled = FALSE;
- TRY
- {
- switch (pEvent->m_eventKind)
- {
- case AFX_EVENT::event:
- // do standard method call
- VARIANT var;
- AfxVariantInit(&var);
- DISPPARAMS dispparams;
- dispparams.rgvarg = NULL;
- if (bRange)
- {
- memcpy(&dispparams, pEvent->m_pDispParams, sizeof(DISPPARAMS));
- dispparams.rgvarg = new VARIANT[++dispparams.cArgs];
- memcpy(dispparams.rgvarg, pEvent->m_pDispParams->rgvarg,
- sizeof(VARIANT) * (dispparams.cArgs-1));
- VARIANT* pvarID = &dispparams.rgvarg[dispparams.cArgs-1];
- V_VT(pvarID) = VT_I4;
- V_I4(pvarID) = idCtrl;
- }
- hResult = CallMemberFunc(&pEntry->dispEntry, DISPATCH_METHOD, &var,
- (bRange ? &dispparams : pEvent->m_pDispParams), &uArgError);
- ASSERT(FAILED(hResult) || (V_VT(&var) == VT_BOOL));
- bHandled = V_BOOL(&var);
- if (bRange)
- delete [] dispparams.rgvarg;
- break;
- case AFX_EVENT::propChanged:
- {
- if (bRange)
- {
- PFN_CHANGED_RANGE pfn = (PFN_CHANGED_RANGE)pEntry->dispEntry.pfnSet;
- bHandled = (this->*pfn)(idCtrl);
- }
- else
- {
- PFN_CHANGED pfn = (PFN_CHANGED)pEntry->dispEntry.pfnSet;
- bHandled = (this->*pfn)();
- }
- hResult = S_OK;
- }
- break;
- case AFX_EVENT::propRequest:
- {
- BOOL bAllow = TRUE;
- if (bRange)
- {
- PFN_REQUEST_RANGE pfn = (PFN_REQUEST_RANGE)pEntry->dispEntry.pfn;
- bHandled = (this->*pfn)(idCtrl, &bAllow);
- }
- else
- {
- PFN_REQUEST pfn = (PFN_REQUEST)pEntry->dispEntry.pfn;
- bHandled = (this->*pfn)(&bAllow);
- }
- hResult = bAllow ? S_OK : S_FALSE;
- }
- break;
- case AFX_EVENT::propDSCNotify:
- {
- BOOL bAllow = TRUE;
- if (bRange)
- {
- PFN_DSCNOTIFY_RANGE pfn = (PFN_DSCNOTIFY_RANGE)pEntry->dispEntry.pfn;
- bHandled = (this->*pfn)(idCtrl, pEvent->m_nDSCState,
- pEvent->m_nDSCReason, &bAllow);
- }
- else
- {
- PFN_DSCNOTIFY pfn = (PFN_DSCNOTIFY)pEntry->dispEntry.pfn;
- bHandled = (this->*pfn)(pEvent->m_nDSCState,
- pEvent->m_nDSCReason, &bAllow);
- }
- hResult = bAllow ? S_OK : S_FALSE;
- }
- break;
- default:
- ASSERT(FALSE); // bogus value for pEvent->m_eventKind
- }
- }
- CATCH_ALL(e)
- {
- if (pEvent->m_pExcepInfo != NULL)
- {
- // fill exception with translation of MFC exception
- COleDispatchException::Process(pEvent->m_pExcepInfo, e);
- }
- DELETE_EXCEPTION(e);
- hResult = DISP_E_EXCEPTION;
- }
- END_CATCH_ALL
- // fill error argument if one is available
- if (FAILED(hResult) && pEvent->m_puArgError != NULL && uArgError != -1)
- *pEvent->m_puArgError = uArgError;
- // fill result code
- pEvent->m_hResult = hResult;
- return bHandled;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Locate event sink map entry
- const AFX_EVENTSINKMAP_ENTRY* PASCAL CCmdTarget::GetEventSinkEntry(
- UINT idCtrl, AFX_EVENT* pEvent)
- {
- const AFX_EVENTSINKMAP* pSinkMap = GetEventSinkMap();
- const AFX_EVENTSINKMAP_ENTRY* pEntry;
- size_t flag = (pEvent->m_eventKind != AFX_EVENT::event);
- while (pSinkMap != NULL)
- {
- // find matching AFX_EVENTSINKMAP_ENTRY
- pEntry = pSinkMap->lpEntries;
- while (pEntry->dispEntry.nPropOffset != -1)
- {
- if ((pEntry->dispEntry.lDispID == pEvent->m_dispid) &&
- (pEntry->dispEntry.nPropOffset == flag))
- {
- if (pEntry->nCtrlIDLast == (UINT)-1)
- {
- // check for wildcard match or exact match
- if ((pEntry->nCtrlIDFirst == (UINT)-1) ||
- (pEntry->nCtrlIDFirst == idCtrl))
- return pEntry;
- }
- else
- {
- // check for range match
- if ((pEntry->nCtrlIDFirst <= idCtrl) &&
- (idCtrl <= pEntry->nCtrlIDLast))
- return pEntry;
- }
- }
- ++pEntry;
- }
- // check base class
- #ifdef _AFXDLL
- pSinkMap = (*pSinkMap->pfnGetBaseMap)();
- #else
- pSinkMap = pSinkMap->pBaseMap;
- #endif
- }
- return NULL; // no matching entry
- }
|