最近の記事
- 9/1 - 将棋始めました
- 5/16 - サーバー引っ越し
- 4/24 - 優先順位
- 3/17 - vbNullString と 空文字列 ""
- 3/15 - InputBox 関数の戻り値
- 3/13 - 紙と Excel と VBA
- 3/9 - 未だに Visual Basic 6
- 11/14 - ぼて閉鎖
- 11/9 - 関数オブジェクトの呼び出し
- 9/7 - メソッドとしての関数オブジェクト
Entering Passive Mode
「設定」ボタンも Application::ConfigureProc で処理されるので、
IDC_CONFIGURE 向けの WM_COMMAND メッセージを処理すればよい。
プラグイン用の設定画面の呼び出しも、一覧表示と同じように作る。
ConfigureProc メソッドをマネージにしないように、
ConfigurePlugin という名前のヘルパメソッドに分離する。
========== Application.hpp ==========
……
class Application {
……
private:
……
void ConfigurePlugin(HWND combobox);
msclr::gcroot manager;
……
};
……
========== end of Application.hpp ==========
ソースファイルでは、プラグマ managed と unmanaged を使うことで、 部分的にマネージコードを使うことが可能だ。
========== Application.cpp ==========
#include "config.hpp" #include "Application.hpp" #include "Dispatcher.hpp" #include "Manager.hpp" #include "HwndWrapper.hpp" //<== ISaver::Configure 用に追加 #include "resid.hpp" #using#using #using "Loafer.ScreenSaver.dll" #pragma unmanaged namespace Loafer { namespace ScreenSaver { namespace Host { …… BOOL Application::ConfigureProc( HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); switch (message) { …… case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_CONFIGURE: // 選択されたプラグインの設定画面を呼び出す ConfigurePlugin(GetDlgItem(hdlg, IDC_PLUGINS)); break; case IDOK: // TODO // break; case IDCANCEL: EndDialog(hdlg, 0); break; } } return FALSE; } // ここから C++/CLI #pragma managed using namespace System; using namespace Loafer::ScreenSaver; using namespace System::Runtime::InteropServices; void Application::LoadPlugins(HWND combobox) { Manager ^manager = gcnew Manager(); …… // Manager をフィールドに保存しておく // Manager ^ は msclr::gcroot に代入可能 this->manager = manager; } void Application::ConfigurePlugin(HWND combobox) { // 選択インデックスを取得 int index = SendMessage(combobox, CB_GETCURSEL, 0, 0); if (index == CB_ERR) return; // 型を取得 Type ^type = static_cast (manager)[index]; // インスタンスを作成 ISaver ^saver = safe_cast (Activator::CreateInstance(type)); // 設定画面を呼び出す saver->Configure(gcnew HwndWrapper(GetParent(combobox))); } }}} // Loafer::ScreenSaver::Host
========== end of Application.cpp ==========
まず、LoadPlugins() で作成した Manager インスタンスは、
後で使えるようにフィールドに保存しておく。
gcroot のお陰で、単に代入だけですむ。
ConfigurePlugin() も、LoadPlugins() と同じように、
コンボボックスのウィンドウハンドルを渡すようにしてある。
CB_GETCURSEL メッセージを送ってインデックスを得た後、
そのインデックスを元に選択された ISaver 実装クラスの Type を得る。
Manager クラスはインデクサを実装しているので、
manager[index] としたいところなのだが、
残念ながら、gcroot に入れて保存しているインスタンスでは、
インデクサの構文は、gcroot への operator [] となってしまいうまくいかない。
そこで、static_cast で Manager ^ に戻してから取得する。
余談だが、メソッドやプロパティを呼ぶのであれば、
gcroot のままで呼び出すことが可能である。
たとえば、Count プロパティであれば、manager->Count; で取得できる。
これは、スマートポインタにほぼ共通した機能だ。
Type を取得できれば、Activator::CreateInstance() でインスタンスを作成し、
Configure() を呼び出して設定画面を表示させる。
この場合、Configure() に渡すオーナーは、ホストの設定ダイアログとなるので、
GetParent() でダイアログのウィンドウハンドルを取得した後、
HwndWrapper にラップして引数に渡して完了となる。
コメント (0 件)