Что такое хук клавиатуры

Обновлено: 04.07.2024

Изначально я мог что-то напечатать, когда нажимал только правую кнопку мыши, используя if (wParam == WM_RBUTTONDOWN) но теперь я хочу того же эффекта, я хочу что-то напечатать, когда нажата правая кнопка мыши + клавиша Ctrl . как я могу этого добиться? Я пробовал это LRESULT CALLBACK MainWindow.

Можно ли читать ввод с клавиатуры, не всегда фокусируя свое консольное приложение? Хотелось бы сделать что-нибудь кнопкой, не заходя всегда в консоль. Разве это как-то не работает с событиями? К сожалению, я нашел только неприглядные решения с помощью Forms. Это решение от @Siarhei Kuchuk мне тоже.

Мне нужно подключить мою клавиатуру и нашел следующий код (справка здесь ) Что я хочу использовать в проекте Console Delphi. Бывает, что после первого теста я отметил, что LowLevelKeyboardProc() Функция никогда не выполняется ( hello никогда не отображается на консоли). Уже SetWindowsHookEx() Рабо.

Для нашего приложения мы создали онлайн-справку, где клиенты могут узнать о нашем приложении. Они могут достичь этого в меню, но я также хотел сделать его доступным, нажав клавишу F1, где бы вы ни находились в нашем приложении (поскольку это в основном используется для справки в других приложениях).

У меня возникли проблемы с выходом из циклов while при использовании клавиш клавиатуры. Вот мой код: LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) < PKBDLLHOOKSTRUCT key = (PKBDLLHOOKSTRUCT)lParam; if (wParam == WM_KEYDOWN && nCode == HC_ACTION) < >if.

Я попытался вызвать ToUnicode внутри низкоуровневого манипулятора клавиатуры и напечатать возвращаемый символ (символы). Однако похоже, что функция не принимает во внимание, были ли нажаты специальные клавиши, такие как shift или caps lock, поэтому вывод такой же, как и из функции MapVirtualKey с т.

Мое приложение запускается от имени текущего пользователя без прав администратора. Затем он устанавливает обработчик клавиатуры, чтобы перехватывать ключевые события, используя SetWindowsHookEx с WH_KEYBOARD_LL (не для внедрения DLL). Он отлично работает для нажатия клавиш в другом окне, не явля.

Я пытаюсь установить ловушку на клавиатуре с помощью SetWindowsHookEx, и я хочу, чтобы программа продолжала работать, поэтому я добавил while (TRUE) после установки ловушки. int main() < SetHook(); while (TRUE) < >return 0; > Теперь это не работает для меня, поэтому я искал об э.

Я хочу зафиксировать кнопку PrintScreen, даже если приложение свернуто или вообще не в фокусе. Я видел несколько фрагментов, но ни один из них не работал в WPF, только в Winforms. Кто-нибудь может дать код для запуска.

Я использую крючки низкого уровня. Я сделал этот класс: class Kayz < static int VKEY; static void (*funcDown)(); static void (*funcUp)(); static HHOOK TheHook; static KBDLLHOOKSTRUCT TheHookStruct; static LRESULT _stdcall HookCallback(int, WPARAM, LPARAM); public: bool Se.

Я работаю над функцией ToUnicodeEx, и она требует состояния клавиатуры в качестве входного параметра. Итак, я использовал функцию GetKeyboardState для этого. Но я заметил, что когда я печатаю комбинации клавиш с клавишами-модификаторами, такими как SHIFT + A , задержка в один символ. Вот пример. .

В одном из моих новых приложений мне нужно отключить клавиши окна, поэтому Кто-нибудь знает, как отключить левую и правую кнопку окна в приложении веб-узла узла.

Есть кое-что, что я пытаюсь сделать с wxPython, и я не могу понять, как. (У меня Windows 7, и я в порядке с решением только для Windows.) Я хочу поймать ключевые события во всем мире. Это означает события нажатия клавиш, нажатия клавиш и символов. (Я пытаюсь построить что-то вроде AHK в Python.) Теп.

В двух словах: блокировка Win после Win + Tab заставляет Windows думать, что Win все еще не работает, поэтому тогда нажатие S с поднятой клавишей Win , например, откроет чудо-кнопку поиска, а не просто наберет "s" . пока пользователь не нажмет Win очередной раз. Отсутствие блокир.

