Version 2.1
イベントと関数
『この前みたいなふざけたことしないでよねー』
「別にふざけてないよん。あれだってプログラムのひとつだもの」
『だって何の意味もないじゃない』
「確かにね、ふふん」
『何よその笑い』
「んじゃ、前回の続きを見ていこうか」
void CCalcDlg::OnBEqual()
{
// TODO: この位置に(略)
MessageBox( " 1 + 2 = 3 " );
}
『これがこの前見たのだよね。相変わらずわけ分かんないなー』
「これはね、大きくこういうふうに見るんだよ」
頭
{
胴体
}
『はぁ?』
「まず【void CCalcDlg::OnBEqual()】が、<頭>。そのあとの中カッコ
( { )から中カッコ閉じ( } )までが、<胴体>」
『それが?』
「これがプログラムの構成単位。つまり、人間で言えば細胞ってところかな」
『ってことは、これがいっぱい集まって<プログラム>が作られてるってこ
と?』
「そういうこと。これと同じファイルの中に、こんなのもあるでしょ」
// システムは、ユーザーが最小化ウィンドウをドラッグしている間、
// カーソルを表示するためにここを呼び出します。
HCURSOR CCalcDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
『うん、ひとつ上にあるね』
「もっと上に行くと、もっとあるよ」
『うん、色々あるね。これが集まって<プログラム>になってるんだ』
「そう。でね、これひとつひとつ、つまりさっきの<頭>と<胴体>の組み
合わせを<関数>って言います」
『関数?』
「そ、<かんすう>。で、さっきのふたつを並べてみるね」
HCURSOR CCalcDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CCalcDlg::OnBEqual()
{
// TODO: (略)
MessageBox( " 1 + 2 = 3 " );
}
「まず、プログラムの<本体>は、<胴体>のところ、つまり中カッコの中
にしか書けません」
『本体って?』
「本で言えば、目次や索引、表紙じゃない部分。<頭>は目次に当たるかな」
『つまりプログラムの中身よね。上のなら、<return ...>とか
<MessageBox( ...>とかがその<本文>ってことになるわけね』
「だから、それ以外のところにはプログラムの本体は書けない、つまり上の
関数の終わり( } )から、次の関数の頭( void ... )までの間にも、プロ
グラムは書けません」
『そりゃそうよね、細胞と細胞の間にDNAとかあったら困っちゃうものね』
「そりゃ困るな。で、今度は<胴体>、つまり中カッコの中の話」
『プログラムの中身よね』
「そう。この中身は<上から下>へと実行されていくから。雰囲気としては、
フランス料理のフルコース、各品が上から順にテーブルに来るって感じかな」
『これは1行だけだけど、いっぱい行があったらそうなるんだ』
「そう。たとえば」
void CCalcDlg::OnBEqual()
{
MessageBox( "1" );
MessageBox( "2" );
MessageBox( "3" );
}
「ってしたら、小さなダイアログボックスが<1><2><3>の順に出て
くるよ」
『ふーん……って、じゃあ "MessageBox" っていうのを書くと、ダイアログ
ボックスが出てきてくれるんだ』
「そうそう。冴えてるじゃん」
『でしょでしょ?』
「じゃあここで問題。この<胴体>の前は、どこ?」
『へ?』
「胴体はさ、中カッコから始まるって言ったでしょ。その前はないのかな」
『う〜ん……さっきの』
HCURSOR CCalcDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
『のあとに、この胴体に入って来るんじゃないの?』
「だったら試してみようか」
HCURSOR CCalcDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
MessageBox( "1" );
}
void CCalcDlg::OnBEqual()
{
}
「火美ちゃんの言ったことがホントなら、これでもダイアログボックスが表
示されるはずだよね」
『……』
【ビルド】を実行し、【実行】する。最初のダイアログが開いたあと、
【=】ボタンを押すが、何も起きない。
『ずるいよずるいよっ!! おじいちゃんが言ってたもん、知らないことを
させられていきなりできるヤツは天才だけだって。知らないことさせるなん
てずるい!』
「でもさ、どうなんだろう、って思ったこと試すのは悪いことじゃないよ?
こういうのを自分で試して、失敗すれば、しっかり憶えるでしょ」
『はいはい、プログラミングは自分で作ってなんぼ、でしょ?』
「そゆこと。んじゃタネあかし。関数はね、<呼ばれる>ものなんだよ」
『呼ばれるって、病院の待合室みたいな感じ?』
「うーん、そういう感じかなー。ダイアログエディタ開いてみて」
『はーい』
VCのウィンドウがダイアログエディタに変わる。
「=ボタンの右クリックメニューの中に【イベント】ってあるでしょ」
『うん、この前これ選んだんだよね』
「イベントっていうのは<出来事>っていう意味。<何かが起きた
ぞっ!!>って感じかな」
そのまま【イベント】を選択する。前回表示した【クラス CCalcDlg 用の
Windows メッセージおよびイベントハンドラの新規作成】というダイアロ
グが表示される
「このダイアログで、どういうイベントが起きたときに、どういうことをさ
せるのか、っていうことを決められるんだよ」
『起きるイベントって、たとえばボタンを押したり、とか?』
「そう! たとえば、真ん中の上に "BN_CLICKED" ってあるでしょ」
『あ、クリック!! これがイベントってこと?』
「そういうこと。ボタンの上でクリックすると、これが送られてくるわけ」
『送られて来るって、どこから?』
「ウィンドウズから。ダイアログとかの<リソース>がウィンドウズからの
借り物ってことは言ったよね」
『だから、ボタンをダブルクリックしたらウィンドウズが<ダブルクリック
したよ>って言ってくれるってわけ? ウィンドウズってそんなに面倒見い
いんだー』
「で、 "BN_CLICKED" をダブルクリックすると……」
テキストエディタが開き、おなじみの関数が表示される。
void CCalcDlg::OnBEqual()
{
}
『これさっきの関数じゃない!』
「そういうこと。つまり、ボタンをクリックするとこの関数が呼ばれる仕組
みになってるわけ」
『へ〜。で、呼ばれたら、<胴体>の中を上から下に行って……そしたら?』
「<胴体>の最後まで行ったら、関数はそこで終わり。呼び出した関数に戻
るんだよ」
『関数から関数を呼び出せるの?』
「そう。たとえば」
void CCalcDlg::OnBEqual()
{
MessageBox( "1" );
}
「この "MessageBox" も、関数なんだよ」
『これも関数? ってことは、"MessageBox" っていうのを呼び出して、そ
の中の<胴体>をくぐってきて、それが終わったらまた戻ってくる、ってこ
と?』
「そういうこと。なんとなく分かってきた?」
『関数が関数を読んで、その関数がまた関数を読んで……終わったら呼んだ
関数に戻って、それが終わったらまた呼んだ関数に戻って……』
「じゃ、見てみようか」
『みみみみみみるって?』
「 "MessageBox" の行を1回クリックしてみて」
『はい、クリック、と』
「そしたらツールバーの<手のひらマーク>クリックして」
『手のひら手のひら……っていっぱいあるけど』
「普通の手のひら。xとか斜線とか付いてないの。もしなかったらメニュー
の【ツール】−【カスタマイズ】でツールバーに貼り付けてね」
ツールバーから<手のひら>を選び、クリックする。
『あ、この行の左に●付いたね』
「そしたらメニューの【ビルド】−【デバッグの開始】−【実行】を選んで」
『うん選んだよ……って、<ビルドしますか?>ってダイアログ出ちゃった
けど』
「あ、さっき変えてからビルドしてなかったからね。【はい】押して」
ハードディスクが回り始める。
『ビルドしてる間に聞きたいんだけどさ、今の【実行】っていうのと同じア
イコンがツールバーにもあるけど?』
「紙と文書の右に下矢印、みたいなのでしょ。うん、こっちでもいいよ」
『もうひとつ、この前した【ビルド】−【実行】とどう違うの?』
「これからする事ができるってこと」
『?』
ビルドが終了し、自動的にアプリが実行されダイアログが表示される。
「じゃ、【=】ボタン押してみて」
『はーい……あれ?』
VCが表示され、先ほどの●の中に矢印が書かれている。
『ど、どうしちゃったの?』
「プログラムが止まったの」
『止まったって、なんか間違えちゃった?』
「間違えてないよ。●を付けた行を実行しようとすると、一度止まるように
なってるんだよ」
『あ、●を付けたから止まったんだ。良かったー。これをするために、違う
【実行】にしたってこと?』
「そういうこと。じゃ、探検してみようか」
『探検?』
「ツールバーの<中カッコに入る>みたいなボタンをクリックしてみて」
『なんか起こるのかな……』
そのボタンを押す。テキストエディタが別の見たことのないファイルを表
示し、その中ほどに先ほどの矢印が表示されている。
int CWnd::MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption, UINT nType)
{
if (lpszCaption == NULL)
lpszCaption = AfxGetAppName();
int nResult = ::MessageBox(GetSafeHwnd(), lpszText, lpszCaption, nType);
return nResult;
}
『これって関数だよね……あ! "MessageBox" って書いてある! それに
矢印が<胴体>の最初に来てるし、この関数を呼んだから、この胴体に移っ
たんだよね?』
「そういうこと。これで<関数を呼ぶ>ってことがちょっとわかった?」
『でも "CWnd::" ってなに?』
「これはまた今度ね。じゃ、今度は<中カッコの上を越えていく>っていう
ボタンを押して」
『あれ、さっきのと違うんだ』
押すと、ひとつ下へと矢印が進む。
「さっきのボタンは<関数の中へとどんどん深く入っていく>の、今押した
のは<関数の中には入らないで、行を進めていく>の」
『そうよねー、どんどん深く入ってっちゃったら、なーんか帰ってこれなさ
そう』
「そうだね、最初は少しずつがいいかな。もう一度ボタン押してみて」
『はーい』
「もういちど」
『はぁい』
「さらに」
『はー……あれ? ボタン、単色表示になっちゃったよ』
「じゃ、アプリの方見てみようか」
タスクバーから "Calc" を選ぶ。すると、小さなダイアログが表示されて
いた。中の文は "1" 。
『あれ? いつのまに?』
「いつのまに、かな?」
『え? ……えっとねー、今矢印が<胴体>の3行目にあるから、3行目か
ら4行目に行こうとしたときになったってことよね。つまりその間に、この
ちいちゃいダイアログが表示された、ってこと?』
「そういうこと! こういうふうに見ていくと、どこで何してるのか、おお
ざっぱにだけどわかるでしょ」
『うん、なんていうか、足がかりつかめた感じ』
「じゃ、小さなダイアログ閉じて」
『はーい』
【OK】を押すと、VCに戻り、矢印が4行目に来ている。
『そのままさっきの<上を越えてる>ボタンを押せばいいんだよね』
「そうそう」
そのボタンを2度ほど押すと、先ほどの【void CCalcDlg::
OnBEqual() 】へと戻ってきて、閉じカッコの所に矢印が来ている。
『あ、ホントに戻ってきた! こういうふうに、関数を呼んで、帰って来る
んだ』
「あとは、さっきの【実行】を選べば、すーっと流れていくようになるから」
その<文章の書かれた紙の脇に下矢印>のボタンを押せば、 "Calc" ダイ
アログが再び表示される。
「今日はこんなとこかな。どう?」
『とにかく、関数がいっぱい集まってプログラムができてること、関数を呼
び合ってプログラムが実行されてるってこと、よね』
「そういうこと。それがわかれば全然OK!」
『なんとなーく、分かってきたかも』
/*
Preview Next Story!
*/
『今回はこの前分からなかったことも少し分かったし、良かったかも』
「分からないことができて、それを解消して、この繰り返しかな」
『着実に一歩一歩、って感じかな』
「じゃ、来週はじみーなお勉強しようか」
『げげー』
「というわけで次回」
< Version 2.2 変数を作ろう! >
『につづく!!』
「変数なんて、なんか初心に戻る感じだなー」
『水希ちゃんがその変数っていうの勉強したの、いつぐらいのこと?』
「小学生の時」
『エリートっすね……』