C# hook - 计算键盘上的击键次数

标签 c# hook

统计程序。不是键盘记录器。对我来说,要知道我浪费了多少生命在毫无意义的敲击键盘上;}}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace StatisticChar
{
    public partial class Form1 : Form
    {
        private GlobalKeyboardHook _globalKeyboardHook;

        public void SetupKeyboardHooks()
        {
            _globalKeyboardHook = new GlobalKeyboardHook();
            _globalKeyboardHook.KeyboardPressed += OnKeyPressed;
        }
        private void OnKeyPressed(object sender, GlobalKeyboardHookEventArgs e)
        {


            if (e.KeyboardState == GlobalKeyboardHook.KeyboardState.KeyDown)
            {
                var znak = $"{(char)e.KeyboardData.VirtualCode} {e.KeyboardData.VirtualCode}";


                //////////////////////    SEKCJA F1   ///////////////////////////////////////////
                if ((e.KeyboardData.VirtualCode >= 112) && (e.KeyboardData.VirtualCode <= 123))
                {
                    znak = "F" + (e.KeyboardData.VirtualCode - 111).ToString();
                }

                //////////////////////   SEKCJA NUMERYCZNA ///////////////////////////////////////////

                if ((e.KeyboardData.VirtualCode >= 96) && (e.KeyboardData.VirtualCode <= 105))
                {
                    znak = (e.KeyboardData.VirtualCode - 96).ToString();
                }


                if (e.KeyboardData.VirtualCode == 144)
                {
                    znak = "NumLock";
                }

                if (e.KeyboardData.VirtualCode == 111)
                {
                    znak = "/";
                }

                if (e.KeyboardData.VirtualCode == 106)
                {
                    znak = "*";
                }

                if (e.KeyboardData.VirtualCode == 109)
                {
                    znak = "-";
                }

                if (e.KeyboardData.VirtualCode == 107)
                {
                    znak = "+";
                }

                if (e.KeyboardData.VirtualCode == 107)
                {
                    znak = ",";
                }

                //////////////////////   SEKCJA GŁÓWNA ///////////////////////////////////////////

                if (e.KeyboardData.VirtualCode == 13)
                {
                    znak = "ENTER";
                }

                if (e.KeyboardData.VirtualCode == 192)
                {
                    znak = "`";
                }

                if (e.KeyboardData.VirtualCode == 9)
                {
                    znak = "tabulator";
                }

                if (e.KeyboardData.VirtualCode == 20)
                {
                    znak = "capslock";
                }

                if (e.KeyboardData.VirtualCode == 160)
                {
                    znak = "LewyShift";
                }

                if (e.KeyboardData.VirtualCode == 162)
                {
                    znak = "ctrl";
                }

                if (e.KeyboardData.VirtualCode == 91)
                {
                    znak = "win";
                }

                if (e.KeyboardData.VirtualCode == 32)
                {
                    znak = "spacja";
                }

                if (e.KeyboardData.VirtualCode == 37)
                {
                    znak = "←";
                }

                if (e.KeyboardData.VirtualCode == 39)
                {
                    znak = "→";
                }

                if (e.KeyboardData.VirtualCode == 38)
                {
                    znak = "↑";
                }

                if (e.KeyboardData.VirtualCode == 40)
                {
                    znak = "↓";
                }

                if (e.KeyboardData.VirtualCode == 8)
                {
                    znak = "backup";
                }

                if (e.KeyboardData.VirtualCode == 161)
                {
                    znak = "prawyShift";
                }

                if (e.KeyboardData.VirtualCode == 93)
                {
                    znak = "ppm";
                }

                if (e.KeyboardData.VirtualCode == 45)
                {
                    znak = "insert";
                }

                if (e.KeyboardData.VirtualCode == 44)
                {
                    znak = "printscreen";
                }

                if (e.KeyboardData.VirtualCode == 19)
                {
                    znak = "pause";
                }

                if (e.KeyboardData.VirtualCode == 166)
                {
                    znak = "back";
                }

                if (e.KeyboardData.VirtualCode == 36)
                {
                    znak = "home";
                }

                if (e.KeyboardData.VirtualCode == 35)
                {
                    znak = "end";
                }

                if (e.KeyboardData.VirtualCode == 46)
                {
                    znak = "delete";
                }

                if (e.KeyboardData.VirtualCode == 33)
                {
                    znak = "pageUp";
                }

                if (e.KeyboardData.VirtualCode == 34)
                {
                    znak = "pagDown";
                }

                if (e.KeyboardData.VirtualCode == 163)
                {
                    znak = "PrawyCtrl";
                }



                //////////////////////   INNE, POZOSTAŁE ///////////////////////////////////////////

                if (e.KeyboardData.VirtualCode == 1)
                {
                    znak = "LeftClick";
                }

                if (e.KeyboardData.VirtualCode == 2)
                {
                    znak = "RightClick";
                }



                Statystyki[znak] = Statystyki.ContainsKey(znak) ? ++Statystyki[znak] : 1;
            }
        }
        public new void Dispose()
        {
            base.Dispose();
            _globalKeyboardHook?.Dispose();
        }


        private DateTime data_zbierania_statystyk;
        private static readonly Dictionary<string, int> Statystyki = new Dictionary<string, int>();

        public Form1()
        {
            _globalKeyboardHook = new GlobalKeyboardHook();
            SetupKeyboardHooks();

            var dt = DateTime.Now;
            data_zbierania_statystyk = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0);

            Timer timer = new Timer
            {
                Interval = 1 * 10 * 1000
            };
            timer.Tick += new EventHandler(Timer_Tick);
            timer.Start();

            Timer timer2 = new Timer
            {
                Interval = 1000
            };
            timer2.Tick += new EventHandler(Timer2_Tick);
            timer2.Start();

            InitializeComponent();

        }

        private void Timer2_Tick(object sender, EventArgs e)
        {
           richTextBox1.Text = StatystykiJakoText();
        }

        void Timer_Tick(object sender, EventArgs e)
        {
            Saves();
        }
        void Saves()
        {
            var dt = DateTime.Now;
            var now = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0);

            if (data_zbierania_statystyk < now)
            {
                data_zbierania_statystyk = now;

                string sb = StatystykiJakoText();

                string path = $@"O:\statystyki{dt.Year}-{dt.Month}-{dt.Day}.txt";

                File.AppendAllText(path, sb);

                richTextBox1.Text = "";
                richTextBox1.Text = sb.ToString();
            }
        }

        private string StatystykiJakoText()
        {
            var sb = new StringBuilder();
            sb.Append(Environment.NewLine);
            sb.Append($"Statystyki za dzień: {data_zbierania_statystyk}{Environment.NewLine}");

            foreach (var literka in Statystyki)
            {
                sb.Append($"{literka.Key} - {literka.Value}{Environment.NewLine}");
            }

            return sb.ToString();
        }


    }
}

