ADO 事件模型范例 (VC++)

对实例化 ADO 事件模型的方式进行常规说明。下面是一个在由 #import 伪指令创建的环境中实例化事件模型的特定范例。

常规说明中使用 adoint.h 作为方法声明的引用。但是由于使用 #import 伪指令,因此常规说明中的一些细节需要稍微做些更改。

  • #import 伪指令将 typedef、方法声明数据类型和组合键分解为其基本格式。
  • 所有必须覆盖的纯虚拟方法都被加上前缀“raw_”。

某些代码只反映编码样式。

  • Advise 方法使用的指向 IUnknown 的指针是通过 QueryInterface 调用显式获取的。
  • 不需要在类定义中对析构函数进行显式编码。
  • 用户可能需要使 QueryInterface、AddRef 和 Release 的编码更加可靠。
  • __uuidof() 伪指令的用法可扩展用于获取接口 ID。

最后,该范例还包含某些实用代码。

  • 该范例被编写为控制台应用程序。
  • 应在注释“// Do some work”下插入用户自己的代码。
  • 默认情况下所有事件处理程序不进行任何操作,并且取消进一步的通知。用户应插入应用程序的合适代码,如果需要应允许通知。
// eventmodel.cpp : Defines the entry point for the console application.
//

#import "c:/Program Files/Common Files/System/ADO/msado15.dll" /
   no_namespace rename("EOF", "EndOfFile")
#include <comdef.h>
#include <stdio.h>

//----The Connection events----------------------------------------------

class CConnEvent : public ConnectionEventsVt
{
private:
        ULONG   m_cRef;
    public:
        CConnEvent() { m_cRef = 0; };
        ~CConnEvent() {};


        STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
        STDMETHODIMP_(ULONG) AddRef(void);
        STDMETHODIMP_(ULONG) Release(void);

