文章来源:李世平的专栏 一、问题由来 vc6和vc71的工程向导中都包含非MFC的工程,诸如win32 console project, win32 static library。非MFC工程创建时是不支持MFC特性的,然后我们在处理实际问题时有时会用到MFC相关类,如Cstring, Cedit等等,这是很正常的。可能有人会说,为何不在一开始就创建MFC工程呢?问题在于MFC工程会产生很多向导生成代码,如基于单文档的工程会有View,Doc等类,很多时候我们只需要一个空工程就可以了。 二、常见问题 非MFC工程使用MFC库时最常见的问题就是windows.h重复包含错误,具体如下: fatal error C1189: #error : WINDOWS.H already included. MFC apps must not #include <windows.h> 三、解决办法 非MFC工程使用MFC库时,可参考以下步骤 1、工程设置中,将MFC的使用由原来的“使用标准windows库”改为“在共享DLL中使用MFC”(VC71) 如果是英文版,相关选项是: Microsoft Foundation Classes: Use MFC in a shared dll, no using MFC(VC6) NOTE:因为我用的是中文版的vc71,英文版的vc6. 2、头文件包含 不同的MFC类需包含的头文件是不一样的。 常用的类,如Cstring, Cedit 等,包含afxwin.h就可以了 如果不清楚包含什么头文件的话,可以同msdn进行查询,msdn中,对于MFC类的介绍中,都会给出相应的header file requirement. 3、#include 语句一定要写在首行 这一点很重要,通常出现前面讲到的windows.h重复包含错误,都是因为#include 语句没有写在首行。 另外还要注意的是,如果#include语句是在一个头文件里,那么对应头文件的包含也要写在首行。示例如下: ============= test.h文件的内容如下: #include <afxwin.h> //保证该语句在首行 test.cpp的文件内容如下: #include “test.h” //同样也要保证该语句在首行 ============= ps: 这么做的具体原因我也不知道,我是在实际调试中琢磨出这个道理的。我自己在这个问题上花了很多冤枉时间,写下该篇,就是希望大家不要在这个问题上绊脚。 (3)在进行连接之前要初始化OLE环境,初始化语句 ::CoInitialize(NULL); //初始化OLE/COM库环境 AfxOleInit();//初始化OLE/COM库环境(MFC自带的) 这两句话缺一不可,不然会有运行期错误 程序运行结束后记住::CoUninitialize(); //关闭OLE/COM库环境,释放资源 最后推荐一篇文章:http://farwen.com/ReadNews.asp?NewsID=3279 全文引用如下:
ADO数据库编程入门 |
| 2004-11-16 19:55:41 天宇网苑 Keaton 阅读301次 | 1、使用ADO编程的方法有三种: (1)使用预处理指令#import,例如: #import "c:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF", "adoEOF") rename("BOF", "adoBOF") 程序在编译时读取msado15.dll中的类型库信息,自动生成两个该类型库的头文件和实现文件msado15.tlh和msado15.tli(在Debug或Release目录下)。两个文件中定义了ADO的所有对象和方法,以及一些枚举类型的变量,程序只要直接调用这些方法即可。 (2)通过读取msado15.dll中的类型库信息,建立一个ColeDispatchDriver类的派生类,然后通过它调用ADO对象。 (3)直接使用COM提供的API,例如: CLSID clsid; HRESULT hr = ::CLSIDFromProgID(L"ADODB.Connection", &clsid); if (FAILED(hr)) { ... } ::CoCreateInstance(clsid, NULL, CLSCTX_SERVER, IID_IDispatch, (void **)&pDispatch); if (FAILED(hr)) { ... } 前两种方法类似,第3种方法编程可能最麻烦,但效率最高,程序尺寸最小,并且对ADO的控制能力也最强。 2、以下使用#import方法操作数据库 (1)可以在stdafx.h的所有include指令之后import (2)使用AfxOleInit()初始化COM库,通常在CwinApp::InitInstance的重载函数中添加。 (也可以使用::CoInitialize(NULL),之后在ExitInstance中调用::CoUninitialize) (3)定义_ConnectionPtr变量后调用Connection对象的Open方法建立与服务器的连接。 数据类型_ConnectionPtr实际上是由类模板_com_ptr_t得到的一个具体的实例类。_ConnectionPtr类封装了Connection对象的Idispatch接口指针及其一些必要的操作。可以通过这个指针操纵Connection对象。 例如连接SQLServer数据库,代码如下: // 连接到MS SQL Server _ConnectionPtr pMyConnect = NULL; HRESULT hr = pMyConnect.CreateInstance(__uuidof(Connection)); if (FAILED(hr)) return; _bstr_t strConnect = "Provider=SQLOLEDB; Server=hch; Database=mytest; uid=sa; pwd=sa;"; try { // Open方法连接字串必须四BSTR或者_bstr_t类型 pMyConnect->Open(strConnect, "", "", NULL); } catch(_com_error &e) { MessageBox(e.Description(), "警告", MB_OK|MB_ICONINFORMATION); } (4) //定义_RecordsetPtr变量,调用它Recordset对象的Open,即可打开一个数据集 _RecordsetPtr pRecordset; if (FAILED(pRecordset.CreateInstance(__uuidof(Recordset)))) { return; } try { pRecordset->Open(_variant_t("userinfo"), _variant_t((IDispatch*)pMyConnect), adOpenKeyset, adLockOptimistic, adCmdTable); } catch (_com_error &e) { MessageBox("无法打开userinfo表", "系统提示", MB_OK|MB_ICONINFORMATION); } (5) //定义_RecordsetPtr变量,调用它Recordset对象的Open,即可打开一个数据集 _RecordsetPtr pRecordset; if (FAILED(pRecordset.CreateInstance(__uuidof(Recordset)))) { return; } try { pRecordset->Open(_variant_t("userinfo"), _variant_t((IDispatch*)pMyConnect), adOpenKeyset, adLockOptimistic, adCmdTable); } catch (_com_error &e) { MessageBox("无法打开userinfo表", "系统提示", MB_OK|MB_ICONINFORMATION); } (6) // 读取当前记录集 try { pRecordset->MoveFirst(); while (pRecordset->adoEOF == VARIANT_FALSE) { // Fields是Recordset对象的容器,GetItem方法返回Field对象,Value是Field对象的属性,也可以用GetValue方法 CString sName = (char*)(_bstr_t)(pRecordset->Fields->GetItem(_variant_t("UserName"))->Value); // 或者使用GetValue() //CString sName = (char*)(_bstr_t)(pRecordset->Fields->GetItem(_variant_t("UserName"))->GetValue()); AfxMessageBox(sName); pRecordset->MoveNext(); } } catch (_com_error &e) { MessageBox(e.Description(), "系统提示", MB_OK|MB_ICONINFORMATION); } (7) // 修改记录 try { pRecordset->MoveFirst(); while(pRecordset->adoEOF == VARIANT_FALSE) { pRecordset->Fields->GetItem(_variant_t("Address"))->Value = _bstr_t("北京大学"); pRecordset->Update(); pRecordset->MoveNext(); } } catch (_com_error &e) { MessageBox(e.Description(), "系统提示", MB_OK|MB_ICONINFORMATION); } (8)添加,删除,使用带参数的命令,相应ADO的通知事件,绑定数据,设置过滤条件,索引和排序,事务处理。(略去,请参考其它资料) | |