Kirjautuminen

Haku

Tehtävät

Koodit: ADO tapahtumakäsittelijät Visual C++:ssa

Kirjoittaja: Asko Telinen

Kirjoitettu: 18.05.2004 – 18.05.2004

Tagit: koodi näytille, vinkki

Käyttö:

Peri luokkasi CConnectionEventListener tai CRstEventListener luokasta
ja käsittele halutut tapahtumat perityssä luokassa.

Luo uusi ilmentymä CConnEvents tai CRstEvent luokasta,
liitä joko _ConnectionPtr tai _RecordsetPtr luokkiin
(Attach), jolloin
ne rekisteröidään tapahtumien lähteeksi. Poista lähde ennen
luokan tuhoamista (Detach).

ADOEvents.h

//////////////////////////////////////////////////////////////////////
//
// ADOEvents.h: interface for the CEvents class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_EVENTS_H__A3336C3A_0202_461B_9959_9747D3103A60__INCLUDED_)
#define AFX_EVENTS_H__A3336C3A_0202_461B_9959_9747D3103A60__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#pragma warning(disable: 4786)  // identifier was truncated to '255' characters in the debug information
#pragma warning(disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
#pragma warning(disable : 4192) // automatically excluding 'name' while importing type library 'library'

// ADO COM library
#import <c:\\program files\\common files\\system\\ado\\msado15.dll> no_namespace rename("EOF", "adoEOF")

#include <map>
#include <vector>

