Entering Passive Mode

< ... 3 4 5 6 7 8 9 10 11... >

ホストの作成 #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 の流れとなる。

ホストの作成 #6: 連携テスト

まだ Configure メソッドしか作っていないが、
設定画面を表示させるコードは完成した。
描画用のコードを書いてないので、
スクリーンセーバーの実行テストはできないが、
とりあえず設定画面が表示されるか確認してみたい。

まずは、Dispatcher.cpp をコンパイルしておく。

$ cl /c /W4 /clr /FoDispatcher.obj Dispatcher.cpp

エラーがなければリンクする。

C++/CLI #2: ハンドル ^ とハンドル演算子 %

いきなり出てきた % の文字。これはなんだろうか。
どう見ても剰余演算子の % ではない。

コードを再掲してみよう。

    void Dispatcher::Configure(HWND hdlg) {

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

        // HWND のラッパーを作成
        HwndWrapper window(hdlg);

C++/CLI #1: HwndWrapper マネージクラス

最初に、Dispatcher::Configure を作ってみよう。

    void Dispatcher::Configure(HWND hdlg) {

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

        // 設定画面を呼び出す
        saver.Configure(hdlg); // ダメ

    }

< ... 3 4 5 6 7 8 9 10 11... >
このページのトップへ戻る
© 2008 Project Loafer/Project Fireball and all blog writers. Powered by Nucleus CMS