程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#基礎知識 >> 在ActiveX控件中怎麼樣動態調用DLL函數

在ActiveX控件中怎麼樣動態調用DLL函數

編輯:C#基礎知識

剛到公司不久,接到領導的下達的一個任務,就是把對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;
}


調用時,要先對其進行注冊,否則調用是不會成功的.注冊是在"Windows的開始菜單中調用"運行",在"運行"對話框中輸入:regsvr32 C:\PosActiveX\PosActiveX.dll 注冊成功後就可對COM口進行操作了。還有一點是要特別注意的,必須把你要在ActiveX控件調用的Dll文件拷貝到Windows\System目錄(對於Win9x系統),對於NT,2000系統就要拷貝到WINNT\System32目錄下才能正確的運行。
開發環境:Windows2000和VC6

測試環境:Windows200

代碼使用許可:可用

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved