5)wxWidgetsを使うとVC++でツールアプリケーションがサクサク作れそうな気がしてきました。ゲームなツールを考えるなら、やはりDirectXとの連携がうまく取れるかテストする必要があります。Worldを表示させつつwxWidgetsと連携する簡易なアプリを作ってみます。ループの決め手はRequestMoreだった!wxWidgetsはイベントハンドラ型のライブラリです。よって、メインループは奥底の方にしまわれていて直接はもちろん触れません。実装を見るとメッセージループは絶えず回っているのですが、基本的には何かメッセージがポストされないとハンドラは呼ばれません。DirectXは基本的には常に更新が必要になります。このため、wxWidgetsのアプリケーションレベルのクラスでループ中にガンガン呼ばれるメソッドが必要になります。ところが、そういうメソッドは見当たりません。「ん〜〜困ったなぁ」とGoogle先生に尋ねてみると、なるほど密かにそういう用意がされていました。アプリケーションでもフレームでも良いのですが、アイドル中に呼ばれるOnIdleハンドラを作成します。続いて、そのハンドラとメッセージを結びつけます。event);DECLARE_EVENT_TABLE()};OnIdelメソッドの引数はwxIdelEvent&型にします。{event.RequestMore(true);}EVT_IDLEマクロを用いてアイドル時にOnIdleメソ度を呼び出してもらうようにします。当初これでメッセージが無い時にOnIdleメソッドがガンガン呼ばれるのかなぁと思っていたのですが、実際は何と逆で、何らかのメッセージがポストされないと呼ばれません!なんじゃそりゃーと思ったのですが、ここに裏技チックなものがありました。OnIdleメソッドの中で上の赤文字で示したwxIdleEvent::RequestMoreメソッドを呼びます。すると、アプリケーションフレームワークが気を利かせて、このメソッドをガンガン呼んでくれるようになります。これでOnIdleメソッドを基点にしてDirectXが要求するループを追加していく事ができそうです。ウィンドウハンドルはどうする?続いて必要なのはウィンドウハンドルです。これは簡単でwxWindow::getHWNDメソッドというそのまんまのメソッドが用意されています。wxFrameはwxWindowが親なので同じメソッドを持っています。このメソッドの戻り値はWXHWND型の変数です。これはマルチプラットフォームを意識しているためにHWNDをそのまま返せないという事情があるためと思われます。WindowsならばそのままHWNDにキャストしてしまって構いません。�@と�AでDirectXでの描画に必要な物が揃いました。Worldプログラムを作ってみます。全体像をざっくり考えてみます。DirectXな描画はメインウィンドウに行い、そこに文字列を描画します。描画するだけだとさすがにつまらないので、ダイアログを1枚出して、そこにエディットボックスを1つ追加します。そのエディットボックスに書き込んだテキストがDirectXの画面に反映されるようにしましょう。wxFrame)といったところでしょうか。メインフレームクラスメインフレームクラスはDirectXな描画を行うクラスです。よって、このクラスにIDirect3DDevice9インターフェイスなどのDirectXのコンポーネントを持つことになります。フォント描画も必要なのでID3DXFontも保持です。event);DECLARE_EVENT_TABLE()};#endifメインフレームはwxFrameクラスを継承します。メンバにDialogクラスのオブジェクトがあります。このクラスが持っているエディットボックスに入力された文字列を頂戴しようという目論見です。publicメソッドはコンストラクタデストラクタを除けばたったの一つ、OnIdleメソッドしかありません。このメソッドはアプリケーションからガンガン呼ばれる予定です。非公開のメソッドにはinitD3Dメソッドとdrawメソッドを用意しました。双方とも名前の通りです。drawメソッドがOnIdleメソッド内でガンガン呼ばれるのは言うまでもありません。これでOnIdleメソッドが呼ばれまくりになります!draw();}ん〜短い!よし。ポイントが沢山あります。OnIdleハンドラを呼んでもらうには、EVT_IDLEマクロを使ってOnIdleメソッドを登録する必要があります。コンストラクタでは各種初期化を行っています。Dialogウィンドウの作成も行っています。DirectXの初期化を行うinitD3Dメソッドもここで呼んでいます。最初「コンストラクタの段階ではウィンドウハンドルが取れないかなぁ」と思ったのですが、至ってあっさりと取得できました。これで2段階初期化をする必要がなくなって、コードがよりすっきりしました。デストラクタでは各種解放を行っています。DialogもCloseメソッドで閉じています。このメソッドはwxWidgetsが最初から用意してくれているウィンドウを閉じるメソッドです。initD3DメソッドではDirectXの各種コンポーネントの作成とフォントオブジェクトの作成を行っています。この辺りはもうすっかりおなじみですね。drawメソッド内のポイントは、Dialogウィンドウが持っているエディットボックスに打ち込まれた文字列を取得して描画している部分です。Dialog::getTextメソッドは自前で用意するメソッドです。OnIdleメソッド内では�Aで説明したwxIdleEvent::RequestMoreメソッドを呼びます。これでガンガン呼ばれることになります。後はdrawメソッドもガンガン呼びます。今はこれで問題ありません。DialogクラスDialogクラスはエディットボックス(テキストコントロール)を1つ持つシンプルなダイアログを想定しています。wxWidgetsを使うと、これが笑えるほど短いソースでできてしまいます。"";}};#endifコンストラクタでテキストコントロールを1つ作っています。これだけでテキストコントロールが出るのですから、本当に素晴らしい(T-T)g。後はテキストコントロールに打ち込んだ文字列を取得するgetTextメソッドを公開するだけです。非常〜〜〜に簡単ですね。アプリケーションクラスアプリケーションクラスも今回のサンプルでは大変に短いコードで終わりです。true;}};#endifアプリケーションの初期化時に必ず呼ばれるOnInitメソッド内でメインフレームを作って終わりです。不思議なのが、ローカルでnewしてほったらかしという部分ですよね。これでちゃんとウィンドウを管理してくれているのですから面白いです。main関数メイン関数(エントリ関数)はもう究極に短いです。"MyApp.h"IMPLEMENT_APP(MyApp)すげーー!っと私は思いましたよ、はい。マクロが巧妙に駆使されるとこうなるんだなぁという好例です。実行結果コードは以上です。これを実行すると次のような2枚のウィンドウが出現します。エディットボックスに打ち込んだ文字列が直ちにDirectXな描画に反映しています。やったぜい!と言うことで、めでたくwWidgetsとDirectXの連携ができました。後はもうダイアログ部分を発展させて行けばいくらでもやりたい事ができるようになります。嬉しいのがそれを非常に短いコードで実現できてしまう事です。上のコードも大部分はDirectXの描画で占められていて、ダイアログの作成やテキストコントロールの追加は実質1〜2行です。ホント、wxWidgetsすばらしいよう〜(T-T)gあ、ちなみですね、上のコードには一つ致命的な部分があります。それは、ダイアログを閉じると落ちます。これは、ダイアログの閉じるボタンをクリックしてしまうと、ダイアログウィンドウ自体がアプリケーションによって削除されてしまうためです。ウィンドウの消去権限をメインウィンドウに移せば直ると思うのですが、今回の本質では無いため省きました。悪しからずご了承下さい。DirectXベースのツールを作る基盤が、これで出来たかなぁと感じます。後は創意工夫で何でもできそうですね。