但是,仍然存在一个问题:

  1. 我无法捕捉到每个字符,例如右 alt、F 模式
  2. 无法捕获某些程序(例如 Notepad++)中写入的字符? 有谁能说出为什么会发生这种情况以及如何解决它吗?

  3. 如何处理快捷键,例如 ctrl + c、ctrl + v?

  4. 如果我们保留该键并且不放开它,如何防止按下该键?

最佳答案

如果你想要一个完整的键盘钩子(Hook),使用这些函数会更有趣:

public class WindowsHookAPI
{
    //public delegate IntPtr HookDelegate(
    //    Int32 Code, IntPtr wParam, IntPtr lParam);
    public delegate IntPtr HookDelegate(Int32 Code, IntPtr wParam, IntPtr lParam);

    [DllImport("User32.dll")]
    public static extern IntPtr CallNextHookEx(IntPtr hHook, Int32 nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("User32.dll")]
    public static extern IntPtr UnhookWindowsHookEx(IntPtr hHook);


    [DllImport("User32.dll")]
    public static extern IntPtr SetWindowsHookEx(Int32 idHook, HookDelegate lpfn, IntPtr hmod, Int32 dwThreadId);
}

您一定会捕获所有按键,并且如果您愿意,您可以轻松阻止某些按键..

“它是钩子(Hook)的起源”

像这样安装全局钩子(Hook):

keyBoardHandle = WindowsHookAPI.SetWindowsHookEx(WH_KEYBOARD_LL, keyBoardDelegate, IntPtr.Zero, 0);

以及使用它的示例:

    private WindowsHookAPI.HookDelegate keyBoardDelegate;
    private IntPtr keyBoardHandle;

    // Hook global keyboard
    private const Int32 WH_KEYBOARD_LL          = 13;
    // flags bits of lParam hookstruct
    private const Int32 LLKHF_EXTENDED          = 0b00000001;
    private const Int32 LLKHF_LOWER_IL_INJECTED = 0b00000010;
    private const Int32 LLKHF_INJECTED          = 0b00010000;
    private const Int32 LLKHF_ALTDOWN           = 0b00100000;
    private const Int32 LLKHF_UP                = 0b10000000;
    // value of wParam
    private const Int32 WM_KEYUP                = 0x0101;
    private const Int32 WM_KEYDOWN              = 0x0100;

    private IntPtr KeyboardHookDelegate(Int32 Code, IntPtr wParam, IntPtr lParam)
    {

        hookStruct param = (hookStruct)Marshal.PtrToStructure(lParam, typeof(hookStruct));
        if (Code < 0 || (param.flags & LLKHF_INJECTED) != 0)
        {
            return WindowsHookAPI.CallNextHookEx(keyBoardHandle, Code, wParam, lParam);
        }

        if ((int)wParam == WM_KEYDOWN)
        {
         // see https://learn.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagkbdllhookstruct 
         // for more explanations about type of keys trapped
         // return (IntPtr)1;    // if you want to block some keys
        }

        return WindowsHookAPI.CallNextHookEx(keyBoardHandle, Code, wParam, lParam);
    }

    public struct hookStruct
    {
        public int vkCode;
        public int scanCode;
        public int flags;
        public int time;
        public int dwExtraInfo;
    }

取消 Hook 使用:

WindowsHookAPI.UnhookWindowsHookEx(keyBoardHandle);

关于C# hook - 计算键盘上的击键次数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53979393/

相关文章:

c# - 添加到 CHAR 列末尾的一系列空格

javascript - ASP.NET 中的 SignalR 和 Angular,客户端没有得到响应

c# - 在 WPF 中使用动态资源设置控件背景颜色?

svn - 在 SVN 提交后 Hook 中节省时间?

c++ - 任何 Hook 函数的单一接口(interface)

c# - 如何计算图表的趋势线?

Wordpress 添加新的用户 Hook

python 3 : hook list & dict changes

windows - 如何区分计算机中的两个鼠标?

c# - MySQL查询不返回值,但存在于数据库中