WindowsSDK 備忘録 その四

備忘録の四回目はメモ書きです。

参考にしている教本のPart3(P.163~)からマスコットシステムの設計に入ってますが、教本では、表示機能→スクリプトエンジンという順番で、マスコットシステムに実装してる機能をひとつひとつ解説していってます。しかし、自分のように大掴みでいいから全体の流れを俯瞰して把握したいと考えている者にとっては、焦点がぼやけて全体像が見えにくく感じられます。単純にクラスを使って画面に何かを表示するということだけに焦点を絞って考えるならば、表示機能の仕組みを理解できてればいいので、スクリプトエンジンのことはこの時点では無視して、仕掛けに関して整理してみました。

以下メモ書きより

メインウィンドウに関しては、アプリ起動時に自動生成される。
だが、二階層目の子ウィンドウの生成は、スクリプトで、マスコットの指定時にマスコットのオブジェクトが動的に作成される時、CImageWinodwクラスのコンストラクタによって、子ウィンドウの生成とMapコンテナへの登録が行われる。

スクリプトの進行によるトリガーによって、マスコットが指定されるとCImageWindowクラスのコンストラクタが呼び出される。このコンストラクタ通過時に、HWND MainWindow を親として子ウィンドウを作成し、取得したハンドル値を利用して、Mapコンテナに、ハンドル値をキーにthisオブジェクトを使って、カレントのCImageWindowオブジェクトをデータとして、登録してしまう(P.194)

押さえたいポイントとして、マスコットクラスのオブジェクトやバルーンオブジェクトなど、派生クラスのコンストラクタを通過する前に、必ず親クラスのCImageWindow のコンストラクタも通過し、それぞれ子ウィンドウを作成してはMapコンテナにハンドル値を元に登録されているというのが、第一の点。もうひとつは、これら子ウィンドウは、CImageWindow に内包され、各ウィンドウは共通の1つのプロシージャを使用する点。

ぽもも・ぺけまのいずれも、CImageWindow::WndProcをプロシージャとして使用する。P.193で、
wcex.lpfnWndProc=(WNDPROC)&CImageWindow::WndProc;
と、クラスメンバ関数であるメッセージハンドラをキャストしてレジスタ登録してる。

また、Mapコンテナからハンドル値を元に、各子ウィンドウのオブジェクトを検索して、それぞれの関数を指すようにしている。

P.196の、
case WM_PAINT:
if (imgwnd!=NULL) imgwnd->WmPaint();
などは、ぽもも・ぺけまなどマスコットクラスのオブジェクトの場合は、
CMascot.cpp、CMascot.h に実装・定義されている派生クラスの CMascot::WmPaint();が
適用される。また、バルーンクラスのオブジェクトの場合は、同様に、CBalloon::WmPaint();が
適用される。何故、自動で振り分けられるかというと、

まず、P.195で定義されている imgwnd が、CImageWindow 型の
ポインタとして定義され、派生クラスのオブジェクトが動的に生成された時、先に親クラスの
コンストラクタを通過する際に、thisオブジェクトとしてマスコットやバルーンなど
子クラスのオブジェクトが、オブジェクトへのアドレスを親クラスの型のポインタimgwndに
格納できているというのが、第一点。この際に、参考アドレスの実験に従うと、
(参考)
http://wisdom.sakura.ne.jp/programming/cpp/cpp30.html
親クラスの型のポインタに代入した子クラスのオブジェクトに対して、
ポインタを使って親に実装されてる同名のメンバを呼び出すと、親のメンバ関数を
呼び出す。imgwnd->WmPaint();もこの時、CImageWindowのWmPaint();を
呼び出しているはずなのだが、子クラスのメンバ関数をきちんと呼び出せている。
これは、何故かというと、つまるところ

親クラスのCImageWindow::WmPaint();がvertual指定されていて、
子クラスにWmPaint();の実装がそれぞれ委託されているから大丈夫なのだということ
と結論される。

これは、親クラスのWmPaint();をvirtualでなく、実装してみれば検証できるはず。
きっと、どの子クラスのオブジェクトも、ポインタ呼び出しでは親の関数を使用する
ことになるはず。

以上、メモ書き

コメント

タイトルとURLをコピーしました