📄 events.cpp
字号:
* Purpose:
* Sets the event mapping of a specific ID to a given action.
* To clear an event, call this function with the ID and
* ACTION_NONE.
*
* Parameters:
* id DISPID of the event ID.
* iAction EVENTACTION to assign.
*
* Return Value:
* BOOL TRUE if the assignment happened, FALSE otherwise.
*/
BOOL CEventMap::Set(DISPID id, EVENTACTION iAction)
{
BOOL fRet=FALSE;
if (NULL!=m_pEventMap)
{
UINT i;
for (i=0; i < m_cEvents; i++)
{
if (m_pEventMap[i].id==id)
{
m_pEventMap[i].iAction=iAction;
fRet=TRUE;
}
}
}
return fRet;
}
/*
* CEventMap::Get
*
* Purpose:
* Retrieves the event assignment for a given ID.
*
* Parameters:
* id DISPID of the event ID.
*
* Return Value:
* EVENTACTION The action assigned to this ID. ACTION_NONE
* if the ID is invalid.
*/
EVENTACTION CEventMap::Get(DISPID id)
{
EVENTACTION iAction=ACTION_NONE;
if (NULL!=m_pEventMap)
{
UINT i;
//Scan the list looking for the event
for (i=0; i < m_cEvents; i++)
{
if (m_pEventMap[i].id==id)
{
iAction=m_pEventMap[i].iAction;
break;
}
}
}
return iAction;
}
/*
* CEventMap::Serialize
* CEventMap::Deserialize
*
* Purpose:
* Writes or reads the mappings from DISPID to actions
* into or from a stream.
*
* Parameters:
* pIStream LPSTREAM into which to write or from which to
* read.
*
* Return Value:
* None
*/
void CEventMap::Serialize(LPSTREAM pIStream)
{
EVENTMAP emTemp;
ULONG cbWrite=sizeof(DISPID)+sizeof(EVENTACTION);
if (NULL==pIStream)
return;
/*
* Loop through all the IDs and write the ID and the action
* mapping only. We don't need the event name because that
* will be retrieved when the control is again loaded.
*
* Writing these pieces of info means writing the first
* so many bytes of each EVENTMAP structure, ignoring the
* BSTR of the name.
*/
if (NULL!=m_pEventMap)
{
UINT i;
for (i=0; i < m_cEvents; i++)
pIStream->Write(&m_pEventMap[i], cbWrite, NULL);
}
/*
* Finish off by writing a terminating EVENTMAP structure
* where the action is ACTION_TAILING which only have
* meaning here. The ID is ignored in this tail.
*/
emTemp.id=0;
emTemp.iAction=ACTION_TAILING;
pIStream->Write(&emTemp, cbWrite, NULL);
return;
}
void CEventMap::Deserialize(LPSTREAM pIStream)
{
if (NULL==pIStream)
return;
/*
* When reading back the event mappings we have to be
* careful: the control's event set might have changed
* in the meantime so some events may no longer exist and
* there may be new events. Therefore we read each mapping
* one at a time (until we hit the tailing map) and find
* the ID in the current memory event map. When we find
* a match we update the action in memory.
*/
if (NULL==m_pEventMap)
return;
while (TRUE)
{
ULONG cbRead=sizeof(DISPID)+sizeof(EVENTACTION);
HRESULT hr;
EVENTMAP em;
hr=pIStream->Read(&em, cbRead, NULL);
//Failure to read means a stream problem, to abort
if (FAILED(hr))
break;
//If we hit the tail, we're done
if (ACTION_TAILING==em.iAction)
break;
//Assign the action to the ID, if it exists
Set(em.id, em.iAction);
}
return;
}
//Events IDispatch
/*
* CDispatchEvents::CDispatchEvents
* CDispatchEvents::~CDispatchEvents
*
* Parameters (Constructor):
* pTen PCTenant of the tenant we're in.
*/
CDispatchEvents::CDispatchEvents(PCTenant pTen)
{
m_cRef=0;
m_pTen=pTen;
return;
}
CDispatchEvents::~CDispatchEvents(void)
{
return;
}
/*
* CDispatchEvents::QueryInterface
* CDispatchEvents::AddRef
* CDispatchEvents::Release
*
* Purpose:
* IUnknown members for CDispatchEvents object.
*/
STDMETHODIMP CDispatchEvents::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;
if (IID_IUnknown==riid || IID_IDispatch==riid
|| m_pTen->m_iidEvents==riid)
*ppv=this;
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CDispatchEvents::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CDispatchEvents::Release(void)
{
if (0!=--m_cRef)
return m_cRef;
delete this;
return 0;
}
/*
* CDispatchEvents::GetTypeInfoCount
* CDispatchEvents::GetTypeInfo
* CDispatchEvents::GetIDsOfNames
*
* Purpose:
* These type-information functions are not implemented. The
* only caller of this interface is a control which is the source
* of the type information itself. A control will not have a
* need to call these functions.
*
* Return Value:
* HRESULT E_NOTIMPL in all cases.
*/
STDMETHODIMP CDispatchEvents::GetTypeInfoCount(UINT *pctInfo)
{
*pctInfo=NULL;
return ResultFromScode(E_NOTIMPL);
}
STDMETHODIMP CDispatchEvents::GetTypeInfo(UINT itinfo
, LCID lcid, ITypeInfo **pptInfo)
{
*pptInfo=NULL;
return ResultFromScode(E_NOTIMPL);
}
STDMETHODIMP CDispatchEvents::GetIDsOfNames(REFIID riid
, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgDispID)
{
*rgszNames=NULL;
*rgDispID=NULL;
return ResultFromScode(E_NOTIMPL);
}
/*
* CDispatchEvents::Invoke
*
* Purpose:
* Notifies the container of the event in the control. In this
* container we look in the event mapping for this particular
* site and execute the appropriate action recorded in that
* mapping. If there is no event handler set up, then nothing
* happens.
*
* Parameters:
* dispIDMember DISPID of the method or property of interest.
* riid REFIID reserved, must be NULL.
* lcid LCID of the locale.
* wFlags USHORT describing the context of the invocation.
* pDispParams DISPPARAMS * to the array of arguments.
* pVarResult VARIANT * in which to store the result. Is
* NULL if the caller is not interested.
* pExcepInfo EXCEPINFO * to exception information.
* puArgErr UINT * in which to store the index of an
* invalid parameter if DISP_E_TYPEMISMATCH
* is returned.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP CDispatchEvents::Invoke(DISPID dispIDMember, REFIID riid
, LCID lcid, unsigned short wFlags, DISPPARAMS * pDispParams
, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
HRESULT hr;
VARIANT varResult;
EVENTACTION iAction;
UINT i;
PEVENTMAP pEM;
ODSlu("Events IDispatch called with ID=%lu", dispIDMember);
if (IID_NULL!=riid)
return ResultFromScode(E_INVALIDARG);
/*
* We ignore lcid in this function. A multilingual application
* might use it to determine the meaning of certain parameters
* or perhaps as an indication of how to format data like
* time, date, and currency or any other language or locale-
* sensitive data.
*/
/*
* Variable handling: we don't actually do anything with any
* of the variables from the control's events, so we don't have
* any VARIANTARG variables to initialize.
*/
/*
* We don't handle the return value of any events if
* events have them. We should, however, initialize an
* empty return value just so it's not garbage.
*/
if(NULL==pVarResult)
pVarResult=&varResult;
VariantInit(pVarResult);
V_VT(pVarResult)=VT_EMPTY;
//Only method calls are valid.
if (!(DISPATCH_METHOD & wFlags))
return ResultFromScode(DISP_E_MEMBERNOTFOUND);
/*
* Process the event by looking for dispIDMember in the
* list maintained in the tenant that maps event IDs to
* actions. If we find the ID, then we execute the action,
* otherwise we do nothing.
*
* Control containers that allow more sophisticated programming
* for events would do something on the same order but process
* parameters and call user-implemented functions instead of
* something simple like MessageBeep.
*/
iAction=ACTION_NONE;
pEM=m_pTen->m_pEventMap->m_pEventMap;
for (i=0; i < m_pTen->m_pEventMap->m_cEvents; i++)
{
if (dispIDMember==pEM[i].id)
{
iAction=pEM[i].iAction;
break;
}
}
if (ACTION_NONE==iAction)
hr=ResultFromScode(DISP_E_MEMBERNOTFOUND);
else
{
MessageBeep((UINT)iAction);
hr=NOERROR;
}
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -