MVC
こちらOpenGL GUI Applicationを参考にMVCを使ったwindowsアプリに修正します。
まずは、OpenGLを使わずに単純なアプリで実験します。
MVC
- Model
- アプリケーションのデータを動作を定義
- View、Controllerから完全に独立している。
- View
- Modelからデータを取り出して、画面に出力。
- Controller
- ユーザからのイベントに応答し、データの修正、画面の更新要求を行う。
※一般的なMVCとは異なります。
Model
- アプリケーションに必要なメンバとメソッドを記述します。
class HogeModel : public Model { private: int count; public: HogeModel() : count( 0 ) {} void inc() { count ++; } int get()const{ return count; } };
View
ボタンとラベル、Modelからデータを取得するためのModel*を持たせます。
Modelは参照カウンタを持っているので、ctor/dtorでaddref/releaseを行います。
コントロール(ボタン、ラベル)の初期化はinit_controlsで行います。
Controllerからの更新要求に対して、Modelからデータを取得しラベルを更新します。
class HogeView : public windows::View { private: HogeModel* model; windows::Button button; windows::Label label; public: HogeView( HogeModel* model ) : model( model ) { model->addref(); } ~HogeView() { model->release(); } public: void init_controls( HWND handle ) { button.create( handle, _T( "button" ), //title 1000, //ボタンのid recti( 10, 10, 10 + 100, 10 + 30 ) //ボタンの矩形 ); label.create( handle, _T( "label" ), recti( 120, 10, 120 + 100, 10 + 30 ) ); } public: void update() { tstringstream ss; ss << model->get(); label.set_text( ss.str() ); } };
- tstringstream
typedef std::basic_stringstream< TCHAR > tstringstream;
- recti
typedef rect< int > recti;
Controller
メッセージに対応するメソッドを実装します。
- create
- コントロールの初期化
- command
- ボタン押下時の処理
class HogeController : public windows::Controller { private: HogeModel* model; HogeView* view; public: HogeController( HogeModel* model, HogeView* view ) : model( model ) , view( view ) { model->addref(); view->addref(); } ~HogeController() { model->release(); view->release(); } public: int create() { view->init_controls( handle ); return 0; } int command( int id, int /*event*/ ) { if( id == 1000 ) { model->inc(); view->update(); } return 0; } };
WinMain
int APIENTRY _tWinMain( HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int /*nCmdShow*/ ) { //メモリリーク時にアウトプットウィンドウに情報を出力する _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); //MVC生成 HogeModel* model = new HogeModel(); HogeView* view = new HogeView( model ); HogeController* controller = new HogeController( model, view ); //ウィンドウ生成 windows::CreationParam param = { 400, 300, //width, height _T( "クリック回数をカウント" ), _T( "hoge" ), //title, class_name }; if( windows::Window* window = windows::CreateDefaultWindow( param, controller ) ) { windows::MessageLoop(); window->release(); } //MVC破棄 controller->release(); view->release(); model->release(); return 0; }
プロシージャ
CreateWindowExの最後の引数にControllerを渡して、SetProp、GetProp、RemovePropでウィンドウに関連付けています。
LRESULT CALLBACK Window::WndProc( HWND handle, UINT message, WPARAM wp, LPARAM lp ) { if( message == WM_CREATE ) { Controller* controller = reinterpret_cast< Controller* >( ( ( LPCREATESTRUCT )lp )->lpCreateParams ); if( controller ) { controller->set_handle( handle ); LRESULT ret = controller->create(); SetProp( handle, _T( "controller" ), controller ); return ret; } } Controller* controller = ( Controller* )GetProp( handle, _T( "controller" ) ); if( controller ) { LRESULT ret = 0; switch( message ) { case WM_COMMAND: ret = controller->command( LOWORD( wp ), HIWORD( wp ) ); break; case WM_DESTROY: ret = controller->destroy(); RemoveProp( handle, _T( "controller" ) ); break; default: ret = DefWindowProc( handle, message, wp, lp ); } return ret; } return DefWindowProc( handle, message, wp, lp ); }
ということで、今回はMVCを扱ってみました。
MVCの詳細はネット上にたくさんあるので、そちらを参考にしてください。
次回はこのサンプルにOpenGLを追加していこうと思います。
OpenGLでシェーダを使いたかったのですが、随分と寄り道していますねw