目前的条形码扫描器有点类似外接键盘(其实从消息传送上它就相当于一个键盘),把输入焦点定位到可输入的控件上,一扫描相应的条形码信息就输入到文本框中去了,但是如果没有输入焦点,或另一个不相干的程序获得输入焦点,那就有点乱套了。我想实现的是,不管什么情况,只要扫描器一工作,我的程序就能自动激活,并能获得当前输入的条形码信息。
实现思路:我用的是litele牌的USB口的红外条形码扫描器,仔细分析了一下,扫描成功后,以键盘按键消息的形式把条形码输入信息通知给系统。这样通过键盘钩子就可以方便的获得该信息了。但是,怎样区分信息是键盘还是条形码输入的哪?
很简单,条形码扫描器在很短的时间内输入了至少3个字符以上信息,并且以“回车”作为结束字符,在这种思想指引下,很完美的实现了预定功能。
以下程序要在Win2000/Win XP 下才能运行成功。
form1 中的代码:
'*************************************************************************
'**模块名:frmDemo
'**说明:YFsoft版权所有2006-2007(C)
'**创建人:叶帆http://blog.youkuaiyun.com/yefanqiu
'**日期:2006-08-3014:55:56
'**修改人:
'**日期:
'**描述:
'**版本:V1.0.0
'*************************************************************************
OptionExplicit
PrivateSubForm_Load()
SetHook
EndSub
PrivateSubForm_Unload(CancelAsInteger)
UnHook
EndSub
PrivateSubtmrScan_Timer()
DimstrBarCodeAsString
strBarCode=GetBarCode
IfLen(strBarCode)>0Then
MsgBox"条形码:"&strBarCode
EndIf
EndSub
'**模块名:frmDemo
'**说明:YFsoft版权所有2006-2007(C)
'**创建人:叶帆http://blog.youkuaiyun.com/yefanqiu
'**日期:2006-08-3014:55:56
'**修改人:
'**日期:
'**描述:
'**版本:V1.0.0
'*************************************************************************
OptionExplicit
PrivateSubForm_Load()
SetHook
EndSub
PrivateSubForm_Unload(CancelAsInteger)
UnHook
EndSub
PrivateSubtmrScan_Timer()
DimstrBarCodeAsString
strBarCode=GetBarCode
IfLen(strBarCode)>0Then
MsgBox"条形码:"&strBarCode
EndIf
EndSub
模块中的代码:
'*************************************************************************
'**模块名:basBarCode
'**说明:YFsoft版权所有2006-2007(C)
'**创建人:叶帆http://blog.youkuaiyun.com/yefanqiu
'**日期:2006-08-3015:02:29
'**修改人:
'**日期:
'**描述:获取条形码数据
'**版本:V1.0.0
'*************************************************************************
OptionExplicit
PrivateTypeKeyboardBytes
kbByte(0To255)AsByte
EndType
DimkbArrayAsKeyboardBytes
PrivateDeclareFunctionGetKeyboardStateLib"user32"(pbKeyStateAsKeyboardBytes)AsLong
PrivateDeclareFunctionToAsciiLib"user32"(ByValuVirtKeyAsLong,ByValuScanCodeAsLong,lpbKeyStateAsKeyboardBytes,lpwTransKeyAsLong,ByValfuStateAsLong)AsLong
PrivateDeclareFunctionCallNextHookExLib"user32"(ByValhHookAsLong,ByValncodeAsLong,ByValwParamAsLong,lParamAsAny)AsLong
PrivateDeclareSubCopyMemoryLib"kernel32"Alias"RtlMoveMemory"(lpvDestAsAny,ByVallpvSourceAsLong,ByValcbCopyAsLong)
PrivateDeclareFunctionGetKeyNameTextLib"user32"Alias"GetKeyNameTextA"(ByVallParamAsLong,ByVallpBufferAsString,ByValnSizeAsLong)AsLong
PrivateTypeEVENTMSG
messageAsLong
paramLAsLong
paramHAsLong
TimeAsLong
hwndAsLong
EndType
PrivateTypeBARCODES
VirtKeyAsLong'虚拟码
ScanCodeAsLong'扫描码
KeyNameAsString'键的名称
AscIIAsLong'AscII
ChrAsString'字符
BarCodeAsString'扫描码信息
TimeAsDate'扫描时间
bGetFlagAsBoolean'是否已获取扫描码
EndType
PrivateDeclareFunctionSetWindowsHookExLib"user32"Alias"SetWindowsHookExA"(ByValidHookAsLong,ByVallpfnAsLong,ByValhmodAsLong,ByValdwThreadIdAsLong)AsLong
PrivateDeclareFunctionUnhookWindowsHookExLib"user32"(ByValhHookAsLong)AsLong
PrivateDeclareFunctionGetCurrentTimeLib"kernel32"Alias"GetTickCount"()AsLong
PrivateConstWH_KEYBOARD_LL=13
Privatem_lHookAsLong
Publicg_BarCodeAsBARCODES
'*************************************************************************
'**函数名:SetHook/UnHook
'**输入:无
'**输出:无
'**功能描述:装卸钩子
'**全局变量:
'**调用模块:
'**作者:叶帆
'**日期:2006-08-3015:11:37
'**修改人:
'**日期:
'**版本:V1.0.0
'*************************************************************************
PublicSubSetHook()
m_lHook=SetWindowsHookEx(WH_KEYBOARD_LL,AddressOfCallHookProc,App.hInstance,0)
EndSub
PublicSubUnHook()
Ifm_lHook<>0Then
UnhookWindowsHookExm_lHook
EndIf
EndSub
'*************************************************************************
'**函数名:GetBarCode
'**输入:无
'**输出:(String)-
'**功能描述:获取扫描码
'**全局变量:
'**调用模块:
'**作者:叶帆
'**日期:2006-08-3016:46:04
'**修改人:
'**日期:
'**版本:V1.0.0
'*************************************************************************
PublicFunctionGetBarCode()AsString
Ifg_BarCode.bGetFlag=TrueThen
g_BarCode.bGetFlag=False
GetBarCode=g_BarCode.BarCode
Else
GetBarCode=""
EndIf
EndFunction
'*************************************************************************
'**函数名:CallHookProc
'**输入:ByValcode(Long)-
'**:ByValwParam(Long)-
'**:ByVallParam(Long)-
'**输出:(Long)-
'**功能描述:
'**全局变量:
'**调用模块:
'**作者:叶帆
'**日期:2006-08-3015:03:47
'**修改人:
'**日期:
'**版本:V1.0.0
'*************************************************************************
PrivateFunctionCallHookProc(ByValcodeAsLong,ByValwParamAsLong,ByVallParamAsLong)AsLong
DimmsgAsEVENTMSG
DimstrKeyNameAsString
DimlngKeyAsLong
StaticlngTimeAsLong
StaticstrBarCodeAsString
Ifcode=0Then
CopyMemorymsg,lParam,LenB(msg)
IfwParam=&H100Then'WM_KEYDOWN
g_BarCode.VirtKey=msg.messageAnd&HFF'虚拟码
g_BarCode.ScanCode=msg.paramLAnd&HFF'扫描码
strKeyName=Space(255)
IfGetKeyNameText(g_BarCode.ScanCode*65536,strKeyName,255)>0Then'键名
g_BarCode.KeyName=Trim(strKeyName)
Else
g_BarCode.KeyName=""
EndIf
'---------------------------------------
CallGetKeyboardState(kbArray)
IfToAscii(g_BarCode.VirtKey,g_BarCode.ScanCode,kbArray,lngKey,0)>0Then
g_BarCode.AscII=lngKey
g_BarCode.Chr=Chr(lngKey)
EndIf
'--------------------
IfAbs(GetCurrentTime-lngTime)>50Then
strBarCode=g_BarCode.Chr
Else
If(msg.messageAnd&HFF)=13AndLen(strBarCode)>3Then'回车
g_BarCode.BarCode=strBarCode
g_BarCode.Time=Now
g_BarCode.bGetFlag=True
EndIf
strBarCode=strBarCode&g_BarCode.Chr
EndIf
lngTime=GetCurrentTime
'---------------------------------------
'测试代码
’CallShowKeyInfo
'---------------------------------------
EndIf
EndIf
CallHookProc=CallNextHookEx(m_lHook,code,wParam,lParam)
EndFunction
'显示调试信息
PublicSubShowKeyInfo()
frmDemo.txtKey(0)=g_BarCode.KeyName
frmDemo.txtKey(1)=g_BarCode.VirtKey
frmDemo.txtKey(2)=g_BarCode.ScanCode
frmDemo.txtKey(3)=g_BarCode.AscII
frmDemo.txtKey(4)=g_BarCode.Chr
frmDemo.txtBarCode=g_BarCode.BarCode
frmDemo.lblTime=g_BarCode.Time
EndSub
'**模块名:basBarCode
'**说明:YFsoft版权所有2006-2007(C)
'**创建人:叶帆http://blog.youkuaiyun.com/yefanqiu
'**日期:2006-08-3015:02:29
'**修改人:
'**日期:
'**描述:获取条形码数据
'**版本:V1.0.0
'*************************************************************************
OptionExplicit
PrivateTypeKeyboardBytes
kbByte(0To255)AsByte
EndType
DimkbArrayAsKeyboardBytes
PrivateDeclareFunctionGetKeyboardStateLib"user32"(pbKeyStateAsKeyboardBytes)AsLong
PrivateDeclareFunctionToAsciiLib"user32"(ByValuVirtKeyAsLong,ByValuScanCodeAsLong,lpbKeyStateAsKeyboardBytes,lpwTransKeyAsLong,ByValfuStateAsLong)AsLong
PrivateDeclareFunctionCallNextHookExLib"user32"(ByValhHookAsLong,ByValncodeAsLong,ByValwParamAsLong,lParamAsAny)AsLong
PrivateDeclareSubCopyMemoryLib"kernel32"Alias"RtlMoveMemory"(lpvDestAsAny,ByVallpvSourceAsLong,ByValcbCopyAsLong)
PrivateDeclareFunctionGetKeyNameTextLib"user32"Alias"GetKeyNameTextA"(ByVallParamAsLong,ByVallpBufferAsString,ByValnSizeAsLong)AsLong
PrivateTypeEVENTMSG
messageAsLong
paramLAsLong
paramHAsLong
TimeAsLong
hwndAsLong
EndType
PrivateTypeBARCODES
VirtKeyAsLong'虚拟码
ScanCodeAsLong'扫描码
KeyNameAsString'键的名称
AscIIAsLong'AscII
ChrAsString'字符
BarCodeAsString'扫描码信息
TimeAsDate'扫描时间
bGetFlagAsBoolean'是否已获取扫描码
EndType
PrivateDeclareFunctionSetWindowsHookExLib"user32"Alias"SetWindowsHookExA"(ByValidHookAsLong,ByVallpfnAsLong,ByValhmodAsLong,ByValdwThreadIdAsLong)AsLong
PrivateDeclareFunctionUnhookWindowsHookExLib"user32"(ByValhHookAsLong)AsLong
PrivateDeclareFunctionGetCurrentTimeLib"kernel32"Alias"GetTickCount"()AsLong
PrivateConstWH_KEYBOARD_LL=13
Privatem_lHookAsLong
Publicg_BarCodeAsBARCODES
'*************************************************************************
'**函数名:SetHook/UnHook
'**输入:无
'**输出:无
'**功能描述:装卸钩子
'**全局变量:
'**调用模块:
'**作者:叶帆
'**日期:2006-08-3015:11:37
'**修改人:
'**日期:
'**版本:V1.0.0
'*************************************************************************
PublicSubSetHook()
m_lHook=SetWindowsHookEx(WH_KEYBOARD_LL,AddressOfCallHookProc,App.hInstance,0)
EndSub
PublicSubUnHook()
Ifm_lHook<>0Then
UnhookWindowsHookExm_lHook
EndIf
EndSub
'*************************************************************************
'**函数名:GetBarCode
'**输入:无
'**输出:(String)-
'**功能描述:获取扫描码
'**全局变量:
'**调用模块:
'**作者:叶帆
'**日期:2006-08-3016:46:04
'**修改人:
'**日期:
'**版本:V1.0.0
'*************************************************************************
PublicFunctionGetBarCode()AsString
Ifg_BarCode.bGetFlag=TrueThen
g_BarCode.bGetFlag=False
GetBarCode=g_BarCode.BarCode
Else
GetBarCode=""
EndIf
EndFunction
'*************************************************************************
'**函数名:CallHookProc
'**输入:ByValcode(Long)-
'**:ByValwParam(Long)-
'**:ByVallParam(Long)-
'**输出:(Long)-
'**功能描述:
'**全局变量:
'**调用模块:
'**作者:叶帆
'**日期:2006-08-3015:03:47
'**修改人:
'**日期:
'**版本:V1.0.0
'*************************************************************************
PrivateFunctionCallHookProc(ByValcodeAsLong,ByValwParamAsLong,ByVallParamAsLong)AsLong
DimmsgAsEVENTMSG
DimstrKeyNameAsString
DimlngKeyAsLong
StaticlngTimeAsLong
StaticstrBarCodeAsString
Ifcode=0Then
CopyMemorymsg,lParam,LenB(msg)
IfwParam=&H100Then'WM_KEYDOWN
g_BarCode.VirtKey=msg.messageAnd&HFF'虚拟码
g_BarCode.ScanCode=msg.paramLAnd&HFF'扫描码
strKeyName=Space(255)
IfGetKeyNameText(g_BarCode.ScanCode*65536,strKeyName,255)>0Then'键名
g_BarCode.KeyName=Trim(strKeyName)
Else
g_BarCode.KeyName=""
EndIf
'---------------------------------------
CallGetKeyboardState(kbArray)
IfToAscii(g_BarCode.VirtKey,g_BarCode.ScanCode,kbArray,lngKey,0)>0Then
g_BarCode.AscII=lngKey
g_BarCode.Chr=Chr(lngKey)
EndIf
'--------------------
IfAbs(GetCurrentTime-lngTime)>50Then
strBarCode=g_BarCode.Chr
Else
If(msg.messageAnd&HFF)=13AndLen(strBarCode)>3Then'回车
g_BarCode.BarCode=strBarCode
g_BarCode.Time=Now
g_BarCode.bGetFlag=True
EndIf
strBarCode=strBarCode&g_BarCode.Chr
EndIf
lngTime=GetCurrentTime
'---------------------------------------
'测试代码
’CallShowKeyInfo
'---------------------------------------
EndIf
EndIf
CallHookProc=CallNextHookEx(m_lHook,code,wParam,lParam)
EndFunction
'显示调试信息
PublicSubShowKeyInfo()
frmDemo.txtKey(0)=g_BarCode.KeyName
frmDemo.txtKey(1)=g_BarCode.VirtKey
frmDemo.txtKey(2)=g_BarCode.ScanCode
frmDemo.txtKey(3)=g_BarCode.AscII
frmDemo.txtKey(4)=g_BarCode.Chr
frmDemo.txtBarCode=g_BarCode.BarCode
frmDemo.lblTime=g_BarCode.Time
EndSub