在vc中用ado虽然不是很麻烦但是由于vc没有提供对ado的包装类,象数据感知控件,ADO事件(如记录集的移动事件)等机制都难以在vc下运用和实现,于是乎我在delphi下习惯了的一些运用在vc下都无法做到开发进度非常缓慢,痛苦啊。在网上download 的一些vc运用数据库的例子都做得不伦不类。各位有什么感受也说说啊

解决方案 »

  1.   

    晕,你说的ado都可以做到。这是巧合吗?
      

  2.   

    谁能给个完美的例子来看看,要求有数据感知,ado事件
      

  3.   

    如果有好的例子请发邮件给我e_mail:[email protected]
      

  4.   

    尽管VC对数据库得开发效率不是很高,但是由于VC很灵活,网上有很多封装得很好得源代码,比如楼主说得ADO,可能楼主是DEPHI转过来的,慢慢适应。
      

  5.   

    网上的确有很多ado封装类,但是也只是做了最基本的包装,象ado事件好像就包不进去
      

  6.   

    Delphi转过来的, 概念都不一样了, 肯定要适应一段时间了
      

  7.   

    慢慢适应,偶在学校的时候用VB挂ACCESS,后转VC做毕设,感觉相当不方便,一切习惯就好,VC挂ADO虽然繁琐一些,但可以让你较好的理解ADO
      

  8.   

    http://dev.csdn.net/user/callzjy
    http://dev.csdn.net/user/zswzwy
      

  9.   

    谁能告诉我在vc下ADO事件怎么用啊,没有该机制的话,我要写很多变通代码,累死
      

  10.   

    在vc下使用智能指针操作ado我已经很熟了,可就是不知道如何实现智能感知控件和ADO事件
      

  11.   

    我在CSDN几乎所搜不到vc下使用智能感知控件和ADO事件的帖子,各位如果也搜一下的话,会发现我最近提了好几次类似的问题,但几乎得不到有效的回答,还有人当我初学发一些ADO使用基本操作给我呢,希望有识之士继续顶贴
      

  12.   

    VC开发是没有VB来得快,但是我觉得VC开发更稳定些,程序运行效率更高些。
      

  13.   

    用VC开发当然没有Delphi开发来得快,不过它很灵活.网上有很多例子,你适应了就好了
      

  14.   

    我看了很多例子就是没看见利用ado事件的
      

  15.   

    void CChargeInputExtension::SelectTypeA()
    {
    HRESULT hr = NOERROR;
    bool fComInitialized = false;
    _RecordsetPtr pRs = NULL;
    FieldPtr *rgflds = NULL;
    //CString *p_str;
    long lNumFields, lFld;
    _variant_t vValue,m_sql;
    _bstr_t ll;
    CString         m_temp("");
    m_sql=(_variant_t)msql;

    try
    {
    if (FAILED(hr = ::CoInitialize(NULL)))
    _com_issue_error(hr);

    fComInitialized = true;
    // Open the recordset
    pRs.CreateInstance("ADODB.Recordset.2.5");
    pRs->Open(m_sql,g_pszConnection, adOpenForwardOnly, adLockReadOnly, adCmdUnknown);
    lNumFields = pRs->Fields->Count;
    rgflds = new FieldPtr[lNumFields];
    //p_str = new CString[lNumFields];
    if (!rgflds)
    _com_issue_error(E_OUTOFMEMORY);
    memset(rgflds, 0, lNumFields * sizeof(FieldPtr));
    for (lFld = 0; lFld < lNumFields; lFld++){
    rgflds[lFld] = pRs->Fields->GetItem(lFld);

    //p_str[lFld] = m_temp;
    } while (VARIANT_FALSE == pRs->EndOfFile)
    {
      for (lFld = 0; lFld < lNumFields; lFld++)
    {
      vValue = rgflds[lFld]->Value;
    m_temp.Format("m%d=new Array(",lFld);
             //*pCtxt<< m_temp;
    if (VT_NULL == vValue.vt)
    m_temp="";
    else
    {
    ll=(_bstr_t)vValue; 
    m_temp=(char*)ll;
    m_temp.TrimRight();
    m_temp=m_temp.Mid(0,m_temp.GetLength()-1)+");";
    }
    *pCtxt << m_temp ;
    }
    pRs->MoveNext();
    } }
    catch (_com_error &e)
    {
    OutputErrors(pCtxt, e);
    hr = e.Error();
    } if (rgflds)
    delete[] rgflds;

    pRs = NULL;
    if (fComInitialized)
    ::CoUninitialize();
    ///////////////////////////////////////////////////////////
    }看看这个例子
      

  16.   

    这个例子没有ado事件呀,只是些最基本的ado应用,我说的ado事件是指触发记录移动前,记录移动后这样的事件.
      

  17.   

    以下是我找到的唯一关于在vc下使用ado事件的说明,只是我看得不大懂,大家帮解释下:
    响应ADO的通知事件
    通知事件就是当某个特定事件发生时,由Provider通知客户程序,换句话说,就是由Provider调用客户程序中的一个特定的方法(即事件的处理函数)。所以为了响应一个事件,最关键的就是要实现事件的处理函数。
    (1). 从ConnectionEventsVt接口派生出一个类
    为了响应_Connection的通知事件,应该从ConnectionEventsVt接口派生出一个类:
    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);
      ......
    };
    (2). 实现每一个事件的处理函数(凡是带raw_前缀的方法都把它实现了):
    STDMETHODIMP CConnEvent::raw_InfoMessage( 
             struct Error *pError,
             EventStatusEnum *adStatus,
             struct _Connection *pConnection)
             {
             *adStatus = adStatusUnwantedEvent;
             return S_OK;
             };有些方法虽然你并不需要,但也必须实现它,只需简单地返回一个S_OK即可。但如果要避免经常被调用,还应在其中将adStatus参数设置为adStatusUnwantedEvent,则在本次调用后,以后就不会被调用了。
    另外还必须实现QueryInterface, AddRef, 和Release三个方法: 
     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;
    }
    (3). 开始响应通知事件
     // Start using the Connection events
     IConnectionPointContainer   *pCPC = NULL;
     IConnectionPoint         *pCP = NULL; hr = pConn.CreateInstance(__uuidof(Connection));
       if (FAILED(hr)) return; hr = pConn->QueryInterface(__uuidof(IConnectionPointContainer), 
          (void **)&pCPC);
     if (FAILED(hr)) return;
     hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);
     pCPC->Release();
     if (FAILED(hr)) return; 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; pConn->Open("dsn=Pubs;", "sa", "", adConnectUnspecified); 
    也就是说在连接(Open)之前就做这些事。
    (4). 停止响应通知事件
     pConn->Close();
     // Stop using the Connection events
      hr = pConn->QueryInterface(__uuidof(IConnectionPointContainer), 
          (void **) &pCPC);
       if (FAILED(hr)) return;
       hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);
       pCPC->Release();
       if (FAILED(hr)) return rc;
       hr = pCP->Unadvise( dwConnEvt );
       pCP->Release();
       if (FAILED(hr)) return;
    在连接关闭之后做这件事。 
      

  18.   

    VC不是RAD当然很痛苦啦
    它没有那么多的组件啊
    我不是高手
    所以我早早就转向Delphi了
    你为什么又转回来呢
    是客户要求用VC么
      

  19.   

    vc做数据库也没什么呀,关键是为手熟尔,整天做程序现在CRecordset,CDaoRecordset,CAdoRecordset都用过了,感觉不到vc做数据库有多麻烦,楼主慢慢习惯就好了
      

  20.   

    资料是满大街都有,看你怎么找了。不太清楚“数据感知”是什么概念,帮不到你,ADO Event倒是多的很。
    (以下的例子由 PlatForm SDK 中摘录,请注意。)
    // 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);
    };
      

  21.   

    (接上帖)
    //-----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;
                                  }
      

  22.   

    (唉,抱歉抱歉,代码太长了,多包涵)
    //-----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;", "MyUserName", "MyPassword", 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;
    }别人写的代码至少有一点是可取的:它能用。你自己写的代码怎么都连不上数据库,别人的连上了,那么这个代码对你就有参考作用。至于它的代码漂亮不漂亮,那是另一回事;而其中怎么取舍靠的是你自己,别一句“不伦不类”就完全否定了别人的成果,谢谢。
      

  23.   

    对于要实现事件功能,那的写一个自己的函数了,你可以写一个CADoEvent类在你操作记录的 时候 ,和 数据库连接的时候你发送一个registered message,然后在message 处理函数作你想要做的事情,这样在你移动记录,代开recorder的时候就会触发这个message,你就可以在 message handle 函数中完成你自己的事件,当然你的可以把你的 message handle 函数做成一虚函数,这样你在子类中还可以完成子类的特定函数功能。
      

  24.   

    VC能很好的支持数据库哦!
    我只用ODBC
      

  25.   

    那么如果将ado绑定类绑定对话框界面呢
      

  26.   

    那么如何将ado绑定类绑定对话框界面呢