Действия с индикаторами на клавиатуре в Windows NT

Этот пример демонстрирует управление индикаторами 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);
}

 
« Предыдущая статья   Следующая статья »