Exemple de modèle d’événements ADO (VC ++)
La section Visual C++ de l’Instanciation d’événements ADO par langage fournit une description générale de l’instanciation du modèle d’événement ADO. Voici un exemple spécifique d’instanciation du modèle d’événement dans l’environnement créé par la directive #import.
La description générale utilise adoint.h comme référence pour les signatures de méthode. Toutefois, quelques détails dans la description générale changent légèrement en raison de l’utilisation de la directive #import :
La directive #import résout les typedef, les types de données des signatures de méthode et les modificateurs sur leurs formes fondamentales.
Les méthodes virtuelles pures qui doivent être remplacées sont toutes préfixées par « raw_ ».
Une partie du code reflète simplement le style de codage.
Le pointeur vers IUnknown utilisé par la méthode Advise est obtenu explicitement avec un appel à QueryInterface.
Vous n’avez pas besoin de coder explicitement un destructeur dans les définitions de classe.
Vous pouvez coder des implémentations plus robustes de QueryInterface, AddRef et Release.
La directive __uuidof() est utilisée largement pour obtenir des ID d’interface.
Enfin, l’exemple contient du code de travail.
L’exemple est écrit comme une application console.
Vous devez insérer votre propre code sous le commentaire «
// Do some work
».Tous les gestionnaires d’événements par défaut ne font rien et annulent les notifications ultérieures. Vous devez insérer le code approprié pour votre application et autoriser les notifications si nécessaire.
// ADO_Events_Model_Example.cpp
#import "msado15.dll" no_namespace rename("EOF", "EndOfFile")
// The Connection events
class CConnEvent : public ConnectionEventsVt {
private:
ULONG m_cRef;
public:
CConnEvent() { m_cRef = 0; };
~CConnEvent() {};
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP raw_InfoMessage( struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection);
STDMETHODIMP raw_BeginTransComplete( LONG TransactionLevel,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection);
STDMETHODIMP raw_CommitTransComplete( struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection);
STDMETHODIMP raw_RollbackTransComplete( struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection);
STDMETHODIMP raw_WillExecute( BSTR *Source,
CursorTypeEnum *CursorType,
LockTypeEnum *LockType,
long *Options,
EventStatusEnum *adStatus,
struct _Command *pCommand,
struct _Recordset *pRecordset,
struct _Connection *pConnection);
STDMETHODIMP raw_ExecuteComplete( LONG RecordsAffected,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Command *pCommand,
struct _Recordset *pRecordset,
struct _Connection *pConnection);
STDMETHODIMP raw_WillConnect( BSTR *ConnectionString,
BSTR *UserID,
BSTR *Password,
long *Options,
EventStatusEnum *adStatus,
struct _Connection *pConnection);
STDMETHODIMP raw_ConnectComplete( struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection);
STDMETHODIMP raw_Disconnect( EventStatusEnum *adStatus, struct _Connection *pConnection);
};
// The Recordset events
class CRstEvent : public RecordsetEventsVt {
private:
ULONG m_cRef;
public:
CRstEvent() { m_cRef = 0; };
~CRstEvent() {};
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP raw_WillChangeField( LONG cFields,
VARIANT Fields,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset);
STDMETHODIMP raw_FieldChangeComplete( LONG cFields,
VARIANT Fields,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset);
STDMETHODIMP raw_WillChangeRecord( EventReasonEnum adReason,
LONG cRecords,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset);
STDMETHODIMP raw_RecordChangeComplete( EventReasonEnum adReason,
LONG cRecords,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset);
STDMETHODIMP raw_WillChangeRecordset( EventReasonEnum adReason,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset);
STDMETHODIMP raw_RecordsetChangeComplete( EventReasonEnum adReason,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset);
STDMETHODIMP raw_WillMove( EventReasonEnum adReason,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset);
STDMETHODIMP raw_MoveComplete( EventReasonEnum adReason,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset);
STDMETHODIMP raw_EndOfRecordset( VARIANT_BOOL *fMoreData,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset);
STDMETHODIMP raw_FetchProgress( long Progress,
long MaxProgress,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset);
STDMETHODIMP raw_FetchComplete( struct Error *pError,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset);
};
// Implement each connection method
STDMETHODIMP CConnEvent::raw_InfoMessage( struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CConnEvent::raw_BeginTransComplete( LONG TransactionLevel,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CConnEvent::raw_CommitTransComplete( struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CConnEvent::raw_RollbackTransComplete( struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CConnEvent::raw_WillExecute( BSTR *Source,
CursorTypeEnum *CursorType,
LockTypeEnum *LockType,
long *Options,
EventStatusEnum *adStatus,
struct _Command *pCommand,
struct _Recordset *pRecordset,
struct _Connection *pConnection) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CConnEvent::raw_ExecuteComplete( LONG RecordsAffected,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Command *pCommand,
struct _Recordset *pRecordset,
struct _Connection *pConnection) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CConnEvent::raw_WillConnect( BSTR *ConnectionString,
BSTR *UserID,
BSTR *Password,
long *Options,
EventStatusEnum *adStatus,
struct _Connection *pConnection) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CConnEvent::raw_ConnectComplete( struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CConnEvent::raw_Disconnect( EventStatusEnum *adStatus, struct _Connection *pConnection) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
// Implement each recordset method
STDMETHODIMP CRstEvent::raw_WillChangeField( LONG cFields,
VARIANT Fields,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CRstEvent::raw_FieldChangeComplete( LONG cFields,
VARIANT Fields,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CRstEvent::raw_WillChangeRecord( EventReasonEnum adReason,
LONG cRecords,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CRstEvent::raw_RecordChangeComplete( EventReasonEnum adReason,
LONG cRecords,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CRstEvent::raw_WillChangeRecordset( EventReasonEnum adReason,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CRstEvent::raw_RecordsetChangeComplete( EventReasonEnum adReason,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CRstEvent::raw_WillMove( EventReasonEnum adReason,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CRstEvent::raw_MoveComplete( EventReasonEnum adReason,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CRstEvent::raw_EndOfRecordset( VARIANT_BOOL *fMoreData,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CRstEvent::raw_FetchProgress( long Progress,
long MaxProgress,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CRstEvent::raw_FetchComplete( struct Error *pError,
EventStatusEnum *adStatus,
struct _Recordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
};
STDMETHODIMP CRstEvent::QueryInterface(REFIID riid, void ** ppv) {
*ppv = NULL;
if (riid == __uuidof(IUnknown) || riid == __uuidof(RecordsetEventsVt))
*ppv = this;
if (*ppv == NULL)
return ResultFromScode(E_NOINTERFACE);
AddRef();
return NOERROR;
}
STDMETHODIMP_(ULONG) CRstEvent::AddRef() {
return ++m_cRef;
};
STDMETHODIMP_(ULONG) CRstEvent::Release() {
if (0 != --m_cRef)
return m_cRef;
delete this;
return 0;
}
STDMETHODIMP CConnEvent::QueryInterface(REFIID riid, void ** ppv) {
*ppv = NULL;
if (riid == __uuidof(IUnknown) || riid == __uuidof(ConnectionEventsVt))
*ppv = this;
if (*ppv == NULL)
return ResultFromScode(E_NOINTERFACE);
AddRef();
return NOERROR;
}
STDMETHODIMP_(ULONG) CConnEvent::AddRef() {
return ++m_cRef;
};
STDMETHODIMP_(ULONG) CConnEvent::Release() {
if (0 != --m_cRef)
return m_cRef;
delete this;
return 0;
}
int main() {
HRESULT hr;
DWORD dwConnEvt;
DWORD dwRstEvt;
IConnectionPointContainer *pCPC = NULL;
IConnectionPoint *pCP = NULL;
IUnknown *pUnk = NULL;
CRstEvent *pRstEvent = NULL;
CConnEvent *pConnEvent= NULL;
int rc = 0;
_RecordsetPtr pRst;
_ConnectionPtr pConn;
::CoInitialize(NULL);
hr = pConn.CreateInstance(__uuidof(Connection));
if (FAILED(hr))
return rc;
hr = pRst.CreateInstance(__uuidof(Recordset));
if (FAILED(hr))
return rc;
// Start using the Connection events
hr = pConn->QueryInterface(__uuidof(IConnectionPointContainer), (void **)&pCPC);
if (FAILED(hr))
return rc;
hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);
pCPC->Release();
if (FAILED(hr))
return rc;
pConnEvent = new CConnEvent();
hr = pConnEvent->QueryInterface(__uuidof(IUnknown), (void **) &pUnk);
if (FAILED(hr))
return rc;
hr = pCP->Advise(pUnk, &dwConnEvt);
pCP->Release();
if (FAILED(hr))
return rc;
// Start using the Recordset events
hr = pRst->QueryInterface(__uuidof(IConnectionPointContainer), (void **)&pCPC);
if (FAILED(hr))
return rc;
hr = pCPC->FindConnectionPoint(__uuidof(RecordsetEvents), &pCP);
pCPC->Release();
if (FAILED(hr))
return rc;
pRstEvent = new CRstEvent();
hr = pRstEvent->QueryInterface(__uuidof(IUnknown), (void **) &pUnk);
if (FAILED(hr))
return rc;
hr = pCP->Advise(pUnk, &dwRstEvt);
pCP->Release();
if (FAILED(hr))
return rc;
// Do some work
pConn->Open("dsn=DataPubs;", "", "", adConnectUnspecified);
pRst->Open("SELECT * FROM authors", (IDispatch *) pConn, adOpenStatic, adLockReadOnly, adCmdText);
pRst->MoveFirst();
while (pRst->EndOfFile == FALSE) {
wprintf(L"Name = '%s'\n", (wchar_t*) ((_bstr_t) pRst->Fields->GetItem("au_lname")->Value));
pRst->MoveNext();
}
pRst->Close();
pConn->Close();
// Stop using the Connection events
hr = pConn->QueryInterface(__uuidof(IConnectionPointContainer), (void **) &pCPC);
if (FAILED(hr))
return rc;
hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);
pCPC->Release();
if (FAILED(hr))
return rc;
hr = pCP->Unadvise( dwConnEvt );
pCP->Release();
if (FAILED(hr))
return rc;
// Stop using the Recordset events
hr = pRst->QueryInterface(__uuidof(IConnectionPointContainer), (void **) &pCPC);
if (FAILED(hr))
return rc;
hr = pCPC->FindConnectionPoint(__uuidof(RecordsetEvents), &pCP);
pCPC->Release();
if (FAILED(hr))
return rc;
hr = pCP->Unadvise( dwRstEvt );
pCP->Release();
if (FAILED(hr))
return rc;
CoUninitialize();
}