We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
github.com/landv/HookUsbInput
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Windows.Forms; using static HookUsbInput.NativeMethods; using static System.Net.Mime.MediaTypeNames; // edit控件内容获取,也就是手动输入内容获取。 namespace HookUsbInput { public class NativeMethods { // 定义常量 public const int WM_GETTEXT = 0x000D; public const int WM_GETTEXTLENGTH = 0x000E; public const int WH_KEYBOARD_LL = 13; public const int WM_KEYDOWN = 0x0100; public const int VK_RETURN = 0x0D; public const int WM_SETTEXT = 0x000C; [DllImport("user32.dll")] public static extern bool EnableWindow(IntPtr hWnd, bool bEnable); // 导入 SendMessage 函数 [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam); [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); // 定义委托 public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); // 导入 Windows API 函数 [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumChildWindows(IntPtr hWnd, EnumChildProc lpEnumFunc, IntPtr lParam); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, StringBuilder lParam); [DllImport("user32.dll", SetLastError = true)] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); // 定义枚举窗口的委托 public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); public delegate bool EnumChildProc(IntPtr hWnd, IntPtr lParam); public enum WindowStyles : uint { WS_OVERLAPPED = 0x00000000, WS_POPUP = 0x80000000, WS_CHILD = 0x40000000, WS_MINIMIZE = 0x20000000, WS_VISIBLE = 0x10000000, WS_DISABLED = 0x08000000, WS_CLIPSIBLINGS = 0x04000000, WS_CLIPCHILDREN = 0x02000000, WS_MAXIMIZE = 0x01000000, WS_CAPTION = 0x00C00000, // WS_BORDER | WS_DLGFRAME WS_BORDER = 0x00800000, WS_DLGFRAME = 0x00400000, WS_VSCROLL = 0x00200000, WS_HSCROLL = 0x00100000, WS_SYSMENU = 0x00080000, WS_THICKFRAME = 0x00040000, WS_GROUP = 0x00020000, WS_TABSTOP = 0x00010000, WS_MINIMIZEBOX = 0x00020000, WS_MAXIMIZEBOX = 0x00010000, WS_POPUPWINDOW = WS_OVERLAPPED | WS_POPUP | WS_BORDER | WS_SYSMENU, WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX } public static readonly int GWL_STYLE = -16; // 获取或设置窗口样式用的参数 public static readonly int GWL_EXSTYLE = -20; // 获取或设置扩展窗口样式用的参数 [DllImport("user32.dll", SetLastError = true)] public static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong); [DllImport("user32.dll", SetLastError = true)] public static extern uint GetWindowLong(IntPtr hWnd, int nIndex); } public class EditInputHook { // 用于禁止和恢复编辑框的句柄 public static IntPtr editWndxx = IntPtr.Zero; private static System.Threading.Timer timer; private static string processName; private static string topLevelClassName; private static string childClassName; private static string lastText = ""; private static IntPtr hookId = IntPtr.Zero; private static NativeMethods.LowLevelKeyboardProc hookCallback; // 自定义委托和事件 public delegate void ContentChangedEventHandler(string content); public static event ContentChangedEventHandler ContentChanged; // 开始监控 public static void StartMonitoring(string processName, string topLevelClassName, string childClassName) { EditInputHook.processName = processName; EditInputHook.topLevelClassName = topLevelClassName; EditInputHook.childClassName = childClassName; timer = new System.Threading.Timer(TimerCallback, null, 0, 100); hookCallback = KeyboardHookCallback; using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { hookId = NativeMethods.SetWindowsHookEx(NativeMethods.WH_KEYBOARD_LL, hookCallback, NativeMethods.GetModuleHandle(curModule.ModuleName), 0); } } // 定时器回调函数 private static void TimerCallback(object state) { Process[] processes = Process.GetProcessesByName(processName); if (processes.Length > 0) { uint processId = (uint)processes[0].Id; NativeMethods.EnumWindows(new NativeMethods.EnumWindowsProc((hWnd, lParam) => { NativeMethods.GetWindowThreadProcessId(hWnd, out uint windowProcessId); if (windowProcessId == processId) { NativeMethods.EnumChildWindows(hWnd, new NativeMethods.EnumChildProc((childWnd, childLParam) => { StringBuilder className = new StringBuilder(256); NativeMethods.GetClassName(childWnd, className, className.Capacity); if (className.ToString() == topLevelClassName) { NativeMethods.EnumChildWindows(childWnd, new NativeMethods.EnumChildProc((editWnd, editLParam) => { StringBuilder editClassName = new StringBuilder(256); NativeMethods.GetClassName(editWnd, editClassName, editClassName.Capacity); if (editClassName.ToString() == childClassName) { int textLength = NativeMethods.SendMessage(editWnd, NativeMethods.WM_GETTEXTLENGTH, 0, null).ToInt32(); StringBuilder text = new StringBuilder(textLength + 1); NativeMethods.SendMessage(editWnd, NativeMethods.WM_GETTEXT, text.Capacity, text); //lastText = text.ToString(); if (textLength >= 14) { lastText = text.ToString(); editWndxx = editWnd; } } return true; }), IntPtr.Zero); } return true; }), IntPtr.Zero); } return true; }), IntPtr.Zero); } else { //Console.WriteLine($"未找到名为{processName}.exe的进程。"); } } // 内容变更事件处理函数 private static void OnContentChanged(string content) { ContentChanged?.Invoke(content); } // 键盘钩子回调函数 private static IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0 && wParam == (IntPtr)NativeMethods.WM_KEYDOWN) { int vkCode = Marshal.ReadInt32(lParam); if (vkCode == NativeMethods.VK_RETURN) { if (lastText.Length >= 14) { OnContentChanged(lastText); lastText = string.Empty; lastText = ""; ClearEditControl(processName, topLevelClassName, childClassName); return (IntPtr)1; } else { return NativeMethods.CallNextHookEx(hookId, nCode, wParam, lParam); } } } // 在这里返回下一个钩子的处理结果 return NativeMethods.CallNextHookEx(hookId, nCode, wParam, lParam); } public static void EnableWindowsEditWndxx(bool a) { if (editWndxx!=IntPtr.Zero) { if (a) { //MessageBox.Show(editWndxx.ToString()); NativeMethods.EnableWindow(editWndxx, true); } else { // 禁用窗口 NativeMethods.EnableWindow(editWndxx, false); //MessageBox.Show("禁用输入"); } } } // 清空编辑控件内容方法 public static void ClearEditControl(string processName, string topLevelClassName, string childClassName) { IntPtr editWndx = IntPtr.Zero; Process[] processes = Process.GetProcessesByName(processName); if (processes.Length > 0) { uint processId = (uint)processes[0].Id; NativeMethods.EnumWindows(new NativeMethods.EnumWindowsProc((hWnd, lParam) => { NativeMethods.GetWindowThreadProcessId(hWnd, out uint windowProcessId); if (windowProcessId == processId) { NativeMethods.EnumChildWindows(hWnd, new NativeMethods.EnumChildProc((childWnd, childLParam) => { StringBuilder className = new StringBuilder(256); NativeMethods.GetClassName(childWnd, className, className.Capacity); if (className.ToString() == topLevelClassName) { NativeMethods.EnumChildWindows(childWnd, new NativeMethods.EnumChildProc((editWnd, editLParam) => { StringBuilder editClassName = new StringBuilder(256); NativeMethods.GetClassName(editWnd, editClassName, editClassName.Capacity); if (editClassName.ToString() == childClassName) { int textLength = NativeMethods.SendMessage(editWnd, NativeMethods.WM_GETTEXTLENGTH, 0, null).ToInt32(); StringBuilder text = new StringBuilder(textLength + 1); NativeMethods.SendMessage(editWnd, NativeMethods.WM_GETTEXT, text.Capacity, text); //lastText = text.ToString(); if (textLength >= 14) { editWndx = editWnd; //NativeMethods.ShowWindow(editWnd, 0); //Thread.Sleep(200); //NativeMethods.ShowWindow(editWnd, 5); return true; } } return true; }), IntPtr.Zero); } return true; }), IntPtr.Zero); } return true; }), IntPtr.Zero); } // 清空编辑控件内容 if (editWndx != IntPtr.Zero) { NativeMethods.SendMessage(editWndx, NativeMethods.WM_SETTEXT, 0, new StringBuilder("")); //Thread.Sleep(500); //NativeMethods.ShowWindow(editWndx, 5); } } } }
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace HookUsbInput { public class InputHook { public delegate void ScanerDelegate(ScanerCodes codes); public event ScanerDelegate ScanerEvent; //private const int WM_KEYDOWN = 0x100;//KEYDOWN //private const int WM_KEYUP = 0x101;//KEYUP //private const int WM_SYSKEYDOWN = 0x104;//SYSKEYDOWN //private const int WM_SYSKEYUP = 0x105;//SYSKEYUP //private static int HookProc(int nCode, Int32 wParam, IntPtr lParam); private int hKeyboardHook = 0;//声明键盘钩子处理的初始值 private ScanerCodes codes = new ScanerCodes();//13为键盘钩子 //定义成静态,这样不会抛出回收异常 private static HookProc hookproc; delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); [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 IParam, StringBuilder lpBuffer, int nSize); [DllImport("user32", EntryPoint = "GetKeyboardState")] //获取按键的状态 private static extern int GetKeyboardState(byte[] pbKeyState); [DllImport("user32", EntryPoint = "ToAscii")] //ToAscii职能的转换指定的虚拟键码和键盘状态的相应字符或字符 private static extern bool ToAscii(int VirtualKey, int ScanCode, byte[] lpKeySate, ref uint lpChar, int uFlags); //int VirtualKey //[in] 指定虚拟关键代码进行翻译。 //int uScanCode, // [in] 指定的硬件扫描码的关键须翻译成英文。高阶位的这个值设定的关键,如果是(不压) //byte[] lpbKeyState, // [in] 指针,以256字节数组,包含当前键盘的状态。每个元素(字节)的数组包含状态的一个关键。如果高阶位的字节是一套,关键是下跌(按下)。在低比特,如/果设置表明,关键是对切换。在此功能,只有肘位的CAPS LOCK键是相关的。在切换状态的NUM个锁和滚动锁定键被忽略。 //byte[] lpwTransKey, // [out] 指针的缓冲区收到翻译字符或字符。 //uint fuState); // [in] Specifies whether a menu is active. This parameter must be 1 if a menu is active, or 0 otherwise. [DllImport("kernel32.dll")] //使用WINDOWS API函数代替获取当前实例的函数,防止钩子失效 public static extern IntPtr GetModuleHandle(string name); //public InputHook() //{ //} public bool Start() { if (hKeyboardHook == 0) { hookproc = new HookProc(KeyboardHookProc); //GetModuleHandle 函数 替代 Marshal.GetHINSTANCE //防止在 framework4.0中 注册钩子不成功 IntPtr modulePtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName); //WH_KEYBOARD_LL=13 //全局钩子 WH_KEYBOARD_LL // hKeyboardHook = SetWindowsHookEx(13, hookproc, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0); hKeyboardHook = SetWindowsHookEx(13, hookproc, modulePtr, 0); } return (hKeyboardHook != 0); } public bool Stop() { if (hKeyboardHook != 0) { bool retKeyboard = UnhookWindowsHookEx(hKeyboardHook); hKeyboardHook = 0; return retKeyboard; } return true; } private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) { EventMsg msg = (EventMsg)Marshal.PtrToStructure(lParam, typeof(EventMsg)); codes.Add(msg); if (ScanerEvent != null && msg.message == 13 && msg.paramH > 0 && !string.IsNullOrEmpty(codes.Result)) { if (codes.Result.Length>=14) { ScanerEvent(codes); } else { return 1; } } return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam); } public class ScanerCodes { // 这里设置毫秒数,打字快的会受到影响(打字快并且按了回车键的时候是) private int ts = 100; // 指定输入间隔为毫秒以内时为连续输入 private List<List<EventMsg>> _keys = new List<List<EventMsg>>(); private List<int> _keydown = new List<int>(); // 保存组合键状态 private List<string> _result = new List<string>(); // 返回结果集 private DateTime _last = DateTime.Now; private byte[] _state = new byte[256]; private string _key = string.Empty; private string _cur = string.Empty; public EventMsg Event { get { if (_keys.Count == 0) { return new EventMsg(); } else { return _keys[_keys.Count - 1][_keys[_keys.Count - 1].Count - 1]; } } } public List<int> KeyDowns { get { return _keydown; } } public DateTime LastInput { get { return _last; } } public byte[] KeyboardState { get { return _state; } } public int KeyDownCount { get { return _keydown.Count; } } public string Result { get { if (_result.Count > 0) { return _result[_result.Count - 1].Trim(); } else { return null; } } } public string CurrentKey { get { return _key; } } public string CurrentChar { get { return _cur; } } public bool isShift { get { return _keydown.Contains(160); } } public void Add(EventMsg msg) { #region 记录按键信息 // 首次按下按键 if (_keys.Count == 0) { _keys.Add(new List<EventMsg>()); _keys[0].Add(msg); _result.Add(string.Empty); } // 未释放其他按键时按下按键 else if (_keydown.Count > 0) { _keys[_keys.Count - 1].Add(msg); } // 单位时间内按下按键 else if (((TimeSpan)(DateTime.Now - _last)).TotalMilliseconds < ts) { _keys[_keys.Count - 1].Add(msg); } // 从新记录输入内容 else { _keys.Add(new List<EventMsg>()); _keys[_keys.Count - 1].Add(msg); _result.Add(string.Empty); } #endregion _last = DateTime.Now; #region 获取键盘状态 // 记录正在按下的按键 if (msg.paramH == 0 && !_keydown.Contains(msg.message)) { _keydown.Add(msg.message); } // 清除已松开的按键 if (msg.paramH > 0 && _keydown.Contains(msg.message)) { _keydown.Remove(msg.message); } #endregion #region 计算按键信息 int v = msg.message & 0xff; int c = msg.paramL & 0xff; StringBuilder strKeyName = new StringBuilder(500); if (GetKeyNameText(c * 65536, strKeyName, 255) > 0) { _key = strKeyName.ToString().Trim(new char[] { ' ', '\0' }); GetKeyboardState(_state); if (_key.Length == 1 && msg.paramH == 0)// && msg.paramH == 0 { // 根据键盘状态和shift缓存判断输出字符 _cur = ShiftChar(_key, isShift, _state).ToString(); _result[_result.Count - 1] += _cur; } //判断是+ 强制添加+ else if (_key.Length == 5 && msg.paramH == 0 && msg.paramL == 78 && msg.message == 107)// && msg.paramH == 0 { // 根据键盘状态和shift缓存判断输出字符 _cur = Convert.ToChar('+').ToString(); _result[_result.Count - 1] += _cur; } // 备选 else { _cur = string.Empty; } } #endregion } private char ShiftChar(string k, bool isShiftDown, byte[] state) { bool capslock = state[0x14] == 1; bool numlock = state[0x90] == 1; bool scrolllock = state[0x91] == 1; bool shiftdown = state[0xa0] == 1; char chr = (capslock ? k.ToUpper() : k.ToLower()).ToCharArray()[0]; if (isShiftDown) { if (chr >= 'a' && chr <= 'z') { chr = (char)((int)chr - 32); } else if (chr >= 'A' && chr <= 'Z') { if (chr == 'Z') { string s = ""; } chr = (char)((int)chr + 32); } else { string s = "`1234567890-=[];',./"; string u = "~!@#$%^&*()_+{}:\"<>?"; if (s.IndexOf(chr) >= 0) { return (u.ToCharArray())[s.IndexOf(chr)]; } } } return chr; } } public struct EventMsg { public int message; public int paramL; public int paramH; public int Time; public int hwnd; } } }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
github.com/landv/HookUsbInput
EditInputHook.cs
inputHook.cs
The text was updated successfully, but these errors were encountered: