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;
}
|