感觉vc对数据库的支持很弱啊,好痛苦 在vc中用ado虽然不是很麻烦但是由于vc没有提供对ado的包装类,象数据感知控件,ADO事件(如记录集的移动事件)等机制都难以在vc下运用和实现,于是乎我在delphi下习惯了的一些运用在vc下都无法做到开发进度非常缓慢,痛苦啊。在网上download 的一些vc运用数据库的例子都做得不伦不类。各位有什么感受也说说啊 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 晕,你说的ado都可以做到。这是巧合吗? 谁能给个完美的例子来看看,要求有数据感知,ado事件 如果有好的例子请发邮件给我e_mail:[email protected] 尽管VC对数据库得开发效率不是很高,但是由于VC很灵活,网上有很多封装得很好得源代码,比如楼主说得ADO,可能楼主是DEPHI转过来的,慢慢适应。 网上的确有很多ado封装类,但是也只是做了最基本的包装,象ado事件好像就包不进去 Delphi转过来的, 概念都不一样了, 肯定要适应一段时间了 慢慢适应,偶在学校的时候用VB挂ACCESS,后转VC做毕设,感觉相当不方便,一切习惯就好,VC挂ADO虽然繁琐一些,但可以让你较好的理解ADO http://dev.csdn.net/user/callzjyhttp://dev.csdn.net/user/zswzwy 谁能告诉我在vc下ADO事件怎么用啊,没有该机制的话,我要写很多变通代码,累死 在vc下使用智能指针操作ado我已经很熟了,可就是不知道如何实现智能感知控件和ADO事件 我在CSDN几乎所搜不到vc下使用智能感知控件和ADO事件的帖子,各位如果也搜一下的话,会发现我最近提了好几次类似的问题,但几乎得不到有效的回答,还有人当我初学发一些ADO使用基本操作给我呢,希望有识之士继续顶贴 VC开发是没有VB来得快,但是我觉得VC开发更稳定些,程序运行效率更高些。 用VC开发当然没有Delphi开发来得快,不过它很灵活.网上有很多例子,你适应了就好了 我看了很多例子就是没看见利用ado事件的 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(); ///////////////////////////////////////////////////////////}看看这个例子 这个例子没有ado事件呀,只是些最基本的ado应用,我说的ado事件是指触发记录移动前,记录移动后这样的事件. 以下是我找到的唯一关于在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;在连接关闭之后做这件事。 VC不是RAD当然很痛苦啦它没有那么多的组件啊我不是高手所以我早早就转向Delphi了你为什么又转回来呢是客户要求用VC么 vc做数据库也没什么呀,关键是为手熟尔,整天做程序现在CRecordset,CDaoRecordset,CAdoRecordset都用过了,感觉不到vc做数据库有多麻烦,楼主慢慢习惯就好了 资料是满大街都有,看你怎么找了。不太清楚“数据感知”是什么概念,帮不到你,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);}; (接上帖)//-----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;", "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;}别人写的代码至少有一点是可取的:它能用。你自己写的代码怎么都连不上数据库,别人的连上了,那么这个代码对你就有参考作用。至于它的代码漂亮不漂亮,那是另一回事;而其中怎么取舍靠的是你自己,别一句“不伦不类”就完全否定了别人的成果,谢谢。 对于要实现事件功能,那的写一个自己的函数了,你可以写一个CADoEvent类在你操作记录的 时候 ,和 数据库连接的时候你发送一个registered message,然后在message 处理函数作你想要做的事情,这样在你移动记录,代开recorder的时候就会触发这个message,你就可以在 message handle 函数中完成你自己的事件,当然你的可以把你的 message handle 函数做成一虚函数,这样你在子类中还可以完成子类的特定函数功能。 VC能很好的支持数据库哦!我只用ODBC 那么如果将ado绑定类绑定对话框界面呢 那么如何将ado绑定类绑定对话框界面呢 CFile如何格式化输出 带图钉按扭的Dockbar vc控制台程序能用ADO连接数据库么?或者有什么别的方法。 100分求解文件下载的问题! 关于触发自绘事件 在VC下没有问题而在VC.NET2003下出现这样的问题,望高手给予解释 异步串行通信中的WaitCommEvent()? 飞卡循迹智能车图像分析,求各路大侠指点 vc的有关运行exe文件问题 to: yes_start(Tonny2000) :麻烦你提供给我图象放大的代码,内有我的地址。 初次接触IE编程!如何操控网页中的控件和得到服务器给网页的返回值?????? 请问在ocx中使用ODBC可以吗?
http://dev.csdn.net/user/zswzwy
{
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();
///////////////////////////////////////////////////////////
}看看这个例子
响应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;
在连接关闭之后做这件事。
它没有那么多的组件啊
我不是高手
所以我早早就转向Delphi了
你为什么又转回来呢
是客户要求用VC么
(以下的例子由 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);
};
//-----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;", "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;
}别人写的代码至少有一点是可取的:它能用。你自己写的代码怎么都连不上数据库,别人的连上了,那么这个代码对你就有参考作用。至于它的代码漂亮不漂亮,那是另一回事;而其中怎么取舍靠的是你自己,别一句“不伦不类”就完全否定了别人的成果,谢谢。
我只用ODBC