Windows において, キーボードの LED の点灯を制御させたくなり, ちょっと調べてみました.
一番簡単な方法は, 仮想的にロックキーが押されたようにすることの ようです. 例えば Scroll Lock だと, 次のようにすれば LED が明滅します.
#include <windows.h> int main(int argc, char **argv){ for (int i=0;i < 10;i++){ keybd_event(VK_SCROLL, 0, 0, 0); keybd_event(VK_SCROLL, 0, KEYEVENTF_KEYUP, 0); Sleep(500); keybd_event(VK_SCROLL, 0, 0, 0); keybd_event(VK_SCROLL, 0, KEYEVENTF_KEYUP, 0); Sleep(500); } return 0; } |
ScrollLock キーなんて, まず使わないからいいだろうと とある監視プログラムに組み込んでみたのですが, ある時別件で X-Deep/32 上で emacs を操作していると, いきなりビープ音が鳴り響きます. 「未定義のキーを押された」と解釈されたようです.
何か素敵な関数は無いかと色々探してみたのですが, I/O ポートを叩く原始的な方法しか解は無さそうです. とは言え, Xp 系ではプログラムから直接 I/O を叩けません.
似たようなものに, パラレルポートを入出力 I/O として使う問題が ありますが, こちらには GiveIO.sys という 便利な解があります. ある時, GiveIO.sys はパラレルポート周りの I/O (0x378〜a: 機種によって若干違う) を開放してるのでなく, inp(), outp() 全体を開放しているのでないかと 考え, 実験してみました.
予想は的中し, 無事以下のようなコードで LED のみを制御できるようになりました.
#include <windows.h> #include <conio.h> int main(int argc, char **argv){ HANDLE h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { fprintf(stderr, "Error: no giveio.sys\n"); exit(0); } CloseHandle(h); for (int i=0;i < 10;i++){ while (_inp(0x64) & 2); _outp(0x60, 0xed); while (_inp(0x64) & 2); _outp(0x60, 0x01); Sleep(500); while (_inp(0x64) & 2); _outp(0x60, 0xed); while (_inp(0x64) & 2); _outp(0x60, 0x00); Sleep(500); } return 0; } |
ちなみに, プログラムを 95/98/Me 系でも動かすためには HANDLE h= 〜 CloseHandle(h); の処理を NT/2000/Xp でのみ 走らせる必要があります. 判定は次のような感じでしょうか.
bool IsWindowsNT(){ OSVERSIONINFOA *posvi = (OSVERSIONINFOA *)_alloca(sizeof(OSVERSIONINFOA)); posvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); GetVersionExA(posvi); if(posvi->dwPlatformId == VER_PLATFORM_WIN32_NT) return true; return false; } |