読者です 読者をやめる 読者になる 読者になる

CWindow::DynamicWindowProc

前回、StaticWindowProcを追加したことで、CWindowクラスにウィンドウプロシージャをメンバとして組み込むことができた・・・。

ただ、スタティックなメンバであるため、複数のウィンドウオブジェクトが同時に処理をすると、それぞれ競合してしまう可能性がある・・・。

またスタティックメンバ関数は、継承してウィンドウプロシージャをオーバーライドすることができないため、派生のウィンドウオブジェクトではウィンドウプロシージャを名前を変えて定義する必要がある・・・。

そこで、メンバ関数としてDynamicWindowProcを用意し、StaticWindowProcから呼び出すようにする・・・。
そして、DynamicWindowProcでは、それぞれのメッセージ処理をする・・・。

まず、Window.hにて、

staticなStaticWindowProcと、virtualなDynamicWindowProc、これらを用意・・・。

DynamicWindowProcは、

まるでウィンドウプロシージャのようである・・・。

さて、StaticWindowProcはどうやってこのDynamicWindowProcを呼び出しているのだろうか?
StaticWindowProcでは、

まずCWindowオブジェクトポインタpWindowを用意し、NULLにセット・・・。

WM_CREATEは、この中で処理するメッセージとしてはちょっと特殊で、CreateStruct構造体のポインタをlParamから取得しておく・・・。

lpCreateParamsという要素に、実は生成するウィンドウのCWindowオブジェクトのポインタが入っているので、それを取り出してpWindowに格納している・・・。

これは、CWindowのCreateメンバ関数の中の、

ここの最後の引数のthis、これをLPVOIDにキャストして渡している・・・。
そうすると、先ほどのlpCreateParamsのところに、thisつまりCWindowオブジェクト自身のポインタを渡すことができるのである・・・。

なぜこんなことをするのかというと、CWindowオブジェクトのポインタpWindowとウィンドウハンドルhwndを1対1で紐付けたいからである・・・。
紐付けられれば、オブジェクトごとにウィンドウ操作ができ、それぞれの処理を独立させることができるからだ・・・。
(独立といっても、CWindow同士ならおなじCWindow::DynamicWindowProcを通る・・・。ただ、それぞれが違うオブジェクトインスタンスなので、処理が競合することはない。)

紐付けるために、

スタティックメンバオブジェクトとして、std::mapのm_mapWindowMapを用意・・・。

これWindow.cppにもいるので注意・・・。

このm_mapWindowMapに、

hwndとpWindowをペアにしてセットする・・・。

WM_CREATEの場合はそのあと、

pWindowがNULLではないので、pWindowからDynamicWindowProcを呼ぶ・・・。

WM_CREATE以外の場合は、lpCreateStructが渡されないので、

m_mapWindowMapからhwndをキーにして、pWindowを取り出す・・・。
このとき、hwndが無い場合は取り出さない・・・。ここ注意・・・。

pWindowがあったら、先ほどと同様にDynamicWindowProcを呼び、万が一なかったら、

普通のDefWindowProcを呼ぶ・・・。

こうやって、CWindowオブジェクトごとにDynamicWindowProcを呼ぶことができ、それぞれの処理を独立させることができる・・・。

実は、hwndとpWindowの関係を保存する方法として、std::mapを使う方法以外に、GetWindowLongのGWL_USERDATAを使う方法、SetProp/GetPropを使う方法があるのだが、どちらも構造上の問題があるため、今回はstd::mapで行う方法にした・・・。

f:id:BG1:20150519150903p:plain

これでウィンドウプロシージャごとオーバーライドできる・・・。

https://github.com/bg1bgst333/Test/blob/master/winapi/CWindow/DynamicWindowProc/src/DynamicWindowProc/DynamicWindowProc/WinMain.cpp
https://github.com/bg1bgst333/Test/blob/master/winapi/CWindow/DynamicWindowProc/src/DynamicWindowProc/DynamicWindowProc/Application.h
https://github.com/bg1bgst333/Test/blob/master/winapi/CWindow/DynamicWindowProc/src/DynamicWindowProc/DynamicWindowProc/Application.cpp
https://github.com/bg1bgst333/Test/blob/master/winapi/CWindow/DynamicWindowProc/src/DynamicWindowProc/DynamicWindowProc/Window.h
https://github.com/bg1bgst333/Test/blob/master/winapi/CWindow/DynamicWindowProc/src/DynamicWindowProc/DynamicWindowProc/Window.cpp