当前位置:网站首页>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
边栏推荐
- Netdata mail alarm configuration
- Huawei machine learning service speech recognition function enables applications to paint "sound" and color
- @Table burst red
- 成功解决ValueError: Only TF native optimizers are supported in Eager mode
- Return value‘s Lifetime
- C语言的指针详解
- Want to make a wechat game for answering questions? Reading this article is enough
- 【毕业季·进击的技术er】1076万毕业生,史上最难就业季?卷又卷不过,躺又躺不平,敢问路在何方?
- Open source machine learning platform
- 打造一个 API 快速开发平台,牛逼!
猜你喜欢

高校女生穿旗袍答辩!网友:导师说论文要是和旗袍一样漂亮就好了

二叉树习题总结

C language memory function

Qitai observation: professional elites must step on the huge pit of entrepreneurship - learning effect pit

MySQL tuning

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

Pod security policy (PSP)

Korean AI team plagiarizes the shock academic world! One tutor with 51 students, or plagiarism recidivist

mysql调优

What if the excel table exported from the repair record is too large?
随机推荐
Cvpr2022 | a convnet for the 2020s & how to design neural network Summary
如何让 Dapper 支持 DateOnly 类型
Learn from the official motor and BLDC control strategies, and make money as soon as you learn
Repoptimizer: it's actually repvgg2
Openssl证书工具使用手册
Netdata mail alarm configuration
#yyds干货盘点# 解决剑指offer:在二叉树中找到两个节点的最近公共祖先
DeeCamp2022正式开营!李开复、张亚勤亲授大师课 | 创新事
存算一体为何是造芯新方向?|对撞派 x 知存科技
How can the sports app keep the end-to-side background alive to make the sports record more complete?
AOSP ~ initialization language
Can I open an account online? Is it safe
Cvpr2022 𞓜 future transformer with long-term action expectation
Aurora · Huffman tree generation (segment tree structure non pointer) (imitating adjacency table)
【云驻共创】通过Rust语言计算加速技术突破图片识别性能瓶颈
手把手教你在windows上安装mysql8.0最新版本数据库,保姆级教学
*打卡算法*LeetCode 146. LRU 缓存 算法解析
What if the excel table exported from the repair record is too large?
Teach you how to install the latest version of mysql8.0 database on windows, nanny level teaching
*Clock in algorithm *leetcode 146 Analysis of LRU cache algorithm