用ATL开发一个web控件,如何用属性返回值,给js调用

用ATL开发一个web控件,怎么用属性返回值,给js调用
我通过添加向导添加属性,只有get和put函数。
请各位帮帮忙,具体一点

------解决方案--------------------
【一】新建一工程,projects 选择 ATL COM AppWizard,project name 填写工程名称,这里填写MyCom,然后点击Ok

Service Type 有三个选项:
1:Dynamic link library(DLL) 建立一个 DLL 的组件程序 默认选择
2:Executable(EXE) 建立一个 EXE 的组件程序
3:Service 建立一个服务程序,系统启动后就会加载并执行的程序

保持默认

还有3个复选框:
1:Allow merging of proxy/stub code
选择该项表示把“代理/存根”代码合并到组件程序中,否则需要单独编译,单独注册代理存根程序。代理/存根,这个是什么概念?当调用者调用进程外或远程组件功能的时候,其实是代理/存根负责数据交换的,非特别要求一般不选。

2:Support MFC 支持MFC
除非有特殊的原因,我们写 ATL 程序,最好不要选择该项。你可能会说,如果没有MFC的支持,那CString怎么办呀?
  1、你会STL吗?可以用 STL 中的 string 代替;
  2、自己写个 MyString 类,嘿嘿;
  3、悄悄地、秘密地、不要告诉别人(特别是别告诉微软),把 MFC 中的 CString 源码拿过来用;
  4、使用 CComBSTR 类,至少也能简化我们字符串操作;
  5、直接用 API 操作字符串,反正我们大家学习 C 语言的时候,都是从这里干起的。


3:Support MTS
支持事务处理,也就是是否支持 COM+ 功能


保持默认


点击完成

在类视图ClassView里只有一个Globals文件夹,其下只看到一些全局方法及一个全局变量,没有任何的类,AppWizard只给我们生成了框架,类需要我们自己添加。


【二】添加组件类(即添加ATL对象):
Insert菜单->New ATL Object...
左边category(类别)列表框选择 objects(这个类别是内存组件),右边列表框选择 Simple Object,点击下一步,出现 New ATL Object 属性对话框:

<!--- Categroy 类别 注释--->
Categroy Objects 普通组件,是内存组件,这类组件没有界面的,封装的是一些方法,在asp中用CreateObject方式创建对象并调用其暴露的方法。
Categroy Controls ActiveX 控件,是控件组件,这类组件是有界面的,在HTML中只能通过<Object CLASSID="CLSID:XXX-XXX-XXX"></Object>方式来调用,在VC,VB中直接插入ActiveX控件的方式来使用。

Categroy Miscellaneous 辅助杂类组件
Categroy Data Access 数据库类组件
<!--- Categroy 类别 注释完毕--->

names属性页:
Short Name:填写要创建的类名,这里填写MyClass,其它输入框随着Short Name的填写而自动填写,也可以修改,但一般保持默认。

coclass:组件类名称
interface:接口名称
Type:类型说明
ProgId:创建对象时所引用的字符串,这里自动填写的MyCom.MyClass,在asp中:set obj=Server.createObject("MyCom.MyClass")



attribute 接口属性:
Threading Model 选择组件支持的线程模型。
Apartment:当在线程中调用组件函数的时候,这些调用会排队进行(默认的)
Interface 接口基本类型
Dual 表示支持双接口,同时支持自定义接口和 IDispatch 接口,一定要选这个(默认)
Aggregation 我们写的组件,将来是否允许被别人聚合(组件的使用2种:聚合和包容)使用,Only 表示必须被聚合才能使用,有点类似 C++ 中的纯虚类,你要是总工程师,只负责设计但不亲自写代码的话,才选择它。

Support ISupportErrorInfo 是否支持丰富信息的错误处理接口
Support Connection Points 是否支持连接点接口(事件、回调)
Free Threaded Marshaler 没有实现的功能


组件的重用方法有2个,聚合和包容


保持默认

点击<完成>

这个动作做了那些事情?
1:在MyCom.idl中,定义了一个接口 IMyClass,和定义了一个coclass组件类;
2:生成了MyClass.h,MyClass.cpp文件,创建了CMyClass类,这个类继承了IMyClass接口(底层封装的),还实现了其它一系列接口,其中包括自动化接口。

还做了许多其它隐含的工作,不过不用我们去过多的关心


现在 在类视图ClassView里 可以看到一个CMyClass类和一个IMyClass接口(前面的图标像平放的勺子)



【三】为接口IMyClass增加方法

在类视图中,鼠标右键IMyClass接口->Add Method...
Method Name:填写方法名称
Parameters:填写参数表,参数表的格式:

[in]表示参数方向是输入;[out]表示参数方向是输出;[out,retval]表示参数方向是输出,同时可以作为函数运算结果的返回值。一个函数中,可以有多个[in]、[out],但[retval]只能有一个,并且要和[out]组合后在最后一个位置。

如果有多个返回值,方法的返回值可以是BSTR*类型的,其它返回值只能是VARIANT* 类型的。
如果方法的“最终”返回值类型是BSTR,赋值时“不能是静态字符串”


比如:
STDMETHODIMP CTest::GetParam(long channelid, BSTR path_, VARIANT *r_pk, VARIANT *r_pp, BSTR *ret)
{
r_pk->vt=VT_BSTR;
r_pk->bstrVal=L"[1-9][\\d]{8}";

r_pp->vt=VT_BSTR;
r_pp->bstrVal=L"[1-9][\\d]{11}";

CString msg="ok";
*ret=msg.AllocSysString();

/*
//怪事:
*ret=L"ok";//静态字符串,客户端调用此方法后,方法的返回值为空

//如果方法的返回值类型是:VARIANT,即:VARIANT *ret
ret->vt=VT_BSTR;
ret->bstrVal=L"ok";//这样也不行的
*/
}

有返回值的方法:
[in]参数类型 参数名称,[in]参数类型 参数名称,...,[out,retval]返回值类型* 名称
无返回值的方法:
[in]参数类型 参数名称,[in]参数类型 参数名称,...

这里Method Name:填写:AddNumber
Parameters:[in]int x,[in]int y,[out,retval]int* ret

点击ok。

这个操作ClassWizard做了那些操作呢?
在c++中,要增加一个函数,需要修改两个地方:一是头文件(.h)中类的函数声明,二是函数体(.cpp)文件的实现处,而ATL还要修改一个地方,就是接口定义(IDL)文件,就是在接口中定义方法。