typedef std::map<DWORD, DWORD> EVENTMAP;
typedef EVENTMAP::iterator EVENTITERATOR;


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Connection events listener ( to listen connection events, derive from this class and add listener
// to connection manager )
//
class CConnectionEventListener //: public CEventListener
{
public:
    // event handlers
    STDMETHOD_(VOID, InfoMessage)(struct Error* pError, EventStatusEnum* adStatus, struct _Connection* pConnection) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, WillConnect)(BSTR* ConnectionString, BSTR * UserID, BSTR* Password,long* Options,EventStatusEnum* adStatus, struct _Connection * pConnection) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, ConnectComplete)(struct Error* pError,EventStatusEnum* adStatus, struct _Connection* pConnection) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, Disconnect)(EventStatusEnum* adStatus, struct _Connection* pConnection) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, BeginTransComplete)(LONG TransactionLevel, struct Error* pError, EventStatusEnum* adStatus, struct _Connection *pConnection) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, CommitTransComplete)(struct Error *pError, EventStatusEnum *adStatus, struct _Connection *pConnection) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, RollbackTransComplete)(struct Error *pError, EventStatusEnum *adStatus, struct _Connection *pConnection) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, WillExecute)(BSTR *Source, CursorTypeEnum *CursorType, LockTypeEnum *LockType, long *Options, EventStatusEnum *adStatus, struct _Command *pCommand, struct _Recordset *pRecordset, struct _Connection *pConnection) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, ExecuteComplete)(LONG RecordsAffected, struct Error *pError, EventStatusEnum *adStatus, struct _Command *pCommand, struct _Recordset *pRecordset, struct _Connection *pConnection) { *adStatus = adStatusUnwantedEvent; }
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Recordset events listener ( to listen recordset events, derive from this class and add listener
// to recordset manager )
//
class CRstEventListener //: public CEventListener
{
public:
    // event handlers
    STDMETHOD_(VOID, WillChangeField)(LONG cFields, VARIANT Fields, EventStatusEnum *adStatus, struct _Recordset *pRecordset) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, FieldChangeComplete)(LONG cFields,VARIANT Fields,struct Error *pError,EventStatusEnum *adStatus,struct _Recordset *pRecordset) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, WillChangeRecord)(EventReasonEnum adReason,LONG cRecords,EventStatusEnum *adStatus,struct _Recordset *pRecordset) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, RecordChangeComplete)(EventReasonEnum adReason,LONG cRecords,struct Error *pError,EventStatusEnum *adStatus,struct _Recordset *pRecordset) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, WillChangeRecordset)(EventReasonEnum adReason,EventStatusEnum *adStatus,struct _Recordset *pRecordset) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, RecordsetChangeComplete)(EventReasonEnum adReason,struct Error *pError,EventStatusEnum *adStatus,struct _Recordset *pRecordset) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, WillMove)(EventReasonEnum adReason,EventStatusEnum *adStatus,struct _Recordset *pRecordset) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, MoveComplete)(EventReasonEnum adReason,struct Error *pError,EventStatusEnum *adStatus,struct _Recordset *pRecordset) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, EndOfRecordset)(VARIANT_BOOL *fMoreData,EventStatusEnum *adStatus,struct _Recordset *pRecordset) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, FetchProgress)(long Progress,long MaxProgress,EventStatusEnum *adStatus,struct _Recordset *pRecordset) { *adStatus = adStatusUnwantedEvent; }
    STDMETHOD_(VOID, FetchComplete)(struct Error *pError,EventStatusEnum *adStatus,struct _Recordset *pRecordset) { *adStatus = adStatusUnwantedEvent; }
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// IUnknown interface implemetation for event handlers
//
template<class EventType> class CEventIUnknownImpl : public EventType
{
private:
    ULONG m_ulRefCount;

public:
    CEventIUnknownImpl() : m_ulRefCount(1) { }
    virtual ~CEventIUnknownImpl()          { }

    STDMETHOD(QueryInterface)(REFIID iid, LPVOID * ppvObject) {
        if ( ::IsEqualIID(__uuidof(IUnknown), iid) || IsEqualIID(__uuidof(EventType), iid) ) {
            *ppvObject = this;
            return S_OK;
        }
        return E_NOINTERFACE;
    }

    STDMETHOD_(ULONG, AddRef)()    { return m_ulRefCount++; }
    STDMETHOD_(ULONG, Release)()  {
        if ( --m_ulRefCount == 0 ) {
            delete this;
            return 0;
        }
        return m_ulRefCount;
    }
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Container for event listeners
//
template<class ListenerType> class CListenerContainer
{
    typedef std::vector<ListenerType *> list;
    typedef list::iterator              iterator;

private:
    list m_Listeners;

public:
    CListenerContainer() { }
    virtual ~CListenerContainer() { Clear(); }

    STDMETHOD_(long, AddListener)(ListenerType *Listener) {
        if ( !Listener ) { return -1; }
        for ( long m = 0; m < m_Listeners.size(); m++ ) {
            if ( m_Listeners.at(m) == Listener ) { return m; }
        }
        m_Listeners.push_back(Listener);
        return GetListenerCount() - 1;
    }

    STDMETHOD_(bool, RemoveListener)(ListenerType *Listener) {
        for ( long m = 0; m < m_Listeners.size(); m++ ) {
            if ( m_Listeners.at(m) == Listener ) {
                m_Listeners.erase(m_Listeners.begin() + m);
                return true;
            }
        }
        return false;
    }

    STDMETHOD_(ListenerType *, GetListener)(long index) {
        if ( index < 0 || index >= GetListenerCount() ) { return NULL; }
        return m_Listeners.at(index);
    }

    STDMETHOD_(long, GetListener)(ListenerType *Listener) {
        if ( Listener ) {
            for ( long m = 0; m < GetListenerCount(); m++ ) {
                if ( m_Listeners.at(m) == Listener ) { return m; }
            }
        }
        return -1;
    }

    STDMETHOD_(long, GetListenerCount)()    { return m_Listeners.size(); }

    STDMETHOD_(void, Clear)() {
        while ( GetListenerCount() > 0 ) {
            m_Listeners.erase(m_Listeners.begin());
        }
    }
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Event source implementation
template<class ClassPtr, class EventClassVt, class EventType> class CEventSourceImpl :
    public CEventIUnknownImpl<EventClassVt>
{
protected:
    EVENTMAP *m_Events;

public:
    CEventSourceImpl() : m_Events(NULL) { m_Events = new EVENTMAP(); }
    virtual ~CEventSourceImpl() {
        delete m_Events;
    }

    STDMETHOD_(IUnknown *, GetIUnknown)() = 0;

    STDMETHOD(Attach)(ClassPtr &pItem) {

        if ( !pItem.GetInterfacePtr() ) { return E_NOINTERFACE; }

        HRESULT hr = S_OK;
        IConnectionPointContainer *pCPC = NULL;
        IConnectionPoint *pCP = NULL;

        hr = pItem->QueryInterface(IID_IConnectionPointContainer, (LPVOID *)&pCPC);

        if ( SUCCEEDED(hr) ) {

            hr = pCPC->FindConnectionPoint(__uuidof(EventType), &pCP);
            pCPC->Release();    // Always Release now, even before checking.

            if ( SUCCEEDED(hr) ) {
                IUnknown *pUnk = GetIUnknown();
                DWORD dwEvtClass = 0;
                hr = pCP->Advise(pUnk, &dwEvtClass);    //Turn on event support.
                pCP->Release();

                if ( SUCCEEDED(hr) ) {
                    DWORD dwKey = (LONG)((VOID *)pItem.GetInterfacePtr());
                    m_Events->insert(EVENTMAP::value_type(dwKey, dwEvtClass));
                    CEventIUnknownImpl<EventClassVt>::AddRef(); // Add reference. This will prevent connection object from releasing CConnEvents instance
                }
            }

        }

        return hr;
    }

    STDMETHOD(Detach)(ClassPtr &pItem) {

        if ( !pItem.GetInterfacePtr() ) { return E_NOINTERFACE; }

        HRESULT hr = S_OK;
        IConnectionPointContainer *pCPC = NULL;
        IConnectionPoint *pCP = NULL;

        hr = pItem->QueryInterface(IID_IConnectionPointContainer, (LPVOID *)&pCPC);

        if ( SUCCEEDED(hr) ) {

            hr = pCPC->FindConnectionPoint(__uuidof(EventType), &pCP);
            pCPC->Release();    // Always Release now, even before checking.

            if ( SUCCEEDED(hr) ) {

                DWORD dwKey = (LONG)((VOID *)pItem.GetInterfacePtr());
                EVENTITERATOR iItem = m_Events->find(dwKey); // Find Item

                if ( iItem != m_Events->end() ) {
                    hr = pCP->Unadvise(iItem->second); // Connection object decreases reference count
                }
                else {
                    hr = E_INVALIDARG; // Connection not found. Return invalid argument
                }

                pCP->Release();
            }
        }

        return hr;
    }
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Connection event handler
//
class CConnEvents : public CListenerContainer<CConnectionEventListener>,
                    public CEventSourceImpl<_ConnectionPtr, ConnectionEventsVt, ConnectionEvents>
{
public:
    CConnEvents();
    virtual ~CConnEvents();

    STDMETHOD_(IUnknown *, GetIUnknown)() { return this; }

public:

    // Event wrappers
    STDMETHOD(raw_InfoMessage)(struct Error* pError, EventStatusEnum* adStatus, struct _Connection* pConnection);
    STDMETHOD(raw_WillConnect)(BSTR* ConnectionString, BSTR * UserID, BSTR* Password,long* Options, EventStatusEnum* adStatus, _Connection * pConnection);
    STDMETHOD(raw_ConnectComplete)(Error* pError,EventStatusEnum* adStatus, _Connection* pConnection);
    STDMETHOD(raw_Disconnect)(EventStatusEnum* adStatus,_Connection* pConnection);
    STDMETHOD(raw_BeginTransComplete)(LONG TransactionLevel, struct Error* pError, EventStatusEnum* adStatus, struct _Connection *pConnection);
    STDMETHOD(raw_CommitTransComplete)(struct Error *pError, EventStatusEnum *adStatus, struct _Connection *pConnection);
    STDMETHOD(raw_RollbackTransComplete)(struct Error *pError, EventStatusEnum *adStatus, struct _Connection *pConnection);
    STDMETHOD(raw_WillExecute)(BSTR *Source, CursorTypeEnum *CursorType, LockTypeEnum *LockType, long *Options, EventStatusEnum *adStatus, struct _Command *pCommand, struct _Recordset *pRecordset, struct _Connection *pConnection);
    STDMETHOD(raw_ExecuteComplete)(LONG RecordsAffected, struct Error *pError, EventStatusEnum *adStatus, struct _Command *pCommand, struct _Recordset *pRecordset, struct _Connection *pConnection);
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// recordset event handler
//
class CRstEvents : public CListenerContainer<CRstEventListener>,
                   public CEventSourceImpl<_RecordsetPtr, RecordsetEventsVt, RecordsetEvents>
{
public:
    CRstEvents();
    virtual ~CRstEvents();

    STDMETHOD_(IUnknown *, GetIUnknown)() { return this; }

public:
    STDMETHOD(raw_WillChangeField)(LONG cFields, VARIANT Fields, EventStatusEnum *adStatus, struct _Recordset *pRecordset);
    STDMETHOD(raw_FieldChangeComplete)(LONG cFields,VARIANT Fields,struct Error *pError,EventStatusEnum *adStatus,struct _Recordset *pRecordset);
    STDMETHOD(raw_WillChangeRecord)(EventReasonEnum adReason,LONG cRecords,EventStatusEnum *adStatus,struct _Recordset *pRecordset);
    STDMETHOD(raw_RecordChangeComplete)(EventReasonEnum adReason,LONG cRecords,struct Error *pError,EventStatusEnum *adStatus,struct _Recordset *pRecordset);
    STDMETHOD(raw_WillChangeRecordset)(EventReasonEnum adReason,EventStatusEnum *adStatus,struct _Recordset *pRecordset);
    STDMETHOD(raw_RecordsetChangeComplete)(EventReasonEnum adReason,struct Error *pError,EventStatusEnum *adStatus,struct _Recordset *pRecordset);
    STDMETHOD(raw_WillMove)(EventReasonEnum adReason,EventStatusEnum *adStatus,struct _Recordset *pRecordset);
    STDMETHOD(raw_MoveComplete)(EventReasonEnum adReason,struct Error *pError,EventStatusEnum *adStatus,struct _Recordset *pRecordset);
    STDMETHOD(raw_EndOfRecordset)(VARIANT_BOOL *fMoreData,EventStatusEnum *adStatus,struct _Recordset *pRecordset);
    STDMETHOD(raw_FetchProgress)(long Progress,long MaxProgress,EventStatusEnum *adStatus,struct _Recordset *pRecordset);
    STDMETHOD(raw_FetchComplete)(struct Error *pError,EventStatusEnum *adStatus,struct _Recordset *pRecordset);
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////


#endif // !defined(AFX_EVENTS_H__A3336C3A_0202_461B_9959_9747D3103A60__INCLUDED_)

ADOEvents.cpp

//////////////////////////////////////////////////////////////////////
//
// Events.cpp: implementation of the CEvents class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ADOEvents.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Connection event handler
//
CConnEvents::CConnEvents()
{
}

CConnEvents::~CConnEvents()
{
}


// Error event
STDMETHODIMP CConnEvents::raw_InfoMessage(struct Error* pError, EventStatusEnum* adStatus, struct _Connection* pConnection)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->InfoMessage(pError, adStatus, pConnection);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
}

// Connection events
STDMETHODIMP CConnEvents::raw_WillConnect(BSTR* ConnectionString, BSTR * UserID, BSTR* Password,long* Options, EventStatusEnum* adStatus, _Connection * pConnection)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->WillConnect(ConnectionString, UserID, Password, Options, adStatus, pConnection);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
}

STDMETHODIMP CConnEvents::raw_ConnectComplete(Error* pError,EventStatusEnum* adStatus, _Connection* pConnection)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->ConnectComplete(pError, adStatus, pConnection);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
}

// Disconnect
STDMETHODIMP CConnEvents::raw_Disconnect(EventStatusEnum* adStatus,_Connection* pConnection)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->Disconnect(adStatus, pConnection);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
}

STDMETHODIMP CConnEvents::raw_BeginTransComplete(LONG TransactionLevel, struct Error* pError, EventStatusEnum* adStatus, struct _Connection *pConnection)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->BeginTransComplete(TransactionLevel, pError, adStatus, pConnection);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
}

