适用于:Access 2013、Office 2013
这是如何在 Microsoft Visual C++ 中实例化 ADO 事件的架构说明。 有关完整说明 ,请参阅 ADO 事件模型示例 (VC++) 。
创建从在文件 adoint.h 中找到的 ConnectionEventsVt 和 RecordsetEventsVt 接口派生的类。
// 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++ 工具来简化这部分任务。
通过发出 Recordset 和 Connection 对象的 QueryInterface 来获取 IConnectionPointContainer 和 IConnectionPoint 接口,以便通知事件处理程序可用。 然后对每个类发出 IConnectionPoint::Advise。
例如,假设您正在使用返回 True 的布尔函数,如果它成功,将通知 Recordset 对象您的事件处理程序已经可用。
// 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
#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;
}
};
// EndEventExampleVC05