ADO イベントのインスタンス化: Visual C++
ここでは、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 オブジェクトで IConnectionPointContainer と IConnectionPoint インターフェイスを取得する QueryInterface を発行して、イベント ハンドラーが使用可能であることを知らせます。 次に、各クラスごとに IConnectionPoint::Advise を発行します。
たとえば、イベント ハンドラーが使用可能であることを 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;
}
};