您的位置:首页 > 其它

在ActiveX控件中如何动态调用DLL函数

2009-10-08 16:38 176 查看
刚到公司不久,接到领导的下达的一个任务,就是把对POS机操作功能封装在ActiveX控件中,在IE中调用。这样就能实现在IE上直接对POS机进行操作。而我要封装的这个动态库,厂家只提供了一个单的动态库和一百多字的说明,也就是说明一下动态库中有机个函数和其对应的参数。也就是厂家就连动态库对应的头文件也没有提供。:-(这样也行?!

接到这个任务后,我第一想到的是用VC的ATL来实现它。你问我为什么要用ATL也不用别的,如CB、Delphi之类的。我只能说我觉得写ActiveX还是用VC好;况且还要对硬件进行操作,这样一来当然是用VC了。别说我没提醒你,用CB、Delphi之类的有可能会出现预想不到的惊奇......

现在让我带着进入正题吧!先用ATLCOMAppWizard生成一个名叫PosActiveX的工程,生成时系统会问你是生成DLL还是EXE。当然是DLL的了。生成好后加入一个接口叫IPosCtrl,当然了要在Web上用,所以生成的接口一定是要小所以选择LiteControl的。你可别问我怎么加入,如果这都不会,那我写的这文章是不适合你看的。所以等你学会加入接口后再看。接口加好后,我就要实现方法了。首先用接口一般都要对其进行初始化。所以加入一个叫Init(shortnCom)的接口方法,该方法完成加载DLL和DLL中的功能函数,还有就是打开对POS机进行操作的COM口;还有一个是修改POS机的时间的方法叫ModifyPosDT(BSTRbstrDT);还有个是清空POS机中数据的方法--EmptyPos()。最后,当你不想用时就要关闭所打开的COM口--Quit()。在生成接口IPosCtrl时同时会生成CPosCtrl类。我有个习惯,就是我一般是把实现方法都写在类中,而接口只时输出该类中你想输出的方法。所以在类中我就写了以下几个方法:

InitDll()----加载DLL库和其中的功能函数;
ExitDll()----卸载DLL库,用完后不卸载是在占用内存。所以它是少不了的。
SetPosDateTime(char*pchDT)---设置POS机的时间。
ClearPos()----清空POS机中的记录。

在类中我就写了这几个方法。

在说一下我要输出的接口方法有:

Init(shortnCom)----初化接口,为调用做准备。
Quit()----退出程序时,调用它退出接口调用。
ModifyPosDT(BSTRbstrDT)----设置POS机时间。
EmptyPos()----清空POS机数据。

完了就这么多。
现在来看看我的源程序吧!

//PosCtrl.cpp:ImplementationofCPosCtrl

#include"stdafx.h"

#include"PosActiveX.h"

#include"PosCtrl.h"


//--------------------------------------------------------

//Police.dll所用到的常量定义

//--------------------------------------------------------

#defineCom_UpRecord1

#defineCom_UpPoliceLen2

#defineCom_UpSimpleDataLen3

#defineCom_UpSimplePunishLen4

#defineCom_UpGeneralDataLen5

#defineCom_UpGeneralPunishLen6


#defineCom_EmptyPolice7

#defineCom_EmptySimpleData8

#defineCom_EmptySimplePunish9

#defineCom_EmptyGeneralData10

#defineCom_EmptyGeneralPunish11


#defineCom_DownRecord0x80

#defineCom_DownStreetCodeLen0x81

#defineCom_DownBlackListLen0x82

#defineCom_DownPeccancySimpleLen0x83

#defineCom_DownPeccancyGeneralLen0x84

#defineCom_DownDateTime0x85

#defineCom_Exit0x86

#defineCom_Init0x87


#defineErr_UpSimpleDataLen0

#defineErr_UpSimplePunishLen1

#defineErr_UpGeneralDataLen2

#defineErr_UpGeneralPunishLen3

#defineErr_UpPoliceLen4

[code]#defineErr_UpRecord5

#defineErr_DownStreetCodeLen6

#defineErr_DownSimplePeccancyCodeLen7

#defineErr_DownGeneralPeccancyCodeLen8

#defineErr_DownBlackList9

#defineErr_DownDateTime10

#defineErr_EmptyData11

#defineErr_GetCode12;


#defineConst_Terminator0x20


#pragmadata_seg("mydata")


staticHINSTANCEDLLInst=NULL;//动态库句柄


#pragmadata_seg()//


HANDLEhCom;//COM串口句柄


//------------------------------------------------------

//POLICE.DLL动态库函数功能定义

//------------------------------------------------------

HANDLE(__stdcall*Init_comm)(LPSTRstr);//初始化通信口

BYTE(__stdcall*Exit)(HANDLEhCom);//关闭通信口

BYTE(__stdcall*Protocol)(HANDLEhCom,BYTEcmd,BYTElen,BYTE*_dt,BYTE*prlen,BYTE*prdt);//通信协议

BYTE(__stdcall*Pipe_control)(HANDLEhCom,BYTEmode);//多路控制typedef

BYTE(__stdcall*Dev_escape)(HANDLEhCom);//断开多路控制


//----------------------------------------------------------------------------//
//功能:加载Police.dll动态库和其中的一些功能函数
//输入/输出参数:无
//版本:1.0
//修改:
//----------------------------------------------------------------------------//
voidCPosCtrl::InitDll()

{

DLLInst=LoadLibrary("police.dll");

if(DLLInst!=NULL)

{

Init_comm=(HANDLE(__stdcall*)(LPSTR))GetProcAddress(DLLInst,"Init_comm");

Exit=(BYTE(__stdcall*)(HANDLE))(GetProcAddress(DLLInst,"Exit"));

Protocol=(BYTE(__stdcall*)(HANDLE,BYTE,BYTE,BYTE*_dt,BYTE*prlen,BYTE*prdt))(GetProcAddress(DLLInst,"Protocol"));

Pipe_control=(BYTE(__stdcall*)(HANDLE,BYTE))(GetProcAddress(DLLInst,"Pipe_control"));

Dev_escape=(BYTE(__stdcall*)(HANDLE))(GetProcAddress(DLLInst,"Dev_escape"));

[code]}
else

{

::MessageBox(NULL,"加载动态库失败!","提示信息",MB_OK|MB_ICONINFORMATION);

exit(0);

}

}


//----------------------------------------------------------------------------//
//功能:释放动态库
//输入/输出参数:无
//版本:1.0
//修改:
//----------------------------------------------------------------------------//
voidCPosCtrl::ExitDll()

{

if(DLLInst!=NULL)

FreeLibrary(DLLInst);

}


//----------------------------------------------------------------------------//
//功能:控件接口方法,对外提供关闭串口,释放动态库。
//输入/输出参数:无//版本:1.0
//修改:
//----------------------------------------------------------------------------//
STDMETHODIMPCPosCtrl::Quit()

{

//TODO:Addyourimplementationcodehere


(*Exit)(hCom);

ExitDll();

::MessageBox(NULL,"关闭COM口成功","提示信息",MB_OK|MB_ICONINFORMATION);

returnS_OK;

}


STDMETHODIMPCPosCtrl::get_ComNo(short*pVal)

{

//TODO:Addyourimplementationcodehere

*pVal=m_ComNo;

returnS_OK;

}


STDMETHODIMPCPosCtrl::put_ComNo(shortnewVal)

{

//TODO:Addyourimplementationcodehere

m_ComNo=newVal;

returnS_OK;

}

//----------------------------------------------------------------------------//
//功能:提供初化动态库的对外接口,并实现打开口串口的功能。
//输入/输出参数:11--要打开的串口号。
//版本:1.0
//修改:
//----------------------------------------------------------------------------//
STDMETHODIMPCPosCtrl::Init(shortnComNo)

{

//TODO:Addyourimplementationcodehere


InitDll();

charstr[20]="";

sprintf(str,"COM%d",nComNo);

hCom=(*Init_comm)((LPSTR)str);

sprintf(str,"%d",hCom);

chartemp[255]="";

strcpy(temp,"打开的端口为COM1,句柄为:");

strcat(temp,str);

::MessageBox(NULL,temp,"提示信息",MB_OK|MB_ICONINFORMATION);

//TCHARstr[255];

//sprintf(str,"%d",hCom);

//MessageBox(str,"Caption",MB_OK);

returnS_OK;

}

//----------------------------------------------------------------------------//
//功能:实现ASCII码到BCD码的转换功能函数
//输入/输出参数:11-想转换的ASCII码,22-返回的BCD码,13-ASCII码的长度,14-返回的BCD码长度
//版本:1.0
//修改:
//----------------------------------------------------------------------------//
voidCPosCtrl::ASCII_TO_BCD(char*cSource,char*cResult,intiSourceLen,intiResultLen)

{

intiBegin,i;

iBegin=0;

if(iSourceLen%2)

{

iBegin=1;

cResult[0]=cSource[0]-''0'';


}

for(i=iBegin;i<iResultLen;i++)

{

cResult[i]=(cSource[2*i-iBegin]-''0'')*16+cSource[2*i-iBegin+1]-''0'';

}

//depriveoffpreData

cResult[iResultLen]=''/0'';

}


//----------------------------------------------------------------------------//
//功能:设置POS机时间函数。
//输入/输出参数:11-想要设置的时间
//版本:1.0
//修改:
//----------------------------------------------------------------------------//[/code]
BOOLCPosCtrl::SetPosDateTime(char*pchDateTime)

{


intn=1;

unsignedcharcInput[257],cOutput[256];

BYTEbyOutput,retVal;

for(inti=0;i<8;i++)

{


(*Pipe_control)(hCom,n);//多路控制

//修改POS机时间

{

if(::MessageBox(NULL,"是否确定修改POS机时间?","提示信息",MB_YESNO)==IDNO)

{

returnFALSE;

}


ASCII_TO_BCD(pchDateTime,(char*)cInput,10,5);

retVal=(*Protocol)(hCom,Com_DownDateTime,5,cInput,&byOutput,cOutput);

if(retVal)

{

::MessageBox(NULL,"修改成功!","提示信息",MB_OK|MB_ICONINFORMATION);

}

else

{

::MessageBox(NULL,"修改不成功!","提示信息",MB_OK|MB_ICONINFORMATION);

}

}


n=n<<1;

}

(*Protocol)(hCom,0x86,5,cInput,&byOutput,cOutput);//下载成功

(*Dev_escape)(hCom);//关闭多路控制

(*Pipe_control)(hCom,0);//多路控制复位

returnTRUE;

}

//----------------------------------------------------------------------------//
//功能:对外提供的修改时间的接口方法
//输入/输出参数:11-想要设置的时间
//版本:1.0
//修改:
//----------------------------------------------------------------------------//

STDMETHODIMPCPosCtrl::ModifyPosDT(BSTRbstrDT)

{

//TODO:Addyourimplementationcodehere

if(SetPosDateTime((char*)bstrDT))

{

returnS_OK;

}

{

returnS_FALSE;

}

}

//----------------------------------------------------------------------------//
//功能:实现清空POS机内数据的函数。
//输入/输出参数:无
//版本:1.0
//修改:
//----------------------------------------------------------------------------//

voidCPosCtrl::ClearPos()

{

intn=1;

unsignedcharcInput[257],cOutput[256];

BYTEbyOutput,retVal;

for(inti=0;i<8;i++)

{


(*Pipe_control)(hCom,n);//多路控制

//清空POS机内的数据


if(::MessageBox(NULL,"是否要清空POS机内数据?","提示信息",MB_YESNO|MB_ICONQUESTION)==IDNO)

{

return;


}

retVal=Protocol(hCom,7,1,cInput,&byOutput,cOutput);//通信协议

if(!retVal)

{

retVal=Protocol(hCom,8,1,cInput,&byOutput,cOutput);

if(!retVal)

{

retVal=Protocol(hCom,9,1,cInput,&byOutput,cOutput);

if(!retVal)

{

retVal=Protocol(hCom,10,1,cInput,&byOutput,cOutput);

if(!retVal)

{

retVal=Protocol(hCom,11,1,cInput,&byOutput,cOutput);

}

}

}

::MessageBox(NULL,"POS机内数据已被清空!","提示信息",MB_OK|MB_ICONINFORMATION);

}

n=n<<1;

}


(*Protocol)(hCom,0x86,5,cInput,&byOutput,cOutput);//下载成功

(*Dev_escape)(hCom);//关闭多路控制

(*Pipe_control)(hCom,0);//多路控制复位

return;

}

//----------------------------------------------------------------------------//
//功能:对外提供的清空POS机内数据的接口方法
//输入/输出参数:无
//版本:1.0
//修改:
//----------------------------------------------------------------------------//


STDMETHODIMPCPosCtrl::EmptyPos()

{

//TODO:Addyourimplementationcodehere

ClearPos();

returnS_OK;

}


下面是调用PosActiveX.Dll的效果,调用时,要先对其进行注册,否则调用是不会成功的.注册是在

"Windows的开始菜单中调用"运行",在"运行"对话框中输入:regsvr32C:/PosActiveX/PosActiveX.dll

注册成功后就可对COM口进行操作了。还有一点是要特别注意的,必须把你要在ActiveX控件调用的Dll

文件拷贝到Windows/System目录(对于Win9x系统),对于NT,2000系统就要拷贝到WI目录下才能正确的运行。开发环境:Windows2000和VC6
测试环境:Windows200

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: