当前位置:网站首页>C keyboard hook
C keyboard hook
2022-06-29 13:48:00 【Full stack programmer webmaster】
Hello everyone , I meet you again , I'm your friend, Quan Jun .
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace KeyboardHookPro
{
public class ScanerHook
{
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;// Declare the initial value of keyboard hook processing
private ScanerCodes codes = new ScanerCodes();//13 For keyboard hook
// Defined as static , This will not throw a collection exception
private static HookProc hookproc;
private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
// Set the hook
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
// Unload hook
private static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
// Continue with the next hook
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("user32", EntryPoint = "GetKeyNameText")]
private static extern int GetKeyNameText(int IParam, StringBuilder lpBuffer, int nSize);
[DllImport("user32", EntryPoint = "GetKeyboardState")]
// Get the status of the key
private static extern int GetKeyboardState(byte[] pbKeyState);
[DllImport("user32", EntryPoint = "ToAscii")]
//ToAscii Function conversion specifies the virtual key code and the corresponding character or character of the keyboard state
private static extern bool ToAscii(int VirtualKey, int ScanCode, byte[] lpKeySate, ref uint lpChar, int uFlags);
//int VirtualKey //[in] Specify virtual key code for translation .
//int uScanCode, // [in] The key of the specified hardware scan code must be translated into English . This value of higher order bits is the key to setting , If it is ( No pressure )
//byte[] lpbKeyState, // [in] The pointer , With 256 Byte array , Contains the status of the current keyboard . Every element ( byte ) The array of contains a key to the State . If the bytes of higher order bits are a set , The key is to fall ( Press down ). At low bits , Such as / Result setting indicates , The key is to switch . In this function , Elbow only CAPS LOCK Keys are related . In the switching state NUM Multiple locks and scroll lock keys are ignored .
//byte[] lpwTransKey, // [out] The buffer of the pointer receives a translated character or character .
//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")]
// Use WINDOWS API Function instead of the function that gets the current instance , Prevent hook failure
public static extern IntPtr GetModuleHandle(string name);
public bool Start()
{
if (hKeyboardHook == 0)
{
hookproc = new HookProc(KeyboardHookProc);
//GetModuleHandle function replace Marshal.GetHINSTANCE
// To prevent the framework4.0 in Failed to register hook
IntPtr modulePtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
//WH_KEYBOARD_LL=13
// global hook 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, int 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))
//{
ScanerEvent(codes);
//}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
public class ScanerCodes
{
private int ts = 100; // Specify the input interval as 300 Continuous input within milliseconds
private List<List<EventMsg>> _keys = new List<List<EventMsg>>();
private List<int> _keydown = new List<int>(); // Save key combination state
private List<string> _result = new List<string>(); // Return result set
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 => _keydown;
public DateTime LastInput => _last;
public byte[] KeyboardState => _state;
public int KeyDownCount => _keydown.Count;
public string Result
{
get
{
if (_result.Count > 0)
{
return _result[_result.Count - 1].Trim();
}
else
{
return null;
}
}
}
public string CurrentKey => _key;
public string CurrentChar => _cur;
public bool isShift => _keydown.Contains(160);
public void Add(EventMsg msg)
{
#region Record key information
// Press the button for the first time
if (_keys.Count == 0)
{
_keys.Add(new List<EventMsg>());
_keys[0].Add(msg);
_result.Add(string.Empty);
}
// Press the key when no other key is released
else if (_keydown.Count > 0)
{
_keys[_keys.Count - 1].Add(msg);
}
// Press the button in unit time
else if ((DateTime.Now - _last).TotalMilliseconds < ts)
{
_keys[_keys.Count - 1].Add(msg);
}
// Input from a new record
else
{
_keys.Add(new List<EventMsg>());
_keys[_keys.Count - 1].Add(msg);
_result.Add(string.Empty);
}
#endregion
_last = DateTime.Now;
#region Get keyboard status
// Record the key being pressed
if (msg.paramH == 0 && !_keydown.Contains(msg.message))
{
_keydown.Add(msg.message);
}
// Clear the released key
if (msg.paramH > 0 && _keydown.Contains(msg.message))
{
_keydown.Remove(msg.message);
}
#endregion
#region Calculate key information
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
{
// Depending on the keyboard status and shift The cache determines the output character
_cur = ShiftChar(_key, isShift, _state).ToString();
_result[_result.Count - 1] += _cur;
}
// alternative
// Judgment is + Force add +
else if (_key.Length == 5 && msg.paramH == 0 && msg.paramL == 78 && msg.message == 107)// && msg.paramH == 0
{
// Depending on the keyboard status and shift The cache determines the output character
_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)(chr - 32);
}
else if (chr >= 'A' && chr <= 'Z')
{
if (chr == 'Z')
{
string s = "";
}
chr = (char)(chr + 32);
}
else
{
string s = "`1234567890-=[];',./";
string u = "[email protected]#$%^&*()_+{}:\"<>?";
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;
}
}
}usage
private ScanerHook listener = new ScanerHook();
public InitHook()
{
listener.Start();
listener.ScanerEvent += Listener_ScanerEvent;// Execute function
this.FormClosed += (sender, e) =>
{
listener.Stop();
};
}
private void Listener_ScanerEvent(ScanerHook.ScanerCodes codes)
{
string msg = codes.Result;// Output here
}Publisher : Full stack programmer stack length , Reprint please indicate the source :https://javaforall.cn/132342.html Link to the original text :https://javaforall.cn
边栏推荐
- C language__ VA_ ARGS__ Usage of
- 【毕业季】这四年一路走来都很值得——老学长の忠告
- 使用 Gerrit + Zadig 实现主干开发主干发布(含字节飞书实践)
- Detailed explanation of machine learning out of fold prediction | using out of fold prediction oof to evaluate the generalization performance of models and build integrated models
- Getting started with SQLite3
- Force buckle: merging two ordered linked lists
- 脚本中的node命令不在控制台打印执行日志
- What is the reason why the gbase8s database encountered a 951 error?
- urllib urllib2
- MySQL常用语句和命令汇总
猜你喜欢

基于51单片机控制的BUCK开关电源Proteus仿真

weserver發布地圖服務

C language character function

手把手教你在windows上安装mysql8.0最新版本数据库,保姆级教学

win32版俄罗斯方块(学习MFC必不可少)

WinDbg common commands

Use Gerrit + Zadig to realize trunk development and trunk publishing (including byte flying Book Practice)

Technology sharing | broadcast function design in integrated dispatching

Uncover the secret! Pay attention to those machines under the membership system!

Windbg常用命令详解
随机推荐
Teach you how to install the latest version of mysql8.0 database on windows, nanny level teaching
B+ tree | MySQL index usage principle
[graduation season] it's worth it all the way over the past four years -- advice from the senior students
urllib urllib2
Return value‘s Lifetime
3个最佳实践助力企业改善供应链安全
WinDbg debugging tool introduction
C语言字符函数
Weserver Publishing Map Service
Repoptimizer: it's actually repvgg2
What if the excel table exported from the repair record is too large?
Online text filter less than specified length tool
[cloud resident co creation] break through the performance bottleneck of image recognition through rust language computing acceleration technology
[graduation season · advanced technology Er] 10.76 million graduates, the most difficult employment season in history? I can't roll it up again. I lie down again and again. Where is the road?
Ordinary users use vscode to log in to SSH and edit the root file
Redis deletion policy and eviction algorithm
Mirror vulnerability scanner: trivy
Autonomous and controllable city! Release of the first domestic artiq architecture quantum computing measurement and control system
脚本中的node命令不在控制台打印执行日志
【系统设计】邻近服务