com笔记总结.txt
上传用户:weisheen
上传日期:2022-07-09
资源大小:19390k
文件大小:82k
源码类别:
ActiveX/DCOM/ATL
开发平台:
Visual C++
- 1. 1.1 OOP: 类, 对象, 继承,重载,重写,引用;
- OOC:组件,组件实例(设计状态/运用状态), 引用;
- 1.2 OOP{cpp/java/c#/vb.net/...}
- OOC{COM/EJB/CORBA}(Component Object Model) COM+(提供组件运行平台和企业级服务)
- /DCOM(分布式的COM)
- 1.3 组件的特征(OOC):
- 1. 二进制封装;
- 2. BITS原则: (Bit Service)原则;
- 2.1 软件实体通过接口对外提供服务;
- 2.2 软件接口通过接口依赖其它的软件实体;
- 3. 组件需要部署和安装;独立编译/安装/部署,独立的软件实体;
- 1.4 组件接口定义:
- 1.4.1 刻画组件的功能;完整刻画;
- 1.4.2 接口的定义语言:c/cpp;java/c#/vb.net;不满足通用性
- 1.4.3 如果采用 MIDL, 只能定义接口;
- 1.5 IDL语言基础:
- import, 调用其它接口定义文件;
- interface, 定义接口;
- coclass, 定义接口实现者,COM类,或COM构件;
- library, 组件库;对应一个具体组件;
- MFC: CObject;
- COM: IUnknown;//提供组件功能查询;查的是接口;和 new ====>基类级别
- 组件(library)/构件(coclass)/接口(interface);组件实体;
- 1.6 COM组件实体的定义方法;
- 1.1 GUID, 512位随机数据;GUIDGen.exe;
- [头:uuid,指定名字;
- helpstring,说明性信息;pointer_default定义借口指针的一种模式;
- version,版本;
- default, ]
- 名字
- {
- }
- 1.7 通过IDL,编写add, sub;使用midl.exe编译成C;
- 1.8 COM数据类型列表;
- HRESULT,32整数;代表执行的结果;0表示正确,非零表示错误;
- BSTR, 宽字符串;使用Unicode码;(一个字符,两个字节)
- 前两个字节,对应字符串中字符个数,后面依次为UNICDODE码;
- "hello", [h][e][l][l][o][ ]
- [0][5][0][h][0][e][0][l][0][l][0][o]
- VARIANT 智能型数据类型;(万能型)
- vt属性,表示当前变量所用作的类型;
- 值,根据类型不同在不同属性中;
- 1.9 ATL库中的方法宏:
- 1.9.1 方法声明宏:STDMETHOD;
- 1.9.2 方法实现宏:STDMETHODIMP;
- 1.10 com 安装和卸载 regsvr32.exe *.dll; regsvr32.exe -u *.dll
- 2. COM接口定义技术;
- 2.1 Custom,自定义接口; 必须使用.idl文件;
- 2.1.1 IUnknown接口;
- 2.1.1.1 管理组件的生命周期;
- 2.1.1.2 管理组件的功能列表;
- 2.1.2 IUnknonw的实现(CComObjectRootEx);
- 2.1.2.1 和生命周期相关(add/release)
- DECLARE_PROTECT_FINAL_CONSTRUCT;
- CComObjectRootEx<线程类型>
- 2.1.2.2 接口映射表;
- 将接口类型添加到接口映射表中,否则QueryInterface找不到;
- 2.1.2.3 COM资源使用原则“谁使用谁释放”;
- 3. 练习,使用WebBrowser组件熟悉COM的基本概念和特征。
- 3.1 IHTML****;
- 3.2 IWebBrowser;
- 3.3 IHTMLDocument; IHTMLDocument2,IHTMLDocument3,IHTMLDocument4
- 3.4 IHTMLElement;
- 3.5 IHTMLImgElement
- 4. COM结构;
- 4.1 COM层次结构: 组件中包含多个构件,构件实现多个接口;
- 4.2 接口映射表(同一个构件上的接口进行映射);
- 4.3 构件映射表(同一个组件上构件的映射);
- 4.4 ATL应用程序实体; CComModule _Module;
- 4.3 ATL在DllMain方法中,组装COM组件;
- MFC WinMain CWinApp theApp 多个窗口 消息映射
- ATL DllMain CComModule _Module 多个构件 接口映射 构件映射
- MFC initialInstance
- ATL _Module.init;
- DllCanUnloadNow,判断组件是否能够卸载;
- DllGetClassObject,被CoCreateInstance方法调用,生成构件;_Module.GetClassObject
- DllRegisterServer,将组件的ID和名称的关联信息写入注册表;
- DllUnregisterServer,将组件的ID和名称关联信息删除;
- 5. COM数据类型列表;
- HRESULT,32整数;代表执行的结果;0表示正确,非零表示错误;
- BSTR, 宽字符串;使用Unicode码;(一个字符,两个字节)
- 前两个字节,对应字符串中字符个数,后面依次为UNICDODE码;
- "hello", [h][e][l][l][o][ ]
- [0][5][0][h][0][e][0][l][0][l][0][o]
- VARIANT 智能型数据类型;(万能型)
- vt属性,表示当前变量所用作的类型;
- 值,根据类型不同在不同属性中;
- 6. 自动化接口; 不需要IDL文件;//有些麻烦
- 1. 自动化接口,主要支持vb,javascript, vbscript, actionscript;调用时不需要头文件;
- 2. 自动化接口是对自定义接口的扩展, 自动化接口也从IUnknown继承;
- 3. 自动化接口从IDispatch继承;
- 4. 不使用头文件调用IDispatch接口;
- HRESULT Invoke(
- DISPID dispIdMember, //调用方法的id;
- REFIID riid, LCID lcid, //保留字,IID_NULL;
- WORD wFlags, //Local_system_default;
- DISPPARAMS FAR *pDispParams, //
- VARIANT FAR *pVarResult, //
- EXCEPINFO FAR *pExcepInfo,
- unsigned int FAR *puArgErr);
- 5. CLSIDFromProgID,根据组建名字查找组建CLSID;
- 6. GetIDsOfNames;
- 7. DISPPARAMS;
- 7. COM中的结构,数组,智能指针
- 7.1 BSTR int VARIANT,基本数据类型
- 7.2 自定义接口/结构;
- 7.3 DTO(只有成员变量,没有方法)
- 7.4 CoTaskMemAlloc/CoTaskMemFree; SysAlloString/SysFreeString;
- 7.5 从COM中获取结构或结构数组;
- 7.6 向COM中传递结构或结构数组;
- 7.7 COM中的属性;
- 7.8 接口智能指针;CComPtr/CComQIPtr;
- 7.9 BSTR智能指针;_bstr_t(<comdef.h>)/CComBSTR(<atlbase.h>);
- 7.10 VARIATN智能指针;_variant_t /CComVariant ;
- 7.11 智能指针:1)是个类;2)管理一个指针;3)自动释放(析构)方法中释放;
- 7.12 智能指针分类(工具类Utility Class)
- 7.12.1 COM接口类 CComPtr/CComQIPtr;
- 7.12.2 字符串指针 CComBSTR/_bstr_t;
- 7.12.2 万能型变量 CComVariant/_variant_t;
- 8. COM回调接口( COM组件的回调和事件);
- 8.1 自定义回调接口;
- 8.1.1 回调的概念;
- 8.1.2 回调三要素:1,回调接口定义;2,私有成员变量;3,公共的设置方法;
- 8.2 自定义COM回调接口(IUnknown)
- 8.2.1 IUnknonw类型的回调接口;
- 8.2.2 实现IUnknown接口;
- 8.3 自定义COM回调接口(IDispatch)
- 8.3.1 IDispatch类型的回调接口;
- 8.3.2 实现IDispatch接口;
- 8.4 COM事件的定义和处理
- 8.4.1 事件(类型,声明,触发,处理)
- 8.4.2 事件类型:事件接口(一种特殊的回调接口),ATL框架提供支持
- 8.4.2.1 dispinterface/attribute/method;
- 8.4.3 事件可以具备多个事件处理代码;
- 3. COM组件的实现技术;
- 3.1 接口映射;
- 3.2 多接口实现;
- 4. COM组件的回调和事件;//COM的主题
- 5. COM组件的合成与集合;
- 6. COM组件的客户端调用技术;
- ---02.22----------------------day09---------------------------------
- COM组件:
- 1.项目FirstDemo(组件类),创建组件:
- 右键-->New ATL Object-->Simple Object-->(Interface)Custom-->右键-->add method------>
- ---hello
- ---([in] BSTR name,[out] BSTR* result); //in表输入,out表输出
- //import:调用其他接口的文件
- //library:组件库
- //coclass:定义接口实现者
- //interface:定义接口
- //uuid:指定名字(微软为了防止名字重复,设定为512位的随机数)
- //helpstring说明性信息
- //pointer_default定义接口指针的模式
- //version版本
- -->再创建一个接口时要手工加入(如上操作的话,都会设定当前接口为默认接口,有些麻烦)
- -->新的接口的uuid可在目录VSCommonTools中的GUIDGEN.EXE中复制一个过来
- -->在实现文件的头文件中的类要继承该接口,在BEGIN_COM_MAP(CMyAbc)中添加接口映射,声明接口类函数(在函数前要加上STDMETHOD),然后在实现文件中重写继承自接口类的函数(在函数前要加上STDMETHODIMP)
- -----------------其中FirstDemo.idl及Debug中的FirstDemo.dll==>COM的安装:regsvr32.exe *.dll(写入注册表)-->卸载:regsvr32.exe -u *.dll(删除注册表信息)
- 2.项目intertest01(组件类)中的myaddinter.idl-->
- (在命令提示窗口中)在文件目录下输入-- cl.exe -->midl.exe myaddinter.idl
- 生成5个文件:myaddinter.h、myaddinter_i.c有用,是必须的
- 3.项目clientDemo(窗体类),导入两个由FirstDemo.idl编译后生成的文件:FirstDemo.h、FirstDemo_i.c--->在clientDemo中必须引入以上两个文件做头文件,即可直接使用(不用重写,直接引用组件提供的功能,但是要声明引用)
- clientDemo03用IUnknonw的QueryInterface来定位要找的接口实现的入口名字。
- ::CoInitialize(NULL);//COM的初始化函数
- ::CoUninitialize();//释放内存
- 4.项目IUnknownDemo包含组件和测试类,组件编译后,测试类通过头文件引用IUnknownDemo.h和IUnknownDemo_i.c;
- ::SysAllocString
- str.AllocSysString()
- ---02.23----------------------day10---------------------------------
- 1.项目demoIe使用WebBrowser组件熟悉COM的基本概念和特征:
- 先建一个MFC项目,然后在窗体中添加WEB控件-->右键->向导->Member Variables中绑定IDC_EXPLORER1为CWebBrowser2(有提示的),然后项目中自动生成 CWebBrowser2类;
- 在Button1中this->m_mybrowser.Navigate("C:\danei.htm",NULL,NULL,NULL,NULL);表按照指定路径打开网页
- 在Button2中,定义IHTMLDocument2(要加头文件mshtml.h)-->表与文本相关,
- --pDisp=this->m_mybrowser.GetDocument();//获取文本信息
- --pDisp->QueryInterface(IID_IHTMLDocument2,(void **)&pDoc);//查询匹配接口
- --IHTMLElementCollection* allImage=NULL;//采集信息放置的地方
- --pDoc->get_images(&allImage);//获取图片
- --allImage->get_length(&iCount);//获取图片数量
- 之后的循环用于循环输出图片路径
- 2.项目demoiechangeimage与项目demoIe相比,只修改循环为改变所有图片
- 其中用到CString strhtml="c:\source.bmp"、strhtml.AllocSysString();
- --AllocSysString()的作用是把CString型转化成BSTR型
- 3.项目demoiechangeLink与项目demoIe相比,添加了一个test.html超链接,且只修改循环为禁用所有超链接:
- --CString strhtml="#";//这个属性的链接是被封掉的即无法打开
- --CString attName="href";
- --VARIANT var;
- --var.vt=VT_BSTR;
- --var.bstrVal=strhtml.AllocSysString();//字符串转BSTR类型,组件类的有些函数参数是BSTR类型
- --mylink->setAttribute(attName.AllocSysString(),var,0);
- setAttribute为设置属性
- 4.项目TestCom1通过手工添加代码来熟悉COM的过程:
- 4.1 TestCom1_01:右键-->new class-->Generic Class(一般类)-->在.idl文件中添加相应接口
- 4.2 TestCom1_02:给接口添加函数;
- 4.3 TestCom1_03:在类头文件中构造组件接口映射表且要组件继承:
- DECLARE_PROTECT_FINAL_CONSTRUCT();
- BEGIN_COM_MAP(CMyTools)
- COM_INTERFACE_ENTRY(IMyAdd)
- END_COM_MAP()
- STDMETHOD(add)(int a, int b, int* c);
- class ATL_NO_VTABLE CMyTools :
- public CComObjectRootEx<CComSingleThreadModel>,
- public CComCoClass<CMyTools,&CLSID_MyTools>,
- public IMyAdd
- 在类的实现文件中导入组件接口实现函数:
- STDMETHODIMP CMyTools::add(int a, int b, int* c)
- {
- *c=a+b;
- return S_OK;
- }
- 4.4 TestCom1_04:在文件夹中添加registry.bin文件,并在资源文件resource.h中加入
- #define IDR_REGISTRY1 205(随意与其他宏不冲突的数字)-->
- 在MyToohs.h中添加#include "resource.h"-->编译后在resources项目分类组中有REGISTRY文件夹自动生成
- -->如果宏不出问题的话在Resource files中可看到registry.bin自动导入
- -->然后在registry.bin中输入文本:
- HKCR
- {
- FirstDemo.MyAbc.1 = s 'MyAbc Class'
- {
- CLSID = s '{AAC11C54-F25F-40fe-A4AC-F2829CE37FD7}'//接口ID
- }
- FirstDemo.MyAbc = s 'MyAbc Class'
- {
- CLSID = s '{AAC11C54-F25F-40fe-A4AC-F2829CE37FD7}'//接口ID
- CurVer = s 'FirstDemo.MyAbc.1'
- }
- NoRemove CLSID
- {
- ForceRemove {AAC11C54-F25F-40fe-A4AC-F2829CE37FD7} = s 'MyAbc Class'
- {
- ProgID = s 'FirstDemo.MyAbc.1'
- VersionIndependentProgID = s 'FirstDemo.MyAbc'
- InprocServer32 = s '%MODULE%'
- {
- val ThreadingModel = s 'Apartment'
- }
- 'TypeLib' = s '{E565170F-79D7-4EFB-9402-4D877139D459}'//组件ID
- }
- }
- }
- 这些内容将完全导入registry.rgs中(自动生成的组件接口文件都有.rgs文件,但是看不到.bin文件.....)
- ---02.26----------------------day11---------------------------------
- 1.项目autoDemo实现自动化接口(与):
- 1.1项目autoDemo01:右键-->New ATL Object-->Simple Object-->(Interface)Dual-->(name:)MyAbc
- //(Interface)Dual为自动化接口实现的关键
- 然后新建一个test项目添加一个按钮用于测试:
- //添加相关头文件
- #include "../autoDemo.h"
- #include "../autoDemo_i.c"
- void CTestDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- IDispatch* pDisp=NULL;
- IMyAbc* pTools=NULL;
- ::CoCreateInstance(CLSID_MyAbc,NULL,CLSCTX_INPROC_SERVER,IID_IDispatch,(void **)&pDisp);
- pDisp->QueryInterface(IID_IMyAbc,(void **)&pTools);
- int iResult=0;
- pDisp->Release();
- pTools->add(12,13,&iResult);
- CString str1;
- str1.Format("%d",iResult);
- MessageBox(str1);
- pTools->Release();
- ::CoUninitialize();
- }
- 1.2项目autoDemo02:再新建一个AutoTest项目添加一个按钮用于测试:
- //不需要引入头文件(与上面按钮代码不在同一个文件内)
- void CAutoTestDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- CString str="AutoDemo.MyAbc";
- CLSID mycomid;//CLSID为_i.c文件中的实现宏
- ::CLSIDFromProgID(L"AutoDemo.MyAbc",&mycomid);//名字匹配,到注册表去找
- IDispatch* pDisp=NULL;
- ::CoCreateInstance(mycomid,NULL,CLSCTX_INPROC_SERVER,IID_IDispatch,(void **)&pDisp);
- DISPID addid;
- BSTR funnames[1];
- funnames[0]=::SysAllocString(L"add");//函数的名字
- pDisp->GetIDsOfNames(IID_NULL,funnames,1,LOCALE_SYSTEM_DEFAULT,&addid);
- ::CoUninitialize();
- }
- 1.3项目autoDemo03为项目autoDemo02的完善,--->比引入头文件麻烦
- 2.项目StructDemo是对一个结构体操作(之前的都是对单独的数据,意义不大):
- 2.1项目StructDemo01先建一个自动接口类(老师在建是选了support MFC):MyStruct,在该.idl文件中添加一个结构体---//因为接口的函数想参数需要
- typedef struct StPerson
- {
- BSTR name;
- UINT age;
- BSTR sex;
- }StPerson;
- --然后右键-->add method-->GetPersonById--([in] UINT id,[out] StPerson** Result)--
- -->并在接口实现文件中添加一个函数------
- //这样赋值- -!
- STDMETHODIMP CMyStruct::GetPersonById(UINT id,StPerson** Result)
- {
- StPerson* p=(StPerson*)::CoTaskMemAlloc(sizeof(StPerson));//申请空间
- p->age=23;
- p->name=::SysAllocString(L"zhangsan");//name为BSTR类型
- p->sex=::SysAllocString(L"male");
- *Result=p;
- return S_OK;
- }
- --->然后新建一个MFC项目test用于读取数据:
- #include "../StructDemo.h"
- #include "../StructDemo_i.c"
- void CTestDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- IMyStruct* pTools=NULL;//接口指针
- ::CoCreateInstance(CLSID_MyStruct,NULL,CLSCTX_INPROC_SERVER,IID_IMyStruct,(void **)&pTools);
- StPerson* pPer=NULL;//结构体指针
- pTools->GetPersonById(1,&pPer);
- CString strName(pPer->name);
- ::SysFreeString(pPer->name);
- UINT uage(pPer->age);
- CString strSex(pPer->sex);
- ::SysFreeString(pPer->sex);
- ::CoTaskMemFree(pPer);//释放结构体指针
- CString str1;
- str1.Format("%s: %d %s",strName,uage,strSex);
- MessageBox(str1);
- ::CoUninitialize();
- }
- 2.2项目StructDemo02再在接口文件中添加一个功能函数:
- STDMETHODIMP CMyStruct::GetAllPerson(UINT* number,StPerson** Result)
- {
- StPerson* p=(StPerson*)::CoTaskMemAlloc(2*sizeof(StPerson));//申请2个空间
- ZeroMemory(p,2*sizeof(StPerson));//初始化数组(连续的)空间
- p->age=23;
- p->name=::SysAllocString(L"芙蓉");
- p->sex=::SysAllocString(L"女");
- (p+1)->age=23;
- (p+1)->name=::SysAllocString(L"李松涛");
- (p+1)->sex=::SysAllocString(L"男");
- *Result=p;
- *number=2;
- return S_OK;
- }
- --->在项目test中添加一个按钮实现输出功能:
- //输出多个结构体数据
- void CTestDlg::OnButton2()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- IMyStruct* pTools=NULL;
- ::CoCreateInstance(CLSID_MyStruct,NULL,CLSCTX_INPROC_SERVER,IID_IMyStruct,(void **)&pTools);
- StPerson* pPer=NULL;
- UINT iSize=0;
- pTools->GetAllPerson(&iSize,&pPer);
- for(int i=0;i<iSize;i++)
- {
- CString strName((pPer+i)->name);
- ::SysFreeString((pPer+i)->name);
- UINT uage((pPer+i)->age);
- CString strSex((pPer+i)->sex);
- ::SysFreeString((pPer+i)->sex);
- CString str1;
- str1.Format("%s: %d %s",strName,uage,strSex);
- MessageBox(str1);
- }
- ::CoTaskMemFree(pPer);
- ::CoUninitialize();
- }
- 2.3项目StructDemo03再在接口文件中添加一个功能函数:
- STDMETHODIMP CMyStruct::SavePerson(UINT number,StPerson* Result, UINT* pResult)
- {
- int iResult=0;
- for(int i=0;i<number;i++)
- {
- iResult+=(Result+i)->age;
- }
- *pResult=iResult;
- return S_OK;
- }
- --->在项目test中添加一个按钮实现输出功能:(用处不大)
- void CTestDlg::OnButton3()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- IMyStruct* pTools=NULL;//用来引入接口的函数
- ::CoCreateInstance(CLSID_MyStruct,NULL,CLSCTX_INPROC_SERVER,IID_IMyStruct,(void **)&pTools);
- StPerson* Ref=new StPerson[2];
- Ref[0].age=12;
- Ref[1].age=13;
- UINT iResult=0;
- pTools->SavePerson(2,Ref,&iResult);
- CString str1;
- str1.Format("%d",iResult);
- MessageBox(str1);
- 2.4项目StructDemo04给接口文件添加属性(函数):右键(接口)-->Add property
- -->属性类型:BSTR ---属性名:UID ---参数:(留空)-->先声明个私有成员BSTR m_uid;-->然后在实现文件中添加:
- TDMETHODIMP CMyStruct::get_UID(BSTR *pVal)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *pVal=::SysAllocString(this->m_uid);
- return S_OK;
- }
- STDMETHODIMP CMyStruct::put_UID(BSTR newVal)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- this->m_uid=::SysAllocString(newVal);
- ::SysFreeString(newVal);
- return S_OK;
- }
- --->在项目test中添加一个按钮实现输出功能:
- void CTestDlg::OnButton5()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- IMyStruct* pTools=NULL;
- ::CoCreateInstance(CLSID_MyStruct,NULL,CLSCTX_INPROC_SERVER,IID_IMyStruct,(void **)&pTools);
- CString str("zhangsan");
- pTools->put_UID(str.AllocSysString());
- BSTR bt;
- pTools->get_UID(&bt);
- CString strName(bt);//__
- ::SysFreeString(bt);
- MessageBox(strName);//__
- }
- 3.项目SmartPtrDemo01为智能指针的用法:
- 先建一个自动接口类(老师在建是选了support MFC):MyAbc;再在接口文件中添加一个功能函数:
- STDMETHODIMP CMyAbc::Hello(BSTR name, BSTR *bstrResult)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- CString strTemp(name);
- ::SysFreeString(name);
- strTemp="Hello: "+strTemp;
- *bstrResult=strTemp.AllocSysString();
- return S_OK;
- }
- --->在项目test中添加两个按钮实现输出功能:
- --按钮一为一般做法:
- #include "../SmartPtrDemo.h"
- #include "../SmartPtrDemo_i.c"
- void CTestDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- IMyAbc* pTools=NULL;
- ::CoCreateInstance(CLSID_MyAbc,NULL,CLSCTX_INPROC_SERVER,IID_IMyAbc,(void **)&pTools);
- BSTR bResult;
- CString str("zhangsan");
- pTools->Hello(str.AllocSysString(),&bResult);
- CString strTemp(bResult);
- MessageBox(strTemp);
- pTools->Release();
- ::CoUninitialize();
- }
- --按钮二为引入智能指针做法:
- #include <atlbase.h>//智能指针类的头文件
- void CTestDlg::OnButton2()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- CComPtr<IMyAbc> mytools;//智能指针
- mytools.CoCreateInstance(CLSID_MyAbc);//. 表示用父类的函数
- BSTR bResult;
- CString str("zhangsan");
- mytools->Hello(str.AllocSysString(),&bResult);
- CString strTemp(bResult);
- MessageBox(strTemp);
- // ::CoUninitialize(); //与智能指针的析构函数冲突,即智能指针已经调用析构函数释放了指针,再释放就出问题了
- }
- ---02.27----------------------day12---------------------------------
- 1.项目 DemoBstr为熟悉智能指针:(项目本身的意义不大)
- 1.1项目DemoBstr01 右键-->New ATL Object-->Simple Object-->(Interface)Dual-->(name:)MyBstr-->
- 添加两个私有成员变量BSTR m_uid;BSTR m_pwd;并初始化-->然后右键-->add method-->Authen--[in] BSTR name, [in] BSTR pwd, [out] BSTR* Result)---->并在接口实现文件中添加一个函数------
- STDMETHODIMP CMyBstr::Authen(BSTR name, BSTR pwd, BSTR *Result)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- if(this->m_pwd!=NULL)
- {
- ::SysFreeString(this->m_pwd);
- this->m_pwd=NULL;
- }
- this->m_pwd=::SysAllocString(pwd);
- ::SysFreeString(pwd);
- if(this->m_uid!=NULL)
- {
- ::SysFreeString(this->m_uid);
- this->m_uid=NULL;
- }
- this->m_uid=::SysAllocString(name);
- ::SysFreeString(name);
- *Result=::SysAllocString(L"OK");
- return S_OK;
- }
- --->然后新建一个MFC项目test并添加一个按钮功能用于读取数据:
- //引入头文件
- #include "../DemoBstr.h"
- #include "../DemoBstr_i.c"
- #include <comdef.h>//_bstr_t类型智能指针相关
- #include <atlbase.h>//智能指针相关
- void CTestDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- _bstr_t name("zhangsan");
- _bstr_t pwd("abc");
- BSTR result;
- CComPtr<IMyBstr> mytools;
- mytools.CoCreateInstance(CLSID_MyBstr);
- mytools->Authen(name,pwd,&result);//自定义接口实现函数
- ::SysFreeString(result);
- }
- 1.2项目DemoBstr02:在项目test上添加第二个按钮功能用于读取数据:
- (只比DemoBstr01多了两句:CString strTemp=(CString)result;MessageBox(strTemp);)
- void CTestDlg::OnButton2()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- CComBSTR name("zhangsan");
- CComBSTR pwd("list");
- CComBSTR result;
- CComPtr<IMyBstr> mytools;//智能指针
- mytools.CoCreateInstance(CLSID_MyBstr);
- mytools->Authen(name,pwd,&result);//自定义接口实现函数
- //result为从接口实现函数Authen()返回的结果
- CString strTemp=(CString)result;//CString strTemp(bResult);
- MessageBox(strTemp);
- }
- 2.项目DemoVariant为熟悉Variant智能指针(CComVariant)(Button3)功能:
- 2.1项目DemoVariant01在接口实现文件中添加一个函数------
- STDMETHODIMP CMyVariant::add(VARIANT a, VARIANT b, VARIANT *c)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- c->vt=VT_I4;
- c->lVal=a.lVal+b.lVal;
- return S_OK;
- }
- 在项目test上添加三个按钮功能:
- #include "../DemoVariant.h"
- #include "../DemoVariant_i.c"
- #include <atlbase.h>
- #include <comdef.h>
- void CTestDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- CoInitialize(NULL);
- CComPtr<IMyVariant> mytools;
- mytools.CoCreateInstance(CLSID_MyVariant);//生成构件
- VARIANT A,B;
- A.vt=VT_I4;
- A.lVal=12;
- B.vt=VT_I4;
- B.lVal=13;
- VARIANT c;
- mytools->add(A,B,&c);
- CString str;
- str.Format("没有强制类型转换:%d",c.lVal);
- MessageBox(str);
- }
- void CTestDlg::OnButton2()
- {
- // TODO: Add your control notification handler code here
- CoInitialize(NULL);
- CComPtr<IMyVariant> mytools;
- mytools.CoCreateInstance(CLSID_MyVariant);
- long a=12;
- long b=13;
- _variant_t vt(a);
- _variant_t vt1(b);
- _variant_t result;
- mytools->add(vt,vt1,&result);
- long c1=(long)result;//强制类型转换使智能指针具体化
- CString str;
- str.Format("强制类型转换后:%d",c1);
- MessageBox(str);
- }
- void CTestDlg::OnButton3()
- {
- // TODO: Add your control notification handler code here
- CoInitialize(NULL);
- CComPtr<IMyVariant> mytools;
- mytools.CoCreateInstance(CLSID_MyVariant);
- long a=12;
- long b=13;
- CComVariant vt(a);//CComVariant的方法比_variant_t的多
- CComVariant vt1(b);
- CComVariant result;
- mytools->add(vt,vt1,&result);
- CString str;
- str.Format("用CComVariant来定义后:%d",result.lVal);
- MessageBox(str);
- }
- 3.项目ComCallBack回调接口的实现:
- 3.1项目ComCallBack01:右键-->New ATL Object-->Simple Object-->(Interface)Dual-->(name:)MyAbc
- -->然后再添加一个新的接口ILogs,并在ILogs中添加接口方法[helpstring("string")] HRESULT WriteLog([in] BSTR message);-->(老师手工)在MyAbc类中添加一个ILogs* pTools;并初始化//声明回调接口变量;
- 及两个接口函数:------
- //设置属性
- STDMETHODIMP CMyAbc::SetLog(ILogs* ptools)
- {
- this->pTools=ptools;
- return S_OK;
- }
- STDMETHODIMP CMyAbc::add(int a, int b,int* c)
- {
- *c=a+b;
- CComBSTR bstr("this result is:");
- char strTemp[500];
- sprintf(strTemp,"%d",c);
- bstr.Append(strTemp);
- if(this->pTools!=NULL)//回调要点,条件返回
- {
- this->pTools->WriteLog(bstr);//另一个接口的实现函数
- }
- else
- *c=0;
- return S_OK;
- }
- 3.2项目ComCallBack02在项目1的基础上添加项目test,并在test 中添加一个继承接口ILogs的普通类MyLog(与接口ILogs关联),在其头文件中声明STDMETHOD(WriteLog)(BSTR message);//STDMETHOD是虚函数的宏
- ------(#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method)-------
- 然后在实现文件中重载该虚函数:(其功能为把信息保存到指定(日志)文件中)
- STDMETHODIMP MyLog::WriteLog(BSTR message)
- {
- CFile f;
- CFileException ex;
- f.Open("./log.txt",CFile::modeCreate| CFile::modeReadWrite,&ex);
- CString str(message);
- f.Write(str.GetBuffer(100),str.GetLength());
- ::SysFreeString(message);
- f.Close();
- return S_OK;
- }
- -->然后添加一个按钮调用接口:
- #include "../ComCallBack.h"
- #include "../ComCallBack_i.c"
- #include <atlbase.h>
- #include "MyLog.h"
- void CTestDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- //装配调用代码;
- ::CoInitialize(NULL);
- CComPtr<IMyAbc> mytools;
- mytools.CoCreateInstance(CLSID_MyAbc);
- ILogs* pLog=new MyLog();
- mytools->SetLog(pLog);//接口注入语句;没有这个句子就无法满足回调的条件
- int iResult=0; //IoC
- mytools->add(12,13,&iResult);
- if(iResult)
- MessageBox("信息保存成功!");
- else
- MessageBox("没有信息要保存!");
- }
- 4.项目DemoIUnknown接口改为继承IUnknown(继承IUnknown更符合COM规范):
- 4.1项目DemoIUnknown01:右键-->New ATL Object-->Simple Object-->(Interface)Dual-->(name:)MyAbc
- -->然后再添加一个新的继承自IUnknown的接口ILog,然后分别添加函数writeLog()、SetLog()、add()---
- [
- object,
- uuid(BA4816E3-7295-4189-B7B5-274676745821),
- helpstring("IMyAbc Interface"),
- pointer_default(unique)
- ]
- interface ILog : IUnknown//继承IUnknown更符合COM规范
- {
- [helpstring("asdfdasf")] HRESULT writeLog([in] BSTR message);//////////
- };
- [
- object,
- uuid(BA4816E3-7295-4189-B7B5-274676745820),
- dual,
- helpstring("IMyAbc Interface"),
- pointer_default(unique)
- ]
- interface IMyAbc : IDispatch
- {
- [id(1), helpstring("method SetLog")] HRESULT SetLog([in] IUnknown* pTools);////
- [id(2), helpstring("method add")] HRESULT add([in] int a, [in] int b, [out] int* c);////
- };
- 4.2项目DemoIUnknown02再新建一个test类并新建一个继承ILog的普通类MyLog,并在其头文件中
- STDMETHOD(writeLog)( BSTR message);//接口自定义的虚函数
- //重载3个IUnknown的虚函数,原型为
- // virtual HRESULT STDMETHODCALLTYPE QueryInterface(
- // /* [in] */ REFIID riid,
- // /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) = 0;
- // virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;
- // virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
- //相关的宏
- //#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method
- //#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method
- STDMETHOD(QueryInterface)(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject);
- STDMETHOD_(ULONG,AddRef)(void);
- STDMETHOD_(ULONG,Release)(void);
- private:
- ULONG ilisongtao;//与AddRef、Release函数相关,要初始化
- --->然后在实现文件中重载:
- STDMETHODIMP MyLog::writeLog( BSTR message)
- {
- //
- return S_OK;
- }
- STDMETHODIMP MyLog::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject)
- {
- if(riid==IID_ILog)
- {
- *ppvObject=(ILog*)this;
- this->AddRef();
- return S_OK;
- }
- else if(riid==IID_IUnknown)
- {
- *ppvObject=(IUnknown*)this;
- this->AddRef();
- return S_OK;
- }
- else
- {
- *ppvObject=NULL;
- return S_FALSE;
- }
- }
- STDMETHODIMP_(ULONG) MyLog::AddRef()
- {
- return this->ilisongtao++;
- }
- STDMETHODIMP_(ULONG) MyLog::Release()
- {
- this->ilisongtao--;
- if(this->ilisongtao==0)
- {
- delete this;
- }
- return this->ilisongtao;
- }
- 4.3
- 5.项目demoActivex建一个窗体COM组件:右键-->New ATL Object-->(controls)Composite Control-->(name:)MyPwd-----------然后可看见一个可编译的窗体文本--->添加控件(对一个按钮操作)
- -->双击按钮,弹出一个事件触发框,把按钮与点击事件绑定,然后双击该点击事件函数就会进入实现函数:
- LRESULT OnClickedButton1(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
- {
- // TODO : Add Code for control notification handler.
- AfxMessageBox("Hello");
- return 0;
- }
- };
- 在文件夹中可看见MyPwd.htm文件,点击后可看见该控件的样式==>COM可被浏览器调用、还有java、.Net....
- 编译后就写进了注册表变成一个MyPwd Class控件---------
- 6.项目testPwd建一个单文档Dlg-->右键(窗体)--->Insert ActiveX Control--->找到MyPwd Class
- --->添加后窗体中的该控件就是项目demoActivex导入的控件
- ---02.28----------------------day13---------------------------------
- 1.(通用性强)项目DispCallBack通过IDisPatch接口实现回调接口:
- 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函数:
- [
- object,
- uuid(8BF1F3AA-6C46-4042-86EF-781E17040E08),
- dual,
- helpstring("ILog Interface"),
- pointer_default(unique)
- ]
- interface ILog : IDispatch
- {
- [id(1), helpstring("method WriteLog")] HRESULT WriteLog([in] BSTR message);
- };
- [
- object,
- uuid(8BF1F3AA-6C46-4042-86ED-781E17040E09),
- dual,
- helpstring("IMyAbc Interface"),
- pointer_default(unique)
- ]
- interface IMyAbc : IDispatch
- {
- [id(1), helpstring("method SetLog")] HRESULT SetLog([in] ILog* mylog);
- [id(2), helpstring("method add")] HRESULT add([in] int a, [in] int b, [out] int* c );
- };
- 然后在MyAbc.h中声明一个私有成员变量IDispatch* pMytools;(昨天的例子中是声明成IUnknown*)并在构造函数中初始化;
- 1.2项目DispCallBack02与01相比:把接口ILog(接口保留)屏蔽掉,并把引用ILog类型改成IDispatch类型,如:SetLog([in] ILog* mylog);==>SetLog([in] IDispatch* mylog);
- STDMETHOD(SetLog)(/*[in]*/ ILog* mylog);==>STDMETHOD(SetLog)(/*[in]*/ IDispatch* mylog);
- STDMETHODIMP CMyAbc::SetLog(ILog *mylog)==>STDMETHODIMP CMyAbc::SetLog(IDispatch *mylog)
- 这样子在接口组件中就不在出现接口ILog的影子了(WriteLog函数是与接口分离的),这样的代码是非常通用的,即把回调接口虚拟化了,并完成具体功能:
- STDMETHODIMP CMyAbc::SetLog(IDispatch *mylog)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- this->pMytools=mylog;
- return S_OK;
- }
- STDMETHODIMP CMyAbc::add(int a, int b, int *c)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- *c=a+b;
- if(this->pMytools!=NULL)
- {
- long id=1;
- //回调方法id;
- DISPID methodid=(DISPID)id;
- //回调方法参数;
- VARIANT paras[1];
- paras[0].vt=VT_BSTR;
- char buffer[20];
- sprintf(buffer,"%d",*c);
- CString str(buffer);
- paras[0].bstrVal=str.AllocSysString();
- DISPPARAMS disp;
- disp.cArgs=1;
- disp.rgvarg=paras;
- disp.cNamedArgs=0;
- disp.rgdispidNamedArgs=NULL;
- //输出参数;
- VARIANT vout;
- EXCEPINFO ex;
- UINT result=0;
- this->pMytools->Invoke(methodid,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_METHOD,
- &disp,&vout,&ex,&result);
- }
- return S_OK;
- }
- 1.3项目DispCallBack03在02的基础上添加一个test项目并添加一个继承ILog接口的类MyLog,声明并重写WriteLog(BSTR message)函数及IDispatch的虚函数:
- STDMETHOD(WriteLog)(BSTR message);
- STDMETHOD(GetTypeInfoCount)(UINT __RPC_FAR *pctinfo);
- STDMETHOD(GetTypeInfo)(
- UINT iTInfo,
- LCID lcid,
- ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
- STDMETHOD(GetIDsOfNames)(
- REFIID riid,
- LPOLESTR __RPC_FAR *rgszNames,
- UINT cNames,
- LCID lcid,
- DISPID __RPC_FAR *rgDispId);
- STDMETHOD(Invoke)(
- DISPID dispIdMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- DISPPARAMS __RPC_FAR *pDispParams,
- VARIANT __RPC_FAR *pVarResult,
- EXCEPINFO __RPC_FAR *pExcepInfo,
- UINT __RPC_FAR *puArgErr);
- STDMETHOD(QueryInterface)(
- REFIID riid,
- void __RPC_FAR *__RPC_FAR *ppvObject);
- STDMETHOD_(ULONG,AddRef)( void);
- STDMETHOD_(ULONG,Release)( void);
- =====================================================
- STDMETHODIMP MyLog::Invoke(
- DISPID dispIdMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- DISPPARAMS __RPC_FAR *pDispParams,
- VARIANT __RPC_FAR *pVarResult,
- EXCEPINFO __RPC_FAR *pExcepInfo,
- UINT __RPC_FAR *puArgErr)
- {
- if(dispIdMember==1)
- {
- BSTR bBuffer=::SysAllocString(pDispParams->rgvarg[0].bstrVal);
- SysFreeString(pDispParams->rgvarg[0].bstrVal);
- return this->WriteLog(bBuffer);
- }
- else
- {
- *puArgErr=1;
- return S_FALSE;
- }
- }
- 1.4项目DispCallBack04完善WriteLog(BSTR message)方法,并添加一个按钮
- STDMETHODIMP MyLog::WriteLog(BSTR message)
- {
- CString msg(message);
- ::SysFreeString(message);
- AfxMessageBox(msg);
- return S_OK;
- }
- #include "../DispCallBack.h"
- #include "../DispCallBack_i.c"
- #include <atlbase.h>
- #include "mylog.h"
- void CTestDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- CoInitialize(NULL);
- ILog* pLog=NULL;
- CComPtr<IMyAbc> pTools;
- pTools.CoCreateInstance(CLSID_MyAbc);
- pLog=new MyLog();
- pTools->SetLog(pLog);
- int iResult;
- pTools->add(12,13,&iResult);
- }
- 2.项目EventDemoCOM 事件的定义和处理:
- 2.1项目EventDemo01-->New ATL Object-->Simple Object-->(Interface)Dual-->(name:)MyAbc-->在接口中添加一个函数add([in] int a, [in] int b, [out] int* c );并实现:
- STDMETHODIMP CMyAbc::add(int a, int b, int *c)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- *c=a+b;
- CString str;
- str.Format("%d",*c);
- this->Fire_OnLog(str.AllocSysString());
- return S_OK;
- }
- ------->(手工代码建控件)在.idl文件的library EVENTDEMOLib(组件)下添加:
- [
- uuid(C26E3137-7CDB-48F9-ACCB-95A272C68E68),
- helpstring("adfasdf")
- ]
- dispinterface _MyEvent //interface MyEvent: IDispatch
- {
- properties:
- methods:
- [id(1),helpstring("adsf")] HRESULT OnLog([in] BSTR msg);
- }
- 并在coclass MyAbc(构件中)添加:
- [default,source] dispinterface _MyEvent;
- 然后可看到自动生成接口MyEvent-->(右键CMyAbc)Implement Connection points-->在_MyEvent选项处打钩-->可看见有类CProxy_MyEvent<class T>生成,其下包含有方法Fire_OnLog(BSTR msg)(与_MyEvent的方法对应)
- 3.项目Event:(有界面的--控件形式)事件处理:(右键)New ATL Object-->controls-->Composite Controls(建控件)-->(name:MyPwds)-->support Connection points--->生成事件接口IMyPwdsEvents、接口IMyPwds及类CMyPwds-->在事件接口IMyabcEvents中添加函数:
- [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后)完成功能代码:
- LRESULT OnClickedButton1(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
- {
- // TODO : Add Code for control notification handler.
- this->Fire_add(::SysAllocString(L"控件制作成功"));
- return 0;
- }
- };
- 编译后即可---------
- -->然后添加一个test项目,在Dialog中右键插入控件MyPwds Class-->(右键Event)绑定IDC_MYPWDS1和方法add-->(点击Edit Exiting后)完成功能代码:
- void CTestDlg::OnaddMypwds1(LPCTSTR msg)
- {
- // TODO: Add your control notification handler code here
- CString str(msg);
- MessageBox(msg);
- }
- 4.项目MyAbc
- 4.1项目MyAbc01:(无界面的--控件形式)事件处理:(右键)New ATL Object-->Simple Object-->(Interface)Dual-->(name:)Abc-->support Connection points--->生成事件接口IAbcEvents、接口IAbc及类CAbc-->在事件接口IAbcEvents中添加函数:
- [id(1), helpstring("method add")] HRESULT WriteLog([in] BSTR msge);
- -->(右键CMyPwds)Implement Connection points-->在_IAbcEvents选项处打钩-->(编译后)可看见有类CProxy_IAbcEvents<class T>生成,其下包含有(自动生成)方法Fire_WriteLog(BSTR msge)(与_IAbcEvents的方法对应):
- template <class T>
- class CProxy_IAbcEvents : public IConnectionPointImpl<T, &DIID__IAbcEvents, CComDynamicUnkArray>
- {
- //Warning this class may be recreated by the wizard.
- public:
- HRESULT Fire_WriteLog(BSTR msge)
- {
- CComVariant varResult;
- T* pT = static_cast<T*>(this);
- int nConnectionIndex;
- CComVariant* pvars = new CComVariant[1];
- int nConnections = m_vec.GetSize();
- for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
- {
- pT->Lock();
- CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
- pT->Unlock();
- IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
- if (pDispatch != NULL)
- {
- VariantClear(&varResult);
- pvars[0] = msge;
- DISPPARAMS disp = { pvars, NULL, 1, 0 };
- //writeLog跟函数pDispatch->Invoke()相关==========
- pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
- }
- }
- delete[] pvars;
- return varResult.scode;
- }
- };
- -->然后在接口IAbc中添加函数(可用右键完成):
- [id(1), helpstring("method add")] HRESULT add([in] int a, [in] int b, [out] int* c);
- 4.2项目MyAbc02在MyAbc01基础上像1.3项目DispCallBack03一样添加项目test,即添加函数:
- STDMETHODIMP MyLog::GetTypeInfoCount(UINT __RPC_FAR *pctinfo)
- {
- return S_FALSE;
- }
- STDMETHODIMP MyLog::GetTypeInfo(
- UINT iTInfo,
- LCID lcid,
- ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
- {
- return S_FALSE;
- }
- STDMETHODIMP MyLog::GetIDsOfNames(
- REFIID riid,
- LPOLESTR __RPC_FAR *rgszNames,
- UINT cNames,
- LCID lcid,
- DISPID __RPC_FAR *rgDispId)
- {
- return S_FALSE;
- }
- STDMETHODIMP MyLog::Invoke(
- DISPID dispIdMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- DISPPARAMS __RPC_FAR *pDispParams,
- VARIANT __RPC_FAR *pVarResult,
- EXCEPINFO __RPC_FAR *pExcepInfo,
- UINT __RPC_FAR *puArgErr)
- {
- //实现day12的WriteLog的功能(基本是复制的):生成日志文件
- CFile f;
- CFileException ex;
- f.Open("./log.txt",CFile::modeCreate| CFile::modeReadWrite,&ex);
- CString str(pDispParams->rgvarg[0].bstrVal);//改变的地方
- f.Write(str.GetBuffer(100),str.GetLength());
- ::SysFreeString(pDispParams->rgvarg[0].bstrVal);
- f.Close();
- return S_OK;
- }
- STDMETHODIMP MyLog::QueryInterface(
- REFIID riid,
- void __RPC_FAR *__RPC_FAR *ppvObject)
- {
- *ppvObject=this;
- return S_OK;
- }
- STDMETHODIMP_(ULONG) MyLog::AddRef( void)
- {
- return 1;
- }
- STDMETHODIMP_(ULONG) MyLog::Release( void)
- {
- return 1;
- }
- ---03.01---------------------day14---------------------------------
- 1.项目DemoError
- 1.1项目DemoError01添加接口时,选择支持异常--Support ISupportsErrorInfo--可看到有异常类自动生成:
- STDMETHODIMP CMyAbc::InterfaceSupportsErrorInfo(REFIID riid)
- {
- static const IID* arr[] =
- {
- &IID_IMyAbc
- };
- for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
- {
- if (InlineIsEqualGUID(*arr[i],riid))
- return S_OK;
- }
- return S_FALSE;
- }
- -->然后给接口添加并实现函数:
- STDMETHODIMP CMyAbc::div(int a, int b, int *c)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- if(b==0)
- {
- CString str("b can not be zero!");
- this->Error(str.AllocSysString());
- return S_FALSE;
- }
- else
- {
- *c=a/b;
- return S_OK;
- }
- }
- 1.2项目DemoError02再建一个新项目test并添加一个按钮捕获异常:(.idl文件没变)
- #include "../DemoError.h"
- #include "../DemoError_i.c"
- #include <atlbase.h>
- void CTest1Dlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- CComPtr<IMyAbc> mytools;
- mytools.CoCreateInstance(CLSID_MyAbc);
- int iResult=0;
- HRESULT hr=mytools->div(12,0,&iResult);
- if(hr!=0)
- {
- ISupportErrorInfo* pError=NULL;//判断是否支持异常
- mytools->QueryInterface(IID_ISupportErrorInfo,(void**)&pError);
- HRESULT h1=pError->InterfaceSupportsErrorInfo(IID_IMyAbc);//判断接口是否支持异常
- if(SUCCEEDED(h1))
- {
- IErrorInfo* pMyException=NULL;
- ::GetErrorInfo(0,&pMyException);
- BSTR msg;
- pMyException->GetDescription(&msg);//捕获错误异常提示
- CString str(msg);
- MessageBox(str);
- }
- }
- }
- 2.项目EquationDemo通过接口(支持异常)实现一元二次方程求根:
- 2.1项目EquationDemo02实现求根函数:
- 在.idl文件中
- //添加与一元二次方程相关两个结构体
- //保存根数据的结构体
- typedef struct Root
- {
- float r1;
- float r2;
- } Root;
- //保存方程系数数据的结构体
- typedef struct Equation
- {
- float a;
- float b;
- float c;
- } Equation;
- STDMETHODIMP CMyEquation::solve(Equation* equ,Root** roots)
- {
- float delta=(equ->b)*(equ->b)-4*equ->a*equ->c;
- if(delta>=0)
- {
- *roots=(Root*)::CoTaskMemAlloc(sizeof(Root));
- float temp1=sqrt(delta);
- (*roots)->r1=0.5*(0-equ->b+temp1)/equ->a;
- (*roots)->r1=0.5*(0-equ->b-temp1)/equ->a;
- return S_OK;
- }
- else
- {
- this->Error(::SysAllocString(L"no root"));
- return S_FALSE;
- }
- }
- 2.2项目EquationDemo03再建一个test项目并添加一个按钮:
- #include "../EquationDemo.h"
- #include "../EquationDemo_i.c"
- #include <atlbase.h>
- void CTestDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- CComPtr<IMyEquation> mytools;
- mytools.CoCreateInstance(CLSID_MyEquation);
- Equation t;
- t.a=1;
- t.b=2;
- t.c=1;
- Root* roots=NULL;
- HRESULT hr=mytools->solve(&t,&roots);
- if(hr!=0)
- {
- ISupportErrorInfo* pSp=NULL;
- mytools->QueryInterface(IID_ISupportErrorInfo,(void **)&pSp);
- if(pSp!=NULL)
- {
- HRESULT hrok=pSp->InterfaceSupportsErrorInfo(IID_IMyEquation);
- if(hrok==S_OK)
- {
- IErrorInfo* pError=NULL;
- ::GetErrorInfo(0,&pError);
- BSTR bMsg;
- pError->GetDescription(&bMsg);
- CString str(bMsg);
- MessageBox(str);
- }
- }
- }
- else
- {
- CString strall;
- strall.Format("root1:%f,root2:%f",roots->r1,roots->r2);
- MessageBox(strall);
- }
- }
- 3.项目TestAdo为ADO(数据库COM)操作:
- 3.1项目TestAdo02为建一个单文档项目,在标准头文件StdAfx.h中添加
- #import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF")--C:Program FilesCommon FilesSystemadomsado15.dll为微软提供的数据库COM相关接口msado15.dll文件--->然后添加三个按钮:
- 测试时hr=0表返回成功
- void CTestAdoDlg::OnButton1()
- {
- ::CoInitialize(NULL);
- _ConnectionPtr myconn; //CComPtr<IConnection>智能指针
- myconn.CreateInstance(__uuidof(Connection));//生成实例
- _bstr_t sql("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena;");//样式
- HRESULT hr=myconn->Open(sql,"scott","tiger",-1);//建立数据源连接--conection的方法
- myconn->Close();//释放数据源连接--conection的方法
- }
- #include <atlbase.h>
- void CTestAdoDlg::OnButton2()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);//初始化环境
- CComPtr<_Connection> mytools;//和OnButton1的声明意义一样
- mytools.CoCreateInstance(__uuidof(Connection));//生成实例
- _bstr_t sql("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena;");
- HRESULT hr=mytools->Open(sql,"scott","tiger",-1);//建立数据源连接
- mytools->Close();//释放数据源连接
- }
- void CTestAdoDlg::OnButton3()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);//初始化环境
- _Connection* mytools=NULL;
- CoCreateInstance(__uuidof(Connection),
- NULL,
- CLSCTX_INPROC_SERVER,
- __uuidof(_Connection),
- (void **)&mytools);//生成实例
- _bstr_t sql("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena;");
- HRESULT hr=mytools->Open(sql,"scott","tiger",-1);//建立数据源连接
- mytools->Close();//释放数据源连接
- }
- 3.2项目TestAdo03在02的button1中添加查询数据库代码:
- void CTestAdoDlg::OnButton1()
- {
- ::CoInitialize(NULL);
- _ConnectionPtr myconn; //连接智能指针
- myconn.CreateInstance(__uuidof(Connection));//生成实例
- _bstr_t sql("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena;");
- HRESULT hr=myconn->Open(sql,"scott","tiger",-1);
- //定义一个sql语句对象;
- _CommandPtr mysql1; //命令智能指针
- mysql1.CreateInstance(__uuidof(Command));//生成实例
- _bstr_t sql1("select * from ocyBooks");
- mysql1->CommandText=sql1;//指定命令文本
- mysql1->CommandType=adCmdText;//指定命令类型
- //以下是新增的代码:
- //制定SQL所查询的数据库;
- mysql1->ActiveConnection=myconn;
- //查询并返回存放在表中的结果集
- _RecordsetPtr mydata=mysql1->Execute(NULL,NULL,adCmdText);//数据操作
- while(!mydata->adoEOF)//列表指针
- {
- _variant_t myid=mydata->GetCollect("BOOKISNB");//获取数据表对应属性名的数据
- _variant_t myname=mydata->GetCollect("BOOKNAME");//获取数据表对应属性名的数据
- _variant_t myauthor=mydata->GetCollect("BOOKAuthor");//获取数据表对应属性名的数据
- CString strName((LPCTSTR)(_bstr_t)myname);//(_bstr_t)为带空字节头的UNicode码
- CString strAuthor((LPCTSTR)(_bstr_t)myauthor);//(LPCTSTR)为不带空字节头的UNicode码
- CString str;
- str.Format("%d;%s;%s",(long)myid,strName,strAuthor);
- MessageBox(str);
- mydata->MoveNext();
- }
- mydata->Close();
- myconn->Close();
- }
- 3.3项目TestAdo04新加一个按钮对Command的操作:
- void CTestAdoDlg::OnButton4()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);//初始化环境
- //_bstr_t sql1("insert into ocyBooks (BookISNB, BookName, BookAuthor) values (123457,'COM','WANGWU')");
- //_bstr_t sql1("delete from ocyBooks");
- _bstr_t sql1("update ocyBooks set BookName='C++' where BookName='COM'");
- _ConnectionPtr myconn;//连接智能指针
- myconn.CreateInstance(__uuidof(Connection));//生成实例
- _bstr_t sql("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena;");
- HRESULT hr=myconn->Open(sql,"scott","tiger",-1);//建立数据源连接
- _CommandPtr cmdsql1;//命令智能指针
- cmdsql1.CreateInstance(__uuidof(Command));//生成实例
- cmdsql1->CommandType=adCmdText;//指定命令类型
- cmdsql1->CommandText=sql1;//指定命令文本
- //制定SQL所查询的数据库;
- cmdsql1->ActiveConnection=myconn;
- VARIANT iResult;
- iResult.vt=VT_I4;//数字类型
- cmdsql1->Execute(&iResult,NULL,adCmdText);//功能和Recordset的一样
- }
- ---03.02---------------------day15---------------------------------
- 1.项目DempParameter添加文本框,输入数据,导入数据库(不是COM方式)
- 1.1基本对话项目DempParameter02添加一个window事件:WM_DESTROY,在自动生成的OnDestroy() 方法中添加::CoUninitialize();//释放环境;
- 在OnInitDialog()方法中添加::CoInitialize(NULL);//初始化环境
- 在头文件中声明一个方法://链接单独用一个函数有利于扩展通用性:
- _ConnectionPtr GetDataConnection(CString datasource, CString uid, CString pwd);
- 然后添加3个文本框(在类向导中绑定3个变量)和1个按钮:
- _ConnectionPtr CDempParameterDlg::GetDataConnection(CString datasource, CString uid, CString pwd)
- {
- CString strFormat="Provider=OraOLEDB.Oracle.1;User Id=%s;Data Source=%s";
- CString str;
- str.Format(strFormat,uid,datasource);
- _ConnectionPtr mytools;
- mytools.CreateInstance(__uuidof(Connection));
- mytools->Open(_bstr_t(str),"",_bstr_t(pwd),-1);
- return mytools;
- }
- void CDempParameterDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- _ConnectionPtr myconn=this->GetDataConnection("tarena","scott","tiger");
- this->UpdateData(TRUE);//更新数据
- CString sqlFormat="insert into ocyBooks(BookIsnb,BookName,BookAuthor) values (%s,'%s','%s')";
- CString sql;
- sql.Format(sqlFormat,this->m_ibsn,this->m_bookname,this->m_author);
- _CommandPtr sqlobj;
- sqlobj.CreateInstance(__uuidof(Command));
- sqlobj->CommandText=_bstr_t(sql);//命令文本
- sqlobj->CommandType=adCmdText;//命令类型
- //制定SQL所查询的数据库;
- sqlobj->ActiveConnection=myconn;
- VARIANT vResult;
- vResult.vt=VT_I4;//转整形
- try{
- sqlobj->Execute(&vResult,NULL,adCmdText);//执行查询
- }
- catch(_com_error ex)
- {
- int i=10;
- i=i+1;
- }
- }
- 1.2单文档项目DempParameter03再添加一个按钮,功能一样:
- void CDempParameterDlg::OnButton2()
- {
- // TODO: Add your control notification handler code here
- this->UpdateData(TRUE);
- _ConnectionPtr myconn=this->GetDataConnection("tarena","scott","tiger");
- //和1的不同点
- _bstr_t sql("insert into ocyBooks(BookIsnb,BookName,BookAuthor) values (?,?,?)");
- _CommandPtr sqlobj;
- sqlobj.CreateInstance(__uuidof(Command));
- sqlobj->CommandType=adCmdText;//命令类型
- sqlobj->CommandText=sql;//命令文本,和1的不同点
- //parameter对象在command对象中用于指定参数化查询或者存储过程的参数
- _ParameterPtr para1=sqlobj->CreateParameter("id",adInteger,adParamInput,4);
- _ParameterPtr para2=sqlobj->CreateParameter("name",adVarChar,adParamInput,20);
- _ParameterPtr para3=sqlobj->CreateParameter("author",adVarChar,adParamInput,20);
- int id=atoi(this->m_ibsn);//字符转整形
- _variant_t vid((long)id);
- para1->Value=vid;
- para2->Value=(_variant_t)(_bstr_t)(this->m_bookname);
- para3->Value=(_variant_t)(_bstr_t)(this->m_author);
- sqlobj->Parameters->Append(para1);//追加
- sqlobj->Parameters->Append(para2);//追加
- sqlobj->Parameters->Append(para3);//追加
- sqlobj->ActiveConnection=myconn;
- VARIANT myvt;
- myvt.vt=VT_I4;
- sqlobj->Execute(&myvt,NULL,adCmdText);
- }
- 2.项目BooksDAL用接口(COM)方式操作数据库:
- 2.1建一个支持异常的COM组件项目BooksDAL01,添加5个方法:
- 在idl文件头添加一个结构体:
- typedef struct DTOBook
- {
- UINT BookIsnb;
- BSTR BookName;
- BSTR BookAuthor;
- }DTOBook;
- STDMETHODIMP CDALMyBools::GetBookByIsbn(UINT bookisbn, DTOBook **mybook)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- return S_OK;
- }
- STDMETHODIMP CDALMyBools::QueryAllBook(DTOBook **allBook)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- return S_OK;
- }
- STDMETHODIMP CDALMyBools::SaveBook(DTOBook *bookdata, UINT *pResult)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- return S_OK;
- }
- STDMETHODIMP CDALMyBools::DeleteBookById(UINT id, UINT *iResult)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- return S_OK;
- }
- STDMETHODIMP CDALMyBools::Update(DTOBook *Book, UINT *iResult)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- return S_OK;
- }
- 2.1项目BooksDAL02在01的基础上声明8个私有成员变量及1个私有成员方法:
- 在头文件中添加:
- #import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adEOF")
- private:
- _ConnectionPtr GetMyConn();
- CString m_sqlQueryById;//通过ID查询
- CString m_sqlQueryAll;//查询所有
- CString m_sqlUpdate;//通过ID更新bookname、bookauthor
- CString m_sqlSave;
- CString m_sqlDelete;
- CString m_UID;//用户名:scott
- CString m_PWD;//密码:tiger
- CString m_DataSource;//数据源:tarena
- 然后在构造方法中初始化:
- CDALMyBools()
- {
- this->m_sqlQueryById="select * from mybooks where bookisnb=?";
- this->m_sqlQueryAll="select * from mybooks";
- this->m_sqlUpdate="update mybooks set bookname=?,bookauthor=? where bookisnb=?";
- //CString m_sqlSave;
- //CString m_sqlDelete;
- }
- 私有成员方法的实现://通用性
- _ConnectionPtr CDALMyBools::GetMyConn()
- {
- CString strFormat="Provider=OraOLEDB.Oracle.1;User Id=%s;Data Source=%s";
- CString str;
- str.Format(strFormat,this->m_UID,this->m_DataSource);
- _ConnectionPtr mytools;
- mytools.CreateInstance(__uuidof(Connection));
- mytools->Open(_bstr_t(str),"",_bstr_t(this->m_PWD),-1);
- return mytools;
- }
- 并在其他方法中调用:
- STDMETHODIMP CDALMyBools::GetBookByIsbn(UINT bookisbn, DTOBook **mybook)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- _ConnectionPtr conn=this->GetMyConn();
- return S_OK;
- }
- 然后添加3个属性(自动生成6个方法):
- STDMETHOD(get_DataSource)(/*[out, retval]*/ BSTR *pVal);
- STDMETHOD(put_DataSource)(/*[in]*/ BSTR newVal);
- STDMETHOD(get_PWD)(/*[out, retval]*/ BSTR *pVal);
- STDMETHOD(put_PWD)(/*[in]*/ BSTR newVal);
- STDMETHOD(get_UID)(/*[out, retval]*/ BSTR *pVal);
- STDMETHOD(put_UID)(/*[in]*/ BSTR newVal);
- 并实现:
- STDMETHODIMP CDALMyBools::get_UID(BSTR *pVal)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- return S_OK;
- }
- //有改动
- STDMETHODIMP CDALMyBools::put_UID(BSTR newVal)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- this->m_UID=CString(newVal);
- ::SysFreeString(newVal);
- return S_OK;
- }
- STDMETHODIMP CDALMyBools::get_PWD(BSTR *pVal)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- return S_OK;
- }
- //有改动
- STDMETHODIMP CDALMyBools::put_PWD(BSTR newVal)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- this->m_PWD=CString(newVal);
- ::SysFreeString(newVal);
- return S_OK;
- }
- STDMETHODIMP CDALMyBools::get_DataSource(BSTR *pVal)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- return S_OK;
- }
- //有改动
- STDMETHODIMP CDALMyBools::put_DataSource(BSTR newVal)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- this->m_DataSource=CString(newVal);
- ::SysFreeString(newVal);
- return S_OK;
- }
- 2.2项目BooksDAL03在02的基础上补充方法GetBookByIsbn():
- STDMETHODIMP CDALMyBools::GetBookByIsbn(UINT bookisbn, DTOBook **mybook)
- {
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- // TODO: Add your implementation code here
- _ConnectionPtr conn=this->GetMyConn();
- *mybook=(DTOBook*)::CoTaskMemAlloc(sizeof(DTOBook));//开辟空间
- _CommandPtr sqlobj;
- sqlobj.CreateInstance(__uuidof(Command));//生成实例
- sqlobj->CommandText=(_bstr_t)this->m_sqlQueryById;//命令类型
- sqlobj->CommandType=adCmdText;//命令文本
- //制定SQL所查询的数据库;
- sqlobj->ActiveConnection=conn;
- //指定参数化查询
- _ParameterPtr para1=sqlobj->CreateParameter("id",adInteger,adParamInput,4);
- para1->Value=_variant_t((long)bookisbn);
- sqlobj->Parameters->Append(para1);
- _RecordsetPtr data=sqlobj->Execute(NULL,NULL,adCmdText);
- if(!data->adEOF)
- {
- (*mybook)->BookIsnb=(UINT)(long)(data->GetCollect("bookisnb"));
- _variant_t vtname=data->GetCollect("bookname");
- (*mybook)->BookName=::SysAllocString(vtname.bstrVal);
- _variant_t vtauthor=data->GetCollect("bookauthor");
- (*mybook)->BookName=::SysAllocString(vtauthor.bstrVal);
- }
- return S_OK;
- }
- 在BooksDAL.h中添加一个结构体:
- typedef struct DTOBook
- {
- UINT BookIsnb;
- BSTR BookName;
- BSTR BookAuthor;
- } DTOBook;
- 然后新建一个test项目并添加一个按钮测试:
- #include "../BooksDAL.h"
- #include "../BooksDAL_i.c"
- #include <atlbase.h>
- #include <comdef.h>
- void CTESTDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- CComPtr<IDALMyBools> mytools;
- mytools.CoCreateInstance(CLSID_DALMyBools);
- DTOBook* pData=NULL;
- mytools->put_PWD(_bstr_t("tiger"));
- mytools->put_UID(_bstr_t("scott"));
- mytools->put_DataSource(_bstr_t("tarena"));
- mytools->GetBookByIsbn(6,&pData);
- }
- 2.3项目BooksDAL04在03的基础上补充添加私有方法:
- _ParameterPtr CDALMyBools::GetIdPara(UINT id,_CommandPtr sqlObj)
- {
- _ParameterPtr para1=sqlObj->CreateParameter("id",adInteger,adParamInput,4);
- para1->Value=_variant_t((long)id);
- return para1;
- }
- 改变按钮代码:
- #include "../BooksDAL.h"
- #include "../BooksDAL_i.c"
- #include <atlbase.h>
- #include <comdef.h>
- void CTESTDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- ::CoInitialize(NULL);
- CComPtr<IDALMyBools> mytools;
- mytools.CoCreateInstance(CLSID_DALMyBools);
- DTOBook* pData=NULL;
- mytools->put_PWD(_bstr_t("csd0910"));
- mytools->put_UID(_bstr_t("csd0910"));
- mytools->put_DataSource(_bstr_t("lisongtao"));
- mytools->GetBookByIsbn(123457,&pData);
- UINT iResult=0;
- mytools->DeleteBookById(123457,&iResult);
- }
- ---03.05---------------------day16---------------------------------
- 1.项目project为数据库连接(用day15的接口)及MFC界面操作实例:
- 1.1项目project01建一个选定支持windows资源管理的单文档项目BookAdminApp,然后新建一个普通类BookEntity并让它继承CObject,且声明3个数据相关变量:
- //要操作的数据成员,与接口的数据对应
- UINT BookIsnb;
- CString BookName;
- CString BookAuthor;
- --->在CBookAdminApp类的初始化方法InitInstance()中添加 ::CoInitialize(NULL);//环境初始化
- --->用CBookAdminDoc类的方法OnNewDocument()读取数据到内存:
- BOOL CBookAdminDoc::OnNewDocument()
- {
- if (!CDocument::OnNewDocument())
- return FALSE;
- // TODO: add reinitialization code here
- // (SDI documents will reuse this document)
- CComPtr<IDALMyBools> mytools;//组件接口指针
- mytools.CoCreateInstance(CLSID_DALMyBools);//生成实例
- DTOBook* pAllBooks=NULL;//数据的结构
- UINT iSize=0;
- //设置连接数据库条件
- mytools->put_DataSource(::SysAllocString(L"tarena"));
- mytools->put_UID(::SysAllocString(L"scott"));
- mytools->put_PWD(::SysAllocString(L"tiger"));
- mytools->QueryAllBook(&pAllBooks,&iSize);//查询数据库
- for(int i=0;i<iSize;i++)
- {
- BookEntity* p1=new BookEntity;//
- p1->BookIsnb=(pAllBooks+i)->BookIsnb;
- p1->BookName=CString((pAllBooks+i)->BookName);
- p1->BookAuthor=CString((pAllBooks+i)->BookAuthor);
- //CString类型用完要释放掉
- ::SysFreeString((pAllBooks+i)->BookName);
- ::SysFreeString((pAllBooks+i)->BookAuthor);
- //保存到内存上;
- this->allBooks.AddTail(p1);
- }
- //释放栈中的结构体
- ::CoTaskMemFree(pAllBooks);
- return TRUE;
- }
- 1.2项目project02在01的CBookAdminView类的方法OnInitialUpdate()完成界面数据初始化:
- //窗体中有数据出现
- void CBookAdminView::OnInitialUpdate()
- {
- CListView::OnInitialUpdate();
- //创建列;
- this->GetListCtrl().InsertColumn(0,"BookName",LVCFMT_CENTER,200);
- this->GetListCtrl().InsertColumn(1,"BookAuther",LVCFMT_CENTER,200);
- //添加数据;
- POSITION ps;
- ps=this->GetDocument()->allBooks.GetHeadPosition();
- while(ps!=NULL)
- {
- BookEntity* be=this->GetDocument()->allBooks.GetNext(ps);
- this->GetListCtrl().InsertItem(0,be->BookName);
- this->GetListCtrl().SetItemText(0,1,be->BookAuthor);
- }
- // TODO: You may populate your ListView with items by directly accessing
- // its list control through a call to GetListCtrl().
- }
- 1.3项目project03添加工具栏按钮实现添加功能:
- -->添加一个对话框,再添加3个文本框,建一个基类为CDialog的MFC类DlgBookAdd并绑定文本框和3个变量再声明一个变量BOOL m_bIsOk;
- 及实现两个按钮功能(用对话框给的OK和cancel):
- void DlgBookAdd::OnOK()
- {
- // TODO: Add extra validation here
- this->UpdateData(TRUE);//(更新后)把文本框数据送到内存中
- m_bIsOk=TRUE;//与工具栏的功能相关
- CDialog::OnOK();
- }
- void DlgBookAdd::OnCancel()
- {
- // TODO: Add extra cleanup here
- m_bIsOk=FALSE;
- CDialog::OnCancel();
- }
- -->再实现工具栏的按钮功能:
- //工具栏添加功能按钮
- void CBookAdminDoc::OnButton32771()
- {
- // TODO: Add your command handler code here
- DlgBookAdd mydlg;//新设的类,绑定文本框和数据变量
- mydlg.DoModal();//弹出对话框
- if(mydlg.m_bIsOk)
- { //对话框数据相关
- UINT isbn=mydlg.m_bookisbn;
- CString name=mydlg.m_bookname;
- CString Author=mydlg.m_bookauthor;
- CString CSisbn;
- DTOBook* dto=new DTOBook;
- dto->BookIsnb=isbn;
- dto->BookName=name.AllocSysString();//转BSTR
- dto->BookAuthor=Author.AllocSysString();
- //将数据添加到数据库中;==>重复的代码
- CComPtr<IDALMyBools> mytools;
- mytools.CoCreateInstance(CLSID_DALMyBools);
- DTOBook* pAllBooks=NULL;
- UINT iSize=0;
- mytools->put_DataSource(::SysAllocString(L"tarena"));
- mytools->put_UID(::SysAllocString(L"scott"));
- mytools->put_PWD(::SysAllocString(L"tiger"));
- //保存数据
- UINT iResult=0;
- mytools->SaveBook(dto,&iResult);
- //刷新界面上的数据==>显示到界面上;
- POSITION ps=this->GetFirstViewPosition();
- while(ps!=NULL)
- {
- CView* pview=this->GetNextView(ps);
- if(pview->GetRuntimeClass()->m_lpszClassName=="CBookAdminView")
- {
- CListView* plist=(CListView*)pview;
- plist->GetListCtrl().InsertItem(0,name);
- plist->GetListCtrl().SetItemText(0,1,Author);
- }
- }
- }
- }
- 1.4项目project04把03的--刷新界面上的数据的代码--及数据库连接相关变量数据归并到函数中去:
- void CBookAdminDoc::OnButton32771()
- {
- // TODO: Add your command handler code here
- DlgBookAdd mydlg;
- mydlg.DoModal();
- if(mydlg.m_bIsOk)
- {
- UINT isbn=mydlg.m_bookisbn;
- CString name=mydlg.m_bookname;
- CString Author=mydlg.m_bookauthor;
- DTOBook* dto=new DTOBook;
- dto->BookIsnb=isbn;
- dto->BookName=name.AllocSysString();
- dto->BookAuthor=Author.AllocSysString();
- //将数据添加到数据库中;
- CComPtr<IDALMyBools> mytools=this->GetDbTools();
- UINT iResult=0;
- mytools->SaveBook(dto,&iResult);
- //刷新界面上的数据;
- CListView* plist=this->GetListView1();
- plist->GetListCtrl().InsertItem(0,name);
- plist->GetListCtrl().SetItemText(0,1,Author);
- }
- }
- CComPtr<IDALMyBools> CBookAdminDoc::GetDbTools()
- {
- CComPtr<IDALMyBools> mytools;
- mytools.CoCreateInstance(CLSID_DALMyBools);
- DTOBook* pAllBooks=NULL;
- UINT iSize=0;
- mytools->put_DataSource(::SysAllocString(L"tarena"));
- mytools->put_UID(::SysAllocString(L"scott"));
- mytools->put_PWD(::SysAllocString(L"tiger"));
- return mytools;
- }
- CListView* CBookAdminDoc::GetListView1()
- {
- CListView* plist=NULL;
- POSITION ps=this->GetFirstViewPosition();
- while(ps!=NULL)
- {
- CView* pview=this->GetNextView(ps);
- if(pview->GetRuntimeClass()->m_lpszClassName=="CBookAdminView")
- {
- plist=(CListView*)pview;
- break;
- }
- }
- return plist;
- }
- 1.5项目project05添加工具栏删除功能按钮(绑定事件):
- void CBookAdminView::OnButton32772()
- {
- // TODO: Add your command handler code here
- //找到被删除的记录ID;
- int index=this->GetListCtrl().GetNextItem(-1,LVNI_SELECTED|LVNI_ALL);
- if(index==-1)
- {
- MessageBox("请首先选中一条记录!");
- }
- else
- {
- UINT iOk=MessageBox("你真的要删除吗?","删除确认",MB_YESNO);
- //从当前的界面上删除;
- if(iOk==6)
- {
- this->GetListCtrl().DeleteItem(index);
- //
- DWORD isbn=this->GetListCtrl().GetItemData(index);
- UINT iResult=0;
- this->GetDocument()->GetDbTools()->DeleteBookById((UINT)isbn,&iResult);
- }
- }
- }
- 1.6项目project06添加工具栏修改数据功能按钮(绑定事件):
- //修改数据
- void CBookAdminView::OnButton32773()
- {
- // TODO: Add your command handler code here
- //1. 获得被编辑的记录id;
- int index=this->GetListCtrl().GetNextItem(-1,LVNI_ALL|LVNI_SELECTED);
- if(index==-1)
- {
- MessageBox("请首先选中一条记录");
- return ;
- }
- //2. 显示被编辑的数据;
- UINT id=(UINT)(this->GetListCtrl().GetItemData(index));
- DTOBook* pCurrentData=NULL;
- this->GetDocument()->GetDbTools()->GetBookByIsbn(id,&pCurrentData);
- //3. 获得修改后的数据;
- DlgBookAdd dlg;
- dlg.m_bookisbn=id;
- dlg.m_bookname=CString(pCurrentData->BookName);
- dlg.m_bookauthor=CString(pCurrentData->BookAuthor);
- ::SysFreeString(pCurrentData->BookName);
- ::SysFreeString(pCurrentData->BookAuthor);
- dlg.DoModal();
- //4. 更新数据库;
- //5. 更新界面;
- }
- 1.7项目project07添加工具栏修改数据功能按钮(绑定事件):
- void CBookAdminView::OnButton32773()
- {
- // TODO: Add your command handler code here
- //1. 获得被编辑的记录id;
- int index=this->GetListCtrl().GetNextItem(-1,LVNI_ALL|LVNI_SELECTED);
- if(index==-1)
- {
- MessageBox("请首先选中一条记录");
- return ;
- }
- //2. 显示被编辑的数据;
- UINT id=(UINT)(this->GetListCtrl().GetItemData(index));
- DTOBook* pCurrentData=NULL;
- this->GetDocument()->GetDbTools()->GetBookByIsbn(id,&pCurrentData);
- //3. 获得修改后的数据;
- DlgBookAdd dlg;
- dlg.m_bookisbn=id;
- dlg.m_bookname=CString(pCurrentData->BookName);
- dlg.m_bookauthor=CString(pCurrentData->BookAuthor);
- ::SysFreeString(pCurrentData->BookName);
- ::SysFreeString(pCurrentData->BookAuthor);
- dlg.DoModal();
- //4. 更新数据库;
- if(!dlg.m_bIsOk) return ;
- pCurrentData->BookAuthor=dlg.m_bookauthor.AllocSysString();
- pCurrentData->BookName=dlg.m_bookname.AllocSysString();
- UINT iResult=0;
- this->GetDocument()->GetDbTools()->Update(pCurrentData,&iResult);
- if(iResult==0) return;
- //5. 更新界面;
- this->GetListCtrl().SetItemText(index,0,dlg.m_bookname) ;
- this->GetListCtrl().SetItemText(index,1,dlg.m_bookauthor);
- }
- ---03.06---------------------day17---------------------------------
- 1.对话框项目OffDemoTecordSet 的open()方法的用法,建3个文本框,N个按钮功能:
- 1.1项目OffDemo01在方法COffDemoDlg::OnInitDialog()中添加初始化环境语句:
- ::CoInitialize(NULL);//初始化环境
- --->然后实现button1的导入数据功能:
- void COffDemoDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- _ConnectionPtr conn;
- conn.CreateInstance(__uuidof(Connection));
- conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=csd0910;Data Source=lisongtao"),"",_bstr_t("csd0910"),-1);
- _RecordsetPtr rs;
- rs.CreateInstance(__uuidof(Recordset));
- _bstr_t sqlobj("select * from mybooks");
- rs->Open((_variant_t)sqlobj,
- _variant_t((IDispatch *)conn,true),//这样写比较麻烦
- adOpenStatic,
- adLockOptimistic,//与UpdateBatch关联
- -1);
- //显示第一条记录;
- if(!rs->adEOF)
- {
- _variant_t isbn=rs->GetCollect("BOOKISNB");
- }
- 1.2项目OffDemo02改进01的open()方法的参数:
- rs->Open((_variant_t)sqlobj,
- conn.GetInterfacePtr(),//改进的参数
- adOpenStatic,adLockOptimistic,-1);
- 1.3项目OffDemo03在02的基础上把几个变量声明到头文件及添加三个按钮功能及一个方法(简化button1的代码):
- public:
- void show();
- _RecordsetPtr rs;
- void COffDemoDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- _ConnectionPtr conn;
- conn.CreateInstance(__uuidof(Connection));
- conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=csd0910;Data Source=lisongtao"),"",_bstr_t("csd0910"),-1);
- rs.CreateInstance(__uuidof(Recordset));
- _bstr_t sqlobj("select * from mybooks");
- rs->Open((_variant_t)sqlobj,conn.GetInterfacePtr(),adOpenStatic,adLockOptimistic,-1);
- //显示第一条记录;
- this->show();
- }
- //显示数据,默认为第一条
- void COffDemoDlg::show()
- {
- if(!rs->adEOF && !rs->BOF)
- {
- this->m_isbn=(UINT)(long)(rs->GetCollect("BOOKISNB"));
- this->m_name=(CString)(LPCTSTR)(_bstr_t)(rs->GetCollect("BOOKNAME"));
- this->UpdateData(FALSE);//(更新后)把数据送到文本框
- }
- }
- //查看后一条数据
- void COffDemoDlg::OnButton7()
- {
- // TODO: Add your control notification handler code here
- if(!rs->adEOF)
- {
- rs->MoveNext();
- show();
- }
- else
- {
- MessageBox("End!!!");
- }
- }
- //查看前一条数据
- void COffDemoDlg::OnButton6()
- {
- // TODO: Add your control notification handler code here
- if(!rs->BOF)
- {
- rs->MovePrevious();
- show();
- }
- else
- {
- MessageBox("Begin!!!");
- }
- }
- //显示第一条数据
- void COffDemoDlg::OnButton9()
- {
- // TODO: Add your control notification handler code here
- if(!rs->BOF)
- {
- rs->MoveFirst();
- show();
- }
- else
- {
- MessageBox("Begin!!!");
- }
- }
- 1.4项目OffDemo05增加两个按钮功能:
- //新增记录时先清空文本框
- void COffDemoDlg::OnButton3()
- {
- // TODO: Add your control notification handler code here
- this->m_isbn=0;
- this->m_name="";
- this->m_author="";
- this->UpdateData(FALSE);//(更新后)把数据送到文本框
- }
- //更新数据库数据
- void COffDemoDlg::OnButton2()
- {
- // TODO: Add your control notification handler code here
- this->UpdateData(TRUE);
- this->rs->AddNew();
- this->rs->GetFields()->GetItem("BookIsnb")->Value=_variant_t((long)(this->m_isbn));
- this->rs->GetFields()->GetItem("BookName")->Value=_variant_t(this->m_name.AllocSysString());
- this->rs->GetFields()->GetItem("BookIsnb")->Value=_variant_t(this->m_author.AllocSysString());
- this->rs->Update();
- this->rs->UpdateBatch(adAffectAll);
- }
- 1.5项目OffDemo06增加两个按钮功能:
- //删除数据库数据
- void COffDemoDlg::OnButton4()
- {
- // TODO: Add your control notification handler code here
- this->rs->Delete(adAffectCurrent);
- this->rs->Update();
- this->rs->UpdateBatch(adAffectAll);
- }
- //更改数据
- void COffDemoDlg::OnButton5()
- {
- // TODO: Add your control notification handler code here
- this->UpdateData(TRUE);
- this->rs->GetFields()->GetItem("BookIsnb")->Value=_variant_t((long)(this->m_isbn));
- this->rs->GetFields()->GetItem("BookName")->Value=_variant_t(this->m_name.AllocSysString());
- this->rs->GetFields()->GetItem("BookAuthor")->Value=_variant_t(this->m_author.AllocSysString());
- this->rs->Update();
- this->rs->UpdateBatch(adAffectAll);
- }
- 2.对话框项目SafeArrayDemo01添加一个按钮(函数与图片保存到数据库有关):
- void CSafeArrayDemoDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- //安全数组定义
- SAFEARRAYBOUND bound[1];
- bound[0].lLbound=0;
- bound[0].cElements=10;
- SAFEARRAY* pArray=::SafeArrayCreate(VT_UI1,1,bound);
- //安全数组赋值;
- BYTE* pCommon=new BYTE[10];//连续的内存
- for(int i=0;i<10;i++)
- {
- pCommon[i]=i;
- }
- for(long j=0;j<10;j++)
- {
- SafeArrayPutElement(pArray,&j,pCommon++);
- }
- //访问安全数组;
- BYTE* pBuffer=NULL;
- SafeArrayAccessData(pArray,(void **)&pBuffer);
- for(int k=0;k<pArray->rgsabound->cElements;k++)
- {
- BYTE bTemp=pBuffer[k];
- }
- SafeArrayUnaccessData(pArray);
- //释放安全数组;
- SafeArrayDestroy(pArray);
- }
- 3.对话框项目DemoBlobInsert01保存及读取图片的相关数据库操作按钮功能:
- 先初始化环境:
- ::CoInitialize(NULL);//初始化
- 3.1项目DemoBlobInsert01为实现保存功能:
- --->实现图片保存数据库按钮功能:
- void CDemoBlobInsertDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- CString strPath="c:\source.bmp";//图片路径
- _ConnectionPtr conn;//连接智能指针
- conn.CreateInstance(__uuidof(Connection));
- //连接数据库源相关参数
- conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena"),_bstr_t(""),_bstr_t("tiger"),-1);
- _RecordsetPtr rs;//对应查询结果链表
- rs.CreateInstance(__uuidof(Recordset));
- //与前面项目相同的地方(离线数据库操作)
- rs->Open(_variant_t("select * from ocyIMGBooks"),
- conn.GetInterfacePtr(),
- adOpenDynamic,
- adLockPessimistic,
- adCmdText);
- rs->AddNew();//添加一个新节点
- //首先插入非BLOB字段;
- rs->Fields->GetItem(_variant_t("BookISNB"))->Value=_variant_t((long)123);
- rs->Fields->GetItem(_variant_t("BookName"))->Value=_variant_t("adsf");
- rs->Fields->GetItem(_variant_t("BookAuthor"))->Value=_variant_t("adsf");
- //插入BLOB字段;
- int iBufferSize=1024*200;//图片大小
- BYTE* pBuffer=new BYTE[iBufferSize];
- SAFEARRAYBOUND bd[1];
- bd[0].cElements=iBufferSize;
- bd[0].lLbound=0;
- SAFEARRAY* pArray=SafeArrayCreate(VT_UI1,1,bd);
- //打开文件
- CFile fsource;
- CFileException ex;
- fsource.Open(strPath,CFile::modeRead,&ex);
- int iReaded=0;
- do
- {
- BYTE* pTemp=pBuffer;
- iReaded=fsource.Read(pBuffer,iBufferSize);//读取二进制文件
- for(long i=0;i<iReaded;i++)
- {
- SafeArrayPutElement(pArray,&i,pTemp++);//复制二进制文件
- }
- VARIANT mydata;
- mydata.vt=VT_ARRAY|VT_UI1;
- mydata.parray=pArray;//复制二进制文件
- rs->Fields->GetItem("BookImage")->AppendChunk(mydata);//添加二进制文件
- } while (iReaded==iBufferSize);
- rs->Update();
- rs->Close();
- conn->Close();
- MessageBox("ok");
- }
- 3.2项目DemoBlobInsert02为实现读取功能:
- void CDemoBlobInsertDlg::OnButton2()
- {
- // TODO: Add your control notification handler code here
- CString strPath="c:\source_bak.bmp";
- _ConnectionPtr conn;
- conn.CreateInstance(__uuidof(Connection));
- conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena"),_bstr_t(""),_bstr_t("tiger"),-1);
- _RecordsetPtr rs;
- rs.CreateInstance(__uuidof(Recordset));
- //查询指定数据操作相关
- rs->Open(_variant_t("select * from ocyIMGBooks where Bookisnb=123"),
- conn.GetInterfacePtr(),
- adOpenDynamic,
- adLockPessimistic,
- adCmdText);
- //打开文件
- CFile fTarget;
- CFileException ex;
- fTarget.Open(strPath,CFile::modeCreate|CFile::modeWrite,&ex);
- int iBufferSize=1024*100;
- _variant_t vt;//不能是VARIANT类型
- int iReaded=0;
- //读数据
- if(!rs->adEOF)
- {
- long iAllSize=rs->GetFields()->GetItem("BookImage")->ActualSize;
- int iReadedAll=0;
- do{
- BYTE* pBuf=NULL;
- vt=rs->Fields->GetItem("BookImage")->GetChunk(1024*100);
- iReaded=vt.parray->rgsabound->cElements;
- SafeArrayAccessData(vt.parray,(void **)&pBuf);//安全数组指针指向一般指针
- fTarget.Write(pBuf,iReaded);
- fTarget.Flush();
- SafeArrayUnaccessData(vt.parray);//关闭安全数组
- iReadedAll+=iReaded;
- }while(iReadedAll<iAllSize);
- }
- rs->Close();
- conn->Close();
- fTarget.Close();
- MessageBox("ok!");
- }
- ---03.07---------------------day18---------------------------------
- 1.项目DemoBlobInsert01修改day17中把图片读入数据库出现的一个BUG:
- void CDemoBlobInsertDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- CString strPath="c:\source.bmp";//读取图片路径
- _ConnectionPtr conn;//连接数据库智能指针
- conn.CreateInstance(__uuidof(Connection));//生成连接实例
- //打开的数据源
- conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=abc"),_bstr_t(""),_bstr_t("tiger"),-1);
- _RecordsetPtr rs;//对应查询结果的链表
- rs.CreateInstance(__uuidof(Recordset));//生成查询实例
- //查询字句及打开方式
- rs->Open(_variant_t("select * from MyIMGBooks"),
- conn.GetInterfacePtr(),
- adOpenDynamic,
- adLockPessimistic,
- adCmdText);
- rs->AddNew();
- //首先插入非BLOB字段;
- rs->Fields->GetItem(_variant_t("BookISNB"))->Value=_variant_t((long)123);
- rs->Fields->GetItem(_variant_t("BookName"))->Value=_variant_t("adsf");
- rs->Fields->GetItem(_variant_t("BookAuthor"))->Value=_variant_t("adsf");
- //插入BLOB字段;
- int iBufferSize=1024*200;//一次读取内存200K个字节
- BYTE* pBuffer=new BYTE[iBufferSize];//连续的字节内存空间
- SAFEARRAYBOUND bd[1];//设定安全数组边界
- bd[0].cElements=iBufferSize;//安全数组最大下标200K
- bd[0].lLbound=0;
- //创建字节、1维、指定边界的安全数组
- SAFEARRAY* pArray=SafeArrayCreate(VT_UI1,1,bd);
- //打开文件
- CFile fsource;
- CFileException ex;//异常保存
- fsource.Open(strPath,CFile::modeRead,&ex);
- int iReaded=0;
- do
- {//获取连续字节内存的首地址
- BYTE* pTemp=pBuffer;
- //以指定大小200K读取图片到连续内存中,iReaded为读到数据的实际大小(最后一次不一定是200K)
- iReaded=fsource.Read(pBuffer,iBufferSize);
- //修改BUG;如果iReaded最后一次不是200K就要出现指定符合iReaded大小边界的安全数组
- if(iReaded!=iBufferSize)
- {
- SafeArrayDestroy(pArray);//清空之前的安全数组
- pArray=NULL;
- SAFEARRAYBOUND bd1[1];
- bd1[0].cElements=iReaded;//指定符合iReaded大小边界的安全数组
- bd1[0].lLbound=0;
- pArray=SafeArrayCreate(VT_UI1,1,bd1);
- }
- for(long i=0;i<iReaded;i++)
- {//把连续内存中的二进制数据复制到安全数组中去
- SafeArrayPutElement(pArray,&i,pTemp++);
- }
- VARIANT mydata;//智能型数据
- mydata.vt=VT_ARRAY|VT_UI1;//数组及字节类型
- mydata.parray=pArray;//获取(保存图片二进制数据)安全数组入口
- //根据属性名索引把mydata中的图片二进制数据上传(追加)到数据库
- rs->Fields->GetItem("BookImage")->AppendChunk(mydata);
- } while (iReaded==iBufferSize);
- //更新数据库
- rs->Update();
- rs->Close();
- conn->Close();
- MessageBox("ok");
- }
- 2.项目AddressAdmin做一个包含(连接数据库)包含数据、图片、(各种功能)按钮的简易的人事管理系统:
- 2.1项目AddressAdmin01只做了对话框界面。
- 2.2项目AddressAdmin02~04图片显示按钮功能初级代码:
- 在标准头文件中添加#include <afxdlgs.h>//CFileDialog的头文件
- 在头文件中声明一个方法和一个变量(在构造函数中初始化):
- public:
- HBITMAP ShowImage();
- LPSTR pBuffer;
- void CAddressAdminDlg::OnButton8()
- {
- // TODO: Add your control notification handler code here
- CFileDialog dlg(TRUE);//打开一个浏览框(选择图片)
- dlg.DoModal();//弹出对话框有效
- CString strFilePath=dlg.GetPathName();//获取该图片的路径(空则为0)
- if(strFilePath.GetLength()>0) //地址有效的时候
- {
- CFile fsource;
- CFileException fex;
- fsource.Open(strFilePath,CFile::modeRead,&fex);//读取的方式打开
- int iSize=fsource.GetLength();//获取图片大小
- if(this->pBuffer!=NULL)//pBuffer在头文件中已定义并在构造函数中初始化了
- {
- delete this->pBuffer;
- this->pBuffer=NULL;
- }
- this->pBuffer=new CHAR[iSize];//连续的字符内存空间
- fsource.Read(this->pBuffer,iSize);//读到缓冲区
- }
- //显示图片;
- this->ShowImage();
- }
- HBITMAP CAddressAdminDlg::ShowImage()
- {
- LPSTR pTempBuffer=this->pBuffer;//由上面的步骤,pBuffer已获取图片二进制数据
- BITMAPFILEHEADER bf;//要过滤的文件头
- int leng=sizeof(bf);//获取要过滤的文件头的长度
- LPSTR pInfor=pTempBuffer+leng;//指针移动指定的长度即把文件头给过滤掉了
- BITMAPINFOHEADER& pInfHeader=*(LPBITMAPINFOHEADER)(pInfor);//强转成bmp格式类型
- BITMAPINFO& pInfo =*(LPBITMAPINFO)(pInfor);//再转
- LPVOID pRGBData =(LPVOID)(pInfo.bmiColors);//void类型指针
- CClientDC dc(this);//用于在窗口客户区画图
- HBITMAP hResult=CreateDIBitmap(dc.m_hDC,&pInfHeader,CBM_INIT,pRGBData,&pInfo,DIB_RGB_COLORS);
- return hResult;
- //BITMAPFILEHEADER; //*.bmp文件头;
- //BITMAPINFOHEADER; //*.bmp格式的信息头;
- //BITMAPINFO; //*.bmp格式主体;
- //RGBQUAD //*.bmp像素格式;
- }
- //在OnPaint()中调用,真正的显示图片到Cstatic中
- void CAddressAdminDlg::show()
- {
- if(this->p_CurrentImag!=NULL)//获取图片信息无误
- {
- CStatic* pStc=(CStatic*)this->GetDlgItem(IDC_STATICimg);
- CPaintDC dc(pStc);
- RECT rt;//定义矩形的左上角坐标和右下角坐标
- pStc->GetClientRect(&rt);
- CDC MemDc;
- //用于在向实际的兼容设备表面发送图象之前在内存中作好准备
- MemDc.CreateCompatibleDC(&dc);//该函数仅用于创建与支持光栅操作的设备上下文
- HBITMAP pTemp=(HBITMAP)MemDc.SelectObject(this->p_CurrentImag);
- dc.BitBlt(0,//指定目标矩形左上角的逻辑横坐标
- 0,//指定目标矩形左上角的逻辑纵坐标
- rt.right,//指定目标矩形和源位图的宽度
- rt.bottom,//指定目标矩形和源位图的高度
- &MemDc,//指向CDC对象的指针,标识待拷贝位图的设备上下文
- 0,//指定源位图左上角的逻辑横坐标
- 0,//指定源位图左上角的逻辑纵坐标
- SRCCOPY);//指定要执行的光栅操作
- MemDc.SelectObject(pTemp);//返回被替代的对象的指针
- }
- }
- 2.3项目AddressAdmin05~06实现按钮update上传数据到数据库功能:
- 在OnInitDialog()中添加 ::CoInitialize(NULL);//数据库环境初始化
- //update上传数据到服务器数据库
- void CAddressAdminDlg::OnButton6()
- {
- // TODO: Add your control notification handler code here
- this->UpdateData(TRUE);//获取文本框数据
- _ConnectionPtr conn;
- conn.CreateInstance(__uuidof(Connection));
- conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena"),_bstr_t(""),_bstr_t("tiger"),-1);
- _RecordsetPtr rs;
- rs.CreateInstance(__uuidof(Recordset));
- rs->Open(_variant_t("select * from MyAddress_ocy"),conn.GetInterfacePtr(),adOpenDynamic,adLockPessimistic,adCmdText);
- rs->AddNew();//添加一个新节点
- //添加非B数据
- rs->GetFields()->GetItem(_variant_t("addr_name"))->Value=_variant_t(this->m_name.AllocSysString());
- rs->GetFields()->GetItem(_variant_t("addr_sex"))->Value=_variant_t(this->m_sex.AllocSysString());
- rs->GetFields()->GetItem(_variant_t("addr_address"))->Value=_variant_t(this->m_address.AllocSysString());
- rs->GetFields()->GetItem(_variant_t("addr_age"))->Value=_variant_t(this->m_age);
- //写b字段;
- SAFEARRAYBOUND bd[1];
- bd[0].lLbound=0;
- bd[0].cElements=this->iSize;//安全数组大小声明为long类型
- SAFEARRAY* pArray=SafeArrayCreate(VT_UI1,1,bd);//初级安全数组
- char* pTemp=(char*)(this->pBuffer);//指向含有图片数据的缓冲区
- for(long i=0;i<iSize;i++)
- {
- SafeArrayPutElement(pArray,&i,pTemp++);//拷贝给安全数组
- }
- VARIANT abc;
- abc.vt=VT_ARRAY | VT_UI1;
- abc.parray=pArray;
- try{
- FieldPtr fld=rs->Fields->GetItem("addr_Picture");
- fld->AppendChunk(abc);//安全数组的数据添加到服务器
- }
- catch(_com_error ex)
- {
- int i=0;
- i++;
- }
- rs->Update();
- rs->Close();
- conn->Close();
- }
- 2.4项目AddressAdmin07打开对话框时即可看到第一条数据信息:
- 在初始化函数OnInitDialog()中添加可实现该功能:
- //连接数据库,把button6 连接数据库的句子搬到这来
- conn.CreateInstance(__uuidof(Connection));
- conn->Open(_bstr_t("Provider=OraOLEDB.Oracle.1;User Id=scott;Data Source=tarena"),_bstr_t(""),_bstr_t("tiger"),-1);
- rs.CreateInstance(__uuidof(Recordset));
- rs->Open(_variant_t("select * from MyAddress_ocy"),conn.GetInterfacePtr(),adOpenDynamic,adLockPessimistic,adCmdText);
- //提取第一条记录;=====>以下在项目AddressAdmin09中该为ShowData()代码用this->ShowData();取代
- if(!rs->adEOF)//判断是否有数据
- {//根据属性名赋值
- _variant_t vtname=rs->Fields->GetItem("addr_name")->Value;
- _variant_t vtage=rs->Fields->GetItem("addr_age")->Value;
- _variant_t vtsex=rs->Fields->GetItem("addr_sex")->Value;
- _variant_t vtaddress=rs->Fields->GetItem("addr_address")->Value;
- //万能型转成所需的内存数据类型
- this->m_age=vtage.lVal;
- this->m_name=CString(vtname.bstrVal);
- this->m_sex=CString(vtsex.bstrVal);
- this->m_address=CString(vtaddress.bstrVal);
- this->UpdateData(FALSE);//上传内存数据到对话框
- this->iSize=rs->Fields->GetItem("addr_picture")->ActualSize;//获取图片大小
- if(this->pBuffer!=NULL)//目的是在下一步前确保>pBuffer为空
- {
- delete this->pBuffer;
- this->pBuffer=NULL;
- }
- this->pBuffer=new CHAR[this->iSize];//开辟和图片大小一致的内存
- //复制图片二进制数据到万能指针中
- _variant_t vtdata=rs->Fields->GetItem("addr_picture")->GetChunk(this->iSize);
- BYTE* pTemp=NULL;
- //万能指针类型转成一般类型
- SafeArrayAccessData(vtdata.parray,(void **)&pTemp);
- //内存复制
- memcpy(this->pBuffer,pTemp,this->iSize);
- //解开安全数组的锁
- SafeArrayUnaccessData(vtdata.parray);
- //显示图片;
- this->p_CurrentImag=this->ShowImage();
- //刷新屏幕;关联静态控件
- CStatic* pDc=(CStatic*)(this->GetDlgItem(IDC_STATICimg));
- pDc->Invalidate();
- 2.5项目AddressAdmin09添加两个按钮功能及数据刷新:
- void CAddressAdminDlg::ShowData()
- {
- //提取第一条记录;
- if(!rs->adEOF && !rs->BOF)
- {
- _variant_t vtname=rs->Fields->GetItem("addr_name")->Value;
- _variant_t vtage=rs->Fields->GetItem("addr_age")->Value;
- _variant_t vtsex=rs->Fields->GetItem("addr_sex")->Value;
- _variant_t vtaddress=rs->Fields->GetItem("addr_address")->Value;
- this->m_age=vtage.lVal;
- this->m_name=CString(vtname.bstrVal);
- this->m_sex=CString(vtsex.bstrVal);
- this->m_address=CString(vtaddress.bstrVal);
- this->UpdateData(FALSE);
- this->iSize=rs->Fields->GetItem("addr_picture")->ActualSize;
- if(this->pBuffer!=NULL)
- {
- delete this->pBuffer;
- this->pBuffer=NULL;
- }
- this->pBuffer=new CHAR[this->iSize];
- _variant_t vtdata=rs->Fields->GetItem("addr_picture")->GetChunk(this->iSize);
- BYTE* pTemp=NULL;
- SafeArrayAccessData(vtdata.parray,(void **)&pTemp);
- memcpy(this->pBuffer,pTemp,this->iSize);
- SafeArrayUnaccessData(vtdata.parray);
- //显示图片;
- this->p_CurrentImag=this->ShowImage();
- //刷新屏幕;
- CStatic* pDc=(CStatic*)(this->GetDlgItem(IDC_STATICimg));
- pDc->Invalidate();
- this->Invalidate(FALSE);
- }
- }
- //显示下一条数据信息
- void CAddressAdminDlg::OnButton3()
- {
- // TODO: Add your control notification handler code here
- if(!this->rs->adEOF)
- {
- this->rs->MoveNext();//往下移
- this->ShowData();
- }
- }
- //显示上一条数据信息
- void CAddressAdminDlg::OnButton2()
- {
- // TODO: Add your control notification handler code here
- if(!this->rs->BOF)
- {
- this->rs->MovePrevious();//往上移
- this->ShowData();
- }
- }
- 2.6项目AddressAdmin10添加删除、更该功能按钮功能:
- //删除数据
- void CAddressAdminDlg::OnButton7()
- {
- // TODO: Add your control notification handler code here
- if(!this->rs->adEOF && !this->rs->BOF)
- {
- this->rs->Delete(adAffectCurrent);
- this->rs->Update();
- this->rs->MoveNext();
- this->ShowData();
- }
- }
- //更改数据
- void CAddressAdminDlg::OnButton9()
- {
- // TODO: Add your control notification handler code here
- this->UpdateData();
- rs->GetFields()->GetItem(_variant_t("addr_name"))->Value=_variant_t(this->m_name.AllocSysString());
- rs->GetFields()->GetItem(_variant_t("addr_sex"))->Value=_variant_t(this->m_sex.AllocSysString());
- rs->GetFields()->GetItem(_variant_t("addr_address"))->Value=_variant_t(this->m_address.AllocSysString());
- rs->GetFields()->GetItem(_variant_t("addr_age"))->Value=_variant_t(this->m_age);
- rs->Update();
- }