Visual C++
適用先: 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
両方のクラスに、各イベント ハンドラー メソッドを実装します。 各メソッドでは、HRESULT として S_OK を返すだけで十分です。 しかし、イベント ハンドラーが使用できることを通知すると、既定ではそのイベント ハンドラーが継続的に呼び出されます。 これを無効にして、2 回目以降は通知しないよう要求するには、 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 を返すブール型 (Boolean) 関数を使用するとします。
// 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