C# 键盘钩子捕获扫码枪

由于扫码枪的输出方式与键盘输出是一样的,由此可以使用键盘钩子来捕获扫码枪数据

文章目录

      • 引用
      • HookApi
      • 常数和结构
      • 安装与卸载
      • 释放不需要的数据
      • 捕获

引用

using System;
using System.Timers;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Runtime.InteropServices;

HookApi

public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);

//安装钩子的函数 
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

//卸下钩子的函数 
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);

//下一个钩挂的函数 
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);

[DllImport("user32")]
public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);

[DllImport("user32")]
public static extern int GetKeyboardState(byte[] pbKeyState);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("user32.dll")]
public static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, uint dwExtraInfo);

常数和结构

public const int WM_KEYDOWN = 0x100;
public const int WM_KEYUP = 0x101;
public const int WM_SYSKEYDOWN = 0x104;
public const int WM_SYSKEYUP = 0x105;
public const int WH_KEYBOARD_LL = 13;

[StructLayout(LayoutKind.Sequential)]

public class KeyboardHookStruct
{
    public int vkCode;
    public int scanCode;
    public int flags;
    public int time;
    public int dwExtraInfo;
}

安装与卸载

private int HookIntPtr;
private HookProc KeysHookDelegate;

/// 
/// 为了延迟释放已经捕获到了的键值
/// 
private static readonly System.Timers.Timer ReleaseTimer = new System.Timers.Timer();

/// 
/// 安装钩子
/// 
public void KeysHook_Set()
{
	KeysHookDelegate = new HookProc(KeyboardHookProc);
	Process NewPro = Process.GetCurrentProcess();
	ProcessModule NewProMod = NewPro.MainModule;
	IntPtr NewIntPtr = GetModuleHandle(NewProMod.ModuleName);
	HookIntPtr = SetWindowsHookEx(WH_KEYBOARD_LL, KeysHookDelegate, NewIntPtr, 0);

	ReleaseTimer.Stop();
	ReleaseTimer.Interval = LoadSetup.Default.KeysDelay;
	ReleaseTimer.Elapsed += new ElapsedEventHandler(ReleaseTimer_Tick);
}

/// 
/// 卸载钩子
/// 
public void KeysHook_Unload()
{
    try
    {
        UnhookWindowsHookEx(HookIntPtr);
        ReleaseTimer.Stop();
    }
    catch { }
}

释放不需要的数据

/// 
/// 释放键列表
/// 
private readonly List KeysList_Release = new List();

/// 
/// 释放所有按键
/// 
private void ReleaseAllKeys()
{
    CodeStr = "";
    try
    {
        foreach (Keys key in KeysList_Release)
        {
            KeysReleaseing = true;
            keybd_event(key, 0, 0, 0);
            keybd_event(key, 0, 2, 0);
            KeysUp = true;
        }
    }
    catch { }
    KeysUp = true;
    KeysReleaseing = false;
    KeysList_Release.Clear();
    ReleaseTimer.Stop();
}

private int OverTime = 0;

/// 
/// 延时释放已捕获的键值,一般是释放手输的键
/// 
private void ReleaseTimer_Tick(object sender, ElapsedEventArgs e)
{
    if (OverTime >= 1)
    {
        ReleaseAllKeys();
        OverTime = 0;
    }
    OverTime++;
}

捕获

/// 
/// 捕获到的字符串
/// 
private string CodeStr = "";

/// 
/// 来判断是否是手输的
/// 
private DateTime DownTime = DateTime.Now;
private DateTime UpTime = DateTime.Now;
private TimeSpan NewSpan = new TimeSpan();

/// 
/// 来判断是否释放不需要的数据
/// 
private bool KeysReleaseing = false;

/// 
/// 来判断键盘按下后是否放开
/// 
private bool KeysUp = true;

private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
    if (nCode >= 0)
    {
        KeyboardHookStruct KeyDataFromHook = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
        Keys AimKeys = (Keys)KeyDataFromHook.vkCode;
        #region Enter处理   一般扫码枪输出完后都会再输出个Enter键
        if (AimKeys == Keys.Enter)
        {
       	    ///判断捕获到的是否是自己所需要的数据
            bool IsPayCode = DataHelper.PayCode_Judge(CodeStr, out bool Vip) ;
            if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
            {
                if (IsPayCode)
                {
                    KeysList_Release.Clear();
                    string TemCode = CodeStr;
                    CodeStr = "";
                    //“TemCode”就是所需要的值了,就可以直接去执行相关函数
                    return 1;
                }
                else
                {
                    ReleaseAllKeys();
                }
            }
            else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
            {
                if (IsPayCode)
                {
                    return 1;
                }
            }
        }
        #endregion

        #region 数字处理  这个可以自行选择需要捕获的键盘值
        else if ((KeyDataFromHook.vkCode >= (int)Keys.D0 && KeyDataFromHook.vkCode <= (int)Keys.D9))
        {
            //判断是否是释放键值中
            if (!KeysReleaseing)
            {
                if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
                {
                	//这是把键值转换为字符串
                    CodeStr += KeysHelper.ToStr(AimKeys);
                    KeysList_Release.Add(AimKeys);
                    DownTime = DateTime.Now;
                    OverTime = 0;
                    if (KeysUp)
                    {
                        ReleaseTimer.Start();
                        KeysUp = false;
                    }
                    else
                    {
                        ReleaseAllKeys();
                    }
                }
                if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
                {
                    KeysUp = true;
                    UpTime = DateTime.Now;
                    NewSpan = UpTime.Subtract(DownTime);
                    //来判断是否是手输,一般扫码枪在20ms以下,这个值可以自己设
                    if (NewSpan.Milliseconds > LoadSetup.Default.KeysDelay)
                    {
                        CodeStr = "";
                    }
                }
                //return 1是键盘不响应
                return 1;
            }
        }
        else
        {
            ReleaseAllKeys();
        }
        #endregion
    }
    return CallNextHookEx(HookIntPtr, nCode, wParam, lParam);
}

你可能感兴趣的:(c#,visual,studio,windows,.net)