#pragma twice

KAB-studio > プログラミング > #pragma twice > 092 Version 5.27 メッセージを送ろう!

#pragma twice 092 Version 5.27 メッセージを送ろう!

前のページへ 表紙・目次へ 次のページへ

 Version 5.27
メッセージを送ろう!

この前は MFC と API 使って、コントロールのハンドルをゲットして操作
したんだよね
そして、今回は MFC を使わずにやってみましょう! じゃ、前回やった
ボタンの文字列を書き換える例から

// いつもの。
void CFileTestDlg::OnBtnShow() 
{
    HWND hBtnWnd
         = ::GetDlgItem( GetSafeHwnd(), IDC_BTN_SHOW );
    ::SetWindowText( hBtnWnd, "あいうえお" );
    return;
//  後は取っておきましょう。

……すっげー簡単じゃん
これは肩慣らしだからね
げ、そうなんだ。えーっとまず、前回も使った GetDlgItem() で
IDC_BTN_SHOW ボタンのウィンドウハンドルをゲットして、それを HWND 型
変数に格納っ
次の行もこの前の API 版
 CWnd::SetWindowText() じゃなくて、今回は API の SetWindowText() 
ね。ビルドして実行、ボタンが〈あいうえお〉になった!
とういうわけで、 API の操作はこれが基本。じゃ、次に、前回の最初に
やったリストボックスの操作をしましょう
はーい!

// いつもの。
void CFileTestDlg::OnBtnShow() 
{
    HWND hLstWnd
         = ::GetDlgItem( GetSafeHwnd(), IDC_LST_DATA );
    ::SendMessage( hLstWnd, LB_ADDSTRING, 0, (LPARAM)"あいうえお" );
    return;
//  後は取っておきましょう。

なんだ、初見の API ひとつ増えただけじゃん
最初の行はさっきと同じ
 IDC_LST_DATA リストボックスのウィンドウハンドルをゲットして、それ
を次の SendMessage() っていう API で使ってるんだよね
とりあえず動作確認
ビルドして実行! うん、ちゃんとリストボックスに〈あいうえお〉って
出たよ。つまりこの SendMessage() っていうのが追加してくれてるんで
しょ?
もちろんそれはそう。でもどうやって追加してると思う?
んー、えっと、第1引数が追加先のウィンドウハンドルでしょ、第2引数、
CListBox::AddString() に似てるから、なんかこれが〈追加っ!〉ってこと
なのかな。あと第4引数が追加する文字列。 LPARAM っていうのにキャスト
してるけど
じゃ、 MSDN の LB_ADDSTRING のページを見てみて
ほい。……日本語のページ出ないよ?
そう、日本語のページはないんです
なんで?
メッセージには日本語のリファレンスがないんです
メッセージ?
そう。〈キーワード〉欄に LB_ っていうのがいっぱいあるでしょ。これ
全部メッセージ
うわいっぱい!
メッセージは、ウィンドウを操作するために、ウィンドウに送るもの
あ、だから LB_ADDSTRING を SendMessage() で送ると、リストボックス
に追加できたんだ!
そういうこと。本来は、ウィンドウやコントロールを操作するためにはこ
のメッセージを送る必要があります
本来? ……そっか、 MFC もこのメッセージっていうの送ってるんだ!
そういうこと
ってことは…… CListBox のメンバ関数、このメッセージって言うのと似
たのばっかり
 CListBox::GetCount() は LB_GETCOUNT 、CListBox::GetTopIndex() は
LB_GETTOPINDEX 
だから
ちょっと待って! えっと、この前の……

// いつものメンバ関数。
void CFileTestDlg::OnBtnShow() 
{
    CListBox *pcListBox
        = (CListBox *)GetDlgItem( IDC_LST_DATA );
    pcListBox->AddString( "あいうえお" );
    return;
//  あとは取っておきましょう。

前回最初のプログラムだね
 AddString() してるとこにブレークポイント置いて、ビルドして実行、
ステップイン……ホントだ、 CListBox::AddString() の中で 
::SendMessage() で LB_ADDSTRING 送ってる!
それだけじゃなくて
ほ、他の CListBox のメンバ関数も LB_ なメッセージ送ってる!
これで、コントロールをどうやって操作していたか分かった?
うん、分かった。でも結構簡単だよね
操作するっていう部分だけならね
どゆこと?
それはあとのお楽しみ。もう少し SendMessage() について見ておこうか
はーい

    ::SendMessage( hLstWnd, LB_ADDSTRING, 0, (LPARAM)"あいうえお" );

 SendMessage() の宣言部も書いておこうか

LRESULT SendMessage(
    HWND hWnd, 
    UINT Msg, 
    WPARAM wParam, 
    LPARAM lParam 
);

第1引数はリストボックスのウィンドウハンドルだね
この第1引数のウィンドウにメッセージを送ります
第2引数はメッセージだよね。あ、 UINT ってことは unsigned int なん

 API は整数値でほとんど間に合わせてるから。ウィンドウスタイルや、
コントロールの ID もそうだったでしょ
メッセージもどっかで #define とか const int とかされてるの?
されてるよ、 winuser.h とかで。 #define だね
第3引数は使わないみたいだけど、じゃーなんで第3引数あるの?
それは、第3引数と第4引数はメッセージによって使い道が違うから
違うってどういうこと?
 WPARAM は unsigned int 、 LPARAM は long 、つまりどっちも
32ビット整数値の符号なしとありね
で、この32ビットサイズに収まるものならなんでも渡しちゃおう、って
いうのがメッセージの考え方
……つまりそれは、整数値も送るし、文字列ポインタも送る、ってことな
のね。なんかそれって危なくない?
危ないよ。メッセージを取り間違えて、キャストし間違えたらアウトだか
らね
なんでそんな危険なことすんの?
そりゃ、メッセージっていうシステムひとつで、いろんなことをできるよ
うになってるからね
うん、確かに、 LB_ なメッセージ、いろんなの送れて、いろんなことで
きるっていうのは分かるんだけど、わざわざそんなことしなくていーじゃん。
関数にしちゃえばいいのに
あ、そっか、これは受け取る側のことを知らないと……
受け取る?
 LB_ADDSTRING を送ったらリストボックスに文字列が追加される、ってい
うのももちろんプログラムとして作られてるんだけど
うん
そのプログラムの中では、送られてきたメッセージをそのまま受け取って
るんです
そのまま受け取る?
 MSDN で WindowProc() っていう API のリファレンスを開いて
ほい

LRESULT CALLBACK WindowProc(
    HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
);

あ、 SendMessage() と同じだ!
これを〈ウィンドウプロシージャ〉って言います
うぃんどうぷろしーじゃ?
ウィンドウはこのウィンドウプロシージャを持ってて、メッセージが送ら
れてくるとこの関数が呼ばれて、引数がそのまま渡されるんです
ウィンドウはって、じゃあこのダイアログとかも?
もちろん、今プログラムしてる FileTest もね。簡単に見ておこうか。
CFileTestDlg::OnBtnShow() の中でブレークポイントをセットして
さっき AddString() にセットしてたからそれでいーや
実行して止まったら、メニューの【表示】−【デバッグウィンドウ】
−【コールスタック】を選んで
あ、初めてのだ
コールスタックは、今実行してる関数を呼んだ関数、さらにその関数を呼
んだ関数、っていうふうに関数をさかのぼって見ることができるもの

CFileTestDlg::OnBtnShow() line 186
_AfxDispatchCmdMsg() line 88
(略。あと小カッコの中身も略)
AfxWndProc() line 368
AfxWndProcBase() line 220 + 21 bytes
KERNEL32! bff7363b()
KERNEL32! bff94497()

うわー、 CFileTestDlg::OnBtnShow() までにこんなにいっぱい関数が呼
ばれてるんだ
下から3行目の AfxWndProcBase() をダブルクリックして
その関数が見られるんだね

AfxWndProcBase(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)

あああっ、その WindowProc() っていうのと引数が同じだ!
メッセージが送られてくるとこの関数が呼ばれて、各引数がそのまま渡さ
れます
つまり、メッセージが送られてきたのをこの関数で受け取るのね
こういう、たったひとつの関数で受け取る仕組みになってるから、いろん
な引数は使えないわけ
その代わり、 WPARAM と LPARAM にいろんな型を詰め込むのね
そういうこと。でもこれじゃ不便だから、メッセージに合わせて引数を変
更して、最終的に CFileTestDlg::OnBtnShow() が呼ばれる、みたいな仕組
みを MFC が持ってるってわけ
なるほど。……ちょっと待った!! って事はつまり、ボタン押したって
ことそのものもメッセージだってゆーの!?
というわけで次回に続く!

/*
    Preview Next Story!
*/
楽しいけど、怖いよね
なにいきなり
プログラムの仕組みとか分かってくると、なんか怖いかも
確かに、なんかタブーに触れてるって感じはあるかな
というわけで次回
< Version 5.28 イベント=メッセージ >
につづく!
たとえるなら、初めて〈つゆだく〉を頼んだ時の感覚?
っておまえ食ったんかい!
はぁ〜い
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。