Как отловить в HookCallback
все клавиши с проверкой по шифтам и.т.п?
Обычный (Keys) Marshal.ReadInt32 (lParam)
просто пишет большими буквами.
public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static readonly LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
try
{
Console.WriteLine((Keys)Marshal.ReadInt32(lParam));
}
catch (AccessViolationException ex) { Console.WriteLine($"Error: {ex.ToString()}"); }
}
return NativeMethods.CallNextHookEx(_hookID, nCode, wParam, lParam);
}
У меня есть идея занести список клавиш в List<Keys>
и оттуда как-то делать проверку.
Но может у Вас есть идеи по лучше?! ( желательно с примером )
Как-то так:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Windows.Forms;
namespace ConsoleApplication1
{
class Program
{
static KeyLogger k;
static void Main(string[] args)
{
k = new KeyLogger();
k.Start();
Console.CancelKeyPress += Console_CancelKeyPress;
Console.WriteLine("Started listening for keyboard events...");
Application.Run();
}
private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
k.Stop();
Application.Exit();
}
}
sealed class KeyLogger : IDisposable //отслеживает события клавиатуры с помощью низкоуровневого хука Windows
{
//объявления типов, констант и функций Windows API
delegate IntPtr KeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
const int WH_KEYBOARD_LL = 13;
const int HC_ACTION = 0;
const int WM_KEYDOWN = 0x0100;
const uint VK_CAPITAL = 0x14;
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern IntPtr SetWindowsHookEx(int idHook, KeyboardProc lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("USER32.dll")]
public static extern short GetKeyState(int vKey);
[DllImport("user32.dll")]
public static extern short GetAsyncKeyState(int vKey);
[DllImport("user32.dll")]
public static extern int ToUnicodeEx(
uint wVirtKey,
uint wScanCode,
byte[] lpKeyState,
[Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff,
int cchBuff,
uint wFlags,
IntPtr dwhkl);
[DllImport("user32.dll")]
public static extern bool GetKeyboardState(byte[] lpKeyState);
[DllImport("user32.dll")]
public static extern uint MapVirtualKey(
uint uCode,
uint uMapType);
[DllImport("user32.dll")]
public static extern IntPtr GetKeyboardLayout(uint idThread);
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
//преобразование виртуального кода клавиши в его Юникод-представление
public static string VKCodeToUnicode(uint vkCode)
{
StringBuilder buf = new StringBuilder();
byte[] keyboardState = new byte[255];
short x;
byte y;
for (int i = 0; i < 255; i++)
{
if (i == VK_CAPITAL)
{
x = GetKeyState(i);
}
else
{
x = GetAsyncKeyState(i);
}
y = 0;
if ((x & 0x8000) != 0) y = (byte)(y | 0x80);
if ((x & 0x0001) != 0) y = (byte)(y | 0x01);
keyboardState[i] = y;
}
ToUnicodeEx(vkCode, MapVirtualKey(vkCode, 0), keyboardState, buf, 5, 0,
GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero)));
return buf.ToString();
}
IntPtr _hookID = IntPtr.Zero;
//начинает отслеживание событий клавиатуры
public void Start()
{
if (disposed) throw new ObjectDisposedException("KeyLogger");
if (_hookID != IntPtr.Zero) return;
_hookID = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookCallback, IntPtr.Zero, 0);
if (_hookID == IntPtr.Zero)
{
int error = Marshal.GetLastWin32Error();
throw new Win32Exception(error, "Failed to install hook! Error: "+ error.ToString());
}
}
//останавливает отслеживание событий клавиатуры
public void Stop()
{
if (disposed) return;
if (_hookID == IntPtr.Zero) return;
UnhookWindowsHookEx(_hookID);
_hookID = IntPtr.Zero;
}
//вызывается Windows при нажатии клавиши
IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
string s = VKCodeToUnicode((uint)vkCode);
Console.Out.WriteLine("Key: " + ((Keys)vkCode).ToString() + "; Character: " + s);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
//так как KeyLogger использует неуправляемый ресурс, реализуем Dispose и Finalize...
bool disposed = false;
public void Dispose()
{
if (disposed) return;
Stop();
disposed = true;
GC.SuppressFinalize(this);
}
~KeyLogger()
{
Dispose();
}
}
}
Известная проблема (Windows 10): если активно консольное окно, всегда распознаются символы раскладки, установленной в момент создания консоли, вместо текущей раскладки.
Основано на данных вопросах:
GetKeyboardState: определение состояния клавиши
Некорректная работа перехватчика нажатых клавиш (кейлоггер) C#
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Имеется 5 элементов на вебстранице содержащих разный текст: 1,7,13,25,4Пример: 13
Задумался как сделать логичнее (правильнее)Есть два класса: один ставит лайки в нём два метода лайки по тэгу и лайки по геолокации, второй...
Собственно есть такой код, где в цикле создаются PictureBox
Подскажите как загуглить что бы почитать о операторе/ключевом слове where в такой конструкции например: