设置全局钩子,扫描枪扫描带字母的条码:字母会重复2次,如果条码是纯数字,扫描条码是什么,钩子显示什么.

wenchuan408 2016-11-28 11:48:33
设置全局钩子,扫描枪扫描带字母的条码:字母会重复2次,如果条码是纯数字,扫描条码是什么,钩子显示什么.
-比如含字母条码在记事本扫描条码 :FQC-01197
-那么通过全局钩子Textbox获得的条码为 :FFQQC-01197 (前两个字母重复了2次)

-比如纯数字条码在记事本扫描条码 :00186178486830
-那么通过全局钩子Textbox获得的条码为 :00186178486830 (正常显示)

请各位大神看一下如下全局钩子类代码,问题出在哪里啊,我弄了好久了,谢谢!

class BarCodeHook
{

public delegate void BarCodeDelegate(BarCodes barCode);
public event BarCodeDelegate BarCodeEvent;

//键盘结构
[StructLayout(LayoutKind.Sequential)]
public struct BarCodes

{
public int VirtKey; //虚拟码
public int ScanCode; //扫描码
public string KeyName; //键名
public uint AscII; //AscII
public char Chr; //字符
public string BarCode; //条码信息
public bool IsValid; //条码是否有效
public DateTime Time; //扫描时间
}

private struct EventMsg
{
public int message;
public int paramL;
public int paramH;
public int Time;
public int hwnd;
}

// 安装钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
// 卸载钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);
// 继续下一个钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
//获取键名的字符串
[DllImport("user32", EntryPoint = "GetKeyNameText")]
private static extern int GetKeyNameText(int lParam, StringBuilder lpBuffer, int nSize);

//将256个虚拟键复制到指定的缓冲区中,获取按键状态
[DllImport("user32", EntryPoint = "GetKeyboardState")]
private static extern int GetKeyboardState(byte[] pbKeyState);

//将指定的虚拟键码和键盘状态为相应的字符串
[DllImport("user32", EntryPoint = "ToAscii")]
private static extern bool ToAscii(int VirtualKey, int ScanCode, byte[] lpKeyState, ref uint lpChar, int uFlags);

//声明定义回调函数
delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
BarCodes barCode = new BarCodes();
int hKeyboardHook = 0;
HookProc KeyboardHookProcedure;
string strBarCode = "";

private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
if (nCode == 0)
{
EventMsg msg = (EventMsg)Marshal.PtrToStructure(lParam, typeof(EventMsg));
if (wParam == 0x100) //WM_KEYDOWN = 0x100
{
barCode.VirtKey = msg.message & 0xff; //虚拟码
barCode.ScanCode = msg.paramL & 0xff; //扫描码
StringBuilder strKeyName = new StringBuilder(255);
if (GetKeyNameText(barCode.ScanCode * 65536, strKeyName, 255) > 0)
{
barCode.KeyName = strKeyName.ToString().Trim(new char[] { ' ', '\0' });
}
else
{
barCode.KeyName = "";
}
byte[] kbArray = new byte[256];
uint uKey = 0;
GetKeyboardState(kbArray);
if (ToAscii(barCode.VirtKey, barCode.ScanCode, kbArray, ref uKey, 0))
{
barCode.AscII = uKey;
barCode.Chr = Convert.ToChar(uKey);
}



if (DateTime.Now.Subtract(barCode.Time).TotalMilliseconds > 50)

{
strBarCode = barCode.Chr.ToString();
}
else
{
if ((msg.message & 0xff) == 13 && strBarCode.Length > 3)
//回车
{
barCode.BarCode = strBarCode;
barCode.IsValid = true;
}
strBarCode += barCode.Chr.ToString();
}

barCode.Time = DateTime.Now;
if (BarCodeEvent != null) BarCodeEvent(barCode);
//触发事件
barCode.IsValid = false;
}
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}

// 安装钩子
public bool Start()
{
if (hKeyboardHook == 0)
{
//WH_KEYBOARD_LL = 13
KeyboardHookProcedure = new HookProc(KeyboardHookProc);
hKeyboardHook = SetWindowsHookEx(13, KeyboardHookProcedure, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
}
return (hKeyboardHook != 0);
}
// 卸载钩子
public bool Stop()
{
if (hKeyboardHook != 0)
{
return UnhookWindowsHookEx(hKeyboardHook);
}
return true;
}
}
...全文
994 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
huashenghn 2018-11-25
  • 打赏
  • 举报
回复
我解决这个问题了,虽然我也不是很懂钩子的原理 if (ToAscii(barCode.VirtKey, barCode.ScanCode, kbArray, ref uKey, 0)) { barCode.Ascll = uKey; barCode.Chr = Convert.ToChar(uKey); } else { return -1; } 把这个else加上去就能解析成功了。
qq_39241368 2017-08-27
  • 打赏
  • 举报
回复
我也遇到这个问题了,你后来是怎么解决的?
zhu5152 2017-04-26
  • 打赏
  • 举报
回复
引用 7 楼 wenchuan408 的回复:
谢谢楼上,按照你的方法确实有效,我也是菜鸟,实在想不通那里出问题了啊.
请问题主是怎么解决这个问题的呢?我也遇到了这样的问题!
zhu5152 2017-04-26
  • 打赏
  • 举报
回复
引用 7 楼 wenchuan408 的回复:
谢谢楼上,按照你的方法确实有效,我也是菜鸟,实在想不通那里出问题了啊.
楼主这个重复的问题是怎么解决的啊?我也遇到了
wenchuan408 2016-11-29
  • 打赏
  • 举报
回复
谢谢楼上,按照你的方法确实有效,我也是菜鸟,实在想不通那里出问题了啊.
正怒月神 2016-11-28
  • 打赏
  • 举报
回复
vs直接连接扫描枪调试就知道问题了吧?
一声-汪 2016-11-28
  • 打赏
  • 举报
回复
if (ToAscii(barCode.VirtKey, barCode.ScanCode, kbArray, ref uKey, 0)) { barCode.AscII = uKey; barCode.Chr = Convert.ToChar(uKey); } 调试时发现这里的barCode.Chr还是正常的,到了下面就出现重复了。 if ((msg.message & 0xff) == 13 && strBarCode.Length > 3) //回车 { barCode.BarCode = strBarCode; barCode.IsValid = true; } strBarCode += barCode.Chr.ToString(); 水平有限,想不通原因,解决方案就是把下面这段代码放到最上面的if(toAscii)这个判断语句里 if (DateTime.Now.Subtract(barCode.Time).TotalMilliseconds > 50) { strBarCode = barCode.Chr.ToString(); } else { if ((msg.message & 0xff) == 13 && strBarCode.Length > 3) //回车 { barCode.BarCode = strBarCode; barCode.IsValid = true; } strBarCode += barCode.Chr.ToString(); } barCode.Time = DateTime.Now;
一声-汪 2016-11-28
  • 打赏
  • 举报
回复
同问!很困惑,扫描枪调试也不好调啊
---涛声依旧--- 2016-11-28
  • 打赏
  • 举报
回复
引用 1 楼 hanjun0612 的回复:
vs直接连接扫描枪调试就知道问题了吧?
qq_28710983 2016-11-28
  • 打赏
  • 举报
回复
来学习一下 ,等待大婶回复
wenchuan408 2016-11-28
  • 打赏
  • 举报
回复
扫描枪为USB 扫描枪,直接扫描条码,一切正常,快来人啊.

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