ATL组件和mfc ActiveX组件都可以供网页去调用,在我其它的博客中详细讲述了ocx组件的开发方式以及在网页中如何调用,在这篇博客中将详细讲解ATL组件的开发以及在网页中的调用。
1 创建ATL组件项目
打开vs2015,选择新建ATL项目
后面的页面都按照默认设置,最后一步点击完成。
项目创建完成后可以看到在解决方案资源管理器中有两个项目,一个项目名称为atl_test,一个项目为atl_testPS
2 添加ATL简单对象类
右键atl_test项目名称,选择添加–类
在打开的添加类对话框中选择添加ATL简单对象
在简称里输入类名,这里输入Test
点击完成,至此ATL简单对象类创建好了。
3 添加函数方法
在类视图中,右键ITest
右键ITest–添加–方法
输入方法名func
在参数特性里勾选in,这样先添加入参
输入入参以及入参类型
然后添加返回类型BSTR*
注意返回类型必须是指针类型
输入返回类型名称,然后勾选retval
点击添加,这样就添加了返回值了。
点击完成。
在Test.cpp中可以看到生成了该函数方法。
添加如下的代码:
#include "stdafx.h"
#include"Test.h"
#include<iostream>
#include<Windows.h>
#include<comutil.h>
using namespace std;
/*
项目属性--C/C++ -- 语言--将Wchar_t设置为内置类型选择是
然后添加comsuppw.lib这个lib库
如果选择否,就添加comsupp.lib这个lib库
*/
#pragma comment(lib,"comsuppw.lib")
// CTest
STDMETHODIMP CTest::func(BSTR name, BSTR* ret)
{
// TODO: 在此添加实现代码
//name为入参
string s1 = _com_util::ConvertBSTRToString(name);
s1 = "from C++" + s1;
//ret为返回值
BSTR bstr_ret = _com_util::ConvertStringToBSTR(s1.c_str());
*ret =bstr_ret;
SysFreeString(bstr_ret);//释放BSTR变量内存
return S_OK;
}
然后右键atl_test这个项目,选择生成
这样就成功生成了ATL组件的dll库了。
4 注册ATL组件库
以管理员权限打开cmd
以cd命令进入到组件库的那个目录
然后输入注册命令:
regsvr32 atl_test.dll
可以看到注册成功
5 在html中使用js进行调用
在项目的idl文件atl_test.idl中可以查看该组件的classid,就是importlib这行代码下面的那个id
然后在网页中object元素中引入这个id就可以调用这个控件
网页中调用代码如下:
<html>
<head>
<title>test</title>
<meta charset="utf-8" />
</head>
<script type="text/javascript">
function test1() {
var ret=atl.func("hello");
alert(ret);
}
</script>
<body>
<object id=atl border=0 classid=CLSID:0F9024DF-450A-4B8B-B5B8-2B49ABA2E49D width="100" height="100";>
</object>
<div align="center">
<input class="submit_01" type="button" value="ATL控件测试" onclick="test1()" />
</div>
</body>
</html>
使用IE浏览器打开这个网页,点击按钮
提示ActiveX控件的提示,点击是
可以看到成功调用了该函数。
6 标记控件为安全控件
当在步骤5中调用该函数时,可以看到有个警告提示框,那么如何避免该弹出框了?当然就是标记ATL组件为安全组件
ATL控件的接口类为CTest,我们打开接口类的头文件Test.h
在继承类的后面添加一个逗号, 然后在后面添加一行
public IObjectSafetyImpl<CTest, INTERFACESAFE_FOR_UNTRUSTED_CALLER>
那个类名改成自己工程的ATL简单类的对象类名
在com映射map里添加这么一行
COM_INTERFACE_ENTRY(IObjectSafety)//添加一个com映射
如果在添加的过程中出现IObjectSafetyImpl未定义 ,那么就包含添加头文件Atlctl.h
整个头文件改完后的代码如下:
// Test.h : CTest 的声明
#pragma once
#include "resource.h" // 主符号
#include "atl_test_i.h"
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。"
#endif
using namespace ATL;
// CTest
class ATL_NO_VTABLE CTest :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CTest, &CLSID_Test>,
public IDispatchImpl<ITest, &IID_ITest, &LIBID_atl_testLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IObjectSafetyImpl<CTest, INTERFACESAFE_FOR_UNTRUSTED_CALLER>
{
public:
CTest()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_TEST)
BEGIN_COM_MAP(CTest)
COM_INTERFACE_ENTRY(ITest)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IObjectSafety)//添加一个com映射
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
STDMETHOD(func)(BSTR name, BSTR* ret);
};
OBJECT_ENTRY_AUTO(__uuidof(Test), CTest)
然后重新生成该工程
重新再次注册该组件,这样在网页中调用就没有出现安全提示了。