Written in Japanese(UTF-8)
2016.8.15
INASOFT


/トップ/NumLockLock ダウンロード/WebHelp/ヘルプトップ

動作原理


(ここでは動作原理の説明のため、ネイティブなWindowsプログラミングに関する用語が登場します)

本ソフトは、主に2つの方法で動いています。

この2つについて、簡単に解説していきます。


タイマ監視によるNumLock/CapsLock/ScrollLock キーの監視

こちらは非常に簡単な原理です。

SetTimer() APIとWM_TIMER メッセージを用いて、1秒おきにNumLock/CapsLock/ScrollLockの各キーの状態を確認します。キー状態の取得は、GetKeyState() API を用います。

数十年前のキーボードでは、これらのキーは、キーボードが本当にロック/アンロックされることにより動作していましたが、現在ではOS制御を実現するために、キーボード上のランプによる状態表示となりました。そのため、ソフトウェア的にこれらのキーの制御(強制的に元に戻す)の実現が可能となりました。

ところで、本当にキーがロックされるタイプのキーボードがまだ用いられていて、本ソフトを使うとどうなるのか…試してみたことがないのでわかりませんが、たぶん、うまく動作しないんだと思います。

キーボードフックによるInsertキーの押下状態の横取りとブロック

【ご注意】現在は、Insertキーの押下状態の横取りのために「グローバルフック」ではなく「ホットキー」の機能が用いられるようになっております。文中に書かれた「NumLockLock.dll」も、現在は同梱しておりません。

こちらは少し、難しい原理です。

この機能が追加されてから、NumLockLock.dll というDLLが同梱されるようになりましたが、このDLLがこの機能を実現しています。

キーボードフックはOSが提供している機能の1つである「グローバルフック」のものを利用しており、すべてのアプリケーションに対して送られるキーボード押下のメッセージを監視・横取りします。つまり、本来であれば、

[キーボード押下]→[OS受け取り]→[各アプリケーションが受け取り]

という流れになるべきところを、

[キーボード押下]→[OS受け取り]→[NumLockLock.dllが横取り]→[各アプリケーションが受け取り]

という流れに変更します。

NumLockLock.dllは必要性(NumLockLock.exeの設定ダイアログによる設定)を判断して、横取りしたキーがInsertキーだったなら、各アプリケーションに伝達したり、しなかったりします。

ちなみにこんなことがセキュアな世界でまかり通ってはいけませんから、当然「各アプリケーション」が(ユーザー アカウント制御上の)管理者権限で動作しているアプリケーションだった場合は、横取りは動かなくなります。つまり、本ソフトはInsertキーブロック機能を発揮できなくなります。

ところで、NumLockLock.dll というように「DLLの形」になっているのは、このDLLがNumLockLock.exeのためのDLLであると同時に、ブロックされる全アプリケーションにヒモ付いて動作するDLLでもある、というためでもあります。これが、OSが提供している機能の1つである「グローバルフック」を利用する上での必須条件でもあります。キーボードフックは、SetWindowsHookEx() API に WH_KEYBOARD を与えた機能で実現しています。

なお、NumLockLock.exeのDLLとして動作しているときの「NumLockLock.dll」と、各アプリケーションのDLLとして動作しているときの「NumLockLock.dll」は、原理的には別プロセスです。そのため、メモリ空間も別物になります。にもかかわらず、「NumLockLock.dll」はNumLockLock.exeの設定ダイアログの設定(Insertキーのブロック有無)を共有しなければなりません。

そのため、同一環境内で動くDLLが同一の設定内容を参照できるよう、共有セクションというテクニックを使うことになります。具体的には、次のようなコーディングです。

// 以下、環境内で共有するグローバル変数
#pragma data_seg(.sh_data")
HHOOK  hHookKeyboardProc = NULL;
HANDLE hModule = NULL;
HWND   ghWnd = NULL;
BOOL   bEnable = TRUE;
#pragma data_seg()

// リンカに対し、.sh_data を読み書き共用とするように指示
#pragma comment(linker, "/SECTION:.sh_data,RWS")

このテクニックを使う場合の注意点は、「各変数は必ず初期化する」「ポインタ変数を使わない」あたりでしょうか。まぁ、筆者も完全にこのあたりを理解して使っているわけではなく、ググってコピペしてなんとなく使っているところが大きいんですけどね(笑)。ちなみに筆者がこれについて最初にググったのは、F1Breakerというソフトを作ったときです。というわけで、このことについて詳しく知りたい方は、ググりましょう。


 目次へ

※このページは、ソフトウェアに付属のヘルプファイルをWeb用に再構築したものです。大部分に自動変換を施しているため、一部は正しく変換しきれずに表示の乱れている箇所があるかもしれませんが、ご容赦下さい。また、本ドキュメントはアーカイブドキュメントであり、内容は、右上の作成日付の時点のものとなっております。一部、内容が古くなっている箇所があるかと思いますが、あらかじめご了承下さい。
※このページへは、自由にリンクしていただいてかまいません。

■このページに関するご意見をお待ちしております → フィードバックページ

/トップ/NumLockLock ダウンロード/WebHelp/ヘルプトップ