home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
vc98
/
mfc
/
src
/
occevent.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-16
|
6KB
|
234 lines
// 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
}