Манипуляции с
индикаторами на клавиатуре в Windows NT
|
Автор: Mark J. McGinty.
Требования: VC5, NT4 SP3-SP5
Этот пример демонстрирует управление
индикаторами 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);
}
Downloads
Скачать демо проект - 24 Kb
Скачать исходник - 6 Kb
|