不用atl做组件该怎样做??? 用mfc做。有没有一个小例子呀??? com specificationimplement IUnknow, IClassFactory, .. and four export functions. 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 ATL也支持MFC的。直接用com写起来有点麻烦 以下是我在用MFC建立COM服务器时总结的,不过现在我都用ATL了,因为太麻烦。用MFC建立COM服务器对象的框架步骤(任务1:建立第一个COM服务器任务2:用VC调用COM接口任务3:用VB调用COM接口任务4:给接口增加新的属性和方法任务5:增加新的自定义接口任务6:继承接口类例子程序在tecsp/docs/samples/comMFCDemo下COM服务器:comMFCDemoCOM对象:coDrawObj,coDrawObjLine,coDrawObjRect任务1:建立第一个COM服务器 操作: 1. 新建一个工程comMFCDemo,MFC AppWizard(dll),Regular DLL using shared MFC DLL,Automation. 说明:此时已建立COM服务器的基本框架,包括用于实例化和注册用的 DllCanUnloadNow(),DllGetObject(),DllRegisterServer()三个函数. 2. 在工程中加入mfcdual.h,mfcdual.cpp文件(在tecsp/comm目录中,应将该目录放在头文件查找路径中) 在stdafx.h中加入 #include "mfcdual.h" #include "comMFCDemo_i.h" 说明:mfcdual.h中定义了一些用于简化编程的宏定义,减少MFC COM编程的重复劳动.按照本文档维护COM对象接口将非常轻松简明. comMFCDemo_i.h是midl从odl文件中生成的,包括COM对象,接口定义,GUID定义等. 3. 编译选项 Project => Settings... => MIDL => Project Options 加入:/h comMFCDemo_i.h MIDL将编译odl文件生成类型库comMFCDemo.tlb,头文件comMFCDemo_i.h,定义文件comMFCDemo_i.c. 任务2:新增一个COM对象 1. 用Class Wizard建立一个新类:CcoDrawObj,基类为CCmdTarget,选择Createable by type ID: comMFCDemo.coDrawObj. 说明:为避免手工添加接口定义,先选择自动化接口,将会自动生成odl文件和相应的接口定义,只需做少量的修改工作即可.选择Createable by type ID是为了能够通过类厂来创建COM对象. 2. 修改odl文件中IDualDrawObj的定义 2.1 将 [ uuid(13144AD4-ECC8-46F4-88F7-2FAC305595EA) ] dispinterface IcoDrawObj 改成: [ uuid(13144AD4-ECC8-46F4-88F7-2FAC305595EA), oleautomation, dual ] interface IcoDrawObj : IDispatch interface IcoDrawObj : IDispatch 说明:建议将COM对象的缺省接口定义成双接口,可以在多种环境中使用. 2.2 删除properties: 和 methods:这两行 2.3 在{}中定义属性和方法 // IcoDrawObj 属性: [propput, helpstring("横坐标")] HRESULT x([in] short new_x); [propget, helpstring("横坐标")] HRESULT x([out, retval] short* ret_x); // IcoDrawObj 方法: [helpstring("绘制图形")] HRESULT Draw(); 说明:上面的注释应保留以方便接口继承时使用;helpstring用于属性和方法的注释说明,应加上;只读属性删除propput定义的两行. 注意new_x和ret_x变量的书写方法,put属性使用new_前缀加上属性名,get属性使用ret_前缀加上属性名,这样是为了方便使用宏定义来自动生成属性声明和实现. 2.4 修改coclass定义 将 coclass coDrawObj { [default] dispinterface IcoDrawObj; }; 改成: coclass coDrawObj { [default] interface IcoDrawObj; }; 2.5 编译odl文件 选择FileView,在comMFCDemo.odl文件上点击右键,选择Compile comMFCDemo.odl,将生成类型库comMFCDemo.tlb,头文件comMFCDemo_i.h和定义文件comMFCDemo_i.c. 将comMFCDemo_i.h和comMFCDemo_i.c加入工程中. 选择Project => Settings... => comMFCDemo_i.c,在右侧面板选择C/C++ => Category:Precompiled Headers => Not using precompiled headers 3. 修改COM对象头文件coDrawObj.h文件 3.1 加入属性对应的内部成员变量:protected,m_前缀加上属性名 short m_x; 3.2 接口声明 // ============== // 双接口支持开始 // ============== // ---------------------- // IcoDrawObj接口声明开始 // ---------------------- // 此处用宏定义是为了支持接口继承 ,在此处添加属性和方法#define DECLARE_INTERFACE_PART_IcoDrawObj \ STDMETHOD(get_x)(THIS_ short FAR* ret_x); \ STDMETHOD(put_x)(THIS_ short new_x); \ STDMETHOD(Draw)(); \ BEGIN_DUAL_INTERFACE_PART(coDrawObj, IcoDrawObj) DECLARE_INTERFACE_PART_IcoDrawObj END_DUAL_INTERFACE_PART(coDrawObj) 需要修改: DECLARE_INTERFACE_PART_IcoDrawObj - IcoDrawObj是接口名字 BEGIN_DUAL_INTERFACE_PART(coDrawObj, IcoDrawObj) - coDrawObj是组件名字,IcoDrawObj是接口名字。 END_DUAL_INTERFACE_PART(coDrawObj) - coDrawObj是组件名字,IcoDrawObj是接口名字。 // ---------------------- // IcoDrawObj接口声明结束 // ---------------------- // ISupportErrorInfo支持 DECLARE_DUAL_ERRORINFO() // ============== // 双接口支持结束 // ============== 说明:需要注意的是宏定义DECLARE_INTERFACE_PART_IcoDrawObj,最后面是接口的名字.该宏主要用于接口继承时,在子接口声明中声明父接口的属性和方法.以后也在该宏定义中添加新的属性和方法的声明. 3.3 属性读写实现 说明:属性读写实现基本结构都很相似,为减少代码书写量和书写错误,特采用宏定义方式. 需要修改部份: 宏定义IMPLEMENT_PROPERTIES_IcoDrawObj是为了用于接口继承,最后面是接口的名字。 目前实现了两种属性读写: 普通属性(short, float等常规类型) DECLARE_PUT_PROPERTY(objClass, baseClass, x)(short new_x) - 需改动部份:x 是属性名字,(short new_x) 与声明中相同。 IMPLEMENT_PUT_PROPERTY(objClass, baseClass, x) - 需改动部份:x 是属性名字。 DECLARE_GET_PROPERTY(objClass, baseClass, x)(short FAR* ret_x) - 需改动部份:x 是属性名字,(short FAR* ret_x) 与声明中相同。 IMPLEMENT_GET_PROPERTY(objClass, baseClass, x) - 需改动部份:x 是属性名字。 接口指针属性 因为接口指针的赋值需要调用AddRef方法,故特别增加此宏定义。使用的唯一不同之处在于PROPERTY后面增加_INTERFACE后缀。// ================// 属性读写实现开始// ================// ---------------------------// IcoDrawObj 属性读写实现开始// ---------------------------#define IMPLEMENT_PROPERTIES_IcoDrawObj(objClass, baseClass) \DECLARE_PUT_PROPERTY(objClass, baseClass, x)(short new_x) \ IMPLEMENT_PUT_PROPERTY(objClass, baseClass, x) \DECLARE_GET_PROPERTY(objClass, baseClass, x)(short FAR* ret_x) \ IMPLEMENT_GET_PROPERTY(objClass, baseClass, x) \// ---------------------------// IcoDrawObj 属性读写实现结束// ---------------------------// ================// 属性读写实现结束// ================// ============// 方法实现开始// ============ 3.4 方法实现 MFC采用嵌套类的形式实现多接口,方法的实现基本结构相同,故采用宏定义减少代码书写量和书写错误。 解决方法是每个接口的方法都调用嵌套父类的同名函数,这样嵌套类方法的实现全部是同一种结构,可以用宏定义生成。 对每一个方法在嵌套父类中创建一个proteced virtual的同名成员函数,建立一个以接口名字命名的实现文件IcoDrawObj.cpp,将同名成员函数的实现放在里面。这样在接口定义好后,可以让程序员只编写这个文件中的函数实现,达到统一控制接口定义的目的。 3.4.1 嵌套类方法实现 以下嵌套类方法实现的宏定义放在头文件coDrawObj.h中属性读写实现的后面。 需要修改部份: 宏定义IMPLEMENT_METHODS_IcoDrawObj用于接口继承,最后面是接口的名字。 STDMETHODIMP objClass::X##baseClass::Draw()最后的方法名字 pThis->Draw(); 最后的方法名字// ============// 方法实现开始// ============// -----------------------// IcoDrawObj 方法实现开始// -----------------------#define IMPLEMENT_METHODS_IcoDrawObj(objClass, baseClass) \STDMETHODIMP objClass::X##baseClass::Draw() \{ \ BEGIN_NEST_INTERFACE_FRAME(objClass, baseClass) \ pThis->Draw();\ END_NEST_INTERFACE_FRAME \} \// -----------------------// IcoDrawObj 方法实现结束// -----------------------// ============// 方法实现结束// ============ 3.4.2 嵌套父类方法实现 IcoDrawObj.cpp文件样本(接口定义完成后,程序员仅需编写此文件中的函数实现即可):// IcoDrawObj.cpp#include "stdafx.h"#include "coDrawObj.h"void CcoDrawObj::Draw(){ AfxMessageBox( "This is coDrawObj.");} to :softsprite(软件精灵) 呵呵.. 感动! 国外的自己的 ?顾不得了,给一份把: [email protected] thanks. 能给我一份吗?[email protected] thankyou . 给我发一份吧。[email protected] 自己down: http://www.codeguru.com/shell/ctxmenu.shtml 修改RecordSet记录集中某一记录出问题,各位大侠给看看 获取子窗口对象 如何实现类似Windows XP安全中心那样知道病毒防护是否打开 如何CView中切分两个窗口CUpView和CDownView? VC怎么对注册表编程,给否给点详细的资料和例子,不胜感激!!~~ 请问richeditctrl 中关于EM_AUTOURLDETECT消息 鼠标坐标问题?? const char * ="hello";怎么用 一个数据库连接问题 VC 6.0,如何获取资源视图内的属性页的大小信息 求助:WinExec函数的例子!急用!!!thanks! 如何自己编写控件?
直接用com写起来有点麻烦
任务2:用VC调用COM接口
任务3:用VB调用COM接口
任务4:给接口增加新的属性和方法
任务5:增加新的自定义接口
任务6:继承接口类
例子程序在tecsp/docs/samples/comMFCDemo下COM服务器:comMFCDemo
COM对象:coDrawObj,coDrawObjLine,coDrawObjRect
任务1:建立第一个COM服务器
操作:
1. 新建一个工程comMFCDemo,MFC AppWizard(dll),Regular DLL using shared MFC DLL,Automation.
说明:此时已建立COM服务器的基本框架,包括用于实例化和注册用的
DllCanUnloadNow(),DllGetObject(),DllRegisterServer()三个函数. 2. 在工程中加入mfcdual.h,mfcdual.cpp文件(在tecsp/comm目录中,应将该目录放在头文件查找路径中)
在stdafx.h中加入
#include "mfcdual.h"
#include "comMFCDemo_i.h"
说明:mfcdual.h中定义了一些用于简化编程的宏定义,减少MFC COM编程的重复劳动.按照本文档维护COM对象接口将非常轻松简明.
comMFCDemo_i.h是midl从odl文件中生成的,包括COM对象,接口定义,GUID定义等. 3. 编译选项
Project => Settings... => MIDL => Project Options
加入:/h comMFCDemo_i.h
MIDL将编译odl文件生成类型库comMFCDemo.tlb,头文件comMFCDemo_i.h,定义文件comMFCDemo_i.c.
任务2:新增一个COM对象
1. 用Class Wizard建立一个新类:CcoDrawObj,基类为CCmdTarget,选择Createable by type ID: comMFCDemo.coDrawObj.
说明:为避免手工添加接口定义,先选择自动化接口,将会自动生成odl文件和相应的接口定义,只需做少量的修改工作即可.选择Createable by type ID是为了能够通过类厂来创建COM对象. 2. 修改odl文件中IDualDrawObj的定义
2.1 将
[ uuid(13144AD4-ECC8-46F4-88F7-2FAC305595EA) ]
dispinterface IcoDrawObj
改成:
[ uuid(13144AD4-ECC8-46F4-88F7-2FAC305595EA),
oleautomation,
dual
]
interface IcoDrawObj : IDispatch
interface IcoDrawObj : IDispatch
说明:建议将COM对象的缺省接口定义成双接口,可以在多种环境中使用. 2.2 删除properties: 和 methods:这两行 2.3 在{}中定义属性和方法 // IcoDrawObj 属性:
[propput, helpstring("横坐标")]
HRESULT x([in] short new_x);
[propget, helpstring("横坐标")]
HRESULT x([out, retval] short* ret_x);
// IcoDrawObj 方法:
[helpstring("绘制图形")]
HRESULT Draw();
说明:上面的注释应保留以方便接口继承时使用;helpstring用于属性和方法的注释说明,应加上;只读属性删除propput定义的两行.
注意new_x和ret_x变量的书写方法,put属性使用new_前缀加上属性名,get属性使用ret_前缀加上属性名,这样是为了方便使用宏定义来自动生成属性声明和实现. 2.4 修改coclass定义
将
coclass coDrawObj
{
[default] dispinterface IcoDrawObj;
};
改成:
coclass coDrawObj
{
[default] interface IcoDrawObj;
};
2.5 编译odl文件
选择FileView,在comMFCDemo.odl文件上点击右键,选择Compile comMFCDemo.odl,将生成类型库comMFCDemo.tlb,头文件comMFCDemo_i.h和定义文件comMFCDemo_i.c.
将comMFCDemo_i.h和comMFCDemo_i.c加入工程中.
选择Project => Settings... => comMFCDemo_i.c,在右侧面板选择C/C++ => Category:Precompiled Headers => Not using precompiled headers
3. 修改COM对象头文件coDrawObj.h文件
3.1 加入属性对应的内部成员变量:protected,m_前缀加上属性名
short m_x;
3.2 接口声明
// ==============
// 双接口支持开始
// ==============
// ----------------------
// IcoDrawObj接口声明开始
// ---------------------- // 此处用宏定义是为了支持接口继承 ,在此处添加属性和方法
#define DECLARE_INTERFACE_PART_IcoDrawObj \
STDMETHOD(get_x)(THIS_ short FAR* ret_x); \
STDMETHOD(put_x)(THIS_ short new_x); \
STDMETHOD(Draw)(); \ BEGIN_DUAL_INTERFACE_PART(coDrawObj, IcoDrawObj)
DECLARE_INTERFACE_PART_IcoDrawObj
END_DUAL_INTERFACE_PART(coDrawObj) 需要修改:
DECLARE_INTERFACE_PART_IcoDrawObj - IcoDrawObj是接口名字
BEGIN_DUAL_INTERFACE_PART(coDrawObj, IcoDrawObj) - coDrawObj是组件名字,IcoDrawObj是接口名字。
END_DUAL_INTERFACE_PART(coDrawObj) - coDrawObj是组件名字,IcoDrawObj是接口名字。 // ----------------------
// IcoDrawObj接口声明结束
// ----------------------
// ISupportErrorInfo支持
DECLARE_DUAL_ERRORINFO()
// ==============
// 双接口支持结束
// ============== 说明:需要注意的是宏定义DECLARE_INTERFACE_PART_IcoDrawObj,最后面是接口的名字.该宏主要用于接口继承时,在子接口声明中声明父接口的属性和方法.以后也在该宏定义中添加新的属性和方法的声明. 3.3 属性读写实现
说明:属性读写实现基本结构都很相似,为减少代码书写量和书写错误,特采用宏定义方式.
需要修改部份:
宏定义IMPLEMENT_PROPERTIES_IcoDrawObj是为了用于接口继承,最后面是接口的名字。
目前实现了两种属性读写:
普通属性(short, float等常规类型)
DECLARE_PUT_PROPERTY(objClass, baseClass, x)(short new_x) - 需改动部份:x 是属性名字,(short new_x) 与声明中相同。
IMPLEMENT_PUT_PROPERTY(objClass, baseClass, x) - 需改动部份:x 是属性名字。
DECLARE_GET_PROPERTY(objClass, baseClass, x)(short FAR* ret_x) - 需改动部份:x 是属性名字,(short FAR* ret_x) 与声明中相同。
IMPLEMENT_GET_PROPERTY(objClass, baseClass, x) - 需改动部份:x 是属性名字。 接口指针属性
因为接口指针的赋值需要调用AddRef方法,故特别增加此宏定义。使用的唯一不同之处在于PROPERTY后面增加_INTERFACE后缀。// ================
// 属性读写实现开始
// ================// ---------------------------
// IcoDrawObj 属性读写实现开始
// ---------------------------#define IMPLEMENT_PROPERTIES_IcoDrawObj(objClass, baseClass) \
DECLARE_PUT_PROPERTY(objClass, baseClass, x)(short new_x) \
IMPLEMENT_PUT_PROPERTY(objClass, baseClass, x) \
DECLARE_GET_PROPERTY(objClass, baseClass, x)(short FAR* ret_x) \
IMPLEMENT_GET_PROPERTY(objClass, baseClass, x) \// ---------------------------
// IcoDrawObj 属性读写实现结束
// ---------------------------// ================
// 属性读写实现结束
// ================// ============
// 方法实现开始
// ============ 3.4 方法实现
MFC采用嵌套类的形式实现多接口,方法的实现基本结构相同,故采用宏定义减少代码书写量和书写错误。
解决方法是每个接口的方法都调用嵌套父类的同名函数,这样嵌套类方法的实现全部是同一种结构,可以用宏定义生成。
对每一个方法在嵌套父类中创建一个proteced virtual的同名成员函数,建立一个以接口名字命名的实现文件IcoDrawObj.cpp,将同名成员函数的实现放在里面。这样在接口定义好后,可以让程序员只编写这个文件中的函数实现,达到统一控制接口定义的目的。 3.4.1 嵌套类方法实现
以下嵌套类方法实现的宏定义放在头文件coDrawObj.h中属性读写实现的后面。
需要修改部份:
宏定义IMPLEMENT_METHODS_IcoDrawObj用于接口继承,最后面是接口的名字。
STDMETHODIMP objClass::X##baseClass::Draw()最后的方法名字
pThis->Draw(); 最后的方法名字// ============
// 方法实现开始
// ============// -----------------------
// IcoDrawObj 方法实现开始
// -----------------------#define IMPLEMENT_METHODS_IcoDrawObj(objClass, baseClass) \
STDMETHODIMP objClass::X##baseClass::Draw() \
{ \
BEGIN_NEST_INTERFACE_FRAME(objClass, baseClass) \
pThis->Draw();\
END_NEST_INTERFACE_FRAME \
} \// -----------------------
// IcoDrawObj 方法实现结束
// -----------------------// ============
// 方法实现结束
// ============ 3.4.2 嵌套父类方法实现
IcoDrawObj.cpp文件样本(接口定义完成后,程序员仅需编写此文件中的函数实现即可):// IcoDrawObj.cpp#include "stdafx.h"
#include "coDrawObj.h"void CcoDrawObj::Draw()
{
AfxMessageBox( "This is coDrawObj.");
}
[email protected]
http://www.codeguru.com/shell/ctxmenu.shtml