Entering Passive Mode

2007-09 - カテゴリ 'C++/CLI' の記事
< 1 2 >

プラグイン選択ダイアログ

プラグインダイアログ

ISaver を実装しているプラグインが複数ある場合、
実行に使うプラグインを決めなければならない。

これを決めるのはもちろん利用者なので、
その設定を行うプラグイン管理画面が必要となる。

ということで、ホストのダイアログボックスを改造し、
好きなプラグインを選択できるようにしてみよう。

リソースファイルを書き換え、
スクリーンセーバーの名前と、
ダイアログボックスの定義を書き換える。

プラグインの動的ロード

プラグインを動的に読み込む所から考えてみよう。

現在 Dispatcher.cpp では、#using ディレクティブを使い、
<HelloSaver.dll> を直接参照しているため、
以下のコード断片だけでインスタンスを作成できる。

    // スクリーンセーバーを作成
    HelloSaver saver;

これを動的に読み込むように切り替えるためには、
まず、HelloSaver.dll への依存を外さなければならない。
そうなると、「HelloSaver」のように、
プラグイン実装のクラス型を直接使うことはできないため、
リフレクションを使ってアクセスすることになる。

ホストの改善 #1: 構想を練る

次のステップに進むか。

現状のホストには大きな制限がある。
それはリソースの問題だ。

スクリーンセーバーの名前とアイコンは、
ホストに Windows のリソースとして埋め込まれる。
これらは、プラグインで置き換えることはできない。

これにより生じる制約は以下の 2 つ。
・表示するスクリーンセーバーの名前を変えられない
・スクリーンセーバーのアイコンを変えられない。

ホストの作成 #8: 動作テスト

スクリーンセーバー

描画コードとの連携も完成したので、
ちゃんと動作するかテストしてみる。

実行してみると、画面の中央に、
「Hello World!」と表示されたことが確認できた。

……これだけだと短すぎるので、もう少し書くか。

このスクリーンセーバーの実行は
C++ ネイティブアプリと違い、起動に多少時間がかかる。

C++/CLI #7: IDisposable と delete

突如現れた delete 構文。
この delete の意味するのは何なんだろうか。

まず、昨日のコードから、大事な部分を引用していこう。

    Graphics ^g = Graphics::FromHdc(...);
    try {
        ...
    } finally {
        delete g;
    }

ホストの作成 #7: 描画コードを呼ぶ

Create/Destroy の準備ができたので、
本題となる Dispatcher::Paint の実装を行う。

    void Dispatcher::Paint(HWND hwnd) {

        // 描画開始
        PAINTSTRUCT ps;
        BeginPaint(hwnd, &ps);

        try {

C++/CLI #6: GCHandle の参照を解放する

GCHandle::Alloc でハンドルに ID を割り当てると、
数値として取り扱えるようになるので便利だが、
不要になった時にはちゃんと解放しなければならない。

これを怠ると、ハンドルへの参照が残ってしまうので、
オブジェクトがガベッジコレクションされなくなり、
メモリリークを引き起こす要因となる。

GCHandle::Alloc で参照したハンドルを解放するためには、
どこかで GCHandle::Free を呼ぶ必要がある。

C++/CLI #5: safe_cast

GCHandle を使って割り当てた ID はただの数値なので、
利用するときにはハンドルに戻さなければならない。

ID からハンドルに戻すのは、
ハンドルから ID に変換した時と逆の手順を踏めば良い。


    // ウィンドウのユーザデータから ID を取得
    LONG_PTR value = GetWindowLongPtr(hwnd, GWLP_USERDATA);
    void *pointer = reinterpret_cast<void *>(value);

C++/CLI #4: ハンドルを数値に変換する

ハンドル型の値は演算も変換もできないため、
そのままではスコープを超えて、
オブジェクトを保持することが困難である。

グローバル領域に変数を確保し、
ハンドル型の値を保持する手はあるが、
変数の可視性を高めてしまうのは、
保守性に劣り、見通しも悪くなるのでやりたくない。

ではどうすれば良いか。

C++/CLI #3: gcnew で動的確保

次に作るのは、描画コードの呼び出しだ。

Configure メソッドを作成した際は、
「HelloSaver saver;」という形で変数を宣言した。

この場合、saver 変数のスコープは、
Configure メソッドの内部なので、
メソッドから戻る直前に変数がスコープから外れ、
自動的にデストラクタが呼び出されて解放される。

でも、描画コードの呼び出し部分の実装は、
Configure のような単発の呼び出しではなく、
Create => Paint => Destroy の流れとなる。

< 1 2 >
このページのトップへ戻る
© 2008 Project Loafer/Project Fireball and all blog writers. Powered by Nucleus CMS