Перехват клавиатуры Windows на C#
Один из разработчиков обучающей системы с модулем тестирования обратился ко мне с достаточно простой на первый взгляд задачей – как при запуске экзамена не допустить переключения приложения. При всей простоте, задача немного усложнилась тем, что комплекс был разработан на .NET Framework и подключать вставки native кода на C++ не очень хотелось. На самом деле язык C# на платформе Windows позволяет работать с WIN API. Осталось только привести пример того, как можно осуществить перехват нажатий на клавиши на чуть более низком уровне.
Собственно ниже пример перехвата клавиатуры на языке C#. Пример этот будет работать как на 32х так и на 64 битной Windows. Программа выводит в отладочную консоль нажатия на клавиши в любом приложении, а также производит блокировку нажатия Alt+Tab. Как вы уже понимаете, перехват клавиатуры ведется на уровне всех приложений. При желании можно даже перехватить Ctrl Alt Del но думаю что детали, тем кому это необходимо, выяснят самостоятельно.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace HookDemoApp
{
internal class HookDemoHelper
{
private const int WH_KEYBOARD_LL = 13;
private LowLevelKeyboardProcDelegate m_callback;
private IntPtr m_hHook;
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(
int idHook,
LowLevelKeyboardProcDelegate lpfn,
IntPtr hMod, int dwThreadId);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern IntPtr GetModuleHandle(IntPtr lpModuleName);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr CallNextHookEx(
IntPtr hhk,
int nCode, IntPtr wParam, IntPtr lParam);
private IntPtr LowLevelKeyboardHookProc(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode < 0)
{
return CallNextHookEx(m_hHook, nCode, wParam, lParam);
}
else
{
var khs = (KeyboardHookStruct)
Marshal.PtrToStructure(lParam,
typeof (KeyboardHookStruct));
Debug.Print("Hook: Code: {0}, WParam: {1},{2},{3},{4} ",
nCode, wParam, lParam,
khs.VirtualKeyCode,
khs.ScanCode, khs.Flags, khs.Time);
Debug.Print(khs.VirtualKeyCode.ToString());
if (khs.VirtualKeyCode == 9 &&
wParam.ToInt32() == 260 &&
khs.ScanCode == 15) //alt+tab
{
System.Console.WriteLine("Alt+Tab pressed!");
IntPtr val=new IntPtr(1);
return val;
}
else
{
return CallNextHookEx(m_hHook, nCode, wParam, lParam);
}
}
}
[StructLayout(LayoutKind.Sequential)]
private struct KeyboardHookStruct
{
public readonly int VirtualKeyCode;
public readonly int ScanCode;
public readonly int Flags;
public readonly int Time;
public readonly IntPtr ExtraInfo;
}
private delegate IntPtr LowLevelKeyboardProcDelegate(
int nCode, IntPtr wParam, IntPtr lParam);
public void SetHook()
{
m_callback =LowLevelKeyboardHookProc;
m_hHook =SetWindowsHookEx(WH_KEYBOARD_LL,
m_callback,
GetModuleHandle(IntPtr.Zero),0);
}
public void Unhook()
{
UnhookWindowsHookEx(m_hHook);
}
}
}
Comments
Anonymous
December 03, 2010
www.sql.ru/.../actualthread.aspxAnonymous
January 22, 2011
Спасибо! Очень кстати, у меня тоже в планах модуль тестирования =)Anonymous
February 04, 2012
Пишет что метод main() не найден. ЧТо делать? Как запустить?Anonymous
May 17, 2012
Максим, в класс вставьте следующий код: public static void Main() { }Anonymous
October 10, 2012
Не могу понять как перехватывать тройное нажатие например Ctrl Alt Del, помогите пожалуйста.Anonymous
June 23, 2013
Подскажите а можно как-нибудь реализовать, что-бы перехватывала нажатия в одном определенном приложении?Anonymous
April 25, 2014
Портировал в форму - не работает. И консоли до этого тоже не работало.Anonymous
May 19, 2015
Не ожидал, работает, и так всё просто.