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++ 도구를 선택합니다.
IConnectionPointContainer 및 IConnectionPoint 인터페이스에 대한 Recordset 및 Connection 개체에서 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;
}
};