        STDMETHODIMP raw_InfoMessage( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_BeginTransComplete( 
            LONG TransactionLevel,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
      
    STDMETHODIMP raw_CommitTransComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_RollbackTransComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_WillExecute( 
            BSTR *Source,
            CursorTypeEnum *CursorType,
            LockTypeEnum *LockType,
            long *Options,
            EventStatusEnum *adStatus,
            struct _Command *pCommand,
            struct _Recordset *pRecordset,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_ExecuteComplete( 
            LONG RecordsAffected,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Command *pCommand,
            struct _Recordset *pRecordset,
            struct _Connection *pConnection);
        
    STDMETHODIMP raw_WillConnect( 
            BSTR *ConnectionString,
            BSTR *UserID,
            BSTR *Password,
            long *Options,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_ConnectComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_Disconnect( 
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
};

//-----The Recordset events----------------------------------------------

class CRstEvent : public RecordsetEventsVt
    {
    private:
        ULONG m_cRef;   
    public:
        CRstEvent() { m_cRef = 0; };
        ~CRstEvent() {};

            STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
            STDMETHODIMP_(ULONG) AddRef(void);
            STDMETHODIMP_(ULONG) Release(void);

            STDMETHODIMP raw_WillChangeField( 
            LONG cFields,
            VARIANT Fields,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_FieldChangeComplete( 
            LONG cFields,
            VARIANT Fields,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_WillChangeRecord( 
            EventReasonEnum adReason,
            LONG cRecords,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_RecordChangeComplete( 
            EventReasonEnum adReason,
            LONG cRecords,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_WillChangeRecordset( 
            EventReasonEnum adReason,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_RecordsetChangeComplete( 
            EventReasonEnum adReason,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_WillMove( 
            EventReasonEnum adReason,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_MoveComplete( 
            EventReasonEnum adReason,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_EndOfRecordset( 
            VARIANT_BOOL *fMoreData,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_FetchProgress( 
            long Progress,
            long MaxProgress,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_FetchComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
};


//-----Implement each connection method----------------------------------

        STDMETHODIMP CConnEvent::raw_InfoMessage( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_BeginTransComplete( 
            LONG TransactionLevel,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_CommitTransComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_RollbackTransComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
    STDMETHODIMP CConnEvent::raw_WillExecute( 
            BSTR *Source,
            CursorTypeEnum *CursorType,
            LockTypeEnum *LockType,
            long *Options,
            EventStatusEnum *adStatus,
            struct _Command *pCommand,
            struct _Recordset *pRecordset,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_ExecuteComplete( 
            LONG RecordsAffected,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Command *pCommand,
            struct _Recordset *pRecordset,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_WillConnect( 
            BSTR *ConnectionString,
            BSTR *UserID,
            BSTR *Password,
            long *Options,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_ConnectComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_Disconnect( 
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };


//-----Implement each recordset method-----------------------------------

        STDMETHODIMP CRstEvent::raw_WillChangeField( 
            LONG cFields,
            VARIANT Fields,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_FieldChangeComplete( 
            LONG cFields,
            VARIANT Fields,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_WillChangeRecord( 
            EventReasonEnum adReason,
            LONG cRecords,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_RecordChangeComplete( 
            EventReasonEnum adReason,
            LONG cRecords,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_WillChangeRecordset( 
            EventReasonEnum adReason,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_RecordsetChangeComplete( 
            EventReasonEnum adReason,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_WillMove( 
            EventReasonEnum adReason,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_MoveComplete( 
            EventReasonEnum adReason,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_EndOfRecordset( 
            VARIANT_BOOL *fMoreData,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_FetchProgress( 
            long Progress,
            long MaxProgress,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_FetchComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };


//-----Implement QueryInterface, AddRef, and Release---------------------

    STDMETHODIMP CRstEvent::QueryInterface(REFIID riid, void ** ppv) 
    {
        *ppv = NULL;
        if (riid == __uuidof(IUnknown) || 
                 riid == __uuidof(RecordsetEventsVt)) *ppv = this;
        if (*ppv == NULL)
            return ResultFromScode(E_NOINTERFACE);
        AddRef();
        return NOERROR;
    }
    STDMETHODIMP_(ULONG) CRstEvent::AddRef(void) { return ++m_cRef; };
    STDMETHODIMP_(ULONG) CRstEvent::Release()   
                                        { 
                                        if (0 != --m_cRef) return m_cRef;
                                        delete this;
                                        return 0;
                                        }

    STDMETHODIMP CConnEvent::QueryInterface(REFIID riid, void ** ppv) 
        
    {
        *ppv = NULL;
        if (riid == __uuidof(IUnknown) || 
             riid == __uuidof(ConnectionEventsVt)) *ppv = this;
        if (*ppv == NULL)
            return ResultFromScode(E_NOINTERFACE);
        AddRef();
        return NOERROR;
    }
    STDMETHODIMP_(ULONG) CConnEvent::AddRef() { return ++m_cRef; };
    STDMETHODIMP_(ULONG) CConnEvent::Release()    
                                        { 
                                        if (0 != --m_cRef) return m_cRef;
                                        delete this;
                                        return 0;
                                        }

//-----Write your main block of code-------------------------------------

int main(int argc, char* argv[])
{
    HRESULT hr;
    DWORD   dwConnEvt;
    DWORD   dwRstEvt;
    IConnectionPointContainer   *pCPC = NULL;
    IConnectionPoint         *pCP = NULL;
    IUnknown               *pUnk = NULL;
    CRstEvent               *pRstEvent = NULL;
    CConnEvent               *pConnEvent= NULL;
    int                     rc = 0;
    _RecordsetPtr            pRst; 
    _ConnectionPtr            pConn;

    ::CoInitialize(NULL);
    
    hr = pConn.CreateInstance(__uuidof(Connection));
    if (FAILED(hr)) return rc;
    
    hr = pRst.CreateInstance(__uuidof(Recordset));
    if (FAILED(hr)) return rc;

    // Start using the Connection events

    hr = pConn->QueryInterface(__uuidof(IConnectionPointContainer), 
        (void **)&pCPC);
    if (FAILED(hr)) return rc;
    hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);
    pCPC->Release();
    if (FAILED(hr)) return rc;

    pConnEvent = new CConnEvent();
    hr = pConnEvent->QueryInterface(__uuidof(IUnknown), (void **) &pUnk);
    if (FAILED(hr)) return rc;
    hr = pCP->Advise(pUnk, &dwConnEvt);
    pCP->Release();
    if (FAILED(hr)) return rc;

    // Start using the Recordset events

    hr = pRst->QueryInterface(__uuidof(IConnectionPointContainer), 
        (void **)&pCPC);
    if (FAILED(hr)) return rc;
    hr = pCPC->FindConnectionPoint(__uuidof(RecordsetEvents), &pCP);
    pCPC->Release();
    if (FAILED(hr)) return rc;

    pRstEvent = new CRstEvent();
    hr = pRstEvent->QueryInterface(__uuidof(IUnknown), (void **) &pUnk);
    if (FAILED(hr)) return rc;
    hr = pCP->Advise(pUnk, &dwRstEvt);
    pCP->Release();
    if (FAILED(hr)) return rc;

    // Do some work

    pConn->Open("dsn=Pubs;", "sa", "", adConnectUnspecified);
    pRst->Open("SELECT * FROM authors", (IDispatch *) pConn, 
            adOpenStatic, adLockReadOnly, adCmdText);
    pRst->MoveFirst();
    while (pRst->EndOfFile == FALSE)
    {
        wprintf(L"Name = '%s'/n", (wchar_t*) 
            ((_bstr_t) pRst->Fields->GetItem("au_lname")->Value));
        pRst->MoveNext();
    }

    pRst->Close();
    pConn->Close();

    // Stop using the Connection events

    hr = pConn->QueryInterface(__uuidof(IConnectionPointContainer), 
        (void **) &pCPC);
    if (FAILED(hr)) return rc;
    hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);
    pCPC->Release();
    if (FAILED(hr)) return rc;
    hr = pCP->Unadvise( dwConnEvt );
    pCP->Release();
    if (FAILED(hr)) return rc;

    // Stop using the Recordset events
    hr = pRst->QueryInterface(__uuidof(IConnectionPointContainer), 
        (void **) &pCPC);
    if (FAILED(hr)) return rc;
    hr = pCPC->FindConnectionPoint(__uuidof(RecordsetEvents), &pCP);
    pCPC->Release();
    if (FAILED(hr)) return rc;
    hr = pCP->Unadvise( dwRstEvt );
    pCP->Release();
    if (FAILED(hr)) return rc;

    CoUninitialize();
    return 1;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值