ADO 事件具現化:Visual C++
這是如何在 Visual C++ 中具現化 ADO 事件的圖解說明。 如需完整描述,請參閱 ADO 事件模型範例 (VC++)。
建立衍生自 ConnectionEventsVt 和 RecordsetEventsVt 介面的類別,這些介面位於檔案 adoint.h 中。
// BeginEventExampleVC01
class CConnEvent : public ConnectionEventsVt
{
public:
STDMETHODIMP InfoMessage(
ADOError *pError,
EventStatusEnum *adStatus,
_ADOConnection *pConnection);
...
}
class CRstEvent : public RecordsetEventsVt
{
public:
STDMETHODIMP WillChangeField(
LONG cFields,
VARIANT Fields,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset);
...
}
// EndEventExampleVC01
在這兩個類別中實作每個事件處理程式方法。 每個方法只要傳回S_OK的 HRESULT 就已足夠。 不過,當您讓事件處理程式可供使用時,它們預設會被持續呼叫。 相反地,您可以將 adStatus 設定為 adStatusUnwantedEvent,以要求在收到第一次通知後,不再接收更多通知。
// BeginEventExampleVC02
STDMETHODIMP CConnEvent::ConnectComplete(
ADOError *pError,
EventStatusEnum *adStatus,
_ADOConnection *pConnection)
{
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
// EndEventExampleVC02
事件類別繼承自 IUnknown,因此您也必須實作 QueryInterface、AddRef和 Release 方法。 同時實作類別建構函式和解構函式。 選擇您最熟悉的 Visual C++ 工具,以簡化工作的這個部分。
請告知您的事件處理程式可用,方法是針對 IConnectionPointContainer 和 IConnectionPoint 介面,在 Recordset 及 Connection 物件上發出 QueryInterface。 然後針對每個類別發出 IConnectionPoint::建議。
例如,假設您使用布林函數,如果它成功地通知 Recordset 物件您有事件處理程序可用,則會傳回 True。
// BeginEventExampleVC03
HRESULT hr;
DWORD dwEvtClass;
IConnectionPointContainer *pCPC = NULL;
IConnectionPoint *pCP = NULL;
CRstEvent *pRStEvent = NULL;
...
_RecordsetPtr pRs;
pRs.CreateInstance(__uuidof(Recordset));
pRStEvent = new CRstEvent;
if (pRStEvent == NULL) return FALSE;
...
hr = pRs->QueryInterface(IID_IConnectionPointContainer, (LPVOID *)&pCPC);
if (FAILED(hr)) return FALSE;
hr = pCPC->FindConnectionPoint(RecordsetEvents, &pCP);
pCPC->Release(); // Always Release now, even before checking.
if (FAILED(hr)) return FALSE;
hr = pCP->Advise(pRstEvent, &dwEvtClass); //Turn on event support.
pCP->Release();
if (FAILED(hr)) return FALSE;
...
return TRUE;
...
// EndEventExampleVC03
此時,RecordsetEvent 家族的事件已啟用,當 Recordset 事件發生時,您的方法將被調用。
稍後,當您想要讓事件處理程式無法使用時,請再次取得連接點,併發出 IConnectionPoint::Unadvise 方法。
// BeginEventExampleVC04
...
hr = pCP->Unadvise(dwEvtClass); //Turn off event support.
pCP->Release();
if (FAILED(hr)) return FALSE;
...
// EndEventExampleVC04
您必須視需要釋放介面和銷毀類別物件。
下列程式代碼顯示 Recordset 事件接收類別的完整範例。
// BeginEventExampleVC05.cpp
// compile with: /LD
#include <adoint.h>
class CADORecordsetEvents : public RecordsetEventsVt {
public:
ULONG m_ulRefCount;
CADORecordsetEvents():m_ulRefCount(1){}
STDMETHOD(QueryInterface)(REFIID iid, LPVOID * ppvObject) {
if (IsEqualIID(__uuidof(IUnknown), iid) || IsEqualIID(__uuidof(RecordsetEventsVt), iid)) {
*ppvObject = this;
return S_OK;
}
else
return E_NOINTERFACE;
}
STDMETHOD_(ULONG, AddRef)() {
return m_ulRefCount++;
}
STDMETHOD_(ULONG, Release)() {
if (--m_ulRefCount == 0) {
delete this;
return 0;
}
else
return m_ulRefCount;
}
STDMETHOD(WillChangeField)( LONG cFields,
VARIANT Fields,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
STDMETHOD(FieldChangeComplete)( LONG cFields,
VARIANT Fields,
ADOError *pError,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
STDMETHOD(WillChangeRecord)( EventReasonEnum adReason,
LONG cRecords,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
STDMETHOD(RecordChangeComplete)( EventReasonEnum adReason,
LONG cRecords,
ADOError *pError,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
STDMETHOD(WillChangeRecordset)( EventReasonEnum adReason,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
STDMETHOD(RecordsetChangeComplete)( EventReasonEnum adReason,
ADOError *pError,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
STDMETHOD(WillMove)( EventReasonEnum adReason,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
STDMETHOD(MoveComplete)( EventReasonEnum adReason,
ADOError *pError,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
STDMETHOD(EndOfRecordset)( VARIANT_BOOL *fMoreData,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
STDMETHOD(FetchProgress)( long Progress,
long MaxProgress,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
STDMETHOD(FetchComplete)( ADOError *pError,
EventStatusEnum *adStatus,
_ADORecordset *pRecordset) {
*adStatus = adStatusUnwantedEvent;
return S_OK;
}
};