Последние три дня я потратил два часа на исследования и не могу понять этого. Это простая программа, которая щелкает левой кнопкой мыши каждые 2,5 секунды 50 раз, а затем программа завершается. Но иногда я хочу закончить программу раньше, нажав клавишу выхода (не мышь). Как завершить программу, наж.

Я хочу иметь возможность завершить свою программу при нажатии определенной клавиши (в этом примере мы скажем, когда нажата клавиша k). Я знаю, что это можно сделать, используя JFrame и KeyListener, но хочу, чтобы мой слушатель работал в фоновом режиме. Моя программа в настоящее время изменяет текс.

Я использую глобальную клавиатуру для работы со считывателем штрих-кода. Считыватель штрих-кода отправляет символ STX перед штрих-кодом и символ ETX после штрих-кода. Иногда функция ToAscii дает правильные коды STX и ETX (0x02 или 0x03), но в большинстве случаев она становится 0x62 (b) или 0x63 (c).

Хочешь стать Черным Властелином своего компьютера? Хочешь знать все тайны разработчиков малвари и антивирусов? Читай статью, медитируй, постигай азы дзена, и да снизойдет на тебя прозрение (всем спокойно, познание Дао и прободение Шамбалы в результате прочтения этой статьи редакцией не гарантируется — прим. ред)!

Что такое хук (hook — крючок, англ.)? Это механизм, позволяющий отследить некое событие в операционной системе. Было оно разработано дяденьками из Microsoft с самыми благими намерениями — позволить программисту более эффективно решать свои задачи путем установки контроля над событиями клавиатуры, мыши и многого другого. Реализовался он при помощи всем известных функций: SetWindowsHook(Ex), UnhookWindowsHook(Ex) и CallNextHook(Ex).

Хук служит для перехвата неких событий до того, как они дойдут до приложения. Эта функция может реагировать на события и, в некоторых случаях, изменять или отменять их. Функции, получающие уведомления о событиях, называются «фильтрующими функ циями» и различаются по типам перехватываемых ими событий. Пример — фильтру ющая функция для перехвата всех событий мыши или клавиатуры. Чтобы Windows смогла вызывать функцию-фильтр, эта функция должна быть установлена, то есть, прикреплена к хуку (например, к клавиатурному). Прикрепление одной или нескольких фильтрующих функций к какомунибудь хуку называется установкой хука. Если к одному хуку прикреплено несколько фильтрующих функций, Windows реализует очередь функций, причем функция, прикрепленная последней, оказывается в начале очереди, а самая первая функция — в ее конце.

Со временем благородное понятие хука извратилось, причиной чего стали действия вирусописателей и малварщиков. Первые вирусы были, как бы это сказать… наивными, наверное. Они представляли собой отдельный exe-файл, напрямую вызывающий нужные функции системы. Шло время и антивирусы, которые появились чуть позже и вдруг стали коммерческими, довольно быстро научились ловить вирусы по сигнатурам путем простого сканирования оперативной памяти или дискового пространства.

И вот тут-то, в пылу извечной борьбы между писателями вирусов и их «ловцами» встал один-единственный вопрос, который стоит на повестке дня до сих пор и будет стоять в ближайшем необозримом будущем — это вопрос выживания в операционной системе. Причем он также актуален и для антивирусов, ведь для хорошего системного программиста, пишущего вирусы/ руткиты, вынести процесс антивируса из системы — не слишком сложная задача.

Поэтому можно смело утверждать, что одна из задач антивирусов — это умение сохранить свой процесс в целостности и сохранности от злонамеренных действий вируса. В общем, на сегодняшний день под хуками следует понимать установку контроля над основными системными функциями операционной системы, от которых зависит жизнеспособность любой программы — речь идет, как правило, о функциях работы с процессами, потоками, сетью и интернетом и т.д.

«А как же SetWindowsHook?» — спросишь ты меня. «Прошлый век», — отвечу я. Использовать их давно уже не кошерно.

Что имеем?

Проще всего установить хук в системе путем создания так называемой прокси-функции. Иначе говоря, тебе надо определиться, какую функцию ты перехватываешь, и найти адрес ее вызова. Для этого обычно используется функция GetProcAddress примерно вот так: GetProcAddress(GetModuleHandle("ntdll.dll"), "CsrNewThread").

