⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 events.cpp

📁 英文版的 想要的话可以下载了 为大家服务
💻 CPP
📖 第 1 页 / 共 2 页
字号:
 * 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 + -