Этот пример демонстрирует управление индикаторами Num Lock, Caps Lock и Scroll Lock. Несколько необходимых значений были позаимствованы из заголовков DDK, поэтому для компиляции исходника нет необходимости иметь установленный DDK. Всё, что делает эта программка - это открывает обработчик драйвера клавиатуры, а затем вызывает DeviceIoControl, чтобы послать в него управляющие коды функций IOCTL. Конкретно в этом примере запускается отдельный поток, который заставляет мигать индикатор Scroll Lock. /*********************************************************** ** NTKbdLites.c ** ** ** ** Copyright 1999 Mark J. McGinty, All Rights Reserved ** ** Free Usage granted to the public domain. ** ** ** ***********************************************************/
#include <windows.h> #include <winioctl.h> #include "NTKbdLites.h"
// Code can be built as either a DLL or a static link library // #ifdef STATIC_LIBRARY #define DECLSPEC #else #define DECLSPEC __declspec(dllexport) #endif
// FlashKeyboardLight // // Flashes the keyboard indicator, specified by LightFlag, one time, // at the rate indicated by Duration. All lights are left in their // previous states when this call returns. // // Possible LightFlags: // KEYBOARD_CAPS_LOCK_ON // KEYBOARD_NUM_LOCK_ON // KEYBOARD_SCROLL_LOCK_ON
int DECLSPEC FlashKeyboardLight(HANDLE hKbdDev, UINT LedFlag, int Duration) { KEYBOARD_INDICATOR_PARAMETERS InputBuffer; // Input buffer for DeviceIoControl KEYBOARD_INDICATOR_PARAMETERS OutputBuffer; // Output buffer for DeviceIoControl UINT LedFlagsMask; BOOL Toggle; ULONG DataLength = sizeof(KEYBOARD_INDICATOR_PARAMETERS); ULONG ReturnedLength; // Number of bytes returned in output buffer int i;
InputBuffer.UnitId = 0; OutputBuffer.UnitId = 0;
// Сохраняем текущее состояние индикаторов // if (!DeviceIoControl(hKbdDev, IOCTL_KEYBOARD_QUERY_INDICATORS, &InputBuffer, DataLength, &OutputBuffer, DataLength, &ReturnedLength, NULL)) return GetLastError();
// Маскируем бит света, которым будем управлять // LedFlagsMask = (OutputBuffer.LedFlags & (~LedFlag));
// Устанавливаем переменную переключателя, чтобы отразить текущее состояние. // Toggle = (OutputBuffer.LedFlags & LedFlag);
for (i = 0; i < 2; i++) { Toggle ^= 1; InputBuffer.LedFlags = (LedFlagsMask | (LedFlag * Toggle));
if (!DeviceIoControl(hKbdDev, IOCTL_KEYBOARD_SET_INDICATORS, &InputBuffer, DataLength, NULL, 0, &ReturnedLength, NULL)) return GetLastError();
Sleep(Duration); } return 0; }
HANDLE DECLSPEC OpenKeyboardDevice(int *ErrorNumber) { HANDLE hndKbdDev; int *LocalErrorNumber; int Dummy;
if (ErrorNumber == NULL) LocalErrorNumber = &Dummy; else LocalErrorNumber = ErrorNumber;
*LocalErrorNumber = 0; if (!DefineDosDevice (DDD_RAW_TARGET_PATH, "Kbd", "\\Device\\KeyboardClass0")) { *LocalErrorNumber = GetLastError(); return INVALID_HANDLE_VALUE; }
hndKbdDev = CreateFile("\\\\.\\Kbd", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hndKbdDev == INVALID_HANDLE_VALUE) *LocalErrorNumber = GetLastError();
return hndKbdDev; }
int DECLSPEC CloseKeyboardDevice(HANDLE hndKbdDev) { int e = 0;
if (!DefineDosDevice (DDD_REMOVE_DEFINITION, "Kbd", NULL)) e = GetLastError();
if (!CloseHandle(hndKbdDev)) e = GetLastError();
return e; }
// Процедура, которая будет запущена как поток, которая будет заставлять мигать индикатор. // DWORD WINAPI FlashKeyboardLightThd(LPVOID lpv) { LPFLASH_KBD_THD_INIT pInit = (LPFLASH_KBD_THD_INIT)lpv; FLASH_KBD_THD_INIT Init = *pInit; HANDLE hndKbdDev; HANDLE heventCancel = OpenEvent(EVENT_ALL_ACCESS, FALSE, Init.EventName);
if (heventCancel == NULL) ExitThread(-1);
hndKbdDev = OpenKeyboardDevice(NULL); if (hndKbdDev == INVALID_HANDLE_VALUE) { CloseHandle(heventCancel); ExitThread(-1); }
for (;;) { FlashKeyboardLight(hndKbdDev, Init.LightFlag, Init.Duration); if (WaitForSingleObject(heventCancel, Init.Duration) != WAIT_TIMEOUT) break; }
Sleep(Init.Duration);
CloseHandle(heventCancel); CloseKeyboardDevice(hndKbdDev); ExitThread(0); return 0; }
// Создаём структуру и запускаем поток для мигания индикатора // HANDLE DECLSPEC FlashKeyboardLightInThread(UINT LightFlag, int Duration, LPSTR EventName) { DWORD ThreadId; static FLASH_KBD_THD_INIT FlashInit;
FlashInit.LightFlag = LightFlag; FlashInit.Duration = Duration; lstrcpyn(FlashInit.EventName, EventName, 128);
return CreateThread(NULL, 0, FlashKeyboardLightThd, (LPVOID)&FlashInit, 0, &ThreadId); }
/*********************************************************** ** NTKbdLites.h ** ** ** ** Copyright 1999 Mark J. McGinty, All Rights Reserved ** ** Free Usage granted to the public domain. ** ** ** ***********************************************************/
#include <windows.h>
// // Определяем индикаторы клавиатуры. //
#define IOCTL_KEYBOARD_SET_INDICATORS CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0002, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_KEYBOARD_QUERY_TYPEMATIC CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0008, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_KEYBOARD_QUERY_INDICATORS CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0010, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct _KEYBOARD_INDICATOR_PARAMETERS { USHORT UnitId; // Unit identifier. USHORT LedFlags; // LED indicator state.
} KEYBOARD_INDICATOR_PARAMETERS, *PKEYBOARD_INDICATOR_PARAMETERS;
#define KEYBOARD_CAPS_LOCK_ON 4 #define KEYBOARD_NUM_LOCK_ON 2 #define KEYBOARD_SCROLL_LOCK_ON 1
#ifdef STATIC_LIBRARY #define DECLSPEC #else #define DECLSPEC __declspec(dllexport) #endif
int DECLSPEC FlashKeyboardLight(HANDLE hKbdDev, UINT LightFlag, int Duration); HANDLE DECLSPEC OpenKeyboardDevice(int *ErrorNumber); int DECLSPEC CloseKeyboardDevice(HANDLE hndKbdDev); HANDLE DECLSPEC FlashKeyboardLightInThread(UINT, int, LPSTR);
typedef struct { UINT LightFlag; int Duration; char EventName[128]; } FLASH_KBD_THD_INIT, *LPFLASH_KBD_THD_INIT;
/*********************************************************** ** NTFlashScrollLight.c ** ** ** ** Copyright 1999 Mark J. McGinty, All Rights Reserved ** ** Free Usage granted to the public domain. ** ** ** ** ** ** A short test program, to excersize NTKbdLites.c ** ** ** ***********************************************************/
#include <windows.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <conio.h> #include "NTKbdLites.h" #define CANCEL_EVENT_NAME "TestThreadedFlasherEvent"
void __cdecl main(int argc, char **argv) { HANDLE heventCancel = CreateEvent(NULL, FALSE, FALSE, CANCEL_EVENT_NAME); HANDLE hThread = FlashKeyboardLightInThread(KEYBOARD_SCROLL_LOCK_ON, 250, CANCEL_EVENT_NAME);
printf("\r\n\r\nSample usage of IOCTL_KEYBOARD_SET_INDICATORS"); printf("\r\n\r\n (the Scroll Lock light should be flashing)"); printf("\r\n\r\n\r\npress any key to exit...");
getch(); printf("\r\n");
SetEvent(heventCancel); WaitForSingleObject(hThread, 30000); CloseHandle(heventCancel); exit(0); } |