ATL 编写控件 调用密码键盘 全过程

写在前面:小哆把详细过程贴出来,一方面是记录备份,可以随时再利用,另一方面是分享,希望后来的初学者可以轻松一些。

[这是一个整体,所以,今后就不在赘述其中的东西,除非是前期本人自己理解错误,会更正,同时特别备注]

没有加入加密功能,MD5/DES加密都已实现,但在资源和其他的文章中有描述,本文加入过于赘述。

没有数字签名和发布部分,还未完全明白。


使用软件:Visual Studio 2010


调用:LOADDLL.dll



"文件"
[选项]
(填写名称)

=============================


(1)创建项目

文件 -> 新建 -> ATL项目 -> 填写项目名称"ActiveXTest" -> [应用程序类型]选择[动态链接库(DLL)] -> 完成

完成后,会在右边[解决方案资源管理器]生成很多"头文件.h"和"实现文件.CPP",这些都是默认的不要修改。



(2)添加一个ALT简单对象:

右键点击项目名称"ActiveXTest"选择 -> 添加[类] -> 选择[ATL简单对象] -> 添加 -> 简称(test_op) -> 下一步:其他不变,在[支持]中选择[连接点]和[IE对象支持]和[IEI] -> 完成 -> 选择[覆盖]



(3)给"test_op"添加一个方法,以便WEB页面调用。

[类视图]选择"itest_op"(灰色钥匙图标)鼠标右键添加 -> [添加方法] -> 方法起名为"testFunc"
参数类型选择LONG  参数名iFlag   参数属性选择IN -> 添加
参数类型选择BSTR* 参数名passw  参数属性选择RETVAL -> 点击完成。
属性in指输入参数,属性out指输出参数。

这样在项目中就产生了如下变化:

在test_op.h头文件中添加了一个(在最后一行):

STDMETHOD(testFunc)(LONG iFlag, BSTR* passWord);

并在test_op.cpp文件中添加了一个实现类:

STDMETHODIMP Ctest_op::testFunc(LONG iFlag, BSTR* passWord)
{
// TODO: 在此添加实现代码

return S_OK;
}


(4)在test_op.h 文件中,调用DLL类库。整体代码如下(认为添加的以标注):

// test_op.h : Ctest_op 的声明

#pragma once
#include "resource.h"       // 主符号

#include "ActiveXTest_i.h"
#include "_Itest_opEvents_CP.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_op


class ATL_NO_VTABLE Ctest_op :

	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<Ctest_op, &CLSID_test_op>,
	public ISupportErrorInfo,
	public IConnectionPointContainerImpl<Ctest_op>,
	public CProxy_Itest_opEvents<Ctest_op>,
	public IObjectWithSiteImpl<Ctest_op>,
	public IDispatchImpl<Itest_op, &IID_Itest_op, &LIBID_ActiveXTestLib, /*wMajor =*/ 1, /*wMinor =*/ 0>

{
public:

	//*******begin*****以下三行实现定义 add by 莫小哆_ly

    	typedef int (_stdcall *testGetPwd)(int,char*,char*); //类型定义,对应LOADDLL.dll->LoadFunc方法

	HINSTANCE hInstLibrary;

    	testGetPwd _testGetPwd; //类映射

	//*******end*****

	Ctest_op()
	{
	//*******begin*****开始调用DLL add by 莫小哆_ly

        hInstLibrary = LoadLibrary(L"C:\\WINDOWS\\system32\\LOADDLL.dll");//相对路径时把写好的LOADDLL.dll文件放在此项目生成的目录debug下。

        if (hInstLibrary == NULL)
        {
        FreeLibrary(hInstLibrary);//资源释放
        }else{
        }

        //调用方法,返回方法句柄。

        _testGetPwd = (testGetPwd)GetProcAddress(hInstLibrary, "LoadFunc");

	//*******end*****	
	}


DECLARE_REGISTRY_RESOURCEID(IDR_test_op)

BEGIN_COM_MAP(Ctest_op)
	COM_INTERFACE_ENTRY(Itest_op)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(ISupportErrorInfo)
	COM_INTERFACE_ENTRY(IConnectionPointContainer)
	COM_INTERFACE_ENTRY(IObjectWithSite)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(Ctest_op)
	CONNECTION_POINT_ENTRY(__uuidof(_Itest_opEvents))
END_CONNECTION_POINT_MAP()
// ISupportsErrorInfo
	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);

	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}

public:

	STDMETHOD(testFunc)(LONG iFlag, BSTR* passWord);
};

OBJECT_ENTRY_AUTO(__uuidof(test_op), Ctest_op)


(6)回到在test_op.cpp 文件中,添加实现代码如下:

// test_op.cpp : Ctest_op 的实现

#include "stdafx.h"
#include "test_op.h"


//*****begin*****add by 莫小哆_ly

//#include "md5.h"//用于MD5加密,与本文无关,略去
#pragma comment(lib, "comsuppw.lib")
#include <comutil.h>

//*****end*****


// Ctest_op


STDMETHODIMP Ctest_op::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* const arr[] = 
	{
		&IID_Itest_op
	};

	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}

STDMETHODIMP Ctest_op::testFunc(LONG iFlag, BSTR* passWord)
{
	// TODO: 在此添加实现代码


	//*****begin*****add by 莫小哆_ly

	int iflag = (int)(iFlag);
	char* pwd = new char[7];//参考testFunc的约定长度。
	char* mac = new char[33];
	char *pwd_md5 = new char[32];
	
	_testGetPwd(iflag,pwd,mac);//这里要求厂家提供的dll里(int,char*,char*)
	
	//结尾加结束符,防止数组溢出出现乱码[烫]
	pwd[6]='\0';//密码6位.0.1.2.3.4.5/pwd[6]->结束符
		
	//MD5加密
	//pwd_md5 = MD5String(pwd);


	//char*型转换成BSTR*类型
	*passWord = _com_util::ConvertStringToBSTR(pwd);
	
	//*****end*****
	
	this->_AtlFinalRelease();
	return S_OK;
}


(7)生成DLL:
选[生成],在项目的Debug文件夹里找到dll文件"ActiveXTest.dll"
把LOADDLL.dll按照"test_op.h"里的描述放置,相对路径时可以放入Debug文件夹



(8)打包CAB文件:

利用iexpress.exe软件

1.准备好所有你用到的、调用的dll,外加1个写好的inf文件。[好吧,如果你不会,那小哆后面会一步步教你]

2.解压后,双击iexpress.exe。

[create new self extraction directive file] -> 下一步
[create compressed files only(activex installs)] -> 下一步
[add] ->选中准备好的文件 -> 下一步
[browse] - 选择好路径/命名/保存 ->[store files long file name inside package] -> 下一步
[don't save] -> 下一步 -> 下一步 -> 完成


3.cab包就此生成。

PS:小哆根据项目经验,总结出来的。所以肯定是可行的。

附注:setup.inf文件:

[version]

signature="$CHICAGO{1}quot;

AdvancedINF=2.0

[Add.Code]

ActiveXTest.dll=ActiveXTest.dll

LOADDLL.dll=LOADDLL.dll

[install.files]

ActiveXTest.dll=ActiveXTest.dll

LOADDLL.dll=LOADDLL.dll

[ActiveXTest.dll]

file-win32-x86=thiscab

RegisterServer=yes

clsid={197E37FC-9916-4881-B766-D43FDD0376E8}

DestDir=11

FileVersion=1,0,0,1

[LOADDLL.dll]

file-win32-x86=thiscab

DestDir=11

FileVersion=1,0,0,1

[RegisterFiles]

%11%/ActiveXTest.dll


【说明】

①[Add.Code]中dll顺序:

{举例说明}最终生成和调用的ActiveXTest.dll,其内部调用了LOADDLL.dll。

内部顺序是:

ActiveXTest.dll
LOADDLL.dll

②clsid={197E37FC-9916-4881-B766-D43FDD0376E8}

项目里的idl文件中,有一段这么记录:

library ActiveXTestLib
{
importlib("stdole2.tlb");
[
uuid(197E37FC-9916-4881-B766-D43FDD0376E8)
]
dispinterface _Itest_opEvents
{
properties:
methods:
};

那就选这个uuid吧,别问我为什么,我也不知道

这个到底是什么情况,我也没搞清楚,反正选了个这个可以正常运行。



(8)htm文件

<HTML>

	<HEAD>

		<TITLE>New Page</TITLE>

		<OBJECT id=CaluNumCtrl codeBase="ActiveXTest.CAB#version=1,0,0,1" classid="clsid:3968A893-A79C-4AB9-B2FD-73BA2B76FB23"></OBJECT>

		<script language="javascript">

			function doTest()

			{
				var pwd = CaluNumCtrl.testFunc(1);

				alert(pwd);
			}

		</script>

	</HEAD>

	<BODY>
		
		<input type="button" value="调用" id="btnOK" οnclick="doTest();"></input>
		
	</BODY>

</HTML>


【附注】
<OBJECT id=CaluNumCtrl codeBase="test2.CAB#version=1,0,0,1" classid="clsid:225EDF53-A85F-4CB5-977D-69509C7E675C"></OBJECT>
CLSID 是 ActiveX 项目生成的序号,具体可以在项目的test_op.rgs 文件中找到。

ForceRemove {3968A893-A79C-4AB9-B2FD-73BA2B76FB23} = s 'test_op Class'
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值