Однако просвещенные знают, что она практически всегда перехватывается аверами, и для нахождения адреса функции используют парсинг таблицы импорта той или иной библиотеки, обычно ntdll.dll, kernel32.dll (kernelbase.dll в Windows7) или advapi32.dll.

Далее тебе нужно создать свою прокси-функцию, точь-в-точь повторяющую вызываемую примерно вот таким образом:

int MyNewFunction(void *param1,
int param2, bool param3)
return OriginalFunction(param1,
param2, param3);
>

После этого следует перезаписать адрес вызова OriginalFunction на свой — то есть, на MyNewFunction.

Теперь, если кто-либо захочет вызвать для исполнения OriginalFunction, сначала будет вызвана твоя прокси-функция MyNewFunction, которая уже потом передаст управление на оригинальный адрес. Вот таким вот нехитрым образом действуют, наверное, 8 хуков из 10. Этот способ удобен лишь своей простотой, но при этом представляет собой ужасное палево для аверов. Как? Поразмысли сам — все, что аверу нужно, это сравнить прежний, «законный», адрес функции с тем, что есть на самом деле. Если они отличаются — бьем тревогу. Кстати, встает и следующий вопрос: откуда взять этот самый адрес оригинальной функции? Тут особо гадать не надо — его считывают с нужного файла на диске. Этот подход основывается на том предположении, что вирус не будет патчить таблицу экспорта файла, лежащего на диске, ограничившись патчем виртуальной памяти.

Итак, едем дальше. Как я уже говорил, использование хука в виде прокси-функции хоть и удобная вещь, но, во-первых, палевная, а во-вторых, подходит лишь для начинающих. То есть не для тебя :). Самый распространенный вид хука — это сплайсинг. Уверен, ты не раз слышал это слово. В нашем случае это запись на начало функции пятибайтовой последовательности, которая представляет собой команду jmp по адресу обработчика перехвата. Здесь первый байт — опкод jmp, оставшиеся четыре байта — адрес твоей функции.

Если необходимо вызывать перехватываемую функцию, то перед заменой необходимо сохранить ее начальные байты и перед вызовом восстанавливать их. Недостаток данного метода состоит в следующем: если после восстановления начала функции произошло переключение контекста на другой поток приложения, то он сможет вызвать функцию, минуя перехватчик. Этот недостаток можно устранить, останавливая все побочные потоки приложения перед вызовом, и запуская после вызова. Ну и конечно, сплайсинг, как и прокси-функции, тоже легко выявляется методом сканирования памяти, так как сразу будет видно, что вызов функции идет куда-то в другое место.

Вообще, забегая вперед, должен донести до широкой общественности, что почти все методы перехвата вызова функций так или иначе детектятся сканированием памяти. За исключением двух методов, но об этом читай ниже.

IAT, EAT и другие звери

Возникает вопрос: а на что и, самое главное, где можно ставить свои хуки? Первое, что приходит на ум — конечно же, поставить перехват на Import Address Table (IAT). Когда приложение использует функцию из библиотеки, приложение должно импортировать адрес функции. Каждая DLL, используемая приложением, описана в структуре, называемой IMAGE_IMPORT_DESCRIPTOR. Эта структура содержит имя DLL, чьи функции импортированы приложе нием, и два указателя на два массива структур IMAGE_IMPORT_BY_ NAME. Структура IMAGE_IMPORT_BY_NAME содержит имена импортированных функций, используемых приложением.

Когда операционная система загружает приложение в память, читается структура IMAGE_IMPORT_DESCRIPTOR и каждая требуемая DLL загружается в память приложения.
Как только DLL отображена (mapped), операционная система располагает каждую импортированную функцию в памяти и записывает поверх одного из массивов IMAGE_IMPORT_BY_ NAME с исполнительным адресом функции.

Как только hook-функция появляется в адресном пространстве приложения, твой вирус сможет прочесть формат PE целевого приложения в памяти и заменить целевой адрес функции в IAT адресом hook-функции. Тогда, когда перехватываемая функция будет вызвана, твоя hook-функция будет выполнена вместо первоначальной функции. Чуть более редкий вариант, встречающий в природе, реализованный по приниципу «Если гора не идет к Магомеду. » — перехват Export Address Table (EAT), когда патчится, наоборот, таблица экспорта Dll, которая экспортирует целевую функцию.

