さて、唯一のイベントプロシージャ ep_rad_value_ch ですが、こんな風に定義されています。
void CTGRWindowPlacementDlg::WPDImpl::ep_rad_value_ch(WSCbase* object)
{
WPDImpl* pimpl = m_oi_map.RecallInstanceForTheObject(object);
if( pimpl == 0 )
return;
if( pimpl->_in_rad_value_ch_proc )
return;
pimpl->_in_rad_value_ch_proc = true;
pimpl->OnRadValueChanged(object);
pimpl->_in_rad_value_ch_proc = false;
}
なんだこれは、ですよね。ここでは前述のm_oi_mapを使ってクラスのインスタンスのポインタを得て、
pimpl->OnRadValueChanged(object);
のように処理関数の本体を呼び出しているだけです。
前後を変数で囲ってガードしているのは、OnRadValueChanged()の中の処理でもボタンの選択状態を調整することがあって、それでまたイベントプロシージャが呼び出されたのでは無限ループになってしまうからです。呼び出し自体は禁止出来ないので、ちょっとダサいですが、呼び出された方で判断しています。
では、本当の処理は何をやっているか?
もちろんクラスの関数として普通に処理を実行するだけです。
まず「どのボタンについて呼び出されているか」を求めます。
void CTGRWindowPlacementDlg::WPDImpl::OnRadValueChanged(WSCbase* object)
{
WSCvradio* radio = dynamic_cast<WSCvradio*>(object);
if( radio == 0 || radio->getStatus() != True )
return;
素直にdynamic_castを使っています。WSCbaseにはほぼ同じ機能を提供しているCast()というメンバ関数がありますけれども、これはdynamic_castが無かった時代の名残りだと思います。また、他のボタンがチェックされたことによってこのボタンのチェックが外れて呼び出された時にはやることがないので、その時はすぐに復帰しています。
この先はこの画面特有の処理になりますが、どのグループの何番目のボタンが選択されたのかを求めて、以後の処理を行なっています。
std::vector<WSCvradio*>* group = GetSelectedBtnGroup(radio);
if( group == 0 ) return;
.....
std::vector<WSCvradio*>::iterator iit = std::find(group->begin(),group->end(),radio);
size_t index = iit - group->begin();
この先については割愛します。
細かく吟味したい方は、 http://www.attocraft.jp/contents/archive/TGRWindowPlacementDlg.zip にソースを置いておきますので、よろしければご覧下さい。
(この項終わり)