STDMETHODIMP CConnEvents::raw_CommitTransComplete(struct Error *pError, EventStatusEnum *adStatus, struct _Connection *pConnection)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->CommitTransComplete(pError, adStatus, pConnection);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
}

STDMETHODIMP CConnEvents::raw_RollbackTransComplete(struct Error *pError, EventStatusEnum *adStatus, struct _Connection *pConnection)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->RollbackTransComplete(pError, adStatus, pConnection);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
}

STDMETHODIMP CConnEvents::raw_WillExecute(BSTR *Source, CursorTypeEnum *CursorType, LockTypeEnum *LockType,
    long *Options, EventStatusEnum *adStatus, struct _Command *pCommand,
    struct _Recordset *pRecordset, struct _Connection *pConnection)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->WillExecute(Source, CursorType, LockType, Options, adStatus, pCommand, pRecordset, pConnection);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
}

STDMETHODIMP CConnEvents::raw_ExecuteComplete(LONG RecordsAffected, struct Error *pError, EventStatusEnum *adStatus,
    struct _Command *pCommand, struct _Recordset *pRecordset, struct _Connection *pConnection)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->ExecuteComplete(RecordsAffected, pError, adStatus, pCommand, pRecordset, pConnection);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Recordset event listener
//
CRstEvents::CRstEvents()
{
}

CRstEvents::~CRstEvents()
{
}

// Event handlers

STDMETHODIMP CRstEvents::raw_WillChangeField(LONG cFields, VARIANT Fields, EventStatusEnum *adStatus, struct _Recordset *pRecordset)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->WillChangeField(cFields, Fields, adStatus, pRecordset);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};

STDMETHODIMP CRstEvents::raw_FieldChangeComplete(LONG cFields, VARIANT Fields, struct Error *pError, EventStatusEnum *adStatus, struct _Recordset *pRecordset)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->FieldChangeComplete(cFields, Fields, pError, adStatus, pRecordset);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};

STDMETHODIMP CRstEvents::raw_WillChangeRecord(EventReasonEnum adReason, LONG cRecords, EventStatusEnum *adStatus, struct _Recordset *pRecordset)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->WillChangeRecord(adReason, cRecords, adStatus, pRecordset);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};

STDMETHODIMP CRstEvents::raw_RecordChangeComplete(EventReasonEnum adReason, LONG cRecords, struct Error *pError, EventStatusEnum *adStatus, struct _Recordset *pRecordset)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->RecordChangeComplete(adReason, cRecords, pError, adStatus, pRecordset);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};

STDMETHODIMP CRstEvents::raw_WillChangeRecordset(EventReasonEnum adReason, EventStatusEnum *adStatus, struct _Recordset *pRecordset)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->WillChangeRecordset(adReason, adStatus, pRecordset);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};