STELTH-хуки: поймай меня, если сможешь

Как я уже писал выше, главный недостаток вышеуказанных методов перехвата — это вынужденная модификация памяти, что неизбежно ведет к ее детекту со стороны аверов. Есть ли выход? Как ни странно, есть. Даже два. Первый из них — это зарегистрировать свой обработчик исключений, затем добиться, чтобы он получил управление. Это можно сделать, например, потерев какой-либо участок памяти. Второй способ представляет собой несколько видоизмененный первый. То есть, ты, как и раньше, регистрируешь обработчик исключений, но для их генерирования ты используешь прием, известный среди дебаггеров. Как ты знаешь, дебагрегистры процессора используются для отладки приложений и доступны, как правило, из кернелмода. Однако их можно устанавливать и из юзермодных приложений путем использования функций GetThreadContext/ SetThreadContext. Используются дебаг-регистры для установки точек останова (Breakpoints) на доступе к участку памяти или исполнении.

Всего имеется восемь регистров, их назначение следующее:

  • DR0 - DR3 — Каждый из этих регистров содержит линейный адрес одной из четырех контрольных точек. Если подкачка страниц разрешена, то их значения транслируются в физические адреса по общему алгоритму;
  • DR4 - DR5 — Регистры зарезервированы и в процессоре i486 не используются;
  • DR6 — Отладочный регистр состояния. Он сообщает об условиях, выявленных во время генерирования отладочного исключения (номер 1). Биты регистра устанавливаются аппаратно, а сбрасываются программно;
  • DR7 — Регистр задает вид доступа к памяти, связанный с каждой контрольной точкой.

Итак, все, что тебе нужно сделать — это установить хардварный бряк (hardware breakpoint, он же int 1) на начало функции, чтобы процессор сгенерировал так называемое «одношаговое исключение» (single step exception) и затем, путем установки своего обработчика исключения: AddVectoredExceptionHandler(0, (PVECTORED_EXCEPTION_ HANDLER)DebugHookHandler), перехватить этот самый EXCEPTION_SINGLE_STEP.

При его генерации твой обработчик получит управление желанной функцией. Несомненное достоинство такого метода в том, что он абсолютно невыявляем путем сканирования памяти, поскольку ее модификация здесь не происходит.

int SetDebugBreak(FARPROC address)
int status = -1;
HANDLE thSnap = CreateToolhelp32Snapshot(
TH32CS_SNAPTHREAD, NULL);
THREADENTRY32 te;
te.dwSize = sizeof(THREADENTRY32);
Thread32First(thSnap, &te);
do
if(te.th32OwnerProcessID != GetCurrentProcessId())
continue;
HANDLE hThread = OpenThread(
THREAD_ALL_ACCESS, FALSE, te.th32ThreadID);
CONTEXT ctx;
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
GetThreadContext(hThread, &ctx);
if(!ctx.Dr 0)
ctx.Dr0 = MakePtr( ULONG, address, 0);
ctx.Dr7 |= 0x00000001;
status = 0;
>
else if(!ctx.Dr1)
ctx.Dr1 = MakePtr( ULONG, address, 0);
ctx.Dr7 |= 0x00000004;
status = 1;
>
else if(!ctx.Dr2)
ctx.Dr2 = MakePtr( ULONG, address, 0);
ctx.Dr7 |= 0x00000010;
status = 2;
>
else if(!ctx.Dr3)
ctx.Dr3 = MakePtr( ULONG, address, 0);
ctx.Dr7 |= 0x00000040;
status = 3;
>
else
status = -1;
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
SetThreadContext(hThread, &ctx);
CloseHandle(hThread);
>
while(Thread32Next(thSnap, &te));
return status;
>

Заключение

Как ты видишь, даже в самых сложных ситуациях можно найти возможность исполнить свой код. Уверен, что при этом твой код нацелен исключительно на решение задач по защите твоей системы. Удачи тебе и удачного компилирования!

Хуки предоставляют мощные возможности для приложений Windows. Приложения могут использовать хуки в следующих целях:

