Version 3.18
クラスを超えたおつきあい
「前回は、なんでダイアログが閉じるのか見てみました」
『結局は EndDialog() ってのが呼ばれるかどーかよね』
「で、この関数に渡された値が」
『 CDialog::DoModal() の戻り値になって返ってくる!』
「【OK】ボタンと【キャンセル】ボタンの場合はどうなんだっけ」
『えっと、【OK】の方は IDOK 、【キャンセル】の方は IDCANCEL を
EndDialog() に渡してたんだよね』
「ではそれを踏まえて、この前見た CCalcApp::InitInstance() をもう一度
見てみましょう」
BOOL CCalcApp::InitInstance()
{
// 略
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: ダイアログが <OK> で消された時のコードを
// 記述してください。
}
else if (nResponse == IDCANCEL)
{
// TODO: ダイアログが <キャンセル> で消された時のコードを
// 記述してください。
}
// 略
}
『あ、えーと、なんとなーく分かるような……』
「1行ずつ、ゆっくりと見ていけば分かると思うよ」
『んじゃゆっくりと。まず DoModal() んとこでダイアログ作ってるのよね』
「そう。ダイアログが閉じるまで、この関数から返ってきません」
『で、返ってきたときの戻り値が、 nResponse って変数に入って』
「ちなみに nResponse ってのは、〈整数〉って意味の n と〈反応〉って意
味の Response から来てます。ま、これがMFC流ってとこかな」
『……ちょっと静かにしてくんない?』
「はい……」
『で、 if ってことは、 nResponse が IDOK かどうかってのを見てるんだ
よね』
「……」
『参照くらい言っていーよ』
「はいはい。えっと、 if は Ver 2.8 ( No.019 )で、 == は Ver 2.6
( No.017 )に書いてあります」
『もし nResponse が IDOK なら、〈ダイアログが <OK> で〉とか書かれて
る、中カッコと中カッコ閉じの中に入って、そうでないなら次の else if
に……』
「 else if も Ver 2.8 ( No.019 )に書いてあります」
『 else if の方で、もし、 nResponse が IDCANCEL なら、〈ダイアログが
<キャンセル> 〉とか書かれてる中カッコと中カッコ閉じに入る……』
「つまり?」
『つまり、戻り値が IDOK なら上の TODO んとこに、 IDCANCEL なら下の
TODO んとこに行くってことでしょ?』
「もう少し言うと?」
『え?』
「その戻り値って、なんで返ってくるんだっけ」
『 EndDialog() の……あ、つまり【OK】ボタン押したら上の、【キャンセル】
押したら下のってことなんだ!』
「そういうこと。MFCがそういうプログラムを用意してくれてるってこと
だね」
『ほー』
「ちなみにこういう if の使い方はとーってもオーソドックスなものだから、
簡単に書けるようにね」
『こういうって?』
「関数の戻り値をチェックして、それに合わせて処理するって方法のこと」
『なるほど。書けなきゃダメ?』
「だめ。いくらなんでもこれくらいはそらで書けないと」
『ぶー』
「んじゃ今回の目的。今日は〈【OK】ボタンを押したらアウトプットに結果
を表示する〉ってプログラムを作ります」
『……〈【OK】ボタンを押したら〉は、上の TODO に書けばいいってのは分
かるけど、そのあとが……ねぇ』
「〈アウトプットに表示する〉のは分かるでしょ?」
『 TRACE() 使えばいいんだよね。ってことは、〈結果〉が分かればいいんだ』
「じゃ、ここで先週に引き続き CCalcDlg::OnBEqual() を見てみましょう」
void CCalcDlg::OnBEqual()
{
UpdateData( TRUE );
m_iAns = m_iLh + m_iRh;
UpdateData( FALSE );
}
「これは何してるんだっけ?」
『えーっと、確か、 m_iAns とかは、ダイアログに張り付いてるエディット
ボックスとくっついてるんだよね』
「 Ver 3.11 ( No.036 )だね」
『で、UpdateData( TRUE ) でエディットから m_iAns とかに数字を渡して、
UpdateData( FALSE ) でその逆に m_Ans とかからエディットに渡すんだよね』
「そう。で?」
『で……あ、で、真ん中の行で足し算して、 m_iAns の中に答を入れて、そ
れが次の行でエディットに書き込まれるって仕組みだったよね、確か』
「そういうこと。ってことはつまり、計算結果は m_iAns に入ってるってこ
とでしょ」
『あ、そっか! この m_iAns の中身が分かれば、結果が表示できるんだ。
でもどうやって?』
「 m_iAns ってなんだっけ」
『えーっと、エディットボックスと結びつけられてる変数』
「なに変数だっけ」
『あ、メンバ変数!』
「そう。 CalcDlg.h の中に……」
class CCalcDlg : public CDialog
{
// 略
int m_iAns;
int m_iLh;
int m_iRh;
// 略
};
「こういうふうにすると、 CCalcDlg のメンバ変数になります」
『 CCalcDlg のどんなメンバ関数からでも使えるんだよね』
「メンバ変数については Ver 3.7 ( No.032 )を見てください。で、 m_iAns
は CCalcDlg のメンバ変数でしょ」
『うん』
「で、表示したいのは CCalcApp::InitInstance() の中」
『あ、クラスが違うんだ!』
「そう、今回の鍵はまさにそこにあるわけ。 CCalcApp::InitInstance() を
もう一度見てみると……」
BOOL CCalcApp::InitInstance()
{
// 略
CCalcDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
// 略
}
『あ、この CCalcDlg の変数 dlg を使って、ダイアログを表示してるんだ
から……』
「つまり、この dlg って変数の中に m_iAns が入ってるってこと。これが
取り出せれば」
『取り出せれば目的完了! でもどうやって?』
「ところで dlg.DoModal() って何してると思う?」
『ダイアログ表示してるんでしょ?』
「いや、もっと細かく言うと……」
『えっと、 CDialog の DoModal() ってメンバ関数を……あ』
「んじゃ思う通りに作ってみてみ?」
『んっと……』
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: ダイアログが <OK> で消された時のコードを
// 記述してください。
}
『の TODO のとこに、あ、えーっと』
「細かく細かく、だよ」
『あ、じゃあとりあえずいつもの TRACE() を』
TRACE( "%d\n", );
「その2番目の引数に、数字にあたる変数を入れればいいんだから」
『……もうひとつ変数作っていい?』
「もちろん」
int i;
TRACE( "%d\n", i );
『で、この i に……あってますように』
int i = dlg.m_iAns();
TRACE( "%d\n", i );
『って感じに、メンバ変数もメンバ関数と同じふーに』
「変数なんだから小カッコはいらないでしょう」
『あ、そっか。ってことは当たり?』
「そういうこと!」
int i = dlg.m_iAns;
TRACE( "%d\n", i );
『って書き直してビルドして実行、左に 100 、右に 250 、【+】ボタン押
して結果は 350 、そして【OK】ボタンを押すと……』
アウトプットに 350 と表示される。
『やったー!! なんだ楽勝じゃん』
「またそーゆーことを……。ま、こんなふうに、メンバ関数と同じようにメ
ンバ変数にアクセスできるってことは分かった?」
『うん分かった!』
「んじゃ問題」
『げげ!』
「ダイアログが表示されたときに、答の部分に 100 が表示されるようにす
るにはどうすればいいでしょう」
『おんなじふーにすればいーの?』
「そうだよ。ダイアログが表示する前に、値を入れとかないといけないから」
『 DoModal() を呼ぶ前ってことでしょ、ってことは……』
dlg.m_iAns = 100; // ここに追加。
int nResponse = dlg.DoModal();
『って感じじゃない?』
「正解! 結構分かってきたかな?」
/*
Preview Next Story!
*/
『レジストリってよく聞くよね』
「照り焼きにして食べるとおいしいんだ」
『あたしはカレーがいーな』
「照り焼き!」
『カレー!』
「というわけで次回」
< Version 3.19 レジストリに保存しよう! >
『につづく!!』
「でも〈なんとかとり〉って名前の鳥ってあんまいないけど」
『コウノトリ?』
「コウノトリ食うんかい」