STDMETHODIMP CRstEvents::raw_RecordsetChangeComplete(EventReasonEnum adReason, struct Error *pError, EventStatusEnum *adStatus, struct _Recordset *pRecordset)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->RecordsetChangeComplete(adReason, pError, adStatus, pRecordset);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};

STDMETHODIMP CRstEvents::raw_WillMove(EventReasonEnum adReason, EventStatusEnum *adStatus, struct _Recordset *pRecordset)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->WillMove(adReason, adStatus, pRecordset);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};

STDMETHODIMP CRstEvents::raw_MoveComplete(EventReasonEnum adReason, struct Error *pError, EventStatusEnum *adStatus, struct _Recordset *pRecordset)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->MoveComplete(adReason, pError, adStatus, pRecordset);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};

STDMETHODIMP CRstEvents::raw_EndOfRecordset(VARIANT_BOOL *fMoreData, EventStatusEnum *adStatus, struct _Recordset *pRecordset)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->EndOfRecordset(fMoreData, adStatus, pRecordset);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};

STDMETHODIMP CRstEvents::raw_FetchProgress(long Progress, long MaxProgress, EventStatusEnum *adStatus, struct _Recordset *pRecordset)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->FetchProgress(Progress, MaxProgress, adStatus, pRecordset);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};

STDMETHODIMP CRstEvents::raw_FetchComplete(struct Error *pError, EventStatusEnum *adStatus, struct _Recordset *pRecordset)
{
    for ( LONG m = 0; m < GetListenerCount(); m++ ) {
        GetListener(m)->FetchComplete(pError, adStatus, pRecordset);
    }
    if ( GetListenerCount() == 0 ) { *adStatus = adStatusUnwantedEvent; }
    return S_OK;
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

Kommentit

peki [21.05.2004 08:45:36]

#

Ihan hyvä vinkki.
Tarpeellinen niille, jotka harkitsevat perinpohjaisen windowsohjelmoinnin aloittamista.
Vinkki ei ehkä ole niin tarpeellinen kuitenkaan peli/demo/grafiikka koodaajille.

Kirjoita kommentti

Muista lukea kirjoitusohjeet.
Tietoa sivustosta