Version 10.03
ウィンドウプロシージャ!
「前回はウィンドウクラスの登録をしました」
『ちょっと駆け足だったね』
「そうだね、ウィンドウクラスについてはあとでまた触れるから、その時に
もう一度ちゃんとっていうのがあって」
『そういえばウィンドウクラス名がとっても重要とか言ってたね』
「そう、でもそれはとりあえずは置いておいていいことだから、後回し。そ
れよりもまずビルドが通るようにしたいから」
『動かないとつまんないもんね』
「ちなみに、今回だけじゃまだ動くようにはならないから」
『げ、そなの?』
「それだけ、 MFC を使わないウィンドウアプリは大変ってことだね」
『……じゃなくて』
「じゃなくて?」
『ダイアログプロシージャ使った時ってこんなに面倒じゃなかったじゃな
い』
「あ、そうだね。ダイアログじゃないウィンドウアプリも大変ってこと」
『ダイアログは簡単なのねー』
「ダイアログってそういうためのウィンドウだからね」
『お手軽ウィンドウ?』
「そういうこと。ダイアログひとつ作るのにこんな大変だと困るでしょ」
『ひとつ作るのにも困るけど……』
「さて。では今回は、ウィンドウプロシージャを作ります」
『ウィンドウプロシージャって、ダイアログプロシージャのウィンドウ
版?』
「っていうか、ダイアログプロシージャがウィンドウプロシージャのダイア
ログ版なんだけどね……」
『ウィンドウの方がえらいわけね』
「偉い……」
『で、ウィンドウプロシージャってダイアログプロシージャみたいなの?』
「うん、結構似てるし、でも違うところも結構あるかな」
// ウィンドウプロシージャ。
LRESULT CALLBACK WndProc
( HWND p_hWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
)
{
if( p_uiMessage == WM_DESTROY )
{
// ×ボタンが押されました。
PostQuitMessage( 0 );
return 0;
}
// 標準的な処理をします。
return DefWindowProc( p_hWnd, p_uiMessage, p_wParam, p_lParam );
}
「これを Version 10.01 ( No.179 ) の最後のコードの、」
#include <Windows.h>
「の下に追加して」
『 Version 8.07 ( No.179 ) のダイアログプロシージャは』
// ダイアログプロシージャ。
BOOL CALLBACK DialogProc
( HWND p_hDlgWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
)
{
return FALSE;
}
『と比べると、引数とかかなり似てるね』
「って言うか、実は全部同じ。 LRESULT は long 型から typedef されて
て、 long と int はほぼ同じだから」
『ほぼ同じ?』
「 long と int の関係については Version 4.08 ( No.058 ) を参照」
『 BOOL は int だって前回言ってたもんね。ウィンドウズから呼ばれるか
ら CALLBACK も付いてるし、引数も同じだし』
「ま、 BOOL が int と同じって言っても、 DialogProc() が返していいの
は一応 TRUE と FALSE だけ」
『ウィンドウプロシージャは好きな値を返せるってわけね』
「そゆこと。ダイアログプロシージャは簡単に使える分機能が少ない、って
ところかな」
『で……中身はどうなのかな』
「メッセージ関係はかなり違うから」
『げ、かなり違うの?』
「たとえば、ダイアログが最初に表示されるときに送られてくるメッセージ
ってあったでしょ」
『 WM_INITDIALOG だね。あ、 DIALOG って付いてるからこれはダイアログ
専用なんだ。ってことは WM_INITWINDOW とか?』
「そうじゃないんだよねー、ウィンドウの時は WM_CREATE ってメッセー
ジ」
『げ、全然違う!』
「前の章、 MFC の SDI アプリを作ったとき、 Version 9.03 ( No.164 )
で CMainFrame::OnCreate() でウィンドウの初期化をしてたでしょ」
『ツールバーとか作ってた時のね』
「そのメンバ関数を呼び出すメッセージ、 WM_CREATE が、ウィンドウが作
られるときに送られてくるメッセージ」
『ってことはつまり、同じようなイベントでも、メッセージが違うって事な
んだ。複雑〜』
「ま、同じものの方が多いけど、重要な部分で違うことが多いから、注意が
必要かな」
『ふーん』
「で、中身の話なんだけど、これは実際にプログラムが動くようになってか
ら触れることにします。
『はーい』
「……」
『……あと半分あるよ』
「……じゃあ、次回のコードを先に紹介しちゃいましょう。 WndProc() の
前にこの関数を追加して」
// メッセージループ。
int MessageLoop()
{
BOOL bRes;
MSG stMsg;
// メッセージループです。
while( 1 )
{
// メッセージをキューから取り出します。
bRes = GetMessage( &stMsg, NULL, 0, 0 );
if (
( bRes == 0 )
||
( bRes == -1 )
)
{
// 終了するのでループから抜けます。
break;
}
// メッセージを変換します。
TranslateMessage( &stMsg );
// ウィンドウプロシージャに送ります。
DispatchMessage( &stMsg );
}
return stMsg.wParam;
}
「で、 WinMain() を修正して」
// 最初に呼ばれる関数です。
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
const char pchWndClassName[] = "SimpleWindowClass";
bool bRes
= RegistWndClass( pchWndClassName, p_hInstance );
if( bRes == false )
{
return -1;
}
bRes
= CreateAndShowWnd
( pchWndClassName
, p_hInstance
, p_iCmdShow
);
if( bRes == false )
{
return -1;
}
// 以下の行だけ修正。
return MessageLoop();
}
『どこが違うの?』
「最後の1行だけ」
『あ、ここでさっきの関数を呼んでるわけね』
「その関数が、ダイアログプロシージャにはない、メッセージループってい
うもの」
『めっせーじるーぷ?』
「そう、メッセージのシステムの中でもかなり難しい、一番深い部分にある
機能。というわけで次回に続く!」
/*
Preview Next Story!
*/
『こ、コードばっか……』
「あとで全部まとめるから、今は我慢して」
『でもさ、こういうのだとつまみ食いできないよね』
「つまみ食い?」
『メルマガの』
「あー。まぁ、メルマガだからいいんじゃない?」
『テキトーねー』
「というわけで次回」
< Version 10.04 メッセージループ! >
『につづく!』
「あ、でも別に HTML 化の計画がなくなったわけじゃないんだけどね」
『でも、全然始まんないし……』