com笔记总结.txt
上传用户:weisheen
上传日期:2022-07-09
资源大小:19390k
文件大小:82k
源码类别:

ActiveX/DCOM/ATL

开发平台:

Visual C++

  1. 1.  1.1 OOP:   类,   对象, 继承,重载,重写,引用;
  2.        OOC:组件,组件实例(设计状态/运用状态), 引用;
  3.      1.2       OOP{cpp/java/c#/vb.net/...}
  4.                OOC{COM/EJB/CORBA}(Component Object Model)   COM+(提供组件运行平台和企业级服务)
  5.                  /DCOM(分布式的COM)
  6.       1.3      组件的特征(OOC):   
  7.                         1. 二进制封装;
  8.                         2. BITS原则: (Bit Service)原则;
  9.                             2.1 软件实体通过接口对外提供服务;
  10.                             2.2 软件接口通过接口依赖其它的软件实体;
  11.                         3. 组件需要部署和安装;独立编译/安装/部署,独立的软件实体;
  12.       1.4      组件接口定义:
  13.                         1.4.1 刻画组件的功能;完整刻画;
  14.                         1.4.2 接口的定义语言:c/cpp;java/c#/vb.net;不满足通用性
  15.                         1.4.3 如果采用 MIDL, 只能定义接口;
  16.       1.5      IDL语言基础:
  17.                         import,    调用其它接口定义文件;
  18.                         interface, 定义接口;
  19.                         coclass,   定义接口实现者,COM类,或COM构件;
  20.                         library,     组件库;对应一个具体组件;
  21.                    MFC: CObject;
  22.                    COM:   IUnknown;//提供组件功能查询;查的是接口;和 new ====>基类级别
  23.                    组件(library)/构件(coclass)/接口(interface);组件实体;
  24.       1.6     COM组件实体的定义方法;
  25.                   1.1 GUID, 512位随机数据;GUIDGen.exe;
  26.                    [头:uuid,指定名字;
  27.                    helpstring,说明性信息;pointer_default定义借口指针的一种模式;
  28.                    version,版本;
  29.                    default, ]
  30.                    名字
  31.                    {
  32.                    }
  33.        1.7    通过IDL,编写add, sub;使用midl.exe编译成C;           
  34.        1.8    COM数据类型列表;
  35.                 HRESULT,32整数;代表执行的结果;0表示正确,非零表示错误;
  36.                 BSTR,       宽字符串;使用Unicode码;(一个字符,两个字节)
  37.                                     前两个字节,对应字符串中字符个数,后面依次为UNICDODE码;
  38.                                    "hello",    [h][e][l][l][o][]
  39.                                                     [0][5][0][h][0][e][0][l][0][l][0][o]
  40.                 VARIANT    智能型数据类型;(万能型)
  41.                     vt属性,表示当前变量所用作的类型;
  42.                     值,根据类型不同在不同属性中;
  43.        1.9 ATL库中的方法宏:
  44.                    1.9.1 方法声明宏:STDMETHOD;
  45.                    1.9.2 方法实现宏:STDMETHODIMP;
  46.        1.10 com 安装和卸载  regsvr32.exe *.dll; regsvr32.exe -u *.dll
  47. 2. COM接口定义技术;
  48.        2.1  Custom,自定义接口; 必须使用.idl文件;
  49.            2.1.1 IUnknown接口;
  50.               2.1.1.1 管理组件的生命周期;
  51.               2.1.1.2 管理组件的功能列表;
  52.            2.1.2 IUnknonw的实现(CComObjectRootEx);
  53.               2.1.2.1 和生命周期相关(add/release) 
  54.                       DECLARE_PROTECT_FINAL_CONSTRUCT;
  55.                       CComObjectRootEx<线程类型>
  56.               2.1.2.2 接口映射表;
  57.      将接口类型添加到接口映射表中,否则QueryInterface找不到;
  58.               2.1.2.3 COM资源使用原则“谁使用谁释放”;
  59. 3. 练习,使用WebBrowser组件熟悉COM的基本概念和特征。
  60.             3.1 IHTML****;
  61.             3.2 IWebBrowser;
  62.             3.3 IHTMLDocument; IHTMLDocument2,IHTMLDocument3,IHTMLDocument4
  63.             3.4 IHTMLElement;
  64.             3.5 IHTMLImgElement
  65. 4. COM结构;
  66.             4.1 COM层次结构: 组件中包含多个构件,构件实现多个接口;
  67.             4.2 接口映射表(同一个构件上的接口进行映射);
  68.             4.3 构件映射表(同一个组件上构件的映射);
  69.             4.4 ATL应用程序实体; CComModule _Module;
  70.             4.3 ATL在DllMain方法中,组装COM组件;
  71.           MFC WinMain    CWinApp theApp  多个窗口 消息映射   
  72.           ATL        DllMain    CComModule _Module 多个构件 接口映射   构件映射
  73.           MFC initialInstance
  74.           ATL           _Module.init;
  75.   DllCanUnloadNow,判断组件是否能够卸载;
  76.      DllGetClassObject,被CoCreateInstance方法调用,生成构件;_Module.GetClassObject
  77.      DllRegisterServer,将组件的ID和名称的关联信息写入注册表;
  78.      DllUnregisterServer,将组件的ID和名称关联信息删除;
  79. 5.   COM数据类型列表;
  80.                 HRESULT,32整数;代表执行的结果;0表示正确,非零表示错误;
  81.                 BSTR,       宽字符串;使用Unicode码;(一个字符,两个字节)
  82.                                     前两个字节,对应字符串中字符个数,后面依次为UNICDODE码;
  83.                                    "hello",    [h][e][l][l][o][]
  84.                                                     [0][5][0][h][0][e][0][l][0][l][0][o]
  85.                 VARIANT    智能型数据类型;(万能型)
  86.                     vt属性,表示当前变量所用作的类型;
  87.                     值,根据类型不同在不同属性中;
  88.  
  89. 6.  自动化接口;  不需要IDL文件;//有些麻烦
  90.               1. 自动化接口,主要支持vb,javascript, vbscript, actionscript;调用时不需要头文件;
  91.               2. 自动化接口是对自定义接口的扩展, 自动化接口也从IUnknown继承;
  92.               3. 自动化接口从IDispatch继承;
  93.               4.   不使用头文件调用IDispatch接口;
  94.                     HRESULT Invoke( 
  95. DISPID dispIdMember,   //调用方法的id;
  96. REFIID riid, LCID lcid,    //保留字,IID_NULL;
  97. WORD wFlags,               //Local_system_default;
  98. DISPPARAMS FAR *pDispParams,  //
  99. VARIANT FAR *pVarResult,             //
  100. EXCEPINFO FAR *pExcepInfo, 
  101. unsigned int FAR *puArgErr);
  102.               5. CLSIDFromProgID,根据组建名字查找组建CLSID;
  103.               6. GetIDsOfNames;
  104.               7. DISPPARAMS; 
  105. 7.  COM中的结构,数组,智能指针
  106.               7.1 BSTR int  VARIANT,基本数据类型
  107.               7.2 自定义接口/结构;
  108.               7.3 DTO(只有成员变量,没有方法)
  109.               7.4 CoTaskMemAlloc/CoTaskMemFree;  SysAlloString/SysFreeString;
  110.               7.5 从COM中获取结构或结构数组;
  111.               7.6 向COM中传递结构或结构数组;
  112.               7.7 COM中的属性;
  113.               7.8 接口智能指针;CComPtr/CComQIPtr;
  114.               7.9   BSTR智能指针;_bstr_t(<comdef.h>)/CComBSTR(<atlbase.h>);
  115.               7.10 VARIATN智能指针;_variant_t   /CComVariant  ;
  116.               7.11 智能指针:1)是个类;2)管理一个指针;3)自动释放(析构)方法中释放;
  117.               7.12  智能指针分类(工具类Utility Class)
  118.                     7.12.1 COM接口类 CComPtr/CComQIPtr;
  119.                     7.12.2 字符串指针  CComBSTR/_bstr_t;
  120.                     7.12.2 万能型变量  CComVariant/_variant_t;
  121. 8.  COM回调接口( COM组件的回调和事件);
  122.        8.1 自定义回调接口;
  123.             8.1.1 回调的概念;
  124.             8.1.2 回调三要素:1,回调接口定义;2,私有成员变量;3,公共的设置方法;       
  125.        8.2 自定义COM回调接口(IUnknown)
  126.             8.2.1 IUnknonw类型的回调接口;
  127.             8.2.2 实现IUnknown接口;
  128.        8.3 自定义COM回调接口(IDispatch)
  129.             8.3.1 IDispatch类型的回调接口;
  130.             8.3.2 实现IDispatch接口;         
  131.        8.4 COM事件的定义和处理
  132.             8.4.1 事件(类型,声明,触发,处理)
  133.             8.4.2 事件类型:事件接口(一种特殊的回调接口),ATL框架提供支持
  134.             8.4.2.1 dispinterface/attribute/method;            
  135.             8.4.3 事件可以具备多个事件处理代码;
  136. 3.  COM组件的实现技术;
  137.        3.1 接口映射;
  138.        3.2 多接口实现;
  139. 4.  COM组件的回调和事件;//COM的主题
  140. 5.  COM组件的合成与集合;
  141. 6.  COM组件的客户端调用技术;
  142. ---02.22----------------------day09---------------------------------
  143. COM组件:
  144. 1.项目FirstDemo(组件类),创建组件:
  145. 右键-->New ATL Object-->Simple Object-->(Interface)Custom-->右键-->add method------>
  146. ---hello
  147. ---([in] BSTR name,[out] BSTR* result); //in表输入,out表输出 
  148. //import:调用其他接口的文件
  149. //library:组件库
  150. //coclass:定义接口实现者
  151. //interface:定义接口
  152. //uuid:指定名字(微软为了防止名字重复,设定为512位的随机数)
  153. //helpstring说明性信息
  154. //pointer_default定义接口指针的模式
  155. //version版本
  156. -->再创建一个接口时要手工加入(如上操作的话,都会设定当前接口为默认接口,有些麻烦)
  157. -->新的接口的uuid可在目录VSCommonTools中的GUIDGEN.EXE中复制一个过来
  158. -->在实现文件的头文件中的类要继承该接口,在BEGIN_COM_MAP(CMyAbc)中添加接口映射,声明接口类函数(在函数前要加上STDMETHOD),然后在实现文件中重写继承自接口类的函数(在函数前要加上STDMETHODIMP)
  159. -----------------其中FirstDemo.idl及Debug中的FirstDemo.dll==>COM的安装:regsvr32.exe *.dll(写入注册表)-->卸载:regsvr32.exe -u *.dll(删除注册表信息)
  160. 2.项目intertest01(组件类)中的myaddinter.idl-->
  161. (在命令提示窗口中)在文件目录下输入-- cl.exe -->midl.exe myaddinter.idl
  162. 生成5个文件:myaddinter.h、myaddinter_i.c有用,是必须的
  163. 3.项目clientDemo(窗体类),导入两个由FirstDemo.idl编译后生成的文件:FirstDemo.h、FirstDemo_i.c--->在clientDemo中必须引入以上两个文件做头文件,即可直接使用(不用重写,直接引用组件提供的功能,但是要声明引用)
  164. clientDemo03用IUnknonw的QueryInterface来定位要找的接口实现的入口名字。
  165. ::CoInitialize(NULL);//COM的初始化函数
  166. ::CoUninitialize();//释放内存
  167. 4.项目IUnknownDemo包含组件和测试类,组件编译后,测试类通过头文件引用IUnknownDemo.h和IUnknownDemo_i.c;
  168. ::SysAllocString
  169. str.AllocSysString()
  170. ---02.23----------------------day10---------------------------------
  171. 1.项目demoIe使用WebBrowser组件熟悉COM的基本概念和特征:
  172. 先建一个MFC项目,然后在窗体中添加WEB控件-->右键->向导->Member Variables中绑定IDC_EXPLORER1为CWebBrowser2(有提示的),然后项目中自动生成 CWebBrowser2类;
  173. 在Button1中this->m_mybrowser.Navigate("C:\danei.htm",NULL,NULL,NULL,NULL);表按照指定路径打开网页
  174. 在Button2中,定义IHTMLDocument2(要加头文件mshtml.h)-->表与文本相关,
  175. --pDisp=this->m_mybrowser.GetDocument();//获取文本信息
  176. --pDisp->QueryInterface(IID_IHTMLDocument2,(void **)&pDoc);//查询匹配接口
  177. --IHTMLElementCollection* allImage=NULL;//采集信息放置的地方
  178. --pDoc->get_images(&allImage);//获取图片
  179. --allImage->get_length(&iCount);//获取图片数量
  180. 之后的循环用于循环输出图片路径
  181. 2.项目demoiechangeimage与项目demoIe相比,只修改循环为改变所有图片
  182. 其中用到CString strhtml="c:\source.bmp"、strhtml.AllocSysString();
  183. --AllocSysString()的作用是把CString型转化成BSTR型
  184. 3.项目demoiechangeLink与项目demoIe相比,添加了一个test.html超链接,且只修改循环为禁用所有超链接:
  185. --CString strhtml="#";//这个属性的链接是被封掉的即无法打开
  186. --CString attName="href";
  187. --VARIANT var;
  188. --var.vt=VT_BSTR;
  189. --var.bstrVal=strhtml.AllocSysString();//字符串转BSTR类型,组件类的有些函数参数是BSTR类型
  190. --mylink->setAttribute(attName.AllocSysString(),var,0);
  191. setAttribute为设置属性
  192. 4.项目TestCom1通过手工添加代码来熟悉COM的过程:
  193.   4.1 TestCom1_01:右键-->new class-->Generic Class(一般类)-->在.idl文件中添加相应接口
  194.   4.2 TestCom1_02:给接口添加函数;
  195.   4.3 TestCom1_03:在类头文件中构造组件接口映射表且要组件继承:
  196. DECLARE_PROTECT_FINAL_CONSTRUCT();
  197. BEGIN_COM_MAP(CMyTools)
  198. COM_INTERFACE_ENTRY(IMyAdd)
  199. END_COM_MAP()
  200.     STDMETHOD(add)(int a, int b, int* c);
  201. class ATL_NO_VTABLE CMyTools  : 
  202.       public CComObjectRootEx<CComSingleThreadModel>,
  203.       public CComCoClass<CMyTools,&CLSID_MyTools>,
  204.       public IMyAdd
  205. 在类的实现文件中导入组件接口实现函数:
  206. STDMETHODIMP CMyTools::add(int a, int b, int* c)
  207. {
  208. *c=a+b;
  209. return S_OK;
  210. }
  211.   4.4 TestCom1_04:在文件夹中添加registry.bin文件,并在资源文件resource.h中加入
  212. #define IDR_REGISTRY1   205(随意与其他宏不冲突的数字)-->
  213. 在MyToohs.h中添加#include "resource.h"-->编译后在resources项目分类组中有REGISTRY文件夹自动生成
  214. -->如果宏不出问题的话在Resource files中可看到registry.bin自动导入
  215. -->然后在registry.bin中输入文本:
  216. HKCR
  217. {
  218. FirstDemo.MyAbc.1 = s 'MyAbc Class'
  219. {
  220. CLSID = s '{AAC11C54-F25F-40fe-A4AC-F2829CE37FD7}'//接口ID
  221. }
  222. FirstDemo.MyAbc = s 'MyAbc Class'
  223. {
  224. CLSID = s '{AAC11C54-F25F-40fe-A4AC-F2829CE37FD7}'//接口ID
  225. CurVer = s 'FirstDemo.MyAbc.1'
  226. }
  227. NoRemove CLSID
  228. {
  229. ForceRemove {AAC11C54-F25F-40fe-A4AC-F2829CE37FD7} = s 'MyAbc Class'
  230. {
  231. ProgID = s 'FirstDemo.MyAbc.1'
  232. VersionIndependentProgID = s 'FirstDemo.MyAbc'
  233. InprocServer32 = s '%MODULE%'
  234. {
  235. val ThreadingModel = s 'Apartment'
  236. }
  237. 'TypeLib' = s '{E565170F-79D7-4EFB-9402-4D877139D459}'//组件ID
  238. }
  239. }
  240. }
  241. 这些内容将完全导入registry.rgs中(自动生成的组件接口文件都有.rgs文件,但是看不到.bin文件.....)
  242. ---02.26----------------------day11---------------------------------
  243. 1.项目autoDemo实现自动化接口(与):
  244.   1.1项目autoDemo01:右键-->New ATL Object-->Simple Object-->(Interface)Dual-->(name:)MyAbc
  245. //(Interface)Dual为自动化接口实现的关键
  246. 然后新建一个test项目添加一个按钮用于测试:
  247. //添加相关头文件
  248. #include "../autoDemo.h"
  249. #include "../autoDemo_i.c"
  250. void CTestDlg::OnButton1() 
  251. {
  252. // TODO: Add your control notification handler code here
  253. ::CoInitialize(NULL);
  254.    IDispatch* pDisp=NULL;
  255.    IMyAbc* pTools=NULL;
  256.    ::CoCreateInstance(CLSID_MyAbc,NULL,CLSCTX_INPROC_SERVER,IID_IDispatch,(void **)&pDisp);
  257.    pDisp->QueryInterface(IID_IMyAbc,(void **)&pTools);
  258.    int iResult=0;
  259.    pDisp->Release();
  260.    pTools->add(12,13,&iResult);
  261.     CString str1;
  262. str1.Format("%d",iResult);
  263. MessageBox(str1);
  264.    pTools->Release();
  265. ::CoUninitialize();
  266. }
  267.   1.2项目autoDemo02:再新建一个AutoTest项目添加一个按钮用于测试:
  268. //不需要引入头文件(与上面按钮代码不在同一个文件内)
  269. void CAutoTestDlg::OnButton1() 
  270. {
  271. // TODO: Add your control notification handler code here
  272. ::CoInitialize(NULL);
  273. CString str="AutoDemo.MyAbc";
  274. CLSID mycomid;//CLSID为_i.c文件中的实现宏
  275. ::CLSIDFromProgID(L"AutoDemo.MyAbc",&mycomid);//名字匹配,到注册表去找
  276. IDispatch* pDisp=NULL;
  277. ::CoCreateInstance(mycomid,NULL,CLSCTX_INPROC_SERVER,IID_IDispatch,(void **)&pDisp);
  278. DISPID addid;
  279. BSTR   funnames[1];
  280. funnames[0]=::SysAllocString(L"add");//函数的名字
  281. pDisp->GetIDsOfNames(IID_NULL,funnames,1,LOCALE_SYSTEM_DEFAULT,&addid);
  282. ::CoUninitialize();
  283. }
  284.   1.3项目autoDemo03为项目autoDemo02的完善,--->比引入头文件麻烦
  285. 2.项目StructDemo是对一个结构体操作(之前的都是对单独的数据,意义不大):
  286.   2.1项目StructDemo01先建一个自动接口类(老师在建是选了support MFC):MyStruct,在该.idl文件中添加一个结构体---//因为接口的函数想参数需要
  287. typedef struct StPerson
  288. {
  289.      BSTR name;
  290.  UINT age;
  291.  BSTR sex;
  292. }StPerson;
  293. --然后右键-->add method-->GetPersonById--([in] UINT id,[out] StPerson** Result)--
  294. -->并在接口实现文件中添加一个函数------
  295. //这样赋值- -!
  296. STDMETHODIMP CMyStruct::GetPersonById(UINT id,StPerson** Result)
  297. {
  298. StPerson* p=(StPerson*)::CoTaskMemAlloc(sizeof(StPerson));//申请空间
  299. p->age=23;
  300. p->name=::SysAllocString(L"zhangsan");//name为BSTR类型
  301. p->sex=::SysAllocString(L"male");
  302. *Result=p;
  303. return S_OK;
  304. }
  305. --->然后新建一个MFC项目test用于读取数据:
  306. #include "../StructDemo.h"
  307. #include "../StructDemo_i.c"
  308. void CTestDlg::OnButton1() 
  309. {
  310. // TODO: Add your control notification handler code here
  311. ::CoInitialize(NULL);
  312. IMyStruct* pTools=NULL;//接口指针
  313. ::CoCreateInstance(CLSID_MyStruct,NULL,CLSCTX_INPROC_SERVER,IID_IMyStruct,(void **)&pTools);
  314. StPerson* pPer=NULL;//结构体指针
  315. pTools->GetPersonById(1,&pPer);
  316. CString strName(pPer->name);
  317. ::SysFreeString(pPer->name);
  318. UINT uage(pPer->age);
  319. CString strSex(pPer->sex);
  320. ::SysFreeString(pPer->sex);
  321. ::CoTaskMemFree(pPer);//释放结构体指针
  322. CString str1;
  323. str1.Format("%s: %d %s",strName,uage,strSex);
  324. MessageBox(str1);
  325. ::CoUninitialize();
  326. }
  327.   
  328.   2.2项目StructDemo02再在接口文件中添加一个功能函数:
  329. STDMETHODIMP CMyStruct::GetAllPerson(UINT* number,StPerson** Result)
  330. {
  331. StPerson* p=(StPerson*)::CoTaskMemAlloc(2*sizeof(StPerson));//申请2个空间
  332. ZeroMemory(p,2*sizeof(StPerson));//初始化数组(连续的)空间
  333. p->age=23;
  334. p->name=::SysAllocString(L"芙蓉");
  335. p->sex=::SysAllocString(L"女");
  336. (p+1)->age=23;
  337. (p+1)->name=::SysAllocString(L"李松涛");
  338. (p+1)->sex=::SysAllocString(L"男");
  339.     *Result=p;
  340. *number=2;
  341. return S_OK;
  342. }
  343. --->在项目test中添加一个按钮实现输出功能:
  344. //输出多个结构体数据
  345. void CTestDlg::OnButton2() 
  346. {
  347. // TODO: Add your control notification handler code here
  348. ::CoInitialize(NULL);
  349. IMyStruct* pTools=NULL;
  350. ::CoCreateInstance(CLSID_MyStruct,NULL,CLSCTX_INPROC_SERVER,IID_IMyStruct,(void **)&pTools);
  351. StPerson* pPer=NULL;
  352. UINT iSize=0;
  353. pTools->GetAllPerson(&iSize,&pPer);
  354. for(int i=0;i<iSize;i++)
  355. {
  356. CString strName((pPer+i)->name);
  357. ::SysFreeString((pPer+i)->name);
  358. UINT uage((pPer+i)->age);
  359. CString strSex((pPer+i)->sex);
  360. ::SysFreeString((pPer+i)->sex);
  361. CString str1;
  362. str1.Format("%s: %d %s",strName,uage,strSex);
  363. MessageBox(str1);
  364. }
  365. ::CoTaskMemFree(pPer);
  366. ::CoUninitialize();
  367. }
  368.   2.3项目StructDemo03再在接口文件中添加一个功能函数:
  369. STDMETHODIMP CMyStruct::SavePerson(UINT number,StPerson* Result, UINT* pResult)
  370. {
  371. int iResult=0;
  372. for(int i=0;i<number;i++)
  373. {
  374. iResult+=(Result+i)->age;
  375. }
  376. *pResult=iResult;
  377. return S_OK;
  378. }
  379. --->在项目test中添加一个按钮实现输出功能:(用处不大)
  380. void CTestDlg::OnButton3() 
  381. {
  382. // TODO: Add your control notification handler code here
  383. ::CoInitialize(NULL);
  384. IMyStruct* pTools=NULL;//用来引入接口的函数
  385. ::CoCreateInstance(CLSID_MyStruct,NULL,CLSCTX_INPROC_SERVER,IID_IMyStruct,(void **)&pTools);
  386.     StPerson* Ref=new StPerson[2];
  387. Ref[0].age=12;
  388. Ref[1].age=13;
  389. UINT iResult=0;
  390. pTools->SavePerson(2,Ref,&iResult);
  391. CString str1;
  392. str1.Format("%d",iResult);
  393. MessageBox(str1);
  394.   2.4项目StructDemo04给接口文件添加属性(函数):右键(接口)-->Add property
  395. -->属性类型:BSTR ---属性名:UID ---参数:(留空)-->先声明个私有成员BSTR m_uid;-->然后在实现文件中添加:
  396. TDMETHODIMP CMyStruct::get_UID(BSTR *pVal)
  397. {
  398. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  399. *pVal=::SysAllocString(this->m_uid);
  400. return S_OK;
  401. }
  402. STDMETHODIMP CMyStruct::put_UID(BSTR newVal)
  403. {
  404. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  405. this->m_uid=::SysAllocString(newVal);
  406. ::SysFreeString(newVal);
  407. return S_OK;
  408. }
  409. --->在项目test中添加一个按钮实现输出功能:
  410. void CTestDlg::OnButton5() 
  411. {
  412. // TODO: Add your control notification handler code here
  413. ::CoInitialize(NULL);
  414. IMyStruct* pTools=NULL;
  415. ::CoCreateInstance(CLSID_MyStruct,NULL,CLSCTX_INPROC_SERVER,IID_IMyStruct,(void **)&pTools);
  416. CString str("zhangsan");
  417. pTools->put_UID(str.AllocSysString());
  418. BSTR bt;
  419. pTools->get_UID(&bt);
  420. CString strName(bt);//__
  421. ::SysFreeString(bt);
  422. MessageBox(strName);//__
  423. }
  424. 3.项目SmartPtrDemo01为智能指针的用法:
  425. 先建一个自动接口类(老师在建是选了support MFC):MyAbc;再在接口文件中添加一个功能函数:
  426. STDMETHODIMP CMyAbc::Hello(BSTR name, BSTR *bstrResult)
  427. {
  428. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  429. // TODO: Add your implementation code here
  430. CString strTemp(name);
  431. ::SysFreeString(name);
  432. strTemp="Hello: "+strTemp;
  433. *bstrResult=strTemp.AllocSysString();
  434. return S_OK;
  435. }
  436. --->在项目test中添加两个按钮实现输出功能:
  437. --按钮一为一般做法:
  438. #include "../SmartPtrDemo.h"
  439. #include "../SmartPtrDemo_i.c"
  440. void CTestDlg::OnButton1() 
  441. {
  442. // TODO: Add your control notification handler code here
  443. ::CoInitialize(NULL);
  444. IMyAbc* pTools=NULL;
  445. ::CoCreateInstance(CLSID_MyAbc,NULL,CLSCTX_INPROC_SERVER,IID_IMyAbc,(void **)&pTools);
  446. BSTR bResult;
  447. CString str("zhangsan");
  448. pTools->Hello(str.AllocSysString(),&bResult);
  449. CString strTemp(bResult);
  450. MessageBox(strTemp);
  451.     pTools->Release();
  452. ::CoUninitialize();
  453. }
  454. --按钮二为引入智能指针做法:
  455. #include <atlbase.h>//智能指针类的头文件
  456. void CTestDlg::OnButton2() 
  457. {
  458. // TODO: Add your control notification handler code here
  459. ::CoInitialize(NULL);
  460. CComPtr<IMyAbc> mytools;//智能指针
  461. mytools.CoCreateInstance(CLSID_MyAbc);//. 表示用父类的函数
  462. BSTR bResult;
  463. CString str("zhangsan");
  464. mytools->Hello(str.AllocSysString(),&bResult);
  465. CString strTemp(bResult);
  466. MessageBox(strTemp);
  467. // ::CoUninitialize(); //与智能指针的析构函数冲突,即智能指针已经调用析构函数释放了指针,再释放就出问题了
  468. }
  469. ---02.27----------------------day12---------------------------------
  470. 1.项目 DemoBstr为熟悉智能指针:(项目本身的意义不大)
  471.   1.1项目DemoBstr01 右键-->New ATL Object-->Simple Object-->(Interface)Dual-->(name:)MyBstr-->
  472. 添加两个私有成员变量BSTR m_uid;BSTR m_pwd;并初始化-->然后右键-->add method-->Authen--[in] BSTR name, [in] BSTR pwd, [out] BSTR* Result)---->并在接口实现文件中添加一个函数------
  473. STDMETHODIMP CMyBstr::Authen(BSTR name, BSTR pwd, BSTR *Result)
  474. {
  475. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  476. // TODO: Add your implementation code here
  477. if(this->m_pwd!=NULL)
  478. {
  479. ::SysFreeString(this->m_pwd);
  480. this->m_pwd=NULL;
  481. }
  482. this->m_pwd=::SysAllocString(pwd);
  483. ::SysFreeString(pwd);
  484. if(this->m_uid!=NULL)
  485. {
  486. ::SysFreeString(this->m_uid);
  487. this->m_uid=NULL;
  488. }
  489. this->m_uid=::SysAllocString(name);
  490. ::SysFreeString(name);
  491. *Result=::SysAllocString(L"OK");
  492. return S_OK;
  493. }
  494. --->然后新建一个MFC项目test并添加一个按钮功能用于读取数据:
  495. //引入头文件
  496. #include "../DemoBstr.h"
  497. #include "../DemoBstr_i.c"
  498. #include <comdef.h>//_bstr_t类型智能指针相关
  499. #include <atlbase.h>//智能指针相关
  500. void CTestDlg::OnButton1() 
  501. {
  502. // TODO: Add your control notification handler code here
  503. ::CoInitialize(NULL);
  504. _bstr_t name("zhangsan");
  505. _bstr_t pwd("abc");
  506. BSTR result;
  507. CComPtr<IMyBstr> mytools;
  508. mytools.CoCreateInstance(CLSID_MyBstr);
  509. mytools->Authen(name,pwd,&result);//自定义接口实现函数
  510. ::SysFreeString(result);
  511. }
  512.   
  513.   1.2项目DemoBstr02:在项目test上添加第二个按钮功能用于读取数据:
  514. (只比DemoBstr01多了两句:CString strTemp=(CString)result;MessageBox(strTemp);)
  515. void CTestDlg::OnButton2() 
  516. {
  517. // TODO: Add your control notification handler code here
  518. ::CoInitialize(NULL);
  519. CComBSTR name("zhangsan");
  520. CComBSTR pwd("list");
  521. CComBSTR result;
  522. CComPtr<IMyBstr> mytools;//智能指针
  523. mytools.CoCreateInstance(CLSID_MyBstr);
  524. mytools->Authen(name,pwd,&result);//自定义接口实现函数
  525. //result为从接口实现函数Authen()返回的结果
  526. CString strTemp=(CString)result;//CString strTemp(bResult);
  527. MessageBox(strTemp);
  528. }
  529. 2.项目DemoVariant为熟悉Variant智能指针(CComVariant)(Button3)功能:
  530.   2.1项目DemoVariant01在接口实现文件中添加一个函数------
  531. STDMETHODIMP CMyVariant::add(VARIANT a, VARIANT b, VARIANT *c)
  532. {
  533. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  534. // TODO: Add your implementation code here
  535. c->vt=VT_I4;
  536. c->lVal=a.lVal+b.lVal;
  537. return S_OK;
  538. }
  539. 在项目test上添加三个按钮功能:
  540. #include "../DemoVariant.h"
  541. #include "../DemoVariant_i.c"
  542. #include <atlbase.h>
  543. #include <comdef.h>
  544. void CTestDlg::OnButton1() 
  545. {
  546. // TODO: Add your control notification handler code here
  547. CoInitialize(NULL);
  548. CComPtr<IMyVariant> mytools;
  549. mytools.CoCreateInstance(CLSID_MyVariant);//生成构件
  550. VARIANT A,B;
  551. A.vt=VT_I4;
  552. A.lVal=12;
  553. B.vt=VT_I4;
  554. B.lVal=13;
  555. VARIANT c;
  556. mytools->add(A,B,&c);
  557. CString str;
  558. str.Format("没有强制类型转换:%d",c.lVal);
  559. MessageBox(str);
  560. }
  561. void CTestDlg::OnButton2() 
  562. {
  563. // TODO: Add your control notification handler code here
  564. CoInitialize(NULL);
  565. CComPtr<IMyVariant> mytools;
  566. mytools.CoCreateInstance(CLSID_MyVariant);
  567. long a=12;
  568. long b=13;
  569. _variant_t vt(a);
  570. _variant_t vt1(b);
  571. _variant_t result;
  572. mytools->add(vt,vt1,&result);
  573. long c1=(long)result;//强制类型转换使智能指针具体化
  574. CString str;
  575. str.Format("强制类型转换后:%d",c1);
  576. MessageBox(str);
  577. }
  578. void CTestDlg::OnButton3() 
  579. {
  580. // TODO: Add your control notification handler code here
  581. CoInitialize(NULL);
  582. CComPtr<IMyVariant> mytools;
  583. mytools.CoCreateInstance(CLSID_MyVariant);
  584. long a=12;
  585. long b=13;
  586. CComVariant vt(a);//CComVariant的方法比_variant_t的多
  587. CComVariant vt1(b);
  588. CComVariant result;
  589. mytools->add(vt,vt1,&result);
  590. CString str; 
  591. str.Format("用CComVariant来定义后:%d",result.lVal);
  592. MessageBox(str);
  593. }
  594. 3.项目ComCallBack回调接口的实现:
  595.   3.1项目ComCallBack01:右键-->New ATL Object-->Simple Object-->(Interface)Dual-->(name:)MyAbc
  596. -->然后再添加一个新的接口ILogs,并在ILogs中添加接口方法[helpstring("string")] HRESULT WriteLog([in] BSTR message);-->(老师手工)在MyAbc类中添加一个ILogs* pTools;并初始化//声明回调接口变量;
  597. 及两个接口函数:------
  598. //设置属性
  599. STDMETHODIMP CMyAbc::SetLog(ILogs* ptools)
  600. {
  601. this->pTools=ptools;
  602. return S_OK;
  603. }
  604. STDMETHODIMP CMyAbc::add(int a, int b,int* c)
  605. {
  606. *c=a+b;
  607. CComBSTR bstr("this result is:");
  608. char strTemp[500];
  609. sprintf(strTemp,"%d",c);
  610. bstr.Append(strTemp);
  611. if(this->pTools!=NULL)//回调要点,条件返回
  612. {
  613. this->pTools->WriteLog(bstr);//另一个接口的实现函数
  614. }
  615. else
  616. *c=0;
  617. return S_OK;
  618. }
  619.   3.2项目ComCallBack02在项目1的基础上添加项目test,并在test 中添加一个继承接口ILogs的普通类MyLog(与接口ILogs关联),在其头文件中声明STDMETHOD(WriteLog)(BSTR message);//STDMETHOD是虚函数的宏
  620. ------(#define STDMETHOD(method)       virtual HRESULT STDMETHODCALLTYPE method)-------
  621. 然后在实现文件中重载该虚函数:(其功能为把信息保存到指定(日志)文件中)
  622. STDMETHODIMP MyLog::WriteLog(BSTR message)
  623. {
  624. CFile f;
  625. CFileException ex;
  626. f.Open("./log.txt",CFile::modeCreate| CFile::modeReadWrite,&ex);
  627. CString str(message);
  628. f.Write(str.GetBuffer(100),str.GetLength());
  629. ::SysFreeString(message);
  630. f.Close();
  631.     return S_OK;
  632. }
  633. -->然后添加一个按钮调用接口:
  634. #include "../ComCallBack.h"
  635. #include "../ComCallBack_i.c"
  636. #include <atlbase.h>
  637. #include "MyLog.h"
  638. void CTestDlg::OnButton1() 
  639. {
  640. // TODO: Add your control notification handler code here
  641. //装配调用代码;
  642. ::CoInitialize(NULL);
  643. CComPtr<IMyAbc> mytools;
  644. mytools.CoCreateInstance(CLSID_MyAbc);
  645. ILogs* pLog=new MyLog();
  646. mytools->SetLog(pLog);//接口注入语句;没有这个句子就无法满足回调的条件
  647. int iResult=0;        //IoC 
  648. mytools->add(12,13,&iResult);
  649. if(iResult)
  650.   MessageBox("信息保存成功!");
  651. else
  652.   MessageBox("没有信息要保存!");
  653. }
  654. 4.项目DemoIUnknown接口改为继承IUnknown(继承IUnknown更符合COM规范):
  655.   4.1项目DemoIUnknown01:右键-->New ATL Object-->Simple Object-->(Interface)Dual-->(name:)MyAbc
  656. -->然后再添加一个新的继承自IUnknown的接口ILog,然后分别添加函数writeLog()、SetLog()、add()---
  657. [
  658. object,
  659. uuid(BA4816E3-7295-4189-B7B5-274676745821),
  660. helpstring("IMyAbc Interface"),
  661. pointer_default(unique)
  662. ]
  663. interface ILog : IUnknown//继承IUnknown更符合COM规范
  664. {
  665. [helpstring("asdfdasf")] HRESULT writeLog([in] BSTR message);//////////
  666. };
  667. [
  668. object,
  669. uuid(BA4816E3-7295-4189-B7B5-274676745820),
  670. dual,
  671. helpstring("IMyAbc Interface"),
  672. pointer_default(unique)
  673. ]
  674. interface IMyAbc : IDispatch
  675. {     
  676. [id(1), helpstring("method SetLog")] HRESULT SetLog([in] IUnknown* pTools);////
  677. [id(2), helpstring("method add")] HRESULT add([in] int a, [in] int b, [out] int* c);////
  678. };
  679.   4.2项目DemoIUnknown02再新建一个test类并新建一个继承ILog的普通类MyLog,并在其头文件中
  680. STDMETHOD(writeLog)( BSTR message);//接口自定义的虚函数
  681. //重载3个IUnknown的虚函数,原型为
  682. //        virtual HRESULT STDMETHODCALLTYPE QueryInterface( 
  683.         //       /* [in] */ REFIID riid,
  684.         //        /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) = 0;    
  685.         //    virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;    
  686.         //    virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
  687. //相关的宏
  688. //#define STDMETHOD(method)       virtual HRESULT STDMETHODCALLTYPE method
  689. //#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method
  690.     STDMETHOD(QueryInterface)(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject);
  691.     STDMETHOD_(ULONG,AddRef)(void);    
  692.     STDMETHOD_(ULONG,Release)(void);  
  693. private:
  694. ULONG ilisongtao;//与AddRef、Release函数相关,要初始化
  695. --->然后在实现文件中重载:
  696. STDMETHODIMP MyLog::writeLog( BSTR message)
  697. {
  698. //
  699. return S_OK;
  700. }
  701. STDMETHODIMP MyLog::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject)
  702. {
  703. if(riid==IID_ILog)
  704. {
  705. *ppvObject=(ILog*)this;
  706. this->AddRef();
  707. return S_OK;
  708. }
  709. else if(riid==IID_IUnknown)
  710. {
  711. *ppvObject=(IUnknown*)this;
  712. this->AddRef();
  713. return S_OK;
  714. }
  715. else
  716. {
  717. *ppvObject=NULL;
  718. return S_FALSE;
  719. }
  720. }
  721. STDMETHODIMP_(ULONG) MyLog::AddRef()
  722. {
  723. return this->ilisongtao++;
  724. }    
  725. STDMETHODIMP_(ULONG) MyLog::Release()
  726. {
  727. this->ilisongtao--;
  728. if(this->ilisongtao==0)
  729. {
  730. delete this;
  731. }
  732. return this->ilisongtao;
  733. }  
  734.   4.3
  735. 5.项目demoActivex建一个窗体COM组件:右键-->New ATL Object-->(controls)Composite Control-->(name:)MyPwd-----------然后可看见一个可编译的窗体文本--->添加控件(对一个按钮操作)
  736. -->双击按钮,弹出一个事件触发框,把按钮与点击事件绑定,然后双击该点击事件函数就会进入实现函数:
  737. LRESULT OnClickedButton1(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  738. {
  739. // TODO : Add Code for control notification handler.
  740. AfxMessageBox("Hello");
  741. return 0;
  742. }
  743. };
  744. 在文件夹中可看见MyPwd.htm文件,点击后可看见该控件的样式==>COM可被浏览器调用、还有java、.Net....
  745. 编译后就写进了注册表变成一个MyPwd Class控件---------
  746. 6.项目testPwd建一个单文档Dlg-->右键(窗体)--->Insert ActiveX Control--->找到MyPwd Class
  747. --->添加后窗体中的该控件就是项目demoActivex导入的控件
  748. ---02.28----------------------day13---------------------------------
  749. 1.(通用性强)项目DispCallBack通过IDisPatch接口实现回调接口:
  750.   1.1项目DispCallBack01不用IUnknow来做回调接口:-->New ATL Object-->Simple Object-->(Interface)Dual-->(name:)MyAbc-->(右键)添加两个方法SetLog([in] ILog* mylog);add([in] int a, [in] int b, [out] int* c );--->然后在.idl文件中接口IMyAbc的上面定义ILog接口(类似于C语言,顺序反的话话报错的)并添加WriteLog函数:
  751. [
  752. object,
  753. uuid(8BF1F3AA-6C46-4042-86EF-781E17040E08),
  754. dual,
  755. helpstring("ILog Interface"),
  756. pointer_default(unique)
  757. ]
  758. interface ILog : IDispatch
  759. {
  760. [id(1), helpstring("method WriteLog")] HRESULT WriteLog([in] BSTR message);
  761. };
  762. [
  763. object,
  764. uuid(8BF1F3AA-6C46-4042-86ED-781E17040E09),
  765. dual,
  766. helpstring("IMyAbc Interface"),
  767. pointer_default(unique)
  768. ]
  769. interface IMyAbc : IDispatch
  770. {     
  771. [id(1), helpstring("method SetLog")] HRESULT SetLog([in] ILog* mylog);
  772. [id(2), helpstring("method add")] HRESULT add([in] int a, [in] int b, [out] int* c );
  773. };
  774. 然后在MyAbc.h中声明一个私有成员变量IDispatch* pMytools;(昨天的例子中是声明成IUnknown*)并在构造函数中初始化;
  775.   1.2项目DispCallBack02与01相比:把接口ILog(接口保留)屏蔽掉,并把引用ILog类型改成IDispatch类型,如:SetLog([in] ILog* mylog);==>SetLog([in] IDispatch* mylog);
  776. STDMETHOD(SetLog)(/*[in]*/ ILog* mylog);==>STDMETHOD(SetLog)(/*[in]*/ IDispatch* mylog);
  777. STDMETHODIMP CMyAbc::SetLog(ILog *mylog)==>STDMETHODIMP CMyAbc::SetLog(IDispatch *mylog)
  778. 这样子在接口组件中就不在出现接口ILog的影子了(WriteLog函数是与接口分离的),这样的代码是非常通用的,即把回调接口虚拟化了,并完成具体功能:
  779. STDMETHODIMP CMyAbc::SetLog(IDispatch *mylog)
  780. {
  781. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  782. // TODO: Add your implementation code here
  783. this->pMytools=mylog;
  784. return S_OK;
  785. }
  786. STDMETHODIMP CMyAbc::add(int a, int b, int *c)
  787. {
  788. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  789. // TODO: Add your implementation code here
  790. *c=a+b;
  791. if(this->pMytools!=NULL)
  792. {
  793. long id=1;
  794. //回调方法id;
  795. DISPID methodid=(DISPID)id;
  796. //回调方法参数;
  797. VARIANT paras[1];
  798. paras[0].vt=VT_BSTR;
  799. char buffer[20];
  800. sprintf(buffer,"%d",*c);
  801. CString str(buffer);
  802. paras[0].bstrVal=str.AllocSysString();
  803. DISPPARAMS disp;
  804. disp.cArgs=1;
  805. disp.rgvarg=paras;
  806. disp.cNamedArgs=0;
  807. disp.rgdispidNamedArgs=NULL;
  808. //输出参数;
  809. VARIANT vout;
  810. EXCEPINFO  ex;
  811. UINT   result=0;
  812. this->pMytools->Invoke(methodid,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_METHOD,
  813. &disp,&vout,&ex,&result);
  814. }
  815. return S_OK;
  816. }
  817.   1.3项目DispCallBack03在02的基础上添加一个test项目并添加一个继承ILog接口的类MyLog,声明并重写WriteLog(BSTR message)函数及IDispatch的虚函数:
  818.     STDMETHOD(WriteLog)(BSTR message);
  819.     STDMETHOD(GetTypeInfoCount)(UINT __RPC_FAR *pctinfo);     
  820.     STDMETHOD(GetTypeInfo)( 
  821. UINT iTInfo,
  822. LCID lcid,
  823. ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);    
  824.     STDMETHOD(GetIDsOfNames)( 
  825. REFIID riid,
  826. LPOLESTR __RPC_FAR *rgszNames,
  827. UINT cNames,
  828. LCID lcid,
  829. DISPID __RPC_FAR *rgDispId);        
  830.     STDMETHOD(Invoke)( 
  831. DISPID dispIdMember,
  832. REFIID riid,
  833. LCID lcid,
  834. WORD wFlags,
  835. DISPPARAMS __RPC_FAR *pDispParams,
  836. VARIANT __RPC_FAR *pVarResult,
  837. EXCEPINFO __RPC_FAR *pExcepInfo,
  838. UINT __RPC_FAR *puArgErr);
  839. STDMETHOD(QueryInterface)( 
  840. REFIID riid,
  841. void __RPC_FAR *__RPC_FAR *ppvObject);        
  842.     STDMETHOD_(ULONG,AddRef)( void);
  843. STDMETHOD_(ULONG,Release)( void);
  844. =====================================================
  845. STDMETHODIMP MyLog::Invoke( 
  846.   DISPID dispIdMember,
  847.   REFIID riid,
  848.   LCID lcid,
  849.   WORD wFlags,
  850.   DISPPARAMS __RPC_FAR *pDispParams,
  851.   VARIANT __RPC_FAR *pVarResult,
  852.   EXCEPINFO __RPC_FAR *pExcepInfo,
  853.   UINT __RPC_FAR *puArgErr)
  854. {
  855. if(dispIdMember==1)
  856. {
  857. BSTR bBuffer=::SysAllocString(pDispParams->rgvarg[0].bstrVal);
  858. SysFreeString(pDispParams->rgvarg[0].bstrVal);
  859. return this->WriteLog(bBuffer);
  860. }
  861. else
  862. {
  863. *puArgErr=1;
  864. return S_FALSE;
  865. }
  866. }        
  867.  1.4项目DispCallBack04完善WriteLog(BSTR message)方法,并添加一个按钮
  868. STDMETHODIMP MyLog::WriteLog(BSTR message)
  869. {
  870. CString msg(message);
  871. ::SysFreeString(message);
  872. AfxMessageBox(msg);
  873. return S_OK;
  874. }  
  875. #include "../DispCallBack.h"
  876. #include "../DispCallBack_i.c"
  877. #include <atlbase.h>
  878. #include "mylog.h"
  879. void CTestDlg::OnButton1() 
  880. {
  881. // TODO: Add your control notification handler code here
  882. CoInitialize(NULL);
  883.     ILog* pLog=NULL;
  884. CComPtr<IMyAbc> pTools;
  885. pTools.CoCreateInstance(CLSID_MyAbc);
  886. pLog=new MyLog();
  887. pTools->SetLog(pLog);
  888. int iResult;
  889. pTools->add(12,13,&iResult);
  890. }
  891.      
  892. 2.项目EventDemoCOM 事件的定义和处理:
  893.   2.1项目EventDemo01-->New ATL Object-->Simple Object-->(Interface)Dual-->(name:)MyAbc-->在接口中添加一个函数add([in] int a, [in] int b, [out] int* c );并实现:
  894. STDMETHODIMP CMyAbc::add(int a, int b, int *c)
  895. {
  896. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  897. // TODO: Add your implementation code here
  898. *c=a+b;
  899. CString str;
  900. str.Format("%d",*c);
  901. this->Fire_OnLog(str.AllocSysString());
  902. return S_OK;
  903. }
  904. ------->(手工代码建控件)在.idl文件的library EVENTDEMOLib(组件)下添加:
  905.     [
  906. uuid(C26E3137-7CDB-48F9-ACCB-95A272C68E68),
  907. helpstring("adfasdf")
  908. ]
  909. dispinterface _MyEvent //interface MyEvent: IDispatch
  910. {
  911. properties:
  912.     methods:
  913. [id(1),helpstring("adsf")] HRESULT OnLog([in] BSTR msg);
  914. }
  915. 并在coclass MyAbc(构件中)添加:
  916. [default,source] dispinterface _MyEvent;
  917. 然后可看到自动生成接口MyEvent-->(右键CMyAbc)Implement Connection points-->在_MyEvent选项处打钩-->可看见有类CProxy_MyEvent<class T>生成,其下包含有方法Fire_OnLog(BSTR msg)(与_MyEvent的方法对应)
  918. 3.项目Event:(有界面的--控件形式)事件处理:(右键)New ATL Object-->controls-->Composite Controls(建控件)-->(name:MyPwds)-->support Connection points--->生成事件接口IMyPwdsEvents、接口IMyPwds及类CMyPwds-->在事件接口IMyabcEvents中添加函数:
  919. [id(1), helpstring("method add")] HRESULT add([in] BSTR msg);-->(右键CMyPwds)Implement Connection points-->在_IMyPwdsEvents选项处打钩-->(编译后)可看见有类CProxy_IMyPwdsEvents<class T>生成,其下包含有方法Fire_add(BSTR msg)(与_IMyPwdsEvents的方法对应)--->然后在dialog中添加一个按钮,然后双击添加button的BN_CLICKED,自动生成函数OnClickedButton1-->(点击Edit Exiting后)完成功能代码:
  920. LRESULT OnClickedButton1(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  921. {
  922. // TODO : Add Code for control notification handler.
  923. this->Fire_add(::SysAllocString(L"控件制作成功"));
  924. return 0;
  925. }
  926. };
  927. 编译后即可---------
  928. -->然后添加一个test项目,在Dialog中右键插入控件MyPwds Class-->(右键Event)绑定IDC_MYPWDS1和方法add-->(点击Edit Exiting后)完成功能代码:
  929. void CTestDlg::OnaddMypwds1(LPCTSTR msg) 
  930. {
  931. // TODO: Add your control notification handler code here
  932. CString str(msg);
  933. MessageBox(msg);
  934. }
  935. 4.项目MyAbc
  936.   4.1项目MyAbc01:(无界面的--控件形式)事件处理:(右键)New ATL Object-->Simple Object-->(Interface)Dual-->(name:)Abc-->support Connection points--->生成事件接口IAbcEvents、接口IAbc及类CAbc-->在事件接口IAbcEvents中添加函数:
  937. [id(1), helpstring("method add")] HRESULT WriteLog([in] BSTR  msge);
  938. -->(右键CMyPwds)Implement Connection points-->在_IAbcEvents选项处打钩-->(编译后)可看见有类CProxy_IAbcEvents<class T>生成,其下包含有(自动生成)方法Fire_WriteLog(BSTR msge)(与_IAbcEvents的方法对应):
  939. template <class T>
  940. class CProxy_IAbcEvents : public IConnectionPointImpl<T, &DIID__IAbcEvents, CComDynamicUnkArray>
  941. {
  942. //Warning this class may be recreated by the wizard.
  943. public:
  944. HRESULT Fire_WriteLog(BSTR msge)
  945. {
  946. CComVariant varResult;
  947. T* pT = static_cast<T*>(this);
  948. int nConnectionIndex;
  949. CComVariant* pvars = new CComVariant[1];
  950. int nConnections = m_vec.GetSize();
  951. for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
  952. {
  953. pT->Lock();
  954. CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
  955. pT->Unlock();
  956. IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
  957. if (pDispatch != NULL)
  958. {
  959. VariantClear(&varResult);
  960. pvars[0] = msge;
  961. DISPPARAMS disp = { pvars, NULL, 1, 0 };
  962. //writeLog跟函数pDispatch->Invoke()相关==========
  963. pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
  964. }
  965. }
  966. delete[] pvars;
  967. return varResult.scode;
  968. }
  969. };
  970. -->然后在接口IAbc中添加函数(可用右键完成):
  971. [id(1), helpstring("method add")] HRESULT add([in] int a, [in] int b, [out] int* c);
  972.   
  973.   4.2项目MyAbc02在MyAbc01基础上像1.3项目DispCallBack03一样添加项目test,即添加函数:
  974. STDMETHODIMP MyLog::GetTypeInfoCount(UINT __RPC_FAR *pctinfo)
  975. {
  976. return S_FALSE;
  977. }        
  978. STDMETHODIMP MyLog::GetTypeInfo( 
  979. UINT iTInfo,
  980. LCID lcid,
  981. ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
  982. {
  983. return S_FALSE;
  984. }        
  985. STDMETHODIMP MyLog::GetIDsOfNames( 
  986. REFIID riid,
  987. LPOLESTR __RPC_FAR *rgszNames,
  988. UINT cNames,
  989. LCID lcid,
  990. DISPID __RPC_FAR *rgDispId)
  991. {
  992. return S_FALSE;
  993. }        
  994. STDMETHODIMP MyLog::Invoke( 
  995. DISPID dispIdMember,
  996. REFIID riid,
  997. LCID lcid,
  998. WORD wFlags,
  999. DISPPARAMS __RPC_FAR *pDispParams,
  1000. VARIANT __RPC_FAR *pVarResult,
  1001. EXCEPINFO __RPC_FAR *pExcepInfo,
  1002. UINT __RPC_FAR *puArgErr)
  1003. {
  1004. //实现day12的WriteLog的功能(基本是复制的):生成日志文件
  1005. CFile f;
  1006. CFileException ex;
  1007. f.Open("./log.txt",CFile::modeCreate| CFile::modeReadWrite,&ex);
  1008. CString str(pDispParams->rgvarg[0].bstrVal);//改变的地方
  1009. f.Write(str.GetBuffer(100),str.GetLength());
  1010. ::SysFreeString(pDispParams->rgvarg[0].bstrVal);
  1011. f.Close();
  1012. return S_OK;
  1013. }        
  1014. STDMETHODIMP MyLog::QueryInterface( 
  1015. REFIID riid,
  1016. void __RPC_FAR *__RPC_FAR *ppvObject)
  1017. {
  1018.     *ppvObject=this;
  1019. return S_OK;
  1020. }        
  1021. STDMETHODIMP_(ULONG) MyLog::AddRef( void)
  1022. {
  1023. return 1;
  1024. }
  1025. STDMETHODIMP_(ULONG) MyLog::Release( void)
  1026. {
  1027. return 1;
  1028. }
  1029. ---03.01---------------------day14---------------------------------
  1030. 1.项目DemoError
  1031.   1.1项目DemoError01添加接口时,选择支持异常--Support ISupportsErrorInfo--可看到有异常类自动生成:
  1032. STDMETHODIMP CMyAbc::InterfaceSupportsErrorInfo(REFIID riid)
  1033. {
  1034. static const IID* arr[] = 
  1035. {
  1036. &IID_IMyAbc
  1037. };
  1038. for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
  1039. {
  1040. if (InlineIsEqualGUID(*arr[i],riid))
  1041. return S_OK;
  1042. }
  1043. return S_FALSE;
  1044. }
  1045. -->然后给接口添加并实现函数:
  1046. STDMETHODIMP CMyAbc::div(int a, int b, int *c)
  1047. {
  1048. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1049. // TODO: Add your implementation code here
  1050. if(b==0)
  1051. {
  1052. CString str("b can not be zero!");
  1053. this->Error(str.AllocSysString());
  1054. return S_FALSE;
  1055. }
  1056. else
  1057. {
  1058. *c=a/b;
  1059. return S_OK;
  1060. }
  1061. }
  1062.   1.2项目DemoError02再建一个新项目test并添加一个按钮捕获异常:(.idl文件没变)
  1063. #include "../DemoError.h"
  1064. #include "../DemoError_i.c"
  1065. #include <atlbase.h>
  1066. void CTest1Dlg::OnButton1() 
  1067. {
  1068. // TODO: Add your control notification handler code here
  1069. ::CoInitialize(NULL);
  1070. CComPtr<IMyAbc> mytools;
  1071. mytools.CoCreateInstance(CLSID_MyAbc);
  1072. int iResult=0;
  1073. HRESULT hr=mytools->div(12,0,&iResult);
  1074. if(hr!=0)
  1075. {
  1076. ISupportErrorInfo* pError=NULL;//判断是否支持异常
  1077. mytools->QueryInterface(IID_ISupportErrorInfo,(void**)&pError);
  1078. HRESULT h1=pError->InterfaceSupportsErrorInfo(IID_IMyAbc);//判断接口是否支持异常
  1079. if(SUCCEEDED(h1))
  1080. {
  1081. IErrorInfo* pMyException=NULL;
  1082. ::GetErrorInfo(0,&pMyException);
  1083. BSTR msg;
  1084. pMyException->GetDescription(&msg);//捕获错误异常提示
  1085. CString str(msg);
  1086. MessageBox(str);
  1087. }
  1088. }
  1089. }
  1090. 2.项目EquationDemo通过接口(支持异常)实现一元二次方程求根:
  1091.   2.1项目EquationDemo02实现求根函数:
  1092. 在.idl文件中
  1093. //添加与一元二次方程相关两个结构体
  1094. //保存根数据的结构体
  1095.     typedef struct Root
  1096. {
  1097. float r1;
  1098. float r2;
  1099. } Root;
  1100. //保存方程系数数据的结构体
  1101.     typedef struct Equation
  1102. {
  1103.   float a;
  1104. float b;
  1105. float c;
  1106. } Equation;
  1107. STDMETHODIMP CMyEquation::solve(Equation* equ,Root** roots)
  1108. {
  1109. float delta=(equ->b)*(equ->b)-4*equ->a*equ->c;
  1110. if(delta>=0)
  1111. {
  1112. *roots=(Root*)::CoTaskMemAlloc(sizeof(Root));
  1113. float temp1=sqrt(delta);
  1114. (*roots)->r1=0.5*(0-equ->b+temp1)/equ->a;
  1115. (*roots)->r1=0.5*(0-equ->b-temp1)/equ->a;
  1116. return S_OK;
  1117. }
  1118. else
  1119. {
  1120. this->Error(::SysAllocString(L"no root"));
  1121. return S_FALSE;
  1122. }
  1123. }
  1124.   
  1125.   2.2项目EquationDemo03再建一个test项目并添加一个按钮:
  1126. #include "../EquationDemo.h"
  1127. #include "../EquationDemo_i.c"
  1128. #include <atlbase.h>
  1129. void CTestDlg::OnButton1() 
  1130. {
  1131. // TODO: Add your control notification handler code here
  1132. ::CoInitialize(NULL);
  1133. CComPtr<IMyEquation> mytools;
  1134. mytools.CoCreateInstance(CLSID_MyEquation);
  1135. Equation t;
  1136. t.a=1;
  1137. t.b=2;
  1138. t.c=1;
  1139. Root* roots=NULL;
  1140. HRESULT hr=mytools->solve(&t,&roots);
  1141. if(hr!=0)
  1142. {
  1143. ISupportErrorInfo* pSp=NULL;
  1144. mytools->QueryInterface(IID_ISupportErrorInfo,(void **)&pSp);
  1145. if(pSp!=NULL)
  1146. {
  1147. HRESULT hrok=pSp->InterfaceSupportsErrorInfo(IID_IMyEquation);
  1148. if(hrok==S_OK)
  1149. {
  1150. IErrorInfo* pError=NULL;
  1151. ::GetErrorInfo(0,&pError);
  1152. BSTR bMsg;
  1153. pError->GetDescription(&bMsg);
  1154. CString str(bMsg);
  1155. MessageBox(str);
  1156. }
  1157. }
  1158. }
  1159. else
  1160. {
  1161. CString strall;
  1162. strall.Format("root1:%f,root2:%f",roots->r1,roots->r2);
  1163. MessageBox(strall);
  1164. }
  1165. }
  1166. 3.项目TestAdo为ADO(数据库COM)操作:
  1167.   3.1项目TestAdo02为建一个单文档项目,在标准头文件StdAfx.h中添加
  1168. #import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF")--C:Program FilesCommon FilesSystemadomsado15.dll为微软提供的数据库COM相关接口msado15.dll文件--->然后添加三个按钮:
  1169. 测试时hr=0表返回成功
  1170. void CTestAdoDlg::OnButton1() 
  1171. {
  1172. ::CoInitialize(NULL);
  1173. _ConnectionPtr myconn;  //CComPtr<IConnection>智能指针
  1174. myconn.CreateInstance(__uuidof(Connection));//生成实例
  1175. _bstr_t sql("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena;");//样式
  1176. HRESULT hr=myconn->Open(sql,"scott","tiger",-1);//建立数据源连接--conection的方法
  1177. myconn->Close();//释放数据源连接--conection的方法
  1178. }
  1179. #include <atlbase.h>
  1180. void CTestAdoDlg::OnButton2() 
  1181. {
  1182. // TODO: Add your control notification handler code here
  1183.     ::CoInitialize(NULL);//初始化环境
  1184. CComPtr<_Connection> mytools;//和OnButton1的声明意义一样
  1185. mytools.CoCreateInstance(__uuidof(Connection));//生成实例
  1186. _bstr_t sql("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena;");
  1187. HRESULT hr=mytools->Open(sql,"scott","tiger",-1);//建立数据源连接
  1188. mytools->Close();//释放数据源连接
  1189. }
  1190. void CTestAdoDlg::OnButton3() 
  1191. {
  1192. // TODO: Add your control notification handler code here
  1193.     ::CoInitialize(NULL);//初始化环境
  1194. _Connection* mytools=NULL;
  1195. CoCreateInstance(__uuidof(Connection),
  1196. NULL,
  1197. CLSCTX_INPROC_SERVER,
  1198. __uuidof(_Connection),
  1199. (void **)&mytools);//生成实例
  1200. _bstr_t sql("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena;");
  1201. HRESULT hr=mytools->Open(sql,"scott","tiger",-1);//建立数据源连接
  1202. mytools->Close();//释放数据源连接
  1203. }
  1204.   3.2项目TestAdo03在02的button1中添加查询数据库代码:
  1205. void CTestAdoDlg::OnButton1() 
  1206. {
  1207. ::CoInitialize(NULL);
  1208. _ConnectionPtr myconn; //连接智能指针 
  1209. myconn.CreateInstance(__uuidof(Connection));//生成实例
  1210. _bstr_t sql("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena;");
  1211. HRESULT hr=myconn->Open(sql,"scott","tiger",-1);
  1212. //定义一个sql语句对象;
  1213.     _CommandPtr mysql1; //命令智能指针
  1214. mysql1.CreateInstance(__uuidof(Command));//生成实例
  1215. _bstr_t sql1("select * from ocyBooks");
  1216. mysql1->CommandText=sql1;//指定命令文本
  1217. mysql1->CommandType=adCmdText;//指定命令类型
  1218. //以下是新增的代码:
  1219. //制定SQL所查询的数据库;
  1220. mysql1->ActiveConnection=myconn;
  1221. //查询并返回存放在表中的结果集
  1222. _RecordsetPtr mydata=mysql1->Execute(NULL,NULL,adCmdText);//数据操作
  1223. while(!mydata->adoEOF)//列表指针
  1224. {
  1225. _variant_t myid=mydata->GetCollect("BOOKISNB");//获取数据表对应属性名的数据
  1226. _variant_t myname=mydata->GetCollect("BOOKNAME");//获取数据表对应属性名的数据
  1227. _variant_t myauthor=mydata->GetCollect("BOOKAuthor");//获取数据表对应属性名的数据
  1228. CString strName((LPCTSTR)(_bstr_t)myname);//(_bstr_t)为带空字节头的UNicode码
  1229. CString strAuthor((LPCTSTR)(_bstr_t)myauthor);//(LPCTSTR)为不带空字节头的UNicode码
  1230. CString str;
  1231. str.Format("%d;%s;%s",(long)myid,strName,strAuthor);
  1232. MessageBox(str);
  1233. mydata->MoveNext();
  1234. }
  1235. mydata->Close();
  1236. myconn->Close();
  1237. }
  1238.   3.3项目TestAdo04新加一个按钮对Command的操作:
  1239. void CTestAdoDlg::OnButton4() 
  1240. {
  1241. // TODO: Add your control notification handler code here
  1242. ::CoInitialize(NULL);//初始化环境
  1243. //_bstr_t sql1("insert into ocyBooks (BookISNB, BookName, BookAuthor) values (123457,'COM','WANGWU')");
  1244. //_bstr_t sql1("delete from ocyBooks");
  1245. _bstr_t sql1("update ocyBooks set BookName='C++' where BookName='COM'");
  1246. _ConnectionPtr myconn;//连接智能指针 
  1247. myconn.CreateInstance(__uuidof(Connection));//生成实例
  1248. _bstr_t sql("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena;");
  1249. HRESULT hr=myconn->Open(sql,"scott","tiger",-1);//建立数据源连接
  1250. _CommandPtr cmdsql1;//命令智能指针
  1251. cmdsql1.CreateInstance(__uuidof(Command));//生成实例
  1252. cmdsql1->CommandType=adCmdText;//指定命令类型
  1253. cmdsql1->CommandText=sql1;//指定命令文本
  1254. //制定SQL所查询的数据库;
  1255. cmdsql1->ActiveConnection=myconn;
  1256. VARIANT iResult;
  1257. iResult.vt=VT_I4;//数字类型
  1258. cmdsql1->Execute(&iResult,NULL,adCmdText);//功能和Recordset的一样
  1259. }
  1260. ---03.02---------------------day15---------------------------------
  1261. 1.项目DempParameter添加文本框,输入数据,导入数据库(不是COM方式)
  1262.   1.1基本对话项目DempParameter02添加一个window事件:WM_DESTROY,在自动生成的OnDestroy() 方法中添加::CoUninitialize();//释放环境;
  1263. 在OnInitDialog()方法中添加::CoInitialize(NULL);//初始化环境
  1264. 在头文件中声明一个方法://链接单独用一个函数有利于扩展通用性:
  1265. _ConnectionPtr GetDataConnection(CString datasource, CString uid, CString pwd);
  1266. 然后添加3个文本框(在类向导中绑定3个变量)和1个按钮:
  1267. _ConnectionPtr CDempParameterDlg::GetDataConnection(CString datasource, CString uid, CString pwd)
  1268. {
  1269. CString strFormat="Provider=OraOLEDB.Oracle.1;User Id=%s;Data Source=%s";
  1270. CString str;
  1271. str.Format(strFormat,uid,datasource);
  1272. _ConnectionPtr mytools;
  1273. mytools.CreateInstance(__uuidof(Connection));
  1274. mytools->Open(_bstr_t(str),"",_bstr_t(pwd),-1);
  1275. return mytools;
  1276. }
  1277. void CDempParameterDlg::OnButton1() 
  1278. {
  1279. // TODO: Add your control notification handler code here
  1280. _ConnectionPtr myconn=this->GetDataConnection("tarena","scott","tiger");
  1281. this->UpdateData(TRUE);//更新数据
  1282. CString sqlFormat="insert into ocyBooks(BookIsnb,BookName,BookAuthor) values (%s,'%s','%s')";
  1283. CString sql;
  1284. sql.Format(sqlFormat,this->m_ibsn,this->m_bookname,this->m_author);
  1285. _CommandPtr sqlobj;
  1286. sqlobj.CreateInstance(__uuidof(Command));
  1287. sqlobj->CommandText=_bstr_t(sql);//命令文本
  1288. sqlobj->CommandType=adCmdText;//命令类型
  1289. //制定SQL所查询的数据库;
  1290. sqlobj->ActiveConnection=myconn;
  1291. VARIANT vResult;
  1292. vResult.vt=VT_I4;//转整形
  1293. try{
  1294. sqlobj->Execute(&vResult,NULL,adCmdText);//执行查询
  1295. }
  1296. catch(_com_error ex)
  1297. {
  1298. int i=10;
  1299. i=i+1;
  1300. }
  1301. }
  1302.   1.2单文档项目DempParameter03再添加一个按钮,功能一样:
  1303. void CDempParameterDlg::OnButton2() 
  1304. {
  1305. // TODO: Add your control notification handler code here
  1306. this->UpdateData(TRUE);
  1307. _ConnectionPtr myconn=this->GetDataConnection("tarena","scott","tiger");
  1308. //和1的不同点
  1309. _bstr_t sql("insert into ocyBooks(BookIsnb,BookName,BookAuthor) values (?,?,?)");
  1310. _CommandPtr sqlobj;
  1311. sqlobj.CreateInstance(__uuidof(Command));
  1312. sqlobj->CommandType=adCmdText;//命令类型
  1313. sqlobj->CommandText=sql;//命令文本,和1的不同点
  1314. //parameter对象在command对象中用于指定参数化查询或者存储过程的参数
  1315. _ParameterPtr para1=sqlobj->CreateParameter("id",adInteger,adParamInput,4);
  1316. _ParameterPtr para2=sqlobj->CreateParameter("name",adVarChar,adParamInput,20);
  1317. _ParameterPtr para3=sqlobj->CreateParameter("author",adVarChar,adParamInput,20);
  1318. int id=atoi(this->m_ibsn);//字符转整形
  1319.     _variant_t vid((long)id);
  1320. para1->Value=vid;
  1321.     para2->Value=(_variant_t)(_bstr_t)(this->m_bookname);
  1322. para3->Value=(_variant_t)(_bstr_t)(this->m_author);
  1323. sqlobj->Parameters->Append(para1);//追加
  1324. sqlobj->Parameters->Append(para2);//追加
  1325. sqlobj->Parameters->Append(para3);//追加
  1326. sqlobj->ActiveConnection=myconn;
  1327. VARIANT myvt;
  1328. myvt.vt=VT_I4;
  1329. sqlobj->Execute(&myvt,NULL,adCmdText);
  1330. }
  1331. 2.项目BooksDAL用接口(COM)方式操作数据库:
  1332.   2.1建一个支持异常的COM组件项目BooksDAL01,添加5个方法:
  1333. 在idl文件头添加一个结构体:
  1334.     typedef struct DTOBook
  1335. {
  1336.    UINT BookIsnb;
  1337.    BSTR BookName;
  1338.    BSTR BookAuthor;
  1339. }DTOBook;
  1340. STDMETHODIMP CDALMyBools::GetBookByIsbn(UINT bookisbn, DTOBook **mybook)
  1341. {
  1342. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1343. // TODO: Add your implementation code here
  1344. return S_OK;
  1345. }
  1346. STDMETHODIMP CDALMyBools::QueryAllBook(DTOBook **allBook)
  1347. {
  1348. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1349. // TODO: Add your implementation code here
  1350. return S_OK;
  1351. }
  1352. STDMETHODIMP CDALMyBools::SaveBook(DTOBook *bookdata, UINT *pResult)
  1353. {
  1354. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1355. // TODO: Add your implementation code here
  1356. return S_OK;
  1357. }
  1358. STDMETHODIMP CDALMyBools::DeleteBookById(UINT id, UINT *iResult)
  1359. {
  1360. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1361. // TODO: Add your implementation code here
  1362. return S_OK;
  1363. }
  1364. STDMETHODIMP CDALMyBools::Update(DTOBook *Book, UINT *iResult)
  1365. {
  1366. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1367. // TODO: Add your implementation code here
  1368. return S_OK;
  1369. }
  1370.   2.1项目BooksDAL02在01的基础上声明8个私有成员变量及1个私有成员方法:
  1371. 在头文件中添加:
  1372. #import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adEOF")
  1373. private:
  1374. _ConnectionPtr GetMyConn();
  1375. CString m_sqlQueryById;//通过ID查询
  1376. CString m_sqlQueryAll;//查询所有
  1377. CString m_sqlUpdate;//通过ID更新bookname、bookauthor
  1378. CString m_sqlSave;
  1379. CString m_sqlDelete;
  1380. CString m_UID;//用户名:scott
  1381. CString m_PWD;//密码:tiger
  1382. CString m_DataSource;//数据源:tarena
  1383. 然后在构造方法中初始化:
  1384. CDALMyBools()
  1385. {
  1386. this->m_sqlQueryById="select * from mybooks where bookisnb=?";
  1387. this->m_sqlQueryAll="select * from mybooks";
  1388. this->m_sqlUpdate="update mybooks set bookname=?,bookauthor=? where bookisnb=?";
  1389. //CString m_sqlSave;
  1390. //CString m_sqlDelete;
  1391. }
  1392. 私有成员方法的实现://通用性
  1393. _ConnectionPtr CDALMyBools::GetMyConn()
  1394. {
  1395. CString strFormat="Provider=OraOLEDB.Oracle.1;User Id=%s;Data Source=%s";
  1396. CString str;
  1397. str.Format(strFormat,this->m_UID,this->m_DataSource);
  1398. _ConnectionPtr mytools;
  1399. mytools.CreateInstance(__uuidof(Connection));
  1400. mytools->Open(_bstr_t(str),"",_bstr_t(this->m_PWD),-1);
  1401. return mytools;
  1402. }
  1403. 并在其他方法中调用:
  1404. STDMETHODIMP CDALMyBools::GetBookByIsbn(UINT bookisbn, DTOBook **mybook)
  1405. {
  1406. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1407. // TODO: Add your implementation code here
  1408. _ConnectionPtr conn=this->GetMyConn();
  1409. return S_OK;
  1410. }
  1411. 然后添加3个属性(自动生成6个方法):
  1412. STDMETHOD(get_DataSource)(/*[out, retval]*/ BSTR *pVal);
  1413. STDMETHOD(put_DataSource)(/*[in]*/ BSTR newVal);
  1414. STDMETHOD(get_PWD)(/*[out, retval]*/ BSTR *pVal);
  1415. STDMETHOD(put_PWD)(/*[in]*/ BSTR newVal);
  1416. STDMETHOD(get_UID)(/*[out, retval]*/ BSTR *pVal);
  1417. STDMETHOD(put_UID)(/*[in]*/ BSTR newVal);
  1418. 并实现:
  1419. STDMETHODIMP CDALMyBools::get_UID(BSTR *pVal)
  1420. {
  1421. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1422. // TODO: Add your implementation code here
  1423. return S_OK;
  1424. }
  1425. //有改动
  1426. STDMETHODIMP CDALMyBools::put_UID(BSTR newVal)
  1427. {
  1428. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1429. // TODO: Add your implementation code here
  1430. this->m_UID=CString(newVal);
  1431. ::SysFreeString(newVal);
  1432. return S_OK;
  1433. }
  1434. STDMETHODIMP CDALMyBools::get_PWD(BSTR *pVal)
  1435. {
  1436. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1437. // TODO: Add your implementation code here
  1438. return S_OK;
  1439. }
  1440. //有改动
  1441. STDMETHODIMP CDALMyBools::put_PWD(BSTR newVal)
  1442. {
  1443. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1444. // TODO: Add your implementation code here
  1445. this->m_PWD=CString(newVal);
  1446. ::SysFreeString(newVal);
  1447. return S_OK;
  1448. }
  1449. STDMETHODIMP CDALMyBools::get_DataSource(BSTR *pVal)
  1450. {
  1451. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1452. // TODO: Add your implementation code here
  1453. return S_OK;
  1454. }
  1455. //有改动
  1456. STDMETHODIMP CDALMyBools::put_DataSource(BSTR newVal)
  1457. {
  1458. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1459. // TODO: Add your implementation code here
  1460. this->m_DataSource=CString(newVal);
  1461. ::SysFreeString(newVal);
  1462. return S_OK;
  1463. }
  1464.   2.2项目BooksDAL03在02的基础上补充方法GetBookByIsbn():
  1465. STDMETHODIMP CDALMyBools::GetBookByIsbn(UINT bookisbn, DTOBook **mybook)
  1466. {
  1467. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1468. // TODO: Add your implementation code here
  1469. _ConnectionPtr conn=this->GetMyConn();
  1470. *mybook=(DTOBook*)::CoTaskMemAlloc(sizeof(DTOBook));//开辟空间
  1471. _CommandPtr sqlobj;
  1472. sqlobj.CreateInstance(__uuidof(Command));//生成实例
  1473. sqlobj->CommandText=(_bstr_t)this->m_sqlQueryById;//命令类型
  1474. sqlobj->CommandType=adCmdText;//命令文本
  1475. //制定SQL所查询的数据库;
  1476. sqlobj->ActiveConnection=conn;
  1477. //指定参数化查询
  1478. _ParameterPtr para1=sqlobj->CreateParameter("id",adInteger,adParamInput,4);
  1479. para1->Value=_variant_t((long)bookisbn);
  1480. sqlobj->Parameters->Append(para1);
  1481. _RecordsetPtr data=sqlobj->Execute(NULL,NULL,adCmdText);
  1482. if(!data->adEOF)
  1483. {
  1484. (*mybook)->BookIsnb=(UINT)(long)(data->GetCollect("bookisnb"));
  1485. _variant_t vtname=data->GetCollect("bookname");
  1486. (*mybook)->BookName=::SysAllocString(vtname.bstrVal);
  1487. _variant_t vtauthor=data->GetCollect("bookauthor");
  1488. (*mybook)->BookName=::SysAllocString(vtauthor.bstrVal);
  1489. }
  1490. return S_OK;
  1491. }
  1492. 在BooksDAL.h中添加一个结构体:
  1493. typedef struct  DTOBook
  1494.     {
  1495.     UINT BookIsnb;
  1496.     BSTR BookName;
  1497.     BSTR BookAuthor;
  1498.     } DTOBook;
  1499. 然后新建一个test项目并添加一个按钮测试:
  1500. #include "../BooksDAL.h"
  1501. #include "../BooksDAL_i.c"
  1502. #include <atlbase.h>
  1503. #include <comdef.h>
  1504. void CTESTDlg::OnButton1() 
  1505. {
  1506. // TODO: Add your control notification handler code here
  1507. ::CoInitialize(NULL);
  1508. CComPtr<IDALMyBools> mytools;
  1509. mytools.CoCreateInstance(CLSID_DALMyBools);
  1510. DTOBook* pData=NULL;
  1511. mytools->put_PWD(_bstr_t("tiger"));
  1512. mytools->put_UID(_bstr_t("scott"));
  1513. mytools->put_DataSource(_bstr_t("tarena"));
  1514. mytools->GetBookByIsbn(6,&pData);
  1515. }
  1516.   2.3项目BooksDAL04在03的基础上补充添加私有方法:
  1517. _ParameterPtr CDALMyBools::GetIdPara(UINT id,_CommandPtr sqlObj)
  1518. {
  1519. _ParameterPtr para1=sqlObj->CreateParameter("id",adInteger,adParamInput,4);
  1520. para1->Value=_variant_t((long)id);
  1521. return para1;
  1522. }
  1523. 改变按钮代码:
  1524. #include "../BooksDAL.h"
  1525. #include "../BooksDAL_i.c"
  1526. #include <atlbase.h>
  1527. #include <comdef.h>
  1528. void CTESTDlg::OnButton1() 
  1529. {
  1530. // TODO: Add your control notification handler code here
  1531. ::CoInitialize(NULL);
  1532. CComPtr<IDALMyBools> mytools;
  1533. mytools.CoCreateInstance(CLSID_DALMyBools);
  1534. DTOBook* pData=NULL;
  1535. mytools->put_PWD(_bstr_t("csd0910"));
  1536. mytools->put_UID(_bstr_t("csd0910"));
  1537. mytools->put_DataSource(_bstr_t("lisongtao"));
  1538. mytools->GetBookByIsbn(123457,&pData);
  1539. UINT iResult=0;
  1540. mytools->DeleteBookById(123457,&iResult);
  1541. }
  1542. ---03.05---------------------day16---------------------------------
  1543. 1.项目project为数据库连接(用day15的接口)及MFC界面操作实例:
  1544.   1.1项目project01建一个选定支持windows资源管理的单文档项目BookAdminApp,然后新建一个普通类BookEntity并让它继承CObject,且声明3个数据相关变量:
  1545. //要操作的数据成员,与接口的数据对应
  1546. UINT BookIsnb;
  1547. CString BookName;
  1548. CString BookAuthor;
  1549. --->在CBookAdminApp类的初始化方法InitInstance()中添加 ::CoInitialize(NULL);//环境初始化
  1550. --->用CBookAdminDoc类的方法OnNewDocument()读取数据到内存:
  1551. BOOL CBookAdminDoc::OnNewDocument()
  1552. {
  1553. if (!CDocument::OnNewDocument())
  1554. return FALSE;
  1555. // TODO: add reinitialization code here
  1556. // (SDI documents will reuse this document)
  1557. CComPtr<IDALMyBools> mytools;//组件接口指针
  1558. mytools.CoCreateInstance(CLSID_DALMyBools);//生成实例
  1559. DTOBook* pAllBooks=NULL;//数据的结构
  1560. UINT iSize=0;
  1561. //设置连接数据库条件
  1562. mytools->put_DataSource(::SysAllocString(L"tarena"));
  1563. mytools->put_UID(::SysAllocString(L"scott"));
  1564. mytools->put_PWD(::SysAllocString(L"tiger"));
  1565. mytools->QueryAllBook(&pAllBooks,&iSize);//查询数据库
  1566. for(int i=0;i<iSize;i++)
  1567. {
  1568. BookEntity* p1=new BookEntity;//
  1569. p1->BookIsnb=(pAllBooks+i)->BookIsnb;
  1570. p1->BookName=CString((pAllBooks+i)->BookName);
  1571. p1->BookAuthor=CString((pAllBooks+i)->BookAuthor);
  1572. //CString类型用完要释放掉
  1573. ::SysFreeString((pAllBooks+i)->BookName);
  1574. ::SysFreeString((pAllBooks+i)->BookAuthor);
  1575. //保存到内存上;
  1576. this->allBooks.AddTail(p1);
  1577. }
  1578. //释放栈中的结构体
  1579. ::CoTaskMemFree(pAllBooks);
  1580. return TRUE;
  1581. }
  1582.   1.2项目project02在01的CBookAdminView类的方法OnInitialUpdate()完成界面数据初始化:
  1583. //窗体中有数据出现
  1584. void CBookAdminView::OnInitialUpdate()
  1585. {
  1586. CListView::OnInitialUpdate();
  1587. //创建列;
  1588. this->GetListCtrl().InsertColumn(0,"BookName",LVCFMT_CENTER,200);
  1589. this->GetListCtrl().InsertColumn(1,"BookAuther",LVCFMT_CENTER,200);
  1590. //添加数据;
  1591. POSITION ps;
  1592. ps=this->GetDocument()->allBooks.GetHeadPosition();
  1593. while(ps!=NULL)
  1594. {
  1595. BookEntity* be=this->GetDocument()->allBooks.GetNext(ps);
  1596. this->GetListCtrl().InsertItem(0,be->BookName);
  1597. this->GetListCtrl().SetItemText(0,1,be->BookAuthor);
  1598. }
  1599. // TODO: You may populate your ListView with items by directly accessing
  1600. //  its list control through a call to GetListCtrl().
  1601. }
  1602.   1.3项目project03添加工具栏按钮实现添加功能:
  1603. -->添加一个对话框,再添加3个文本框,建一个基类为CDialog的MFC类DlgBookAdd并绑定文本框和3个变量再声明一个变量BOOL    m_bIsOk;
  1604. 及实现两个按钮功能(用对话框给的OK和cancel):
  1605. void DlgBookAdd::OnOK() 
  1606. {
  1607. // TODO: Add extra validation here
  1608. this->UpdateData(TRUE);//(更新后)把文本框数据送到内存中
  1609. m_bIsOk=TRUE;//与工具栏的功能相关
  1610. CDialog::OnOK();
  1611. }
  1612. void DlgBookAdd::OnCancel() 
  1613. {
  1614. // TODO: Add extra cleanup here
  1615. m_bIsOk=FALSE;
  1616. CDialog::OnCancel();
  1617. }
  1618. -->再实现工具栏的按钮功能:
  1619. //工具栏添加功能按钮
  1620. void CBookAdminDoc::OnButton32771() 
  1621. {
  1622. // TODO: Add your command handler code here
  1623. DlgBookAdd mydlg;//新设的类,绑定文本框和数据变量
  1624. mydlg.DoModal();//弹出对话框
  1625. if(mydlg.m_bIsOk)
  1626. { //对话框数据相关
  1627. UINT isbn=mydlg.m_bookisbn;
  1628. CString name=mydlg.m_bookname;
  1629. CString Author=mydlg.m_bookauthor;
  1630. CString CSisbn;
  1631. DTOBook* dto=new DTOBook;
  1632. dto->BookIsnb=isbn;
  1633. dto->BookName=name.AllocSysString();//转BSTR
  1634. dto->BookAuthor=Author.AllocSysString();
  1635. //将数据添加到数据库中;==>重复的代码
  1636. CComPtr<IDALMyBools> mytools;
  1637. mytools.CoCreateInstance(CLSID_DALMyBools);
  1638. DTOBook* pAllBooks=NULL;
  1639. UINT iSize=0;
  1640. mytools->put_DataSource(::SysAllocString(L"tarena"));
  1641. mytools->put_UID(::SysAllocString(L"scott"));
  1642. mytools->put_PWD(::SysAllocString(L"tiger"));
  1643. //保存数据
  1644. UINT iResult=0;
  1645. mytools->SaveBook(dto,&iResult);
  1646. //刷新界面上的数据==>显示到界面上;
  1647. POSITION ps=this->GetFirstViewPosition();
  1648. while(ps!=NULL)
  1649. {
  1650. CView* pview=this->GetNextView(ps);
  1651. if(pview->GetRuntimeClass()->m_lpszClassName=="CBookAdminView")
  1652. {
  1653. CListView* plist=(CListView*)pview;
  1654. plist->GetListCtrl().InsertItem(0,name);
  1655. plist->GetListCtrl().SetItemText(0,1,Author);
  1656. }
  1657. }
  1658. }
  1659. }
  1660.   1.4项目project04把03的--刷新界面上的数据的代码--及数据库连接相关变量数据归并到函数中去:
  1661. void CBookAdminDoc::OnButton32771() 
  1662. {
  1663. // TODO: Add your command handler code here
  1664. DlgBookAdd mydlg;
  1665. mydlg.DoModal();
  1666. if(mydlg.m_bIsOk)
  1667. {
  1668. UINT isbn=mydlg.m_bookisbn;
  1669. CString name=mydlg.m_bookname;
  1670. CString Author=mydlg.m_bookauthor;
  1671. DTOBook* dto=new DTOBook;
  1672. dto->BookIsnb=isbn;
  1673. dto->BookName=name.AllocSysString();
  1674. dto->BookAuthor=Author.AllocSysString();
  1675. //将数据添加到数据库中;
  1676. CComPtr<IDALMyBools> mytools=this->GetDbTools();
  1677. UINT iResult=0;
  1678. mytools->SaveBook(dto,&iResult);
  1679. //刷新界面上的数据;
  1680. CListView* plist=this->GetListView1();
  1681. plist->GetListCtrl().InsertItem(0,name);
  1682. plist->GetListCtrl().SetItemText(0,1,Author);
  1683. }
  1684. }
  1685. CComPtr<IDALMyBools> CBookAdminDoc::GetDbTools()
  1686. {
  1687. CComPtr<IDALMyBools> mytools;
  1688. mytools.CoCreateInstance(CLSID_DALMyBools);
  1689. DTOBook* pAllBooks=NULL;
  1690. UINT iSize=0;
  1691. mytools->put_DataSource(::SysAllocString(L"tarena"));
  1692. mytools->put_UID(::SysAllocString(L"scott"));
  1693. mytools->put_PWD(::SysAllocString(L"tiger"));
  1694. return mytools;
  1695. }
  1696. CListView* CBookAdminDoc::GetListView1()
  1697. {
  1698. CListView* plist=NULL;
  1699. POSITION ps=this->GetFirstViewPosition();
  1700. while(ps!=NULL)
  1701. {
  1702. CView* pview=this->GetNextView(ps);
  1703. if(pview->GetRuntimeClass()->m_lpszClassName=="CBookAdminView")
  1704. {
  1705. plist=(CListView*)pview;
  1706. break;
  1707. }
  1708. }
  1709. return plist;
  1710. }
  1711.   1.5项目project05添加工具栏删除功能按钮(绑定事件):
  1712. void CBookAdminView::OnButton32772() 
  1713. {
  1714. // TODO: Add your command handler code here
  1715. //找到被删除的记录ID;
  1716. int index=this->GetListCtrl().GetNextItem(-1,LVNI_SELECTED|LVNI_ALL);
  1717. if(index==-1)
  1718. {
  1719. MessageBox("请首先选中一条记录!");
  1720. }
  1721. else
  1722. {
  1723. UINT iOk=MessageBox("你真的要删除吗?","删除确认",MB_YESNO);
  1724. //从当前的界面上删除;
  1725. if(iOk==6)
  1726. {
  1727. this->GetListCtrl().DeleteItem(index);
  1728. //
  1729. DWORD isbn=this->GetListCtrl().GetItemData(index);
  1730. UINT iResult=0;
  1731. this->GetDocument()->GetDbTools()->DeleteBookById((UINT)isbn,&iResult);
  1732. }
  1733. }
  1734. }
  1735.   1.6项目project06添加工具栏修改数据功能按钮(绑定事件):
  1736. //修改数据
  1737. void CBookAdminView::OnButton32773() 
  1738. {
  1739. // TODO: Add your command handler code here
  1740. //1. 获得被编辑的记录id;
  1741. int index=this->GetListCtrl().GetNextItem(-1,LVNI_ALL|LVNI_SELECTED);
  1742. if(index==-1)
  1743. {
  1744. MessageBox("请首先选中一条记录");
  1745. return ;
  1746. }
  1747. //2. 显示被编辑的数据;
  1748. UINT id=(UINT)(this->GetListCtrl().GetItemData(index));
  1749. DTOBook* pCurrentData=NULL;
  1750. this->GetDocument()->GetDbTools()->GetBookByIsbn(id,&pCurrentData);
  1751. //3. 获得修改后的数据;
  1752. DlgBookAdd dlg;
  1753. dlg.m_bookisbn=id;
  1754. dlg.m_bookname=CString(pCurrentData->BookName);
  1755. dlg.m_bookauthor=CString(pCurrentData->BookAuthor);
  1756. ::SysFreeString(pCurrentData->BookName);
  1757. ::SysFreeString(pCurrentData->BookAuthor);
  1758. dlg.DoModal();
  1759. //4. 更新数据库;
  1760. //5. 更新界面;
  1761. }
  1762.   1.7项目project07添加工具栏修改数据功能按钮(绑定事件):
  1763. void CBookAdminView::OnButton32773() 
  1764. {
  1765. // TODO: Add your command handler code here
  1766. //1. 获得被编辑的记录id;
  1767. int index=this->GetListCtrl().GetNextItem(-1,LVNI_ALL|LVNI_SELECTED);
  1768. if(index==-1)
  1769. {
  1770. MessageBox("请首先选中一条记录");
  1771. return ;
  1772. }
  1773. //2. 显示被编辑的数据;
  1774. UINT id=(UINT)(this->GetListCtrl().GetItemData(index));
  1775. DTOBook* pCurrentData=NULL;
  1776. this->GetDocument()->GetDbTools()->GetBookByIsbn(id,&pCurrentData);
  1777. //3. 获得修改后的数据;
  1778. DlgBookAdd dlg;
  1779. dlg.m_bookisbn=id;
  1780. dlg.m_bookname=CString(pCurrentData->BookName);
  1781. dlg.m_bookauthor=CString(pCurrentData->BookAuthor);
  1782. ::SysFreeString(pCurrentData->BookName);
  1783. ::SysFreeString(pCurrentData->BookAuthor);
  1784. dlg.DoModal();
  1785. //4. 更新数据库;
  1786. if(!dlg.m_bIsOk) return ;
  1787. pCurrentData->BookAuthor=dlg.m_bookauthor.AllocSysString();
  1788. pCurrentData->BookName=dlg.m_bookname.AllocSysString();
  1789. UINT iResult=0;
  1790. this->GetDocument()->GetDbTools()->Update(pCurrentData,&iResult);
  1791. if(iResult==0) return;
  1792. //5. 更新界面;
  1793. this->GetListCtrl().SetItemText(index,0,dlg.m_bookname) ;
  1794. this->GetListCtrl().SetItemText(index,1,dlg.m_bookauthor);
  1795. }
  1796. ---03.06---------------------day17---------------------------------
  1797. 1.对话框项目OffDemoTecordSet 的open()方法的用法,建3个文本框,N个按钮功能:
  1798.   1.1项目OffDemo01在方法COffDemoDlg::OnInitDialog()中添加初始化环境语句:
  1799. ::CoInitialize(NULL);//初始化环境
  1800. --->然后实现button1的导入数据功能:
  1801. void COffDemoDlg::OnButton1() 
  1802. {
  1803. // TODO: Add your control notification handler code here
  1804. _ConnectionPtr conn;
  1805. conn.CreateInstance(__uuidof(Connection));
  1806. conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=csd0910;Data Source=lisongtao"),"",_bstr_t("csd0910"),-1);
  1807. _RecordsetPtr rs;
  1808. rs.CreateInstance(__uuidof(Recordset));
  1809. _bstr_t sqlobj("select * from mybooks");
  1810. rs->Open((_variant_t)sqlobj,
  1811. _variant_t((IDispatch *)conn,true),//这样写比较麻烦
  1812. adOpenStatic,
  1813. adLockOptimistic,//与UpdateBatch关联
  1814. -1);
  1815.     //显示第一条记录;
  1816. if(!rs->adEOF)
  1817. {
  1818. _variant_t isbn=rs->GetCollect("BOOKISNB");
  1819. }
  1820.   1.2项目OffDemo02改进01的open()方法的参数:
  1821. rs->Open((_variant_t)sqlobj,
  1822. conn.GetInterfacePtr(),//改进的参数
  1823. adOpenStatic,adLockOptimistic,-1);
  1824.   1.3项目OffDemo03在02的基础上把几个变量声明到头文件及添加三个按钮功能及一个方法(简化button1的代码):
  1825. public:
  1826. void show();
  1827. _RecordsetPtr rs;
  1828. void COffDemoDlg::OnButton1() 
  1829. {
  1830. // TODO: Add your control notification handler code here
  1831. _ConnectionPtr conn;
  1832. conn.CreateInstance(__uuidof(Connection));
  1833. conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=csd0910;Data Source=lisongtao"),"",_bstr_t("csd0910"),-1);
  1834. rs.CreateInstance(__uuidof(Recordset));
  1835. _bstr_t sqlobj("select * from mybooks");
  1836. rs->Open((_variant_t)sqlobj,conn.GetInterfacePtr(),adOpenStatic,adLockOptimistic,-1);
  1837.     //显示第一条记录;
  1838. this->show();
  1839. }
  1840. //显示数据,默认为第一条
  1841. void COffDemoDlg::show()
  1842. {
  1843. if(!rs->adEOF && !rs->BOF)
  1844. {
  1845. this->m_isbn=(UINT)(long)(rs->GetCollect("BOOKISNB"));
  1846. this->m_name=(CString)(LPCTSTR)(_bstr_t)(rs->GetCollect("BOOKNAME"));
  1847. this->UpdateData(FALSE);//(更新后)把数据送到文本框
  1848. }
  1849. }
  1850. //查看后一条数据
  1851. void COffDemoDlg::OnButton7() 
  1852. {
  1853. // TODO: Add your control notification handler code here
  1854. if(!rs->adEOF)
  1855. {
  1856. rs->MoveNext();
  1857. show();
  1858. }
  1859. else
  1860. {
  1861. MessageBox("End!!!");
  1862. }
  1863. }
  1864. //查看前一条数据
  1865. void COffDemoDlg::OnButton6() 
  1866. {
  1867. // TODO: Add your control notification handler code here
  1868. if(!rs->BOF)
  1869. {
  1870. rs->MovePrevious();
  1871. show();
  1872. }
  1873. else
  1874. {
  1875. MessageBox("Begin!!!");
  1876. }
  1877. }
  1878. //显示第一条数据
  1879. void COffDemoDlg::OnButton9() 
  1880. {
  1881. // TODO: Add your control notification handler code here
  1882. if(!rs->BOF)
  1883. {
  1884. rs->MoveFirst();
  1885. show();
  1886. }
  1887. else
  1888. {
  1889. MessageBox("Begin!!!");
  1890. }
  1891. }
  1892.   1.4项目OffDemo05增加两个按钮功能:
  1893. //新增记录时先清空文本框
  1894. void COffDemoDlg::OnButton3() 
  1895. {
  1896. // TODO: Add your control notification handler code here
  1897. this->m_isbn=0;
  1898. this->m_name="";
  1899. this->m_author="";
  1900. this->UpdateData(FALSE);//(更新后)把数据送到文本框
  1901. }
  1902. //更新数据库数据
  1903. void COffDemoDlg::OnButton2() 
  1904. {
  1905. // TODO: Add your control notification handler code here
  1906. this->UpdateData(TRUE);
  1907. this->rs->AddNew();
  1908. this->rs->GetFields()->GetItem("BookIsnb")->Value=_variant_t((long)(this->m_isbn));
  1909. this->rs->GetFields()->GetItem("BookName")->Value=_variant_t(this->m_name.AllocSysString());
  1910. this->rs->GetFields()->GetItem("BookIsnb")->Value=_variant_t(this->m_author.AllocSysString());
  1911. this->rs->Update();
  1912. this->rs->UpdateBatch(adAffectAll);
  1913. }
  1914.   1.5项目OffDemo06增加两个按钮功能:
  1915. //删除数据库数据
  1916. void COffDemoDlg::OnButton4() 
  1917. {
  1918. // TODO: Add your control notification handler code here
  1919. this->rs->Delete(adAffectCurrent);
  1920. this->rs->Update();
  1921. this->rs->UpdateBatch(adAffectAll);
  1922. }
  1923. //更改数据
  1924. void COffDemoDlg::OnButton5() 
  1925. {
  1926. // TODO: Add your control notification handler code here
  1927. this->UpdateData(TRUE);
  1928. this->rs->GetFields()->GetItem("BookIsnb")->Value=_variant_t((long)(this->m_isbn));
  1929. this->rs->GetFields()->GetItem("BookName")->Value=_variant_t(this->m_name.AllocSysString());
  1930. this->rs->GetFields()->GetItem("BookAuthor")->Value=_variant_t(this->m_author.AllocSysString());
  1931. this->rs->Update();
  1932. this->rs->UpdateBatch(adAffectAll);
  1933. }
  1934. 2.对话框项目SafeArrayDemo01添加一个按钮(函数与图片保存到数据库有关):
  1935. void CSafeArrayDemoDlg::OnButton1() 
  1936. {
  1937. // TODO: Add your control notification handler code here
  1938. //安全数组定义
  1939. SAFEARRAYBOUND bound[1];
  1940. bound[0].lLbound=0;
  1941. bound[0].cElements=10;
  1942. SAFEARRAY* pArray=::SafeArrayCreate(VT_UI1,1,bound);
  1943. //安全数组赋值;
  1944. BYTE* pCommon=new BYTE[10];//连续的内存
  1945. for(int i=0;i<10;i++)
  1946. {
  1947. pCommon[i]=i;
  1948. }
  1949. for(long j=0;j<10;j++)
  1950. {
  1951. SafeArrayPutElement(pArray,&j,pCommon++);
  1952. }
  1953. //访问安全数组;
  1954. BYTE* pBuffer=NULL;
  1955. SafeArrayAccessData(pArray,(void **)&pBuffer);
  1956. for(int k=0;k<pArray->rgsabound->cElements;k++)
  1957. {
  1958. BYTE bTemp=pBuffer[k];
  1959. }
  1960. SafeArrayUnaccessData(pArray);
  1961. //释放安全数组;
  1962.     SafeArrayDestroy(pArray);
  1963. }
  1964. 3.对话框项目DemoBlobInsert01保存及读取图片的相关数据库操作按钮功能:
  1965. 先初始化环境:
  1966. ::CoInitialize(NULL);//初始化
  1967.   3.1项目DemoBlobInsert01为实现保存功能:
  1968. --->实现图片保存数据库按钮功能:
  1969. void CDemoBlobInsertDlg::OnButton1() 
  1970. {
  1971. // TODO: Add your control notification handler code here
  1972. CString strPath="c:\source.bmp";//图片路径
  1973. _ConnectionPtr conn;//连接智能指针
  1974. conn.CreateInstance(__uuidof(Connection));
  1975. //连接数据库源相关参数
  1976. conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena"),_bstr_t(""),_bstr_t("tiger"),-1);
  1977. _RecordsetPtr rs;//对应查询结果链表
  1978. rs.CreateInstance(__uuidof(Recordset));
  1979. //与前面项目相同的地方(离线数据库操作)
  1980. rs->Open(_variant_t("select * from ocyIMGBooks"),
  1981. conn.GetInterfacePtr(),
  1982. adOpenDynamic,
  1983. adLockPessimistic,
  1984. adCmdText);
  1985. rs->AddNew();//添加一个新节点
  1986. //首先插入非BLOB字段;
  1987. rs->Fields->GetItem(_variant_t("BookISNB"))->Value=_variant_t((long)123);
  1988. rs->Fields->GetItem(_variant_t("BookName"))->Value=_variant_t("adsf");
  1989. rs->Fields->GetItem(_variant_t("BookAuthor"))->Value=_variant_t("adsf");
  1990. //插入BLOB字段;
  1991. int iBufferSize=1024*200;//图片大小
  1992. BYTE* pBuffer=new BYTE[iBufferSize];
  1993. SAFEARRAYBOUND bd[1];
  1994. bd[0].cElements=iBufferSize;
  1995. bd[0].lLbound=0;
  1996. SAFEARRAY* pArray=SafeArrayCreate(VT_UI1,1,bd);
  1997. //打开文件
  1998.  CFile fsource;
  1999.  CFileException ex;
  2000.  fsource.Open(strPath,CFile::modeRead,&ex);
  2001.  int iReaded=0;
  2002.  do 
  2003.  {
  2004. BYTE* pTemp=pBuffer;
  2005. iReaded=fsource.Read(pBuffer,iBufferSize);//读取二进制文件
  2006. for(long i=0;i<iReaded;i++)
  2007. {
  2008. SafeArrayPutElement(pArray,&i,pTemp++);//复制二进制文件
  2009. }
  2010. VARIANT mydata;
  2011. mydata.vt=VT_ARRAY|VT_UI1;
  2012. mydata.parray=pArray;//复制二进制文件
  2013. rs->Fields->GetItem("BookImage")->AppendChunk(mydata);//添加二进制文件
  2014.  } while (iReaded==iBufferSize);
  2015.  rs->Update();
  2016.  rs->Close();
  2017.  conn->Close();
  2018.  MessageBox("ok");
  2019. }
  2020.   3.2项目DemoBlobInsert02为实现读取功能:
  2021. void CDemoBlobInsertDlg::OnButton2() 
  2022. {
  2023. // TODO: Add your control notification handler code here
  2024. CString strPath="c:\source_bak.bmp";
  2025. _ConnectionPtr conn;
  2026. conn.CreateInstance(__uuidof(Connection));
  2027. conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena"),_bstr_t(""),_bstr_t("tiger"),-1);
  2028. _RecordsetPtr rs;
  2029. rs.CreateInstance(__uuidof(Recordset));
  2030. //查询指定数据操作相关
  2031. rs->Open(_variant_t("select * from ocyIMGBooks where Bookisnb=123"),
  2032. conn.GetInterfacePtr(),
  2033. adOpenDynamic,
  2034. adLockPessimistic,
  2035. adCmdText);
  2036. //打开文件
  2037. CFile fTarget;
  2038. CFileException ex;
  2039. fTarget.Open(strPath,CFile::modeCreate|CFile::modeWrite,&ex);
  2040. int iBufferSize=1024*100;
  2041. _variant_t vt;//不能是VARIANT类型
  2042. int iReaded=0;
  2043. //读数据
  2044. if(!rs->adEOF)
  2045. {
  2046. long iAllSize=rs->GetFields()->GetItem("BookImage")->ActualSize;
  2047. int iReadedAll=0;
  2048.   do{
  2049.   BYTE* pBuf=NULL;
  2050.   vt=rs->Fields->GetItem("BookImage")->GetChunk(1024*100);
  2051.   iReaded=vt.parray->rgsabound->cElements;
  2052.   SafeArrayAccessData(vt.parray,(void **)&pBuf);//安全数组指针指向一般指针
  2053.   fTarget.Write(pBuf,iReaded);
  2054.   fTarget.Flush();
  2055.   SafeArrayUnaccessData(vt.parray);//关闭安全数组
  2056. iReadedAll+=iReaded;
  2057.   }while(iReadedAll<iAllSize);
  2058. }
  2059. rs->Close();
  2060. conn->Close();
  2061. fTarget.Close();
  2062. MessageBox("ok!");
  2063. }
  2064. ---03.07---------------------day18---------------------------------
  2065. 1.项目DemoBlobInsert01修改day17中把图片读入数据库出现的一个BUG:
  2066. void CDemoBlobInsertDlg::OnButton1() 
  2067. {
  2068. // TODO: Add your control notification handler code here
  2069. CString strPath="c:\source.bmp";//读取图片路径
  2070. _ConnectionPtr conn;//连接数据库智能指针
  2071. conn.CreateInstance(__uuidof(Connection));//生成连接实例
  2072. //打开的数据源
  2073. conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=abc"),_bstr_t(""),_bstr_t("tiger"),-1);
  2074. _RecordsetPtr rs;//对应查询结果的链表
  2075. rs.CreateInstance(__uuidof(Recordset));//生成查询实例
  2076. //查询字句及打开方式
  2077. rs->Open(_variant_t("select * from MyIMGBooks"),
  2078. conn.GetInterfacePtr(),
  2079. adOpenDynamic,
  2080. adLockPessimistic,
  2081. adCmdText);
  2082. rs->AddNew();
  2083. //首先插入非BLOB字段;
  2084. rs->Fields->GetItem(_variant_t("BookISNB"))->Value=_variant_t((long)123);
  2085. rs->Fields->GetItem(_variant_t("BookName"))->Value=_variant_t("adsf");
  2086. rs->Fields->GetItem(_variant_t("BookAuthor"))->Value=_variant_t("adsf");
  2087. //插入BLOB字段;
  2088. int iBufferSize=1024*200;//一次读取内存200K个字节
  2089. BYTE* pBuffer=new BYTE[iBufferSize];//连续的字节内存空间
  2090. SAFEARRAYBOUND bd[1];//设定安全数组边界
  2091. bd[0].cElements=iBufferSize;//安全数组最大下标200K
  2092. bd[0].lLbound=0;
  2093. //创建字节、1维、指定边界的安全数组
  2094. SAFEARRAY* pArray=SafeArrayCreate(VT_UI1,1,bd);
  2095. //打开文件
  2096.  CFile fsource;
  2097.  CFileException ex;//异常保存
  2098.  fsource.Open(strPath,CFile::modeRead,&ex);
  2099.  int iReaded=0;
  2100.  do 
  2101.  {//获取连续字节内存的首地址
  2102. BYTE* pTemp=pBuffer;
  2103. //以指定大小200K读取图片到连续内存中,iReaded为读到数据的实际大小(最后一次不一定是200K)
  2104. iReaded=fsource.Read(pBuffer,iBufferSize);
  2105. //修改BUG;如果iReaded最后一次不是200K就要出现指定符合iReaded大小边界的安全数组
  2106. if(iReaded!=iBufferSize)
  2107. {
  2108. SafeArrayDestroy(pArray);//清空之前的安全数组
  2109. pArray=NULL;
  2110. SAFEARRAYBOUND bd1[1];
  2111. bd1[0].cElements=iReaded;//指定符合iReaded大小边界的安全数组
  2112. bd1[0].lLbound=0;
  2113. pArray=SafeArrayCreate(VT_UI1,1,bd1);
  2114. }
  2115. for(long i=0;i<iReaded;i++)
  2116. {//把连续内存中的二进制数据复制到安全数组中去
  2117. SafeArrayPutElement(pArray,&i,pTemp++);
  2118. }
  2119. VARIANT mydata;//智能型数据
  2120. mydata.vt=VT_ARRAY|VT_UI1;//数组及字节类型
  2121. mydata.parray=pArray;//获取(保存图片二进制数据)安全数组入口
  2122. //根据属性名索引把mydata中的图片二进制数据上传(追加)到数据库
  2123. rs->Fields->GetItem("BookImage")->AppendChunk(mydata);
  2124.  } while (iReaded==iBufferSize);
  2125. //更新数据库
  2126.  rs->Update();
  2127.  rs->Close();
  2128.  conn->Close();
  2129.  MessageBox("ok");
  2130. }
  2131. 2.项目AddressAdmin做一个包含(连接数据库)包含数据、图片、(各种功能)按钮的简易的人事管理系统:
  2132.   2.1项目AddressAdmin01只做了对话框界面。
  2133.   2.2项目AddressAdmin02~04图片显示按钮功能初级代码:
  2134. 在标准头文件中添加#include <afxdlgs.h>//CFileDialog的头文件
  2135. 在头文件中声明一个方法和一个变量(在构造函数中初始化):
  2136. public:
  2137. HBITMAP ShowImage();
  2138. LPSTR  pBuffer;
  2139. void CAddressAdminDlg::OnButton8() 
  2140. {
  2141. // TODO: Add your control notification handler code here
  2142. CFileDialog dlg(TRUE);//打开一个浏览框(选择图片)
  2143. dlg.DoModal();//弹出对话框有效
  2144. CString strFilePath=dlg.GetPathName();//获取该图片的路径(空则为0)
  2145. if(strFilePath.GetLength()>0) //地址有效的时候
  2146. {
  2147. CFile fsource;
  2148. CFileException fex;
  2149. fsource.Open(strFilePath,CFile::modeRead,&fex);//读取的方式打开
  2150. int iSize=fsource.GetLength();//获取图片大小
  2151. if(this->pBuffer!=NULL)//pBuffer在头文件中已定义并在构造函数中初始化了
  2152. {
  2153. delete this->pBuffer;
  2154. this->pBuffer=NULL;
  2155. }
  2156. this->pBuffer=new CHAR[iSize];//连续的字符内存空间
  2157. fsource.Read(this->pBuffer,iSize);//读到缓冲区
  2158. }
  2159. //显示图片;
  2160. this->ShowImage();
  2161. }
  2162. HBITMAP CAddressAdminDlg::ShowImage()
  2163. {
  2164. LPSTR pTempBuffer=this->pBuffer;//由上面的步骤,pBuffer已获取图片二进制数据
  2165. BITMAPFILEHEADER bf;//要过滤的文件头
  2166. int leng=sizeof(bf);//获取要过滤的文件头的长度
  2167. LPSTR pInfor=pTempBuffer+leng;//指针移动指定的长度即把文件头给过滤掉了
  2168. BITMAPINFOHEADER& pInfHeader=*(LPBITMAPINFOHEADER)(pInfor);//强转成bmp格式类型
  2169. BITMAPINFO&       pInfo     =*(LPBITMAPINFO)(pInfor);//再转
  2170. LPVOID            pRGBData  =(LPVOID)(pInfo.bmiColors);//void类型指针
  2171. CClientDC dc(this);//用于在窗口客户区画图
  2172. HBITMAP hResult=CreateDIBitmap(dc.m_hDC,&pInfHeader,CBM_INIT,pRGBData,&pInfo,DIB_RGB_COLORS);
  2173. return hResult;
  2174. //BITMAPFILEHEADER;  //*.bmp文件头;
  2175. //BITMAPINFOHEADER;  //*.bmp格式的信息头;
  2176. //BITMAPINFO;        //*.bmp格式主体;
  2177. //RGBQUAD            //*.bmp像素格式;
  2178. }
  2179. //在OnPaint()中调用,真正的显示图片到Cstatic中
  2180. void CAddressAdminDlg::show()
  2181. {
  2182. if(this->p_CurrentImag!=NULL)//获取图片信息无误
  2183. {
  2184. CStatic* pStc=(CStatic*)this->GetDlgItem(IDC_STATICimg);
  2185. CPaintDC dc(pStc);
  2186. RECT rt;//定义矩形的左上角坐标和右下角坐标
  2187. pStc->GetClientRect(&rt);
  2188. CDC MemDc;
  2189. //用于在向实际的兼容设备表面发送图象之前在内存中作好准备
  2190. MemDc.CreateCompatibleDC(&dc);//该函数仅用于创建与支持光栅操作的设备上下文
  2191. HBITMAP pTemp=(HBITMAP)MemDc.SelectObject(this->p_CurrentImag);
  2192. dc.BitBlt(0,//指定目标矩形左上角的逻辑横坐标
  2193.                0,//指定目标矩形左上角的逻辑纵坐标
  2194. rt.right,//指定目标矩形和源位图的宽度
  2195. rt.bottom,//指定目标矩形和源位图的高度
  2196. &MemDc,//指向CDC对象的指针,标识待拷贝位图的设备上下文
  2197. 0,//指定源位图左上角的逻辑横坐标
  2198. 0,//指定源位图左上角的逻辑纵坐标
  2199. SRCCOPY);//指定要执行的光栅操作
  2200. MemDc.SelectObject(pTemp);//返回被替代的对象的指针
  2201. }
  2202. }
  2203.   2.3项目AddressAdmin05~06实现按钮update上传数据到数据库功能:
  2204. 在OnInitDialog()中添加 ::CoInitialize(NULL);//数据库环境初始化
  2205. //update上传数据到服务器数据库
  2206. void CAddressAdminDlg::OnButton6() 
  2207. {
  2208. // TODO: Add your control notification handler code here
  2209. this->UpdateData(TRUE);//获取文本框数据
  2210. _ConnectionPtr conn;
  2211. conn.CreateInstance(__uuidof(Connection));
  2212. conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena"),_bstr_t(""),_bstr_t("tiger"),-1);
  2213. _RecordsetPtr rs;
  2214. rs.CreateInstance(__uuidof(Recordset));
  2215. rs->Open(_variant_t("select * from MyAddress_ocy"),conn.GetInterfacePtr(),adOpenDynamic,adLockPessimistic,adCmdText);
  2216. rs->AddNew();//添加一个新节点
  2217. //添加非B数据
  2218. rs->GetFields()->GetItem(_variant_t("addr_name"))->Value=_variant_t(this->m_name.AllocSysString());
  2219. rs->GetFields()->GetItem(_variant_t("addr_sex"))->Value=_variant_t(this->m_sex.AllocSysString());
  2220. rs->GetFields()->GetItem(_variant_t("addr_address"))->Value=_variant_t(this->m_address.AllocSysString());
  2221. rs->GetFields()->GetItem(_variant_t("addr_age"))->Value=_variant_t(this->m_age);
  2222. //写b字段;
  2223. SAFEARRAYBOUND bd[1];
  2224. bd[0].lLbound=0;
  2225. bd[0].cElements=this->iSize;//安全数组大小声明为long类型
  2226. SAFEARRAY* pArray=SafeArrayCreate(VT_UI1,1,bd);//初级安全数组
  2227. char* pTemp=(char*)(this->pBuffer);//指向含有图片数据的缓冲区
  2228. for(long i=0;i<iSize;i++)
  2229. {
  2230. SafeArrayPutElement(pArray,&i,pTemp++);//拷贝给安全数组
  2231. }
  2232. VARIANT abc;
  2233. abc.vt=VT_ARRAY | VT_UI1;
  2234. abc.parray=pArray;
  2235. try{
  2236. FieldPtr fld=rs->Fields->GetItem("addr_Picture");
  2237. fld->AppendChunk(abc);//安全数组的数据添加到服务器
  2238. }
  2239. catch(_com_error ex)
  2240. {
  2241. int i=0;
  2242. i++;
  2243. }
  2244. rs->Update();
  2245. rs->Close();
  2246. conn->Close();
  2247. }
  2248.   2.4项目AddressAdmin07打开对话框时即可看到第一条数据信息:
  2249. 在初始化函数OnInitDialog()中添加可实现该功能:
  2250. //连接数据库,把button6 连接数据库的句子搬到这来
  2251. conn.CreateInstance(__uuidof(Connection));
  2252. conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena"),_bstr_t(""),_bstr_t("tiger"),-1);
  2253. rs.CreateInstance(__uuidof(Recordset));
  2254. rs->Open(_variant_t("select * from MyAddress_ocy"),conn.GetInterfacePtr(),adOpenDynamic,adLockPessimistic,adCmdText);
  2255.     //提取第一条记录;=====>以下在项目AddressAdmin09中该为ShowData()代码用this->ShowData();取代
  2256. if(!rs->adEOF)//判断是否有数据
  2257. {//根据属性名赋值
  2258. _variant_t vtname=rs->Fields->GetItem("addr_name")->Value;
  2259. _variant_t vtage=rs->Fields->GetItem("addr_age")->Value;
  2260. _variant_t vtsex=rs->Fields->GetItem("addr_sex")->Value;
  2261. _variant_t vtaddress=rs->Fields->GetItem("addr_address")->Value;
  2262. //万能型转成所需的内存数据类型
  2263. this->m_age=vtage.lVal;
  2264. this->m_name=CString(vtname.bstrVal);
  2265. this->m_sex=CString(vtsex.bstrVal);
  2266. this->m_address=CString(vtaddress.bstrVal);
  2267. this->UpdateData(FALSE);//上传内存数据到对话框
  2268. this->iSize=rs->Fields->GetItem("addr_picture")->ActualSize;//获取图片大小
  2269. if(this->pBuffer!=NULL)//目的是在下一步前确保>pBuffer为空
  2270. {
  2271. delete this->pBuffer;
  2272. this->pBuffer=NULL;
  2273. }
  2274. this->pBuffer=new CHAR[this->iSize];//开辟和图片大小一致的内存
  2275. //复制图片二进制数据到万能指针中
  2276. _variant_t vtdata=rs->Fields->GetItem("addr_picture")->GetChunk(this->iSize);
  2277. BYTE* pTemp=NULL;
  2278. //万能指针类型转成一般类型
  2279. SafeArrayAccessData(vtdata.parray,(void **)&pTemp);
  2280. //内存复制
  2281. memcpy(this->pBuffer,pTemp,this->iSize);
  2282. //解开安全数组的锁
  2283. SafeArrayUnaccessData(vtdata.parray);
  2284. //显示图片;
  2285. this->p_CurrentImag=this->ShowImage();
  2286. //刷新屏幕;关联静态控件
  2287. CStatic* pDc=(CStatic*)(this->GetDlgItem(IDC_STATICimg));
  2288. pDc->Invalidate();
  2289.   2.5项目AddressAdmin09添加两个按钮功能及数据刷新:
  2290. void CAddressAdminDlg::ShowData()
  2291. {
  2292.     //提取第一条记录;
  2293. if(!rs->adEOF && !rs->BOF)
  2294. {
  2295. _variant_t vtname=rs->Fields->GetItem("addr_name")->Value;
  2296. _variant_t vtage=rs->Fields->GetItem("addr_age")->Value;
  2297. _variant_t vtsex=rs->Fields->GetItem("addr_sex")->Value;
  2298. _variant_t vtaddress=rs->Fields->GetItem("addr_address")->Value;
  2299. this->m_age=vtage.lVal;
  2300. this->m_name=CString(vtname.bstrVal);
  2301. this->m_sex=CString(vtsex.bstrVal);
  2302. this->m_address=CString(vtaddress.bstrVal);
  2303. this->UpdateData(FALSE);
  2304. this->iSize=rs->Fields->GetItem("addr_picture")->ActualSize;
  2305. if(this->pBuffer!=NULL)
  2306. {
  2307. delete this->pBuffer;
  2308. this->pBuffer=NULL;
  2309. }
  2310. this->pBuffer=new CHAR[this->iSize];
  2311. _variant_t vtdata=rs->Fields->GetItem("addr_picture")->GetChunk(this->iSize);
  2312. BYTE* pTemp=NULL;
  2313. SafeArrayAccessData(vtdata.parray,(void **)&pTemp);
  2314. memcpy(this->pBuffer,pTemp,this->iSize);
  2315. SafeArrayUnaccessData(vtdata.parray);
  2316. //显示图片;
  2317. this->p_CurrentImag=this->ShowImage();
  2318. //刷新屏幕;
  2319. CStatic* pDc=(CStatic*)(this->GetDlgItem(IDC_STATICimg));
  2320. pDc->Invalidate();
  2321. this->Invalidate(FALSE);
  2322. }
  2323. }
  2324. //显示下一条数据信息
  2325. void CAddressAdminDlg::OnButton3() 
  2326. {
  2327. // TODO: Add your control notification handler code here
  2328. if(!this->rs->adEOF)
  2329. {
  2330. this->rs->MoveNext();//往下移
  2331. this->ShowData();
  2332. }
  2333. }
  2334. //显示上一条数据信息
  2335. void CAddressAdminDlg::OnButton2() 
  2336. {
  2337. // TODO: Add your control notification handler code here
  2338. if(!this->rs->BOF)
  2339. {
  2340. this->rs->MovePrevious();//往上移
  2341. this->ShowData();
  2342. }
  2343. }
  2344.   2.6项目AddressAdmin10添加删除、更该功能按钮功能:
  2345. //删除数据
  2346. void CAddressAdminDlg::OnButton7() 
  2347. {
  2348. // TODO: Add your control notification handler code here
  2349. if(!this->rs->adEOF && !this->rs->BOF)
  2350. {
  2351. this->rs->Delete(adAffectCurrent);
  2352. this->rs->Update();
  2353. this->rs->MoveNext();
  2354. this->ShowData();
  2355. }
  2356. }
  2357. //更改数据
  2358. void CAddressAdminDlg::OnButton9() 
  2359. {
  2360. // TODO: Add your control notification handler code here
  2361. this->UpdateData();
  2362. rs->GetFields()->GetItem(_variant_t("addr_name"))->Value=_variant_t(this->m_name.AllocSysString());
  2363. rs->GetFields()->GetItem(_variant_t("addr_sex"))->Value=_variant_t(this->m_sex.AllocSysString());
  2364. rs->GetFields()->GetItem(_variant_t("addr_address"))->Value=_variant_t(this->m_address.AllocSysString());
  2365. rs->GetFields()->GetItem(_variant_t("addr_age"))->Value=_variant_t(this->m_age);
  2366. rs->Update();
  2367. }