読者です 読者をやめる 読者になる 読者になる

C++/CLIなら面倒は無い?

.NET

引用元はこの辺かな.

また,システムグローバルなキー入力の監視方法には主に3通りあります.

  • (フィルタ)ドライバの作成
  • キーボードフックの使用
  • 低水準キーボードフックの使用

有名な『窓使いの憂鬱』は1を,かおくさんから紹介があった『Xkeymacs』は2を使用しています.

1 は最も強力ですが最も手間がかかります.2は特定アプリケーションのみを監視するのには便利ですが,フックハンドラは DLL に実装しなければならないため .NET での実装上問題があります.また,2ではAlt+Tab などの一部のキーストロークはフックできません.3は使用可能環境に Windows NT 4.0 SP3 以降という制限がありますが,キーボードドライバや SendInput API によって入力された直後をフックすることが出来ます.また3はフックハンドラを DLL に置く必要がないという特徴があり,.NET でも P/Invoke の併用で比較的簡単に実装できます.
http://www.ailight.jp/BBS/Detail.aspx?Header_ID=1784

順番が前後しますが川俣さんのところより.

更にVSUGの掲示板を見ていると、「2は特定アプリケーションのみを監視するのには便利ですが,フックハンドラは DLL に実装しなければならないため .NET からの使用は面倒です.」などという文章を目撃……。C++/CLIで書いていれば、面倒など全く無いのに……。というか、その面倒さこそが、C#が本命言語たりえない理由そのものに見えます。

まあ C++ で正しく Win32 プログラムを書ける人にとっては,C++/CLI は便利なんじゃないでしょうか.もちろん「正しく書ける人は」ですよ.これは例えば Visual C++ 2005 で Win32 DLL プロジェクトを作成し,次のようなコードを書いてしまう人を除外すれば,という意味です.

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

class Test
{
public:
    Test()
    {
        SendMessage( hogehoge1, FOO, BAR );
        GetProcAddress( LoadLibrary( "fugafuga.dll" ), "tekitou" );
    }
    ~Test()
    {
        SendMessage( hogehoge2, FOO, BAR );
        FreeLibrary( fugofugo );
    }
};

// グローバル変数を作成
Test test;

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

これは id:NyaRuRu:20051229#p1 で『窓使いの憂鬱 Ver.3.30』が嵌っていたのと同系統の問題です.ちょっとした一般常識テストですが,Visual C++ で DLL を作りたいなら,以下の事柄は知っておく必要があります.

  1. Visual C++ 2005 で DLL を作成すると,グローバル変数の初期化処理や終了処理が DLL のエントリポイントから呼び出されること.
  2. Windows のアーキテクチャ的に,DLL のエントリポイントで実行可能な処理が制限されていること.

ちなみにこれでもまだフックのフの時にも到達していません.とはいえこの時点で C Runtime Library (CRT) のソースを読み始める必要があるでしょうし,この後さらに Win32 のメッセージ機構や仮想メモリの実装についても理解する必要があるでしょうね.その上で,CLR の実装がどうなっているかについても把握して,CLR との境界部でプロセスを破壊してしまわないように注意しないといけません.もちろん,実装にあたっては使用する言語のルールも守る必要があるでしょう.
そこまで出来るようになったらめでたしめでたしです.おもむろにブラウザを立ち上げて,GDNJ なり VSUG なりにこんなスレッドでも立ててみると良いでしょう.

初歩的な質問ですみません.C++/CLI でグローバルフックのフックハンドラを作成しているのですが,ハンドラ内で .NET Framework の機能を使うことは出来ますか?

なに,後は『ゴキブリ退治キット』*1でゴキブリを退治するぐらい簡単ですよ.きっと面倒など全くありません.

*1:id:akiramei:20051231#p1 より『オブジェクト指向概説