作者:馬雲冬(xacn)
版權所有:馬雲冬(xacn)
轉載請與作者聯系
剛到公司不久,接到領導的下達的一個任務,就是把對POS機操作功能封裝在ActiveX控件中,在IE中調用。這樣就能實現在IE上直接對POS機進行操作。而我要封裝的這個動態庫,廠家只提供了一個單的動態庫和一百多字的說明,也就是說明一下動態庫中有機個函數和其對應的參數。也就是廠家就連動態庫對應的頭文件也沒有提供。:-(
這樣也行?!
接到這個任務後,我第一想到的是用VC的ATL來實現它。你問我為什麼要用ATL也不用別的,如CB、Delphi之類的。我只能說我覺得寫ActiveX還是用VC好;況且還要對硬件進行操作,這樣一來當然是用VC了。別說我沒提醒你,用CB、Delphi之類的有可能會出現預想不到的驚奇......
現在讓我帶著進入正題吧!先用ATL COM AppWizard生成一個名叫PosActiveX的工程,生成時系統會問你是生成DLL還是EXE。當然是DLL的了。生成好後加入一個接口叫IPosCtrl,當然了要在Web上用,所以生成的接口一定是要小所以選擇Lite
Control的。你可別問我怎麼加入,如果這都不會,那我寫的這文章是不適合你看的。所以等你學會加入接口後再看。接口加好後,我就要實現方法了。首先用接口一般都要對其進行初始化。所以加入一個叫Init(short
nCom)的接口方法,該方法完成加載DLL和DLL中的功能函數,還有就是打開對POS機進行操作的COM口;還有一個是修改POS機的時間的方法叫ModifyPosDT(BSTR
bstrDT);還有個是清空POS機中數據的方法--EmptyPos()。最後,當你不想用時就要關閉所打開的COM口--Quit()。在生成接口IPosCtrl時同時會生成CPosCtrl類。我有個習慣,就是我一般是把實現方法都寫在類中,而接口只時輸出該類中你想輸出的方法。所以在類中我就寫了以下幾個方法:
InitDll()----加載DLL庫和其中的功能函數;
ExitDll()----卸載DLL庫,用完後不卸載是在占用內存。所以它是少不了的。
SetPosDateTime(char * pchDT)---設置POS機的時間。
ClearPos()----清空POS機中的記錄。
在類中我就寫了這幾個方法。
在說一下我要輸出的接口方法有:
Init(short nCom)----初化接口,為調用做准備。
Quit()----退出程序時,調用它退出接口調用。
ModifyPosDT(BSTR bstrDT)----設置POS機時間。
EmptyPos()----清空POS機數據。
完了就這麼多。
現在來看看我的源程序吧!
// PosCtrl.cpp : Implementation of CPosCtrl
#include "stdafx.h"
#include "PosActiveX.h"
#include "PosCtrl.h"
//--------------------------------------------------------
// Police.dll所用到的常量定義
//--------------------------------------------------------
#define Com_UpRecord 1
#define Com_UpPoliceLen 2
#define Com_UpSimpleDataLen 3
#define Com_UpSimplePunishLen 4
#define Com_UpGeneralDataLen 5
#define Com_UpGeneralPunishLen 6
#define Com_EmptyPolice 7
#define Com_EmptySimpleData 8
#define Com_EmptySimplePunish 9
#define Com_EmptyGeneralData 10
#define Com_EmptyGeneralPunish 11
#define Com_DownRecord 0x80
#define Com_DownStreetCodeLen 0x81
#define Com_DownBlackListLen 0x82
#define Com_DownPeccancySimpleLen 0x83
#define Com_DownPeccancyGeneralLen 0x84
#define Com_DownDateTime 0x85
#define Com_Exit 0x86
#define Com_Init 0x87
#define Err_UpSimpleDataLen 0
#define Err_UpSimplePunishLen 1
#define Err_UpGeneralDataLen 2
#define Err_UpGeneralPunishLen 3
#define Err_UpPoliceLen 4
#define Err_UpRecord 5
#define Err_DownStreetCodeLen 6
#define Err_DownSimplePeccancyCodeLen 7
#define Err_DownGeneralPeccancyCodeLen 8
#define Err_DownBlackList 9
#define Err_DownDateTime 10
#define Err_EmptyData 11
#define Err_GetCode 12;
#define Const_Terminator 0x20
#pragma data_seg("mydata")
static HINSTANCE DLLInst = NULL; //動態庫句柄
#pragma data_seg() //
HANDLE hCom; //COM串口句柄
//------------------------------------------------------
//POLICE.DLL動態庫函數功能定義
//------------------------------------------------------
HANDLE (__stdcall *Init_comm)(LPSTR str);//初始化通信口
BYTE (__stdcall *Exit)(HANDLE hCom);//關閉通信口
BYTE (__stdcall *Protocol)(HANDLE hCom,BYTE cmd,BYTE len,BYTE *_dt,BYTE
*prlen,BYTE *prdt);//通信協議
BYTE (__stdcall *Pipe_control)(HANDLE hCom,BYTE mode);//多路控制typedef
BYTE (__stdcall *Dev_escape)(HANDLE hCom);//斷開多路控制
//----------------------------------------------------------------------------//
// 功能:加載Police.dll動態庫和其中的一些功能函數
// 輸入/輸出參數:無
// 版本:1.0
// 修改:
//----------------------------------------------------------------------------//
void CPosCtrl::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"));
}
else
{
::MessageBox(NULL,"加載動態庫失敗!", "提示信息", MB_OK | MB_ICONINFORMATION);
exit(0);
}
}
//----------------------------------------------------------------------------//
// 功能:釋放動態庫
// 輸入/輸出參數:無
// 版本:1.0
// 修改:
//----------------------------------------------------------------------------//
void CPosCtrl::ExitDll()
{
if(DLLInst!=NULL)
FreeLibrary(DLLInst);
}
//----------------------------------------------------------------------------//
// 功能:控件接口方法,對外提供關閉串口,釋放動態庫。
// 輸入/輸出參數:無 // 版本:1.0
// 修改:
//----------------------------------------------------------------------------//
STDMETHODIMP CPosCtrl::Quit()
{
// TODO: Add your implementation code here
(*Exit)(hCom);
ExitDll();
::MessageBox(NULL,"關閉COM口成功","提示信息",MB_OK | MB_ICONINFORMATION);
return S_OK;
}
STDMETHODIMP CPosCtrl::get_ComNo(short *pVal)
{
// TODO: Add your implementation code here
*pVal = m_ComNo;
return S_OK;
}
STDMETHODIMP CPosCtrl::put_ComNo(short newVal)
{
// TODO: Add your implementation code here
m_ComNo = newVal;
return S_OK;
}
//----------------------------------------------------------------------------//
// 功能:提供初化動態庫的對外接口,並實現打開口串口的功能。
// 輸入/輸出參數:11--要打開的串口號。
// 版本:1.0
// 修改:
//----------------------------------------------------------------------------//
STDMETHODIMP CPosCtrl::Init(short nComNo)
{
// TODO: Add your implementation code here
InitDll();
char str[20] = "";
sprintf(str,"COM%d",nComNo);
hCom = (*Init_comm)((LPSTR)str);
sprintf(str,"%d",hCom);
char temp[255] = "";
strcpy(temp,"打開的端口為COM1,句柄為:");
strcat(temp,str);
::MessageBox(NULL,temp,"提示信息",MB_OK | MB_ICONINFORMATION);
//TCHAR str[255];
//sprintf(str,"%d",hCom);
//MessageBox(str,"Caption",MB_OK);
return S_OK;
}
//----------------------------------------------------------------------------//
// 功能:實現ASCII碼到BCD碼的轉換功能函數
// 輸入/輸出參數:11-想轉換的ASCII碼,22-返回的BCD碼,13-ASCII碼的長度,14-返回的BCD碼長度
// 版本:1.0
// 修改:
//----------------------------------------------------------------------------//
void CPosCtrl::ASCII_TO_BCD(char *cSource, char *cResult, int iSourceLen,
int iResultLen)
{
int iBegin,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'';
}
//deprive off preData
cResult[iResultLen]=''\0'';
}
//----------------------------------------------------------------------------//
// 功能:設置POS機時間函數。
// 輸入/輸出參數:11-想要設置的時間
// 版本:1.0
// 修改:
//----------------------------------------------------------------------------//
BOOL CPosCtrl::SetPosDateTime(char * pchDateTime)
{
int n=1;
unsigned char cInput[257],cOutput[256];
BYTE byOutput,retVal;
for(int i=0;i<8;i++)
{
(*Pipe_control)(hCom,n); //多路控制
//修改POS機時間
{
if(::MessageBox(NULL,"是否確定修改POS機時間?","提示信息",MB_YESNO)==IDNO)
{
return FALSE;
}
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); //多路控制復位
return TRUE;
}
//----------------------------------------------------------------------------//
// 功能:對外提供的修改時間的接口方法
// 輸入/輸出參數:11-想要設置的時間
// 版本:1.0
// 修改:
//----------------------------------------------------------------------------//
STDMETHODIMP CPosCtrl::ModifyPosDT(BSTR bstrDT)
{
// TODO: Add your implementation code here
if(SetPosDateTime((char *)bstrDT))
{
return S_OK;
}
{
return S_FALSE;
}
}
//----------------------------------------------------------------------------//
// 功能:實現清空POS機內數據的函數。
// 輸入/輸出參數:無
// 版本:1.0
// 修改:
//----------------------------------------------------------------------------//
void CPosCtrl::ClearPos()
{
int n=1;
unsigned char cInput[257],cOutput[256];
BYTE byOutput,retVal;
for(int i=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
// 修改:
//----------------------------------------------------------------------------//
STDMETHODIMP CPosCtrl::EmptyPos()
{
// TODO: Add your implementation code here
ClearPos();
return S_OK;
}
下面是調用PosActiveX.Dll的效果,調用時,要先對其進行注冊,否則調用是不會成功的.注冊是在"Windows的開始菜單中調用"運行",在"運行"對話框中輸入:regsvr32
C:\PosActiveX\PosActiveX.dll 注冊成功後就可對COM口進行操作了。還有一點是要特別注意的,必須把你要在ActiveX控件調用的Dll文件拷貝到Windows\System目錄(對於Win9x系統),對於NT,2000系統就要拷貝到WINNT\System32目錄下才能正確的運行。
開發環境:Windows2000和VC6
測試環境:Windows200
代碼使用許可:可用