Работа с хуками осуществляется через функции SetWindowsHookEx, UnhookWindowsHookEx, вызов следующего обработчика осуществляется через функцию CallNextHookEx. До версии 3.1 Windows предоставляла для управления хуками функции SetWindowsHook, UnhookWindowsHook, и DefHookProc. Эти функции до сих пор реализованы в Win32, только лишь для совместимости со старыми приложениями, и использовать их в новых проектах не рекомендуется.

Начнём сначала, для установки хука успользуется функция SetWindowsHookEx

Первый параметр это числовая константа WH_* которая задаёт тип устанавливаемого хука. Второй параметр это адрес функции-фильтра. Третий параметр это хэндл модуля, содержащего фильтрующую функцию. Этот параметр должен быть равен нулю при установке хука на поток, но данное требование не является строго обязательным, как указано в документации. При установке хука для всей системы или для потока в другом процессе, нужно использовать хэндл DLL, содержащей функцию-фильтр. Четвёртый параметр это идентификатор потока, для которого устанавливается хук. Если он не равен нулю, то хук устанавливается только на указанный поток. Если идентификатор равен нулю, то хук устанавливается на всю систему. Некоторые хуки можно ставить как на всю систему, так и на некоторый поток, некоторые хуки можно поставить только на всю систему. Функция возвращает хендл хука, в случае неудачи функция возвратит ноль. Для снятия хука нужно использовать функцию UnhookWindowsHookEx, которая принимает в качестве единственного параметра хендл установленного хука.

Едем, далее. Все фильтрующие функции должны быть описаны следующим образом:

Так написано в MSDN. Тип LRESULT это тот же integer, WPARAM и LPARAM это тоже integer. CALLBACK это тоже что и stdcall. Чтобы было понятнее, приведу наиболее правильное и логичное (по моему мнению) объявление на pascal:

Для вызова следующей функции в очереди хуков предназначена функция CallNextHookEx

Итак, основные сведения о хуках мы получили. Теперь надо приступить к практике. Наиболее часто встречающийся проблемы поднимаемые на форумах программистов, связанный с хуками, это проблемы с написанием клавиатурных шпионов. Именно клавиатурный шпион мы сейчас и напишем.

Параметр wParam в обработчике хука WH_KEYBOARD содержит виртуальный код клавиши (например, VK_F1, VK_RETURN, VK_LEFT). Параметр lParam расшифровывается следующим образом.

Как мы будем сохранять введённый текст? Разумеется, самый простой способ это сохранение в файл перехваченного кода нажатой клавиши это сохранение в файл сразу же в функции фильтре. Но операции файлового ввода/вывода это операции не слишком быстрые и это приводит к общему уменьшению производительности системы при вводе какого-либо текста (впрочем, на новых машинах это вряд ли можно заметить). Поэтому мы заведём специальное окно-сервер, которому будем отправлять коды нажатых клавиш, это окно будет получать коды нажатых клавиш и сохранять в своём буфере, и скидывать буфер в файл, когда он будет достигать некоторого размера.

Создание и снятие хука, я думаю, особых проблем не составляет, поэтому сразу приступлю к самому обработчику хука.

Основная проблема в при написании клавиатурных хуков заключается в том что обработчику хука передаётся только скан код нажатой клавиши и её виртуальный код. Виртуальный код и скан код говорят нам, какая именно клавиша была нажата, но не говорят, что именно было введено. Поясню, даже если мы вводим русский текст, то клавиатурному хуку будут передаваться коды английских клавиш, т.е. мы вводим слово "привет", а обработчику хука будет передано "GHBDTN". Или, например, мы нажимаем на Shift цифру 7 и вводится знак &, но в клавиатурный хук будт передан только код цифры 7. Для того чтобы преобразовать скан код и виртуальный код в текстовый символ, который был введён, необходимо использовать функцию ToAscii (или ToUnicode).
Её параметры:

Первый параметр это виртуальный код, второй это скан код, третий параметр это указатель на массив в котором сохранено состояние клавиатуры, четвёртый это указатель на переменную, в которую будет сохранён символ, пятый параметр это флаг, определяющий, является ли меню активным. Этот параметр должен быть 1, если меню активно, или иначе 0. Функция возвращает количество символов, полученных в результате преобразования. Состояние клавиатуры можно получить через функцию GetKeyboardState.

Вернёмся в нашей фильтрующей функции.

