ADO 事件模型範例 (VC++)
ADO 事件具現化 (依語言) (部分機器翻譯) 的 Visual C++ 小節提供如何將 ADO 事件模型具現化的一般描述。 以下是在由 #import 指示詞所建立的環境中將事件模型具現化的特定範例。
一般描述會使用 adoint.h 作為方法簽章的參考。 不過,一般描述中有一些詳細資料會因為使用 #import 指示詞而稍微變更:
#import 指示詞會將 typedef、方法簽章資料類型與修飾詞解析為其基本形式。
必須覆寫的純虛擬方法的前面都會加上 "raw_"。
有些程式碼只會反映程式碼撰寫樣式。
Advise 方法所使用的 IUnknown 指標是透過對 QueryInterface 的呼叫明確取得。
您不需要在類別定義中明確撰寫解構函式的程式碼。
建議您撰寫更強固的 QueryInterface、AddRef 與 Release 實作的程式碼。
__uuidof() 指示詞廣泛用來取得介面識別碼。
最後,此範例包含一些可運作的程式碼。
範例已撰寫為主控台應用程式。
您應該在註解 "
// Do some work
" 底下插入您自己的程式碼。所有事件處理常式預設不會執行任何動作,並取消進一步通知。 您應該插入適用於您應用程式的適當程式碼,並視需要允許通知。
// 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();
}