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;
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////Ihan hyvä vinkki.
Tarpeellinen niille, jotka harkitsevat perinpohjaisen windowsohjelmoinnin aloittamista.
Vinkki ei ehkä ole niin tarpeellinen kuitenkaan peli/demo/grafiikka koodaajille.