Для получения текстовой расшифровки нажатой клавиши по её скан коду мы воспользовались функцией GetKeyNameText. Полный текст DLL и приложения находится в архиве прилагающемуся к этой статье.

Если посмотреть получившийся лог, то мы увидим следующий текст в формате <название клавиши, введённый текст>.

Вот и подошёл конец первой статьи про хуки. Качаем, смотрим исходник исследуем, учимся.

Приведем неполный список необходимых системных функций:

    1. [DllImport("user32.dll", CharSet = CharSet.Auto)]
    1. [DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    2. static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
    1. [DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    2. static extern bool UnhookWindowsHookEx(IntPtr hhk);
    1. [DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    2. static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

Если нам понадобится пересылать в главное окно приложения строку (например, название приложения, связанного с клавиатурным вводом), то мы используем тогда такую функцию:

  1. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  2. static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);
    1. [DllImport("user32.dll", SetLastError=true)]
    2. static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    1. [DllImport("user32.dll")]
    2. static extern IntPtr GetForegroundWindow();
    1. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    2. static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int nMaxcount);
    1. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    2. static extern int GetWindowTextLength(IntPtr hWnd);

const int WH_KEYBOARD_LL = 13;
const int HC_ACTION = 0;
const int WM_KEYDOWN = 0x0100;
const int WM_USER = 0x0400;

Кроме всего выше сказанного, нам понадобится еще функция-обработчик, где будет происходить процесс обработки данных. Ее мы прикрепим к делегату, который должно будет передать в функцию SetWindowsHookEx, вторым параметром. В С++ передавали бы в данном случае указатель на функцию-обработчик. Делегат имеет следующий вид:

delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);

Теперь, можно представить примерный код устанавливаемого хука. Ниже, приведем код, размещаемый в отдельной dll:

  1. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  2. private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int nMaxcount);
  3. [DllImport("user32.dll")]
  4. private static extern IntPtr GetForegroundWindow();
  5. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  6. private static extern int GetWindowTextLength(IntPtr hWnd);
  7. [DllImport("user32.dll", SetLastError = true)]
  8. private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
  9. [DllImport("user32.dll", CharSet = CharSet.Ansi)]
  10. private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);
  11. private const int WH_KEYBOARD_LL = 13;
  12. private const int HC_ACTION = 0;
  13. private const int WM_KEYDOWN = 0x0100;
  14. private const int WM_USER = 0x0400;
  15. private static HookProc proc = HookCallback;
  16. public static IntPtr hook = IntPtr.Zero;
  17. private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
  18. if(nCode >= HC_ACTION && wParam == (IntPtr)WM_KEYDOWN)
  19. try
  20. int vkCode = Marshal.ReadInt32(lParam);
  21. IntPtr handle = FindWindow(null, "Wind");
  22. IntPtr ahandle = GetForegroundWindow();
  23. int len = GetWindowTextLength(ahandle);
  24. StringBuilder str = new StringBuilder(len + 1);
  25. GetWindowText(ahandle, str, str.Capacity);
  26. SendMessage(handle, WM_USER + 755, wParam, str.ToString() + "|" + vkCode.ToString());
  27. >
  28. catch(Exception e)
  29. MessageBox.Show(e.Message);
  30. >
  31. >
  32. return CallNextHookEx(hook, nCode, wParam, lParam);
  33. >
  34. public override IntPtr SetHook()
  35. return SetWindowsHookEx(WH_KEYBOARD_LL, proc, IntPtr.Zero, 0);
  36. >
  37. public override void UnsetHook(IntPtr hhk)
  38. UnhookWindowsHookEx(hhk);
  39. >

Функцией SetHook мы устанавливаем собственно сам глобальный хук, передавая в функцию SetWindowsHookEx наш клавиатурный фильтр и экземпляр делегата. SetHook возвращает описатель хука. Функцией UnsetHook мы отменяем установленный хук.

  1. protected override void WndProc(ref Message m)
  2. String keyapp = String.Empty;
  3. switch (m.Msg)
  4. case WM_KEYSTROK:
  5. keyapp = Marshal.PtrToStringAnsi(m.LParam);
  6. MessageBox.Show(keyapp);
  7. break;
  8. >
  9. base.WndProc(ref m);
  10. >

Короткий итог

Читайте также: