#pragma twice

KAB-studio > プログラミング > #pragma twice > 152 Version 8.10 コマンドと通知メッセージ

#pragma twice 152 Version 8.10 コマンドと通知メッセージ

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

 Version 8.10
コマンドと通知メッセージ

前回は、ボタンを押したらダイアログを閉じるようにしました
ボタン押したときのメッセージを受け取って、 EndDialog() で閉じるん
だよね。そう考えると簡単かも
それは簡単に考えてるから
どゆこと?
ダイアログのメッセージを受け取るダイアログプロシージャ。同じよう
に、ウィンドウはすべて、ウィンドウプロシージャを持ってます
ダイアログプロシージャはウィンドウプロシージャの一種なんだもんね
そうそう、だからダイアログもウィンドウプロシージャを持ってるって言
えるし、それにウィンドウは全部持ってるわけだから、たとえばボタンも
ウィンドウプロシージャを持ってるんだ
……不思議に思わない?
何が?
ボタンを押したときのメッセージって、ボタンが受け取るけど
あ! ってことはボタンのウィンドウプロシージャが受け取って、それっ
てダイアログのダイアログプロシージャが受け取らない……けど受け取って
るね
そう、この辺の仕組みをちゃんと把握しておくのが大事かな。まず、実際
にマウスを左クリックしたとかってメッセージについて
マウスを動かしたら WM_MOUSEMOVE みたいな?
そう、そんな感じのメッセージ。マウスの左クリック、ってメッセージは
なくて、左ボタンを押したときのメッセージとして WM_LBUTTONDOWN ってい
うのがあります
ほー、下げるのと上げるのとで別なのね。上げるのは WM_LBUTTONUP なん

ボタンが押されたとかは、実際にはマウスの左ボタンが上がった時だか

ボタン的には、 WM_LBUTTONUP がボタンが押されたって印なわけね
このメッセージについては、実際に Spy++ でボタンのメッセージを見て
いくと分かるから、一度してみて
 Spy++ については Version 5.28 ( No.093 ) を参照〜
というわけで、実際に〈ボタンで左クリックした〉ってメッセージはボタ
ンのウィンドウプロシージャが受け取ってます
つまりダイアログプロシージャが受け取ってないから、他の方法で受け取
らなきゃいけないわけね
そゆこと。そのための方法は3つあります
ひとつは、前回の WM_COMMAND ね
もう一度ダイアログプロシージャだけ見てみようか

// ダイアログプロシージャ。
BOOL CALLBACK DialogProc
    ( HWND p_hDlgWnd
    , UINT p_uiMessage
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    if( p_uiMessage == WM_COMMAND )
    {
        if( LOWORD( p_wParam ) == IDOK )
        {
            // OK ボタンが押されました。
            EndDialog( p_hDlgWnd, IDOK );
            return TRUE;
        }
        else if( LOWORD( p_wParam ) == IDCANCEL )
        {
            // キャンセルボタンが押されました。
            EndDialog( p_hDlgWnd, IDCANCEL );
            return TRUE;
        }
    }
    return FALSE;
}

ボタンが押されると WM_COMMAND ってメッセージが送られてきて、その
WPARAM の LOWORD に押されたボタンの ID が入ってるわけね
この WM_COMMAND は、ボタンを押したときだけじゃなく、メニューが選択
されたときや、アクセラレーターが実行されたときにも送られてきます
メニューはダイアログじゃないときの話よね。それはいいとして、アクセ
ラレーターって何?
アクセラレーターはリソース、あ、ダイアログとかアイコンとかのリソー
スって意味だけど、そのリソースのひとつ
ホントだ、【挿入】で Accelerator ってのがある
これを使うと、たとえば Ctrl+A とか押したときに、なんかのコマンドを
実行できるようになるんです
なんかのコマンド? あ、 WM_COMMAND が送られるってことね
そゆこと。でもこれってあんまり使わないかも
余計なことされるとイヤだし。カスタマイズできるんなら別だけど
それやるとかなり大変……と、話を戻して。この WM_COMMAND は便利だけ
ど、これだけだとちょっと問題があるんだよね
問題?
ダイアログコントロールの中では、ボタンしか使えない
使えない……
まぁ使えなくはないんだけど、たとえばエディットボックスだと……やっ
てみようか。エディットボックスを貼り付けて、その ID を IDC_E_TEST に
して
ぺたほい
ダイアログプロシージャはこう

BOOL CALLBACK DialogProc
    ( HWND p_hDlgWnd
    , UINT p_uiMessage
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    if( p_uiMessage == WM_COMMAND )
    {
        if( LOWORD( p_wParam ) == IDC_E_TEST )
        {
            OutputDebugString( "IDC_E_TEST\n" );
            return TRUE;
        }
    }
    return FALSE;
}

ボタンとほとんど同じね。ビルドして実行! うお、何やってもひっかか
る!
クリックしても、文字を入力しても、どんどん送られてきます。だから、
受け取ることはできるんだけど
なんで送られてきたかは分からないからどーしよーもないのね
いや、分かるんです
げ! そーゆーことは先に言ってよ
まぁまぁ。この〈どういう理由でコマンドが送られてきたのか〉は 
HIWORD( p_wParam ) に入ってます。たとえばこんな感じ

BOOL CALLBACK DialogProc
    ( HWND p_hDlgWnd
    , UINT p_uiMessage
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    if( p_uiMessage == WM_COMMAND )
    {
        if  (
                ( LOWORD( p_wParam ) == IDC_E_TEST )
            &&
                ( HIWORD( p_wParam ) == EN_UPDATE )
            )
        {
            OutputDebugString( "IDC_E_TEST, EN_UPDATE\n" );
            return TRUE;
        }
    }
    return FALSE;
}

まず WPARAM の下2バイトが IDC_E_TEST かどうかチェックして、そのあ
と上2バイトが EN_UPDATE かどうか調べてて、その時だけ入るようにして
るのね
実際に試してみて
ほい。お、今度は文字を入力した時だけ出るようになった。それが
EN_UPDATE なの? 確かにアップデートだし
それが WM_COMMAND が送られてきた〈理由〉。これを【通知コード】また
は【通知メッセージ】って言います
つうちめっせーじ?
そう、英語だと Notify Code または Notify Message 。一般的には
〈コード〉よりも〈メッセージ〉の方が使われてるかも
のてぃふぁいめっせーじね。カタカナより、通知メッセージの方が分かり
やすいかも。だって、その〈意味〉を通知するって意味なんでしょ?
うーん、ちょっと違うかも。通知コードはダイアログコントロールからダ
イアログに送られてくるときに渡されるものだから
コントロールからダイアログへの通知?
そっちの方が意味としては強いかな。通知メッセージはホントはメッセー
ジじゃなくて、上で見たように LPARAM に入ってます
だから通知コードって言うこともあるのね
でも通知コードって呼ばれてるのはあんまり聞かない……話を戻して、通
知メッセージは EN_UPDATE みたいに N が付いてます
 E が Edit の E 、 N が Notify の N ね
ちょっとメッセージを整理しておこうか。普通のメッセージは WM_ で始
まるよね
 WM_COMMAND とかね
通知メッセージは、たとえばエディットボックスだったら EN_ で、ボタ
ンだったら BN_ で始まります
そっか、それがわかればそれで検索すれば通知メッセージ一覧が出るね
そうそう、そうやって調べるといいかもね。たとえば MSDN の
Edit Control Messages ってページにはエディットボックス関連のメッセー
ジ一覧が載ってて
 EN_UPDATE とかもあるね。あれ?  EM_CANUNDO とかって何?  EM_ か
ら始まってる
これはエディットボックスに送るメッセージ。こういう、コントロールに
送るメッセージとかもあるんです。コントロールを操作するためにね
ボタンだったら BM_ なんだ。 M は Message の M ?
たぶん
コントロールまわりだと、全部で3つのメッセージがあるってことなの
ねー
まとめると

WM_ : 普通のメッセージ。ウィンドウプロシージャで受ける
*M_ : コントロールに送って操作する。 EM_ とか
*N_ : 通知メッセージ。コントロールから WM_COMMAND と一緒に来る

あ、最後のはちょっと違うかな
違う?
というわけで次回に続く!

/*
    Preview Next Story!
*/
メッセージひとつでも結構奥が深いよねー
でも次回は MFC の話
なんですとー!?
やっぱり、 MFC は便利だから
なら MFC だけにすればいいのに
ううん、っていうか、 MFC を参考に、 MFC を使わない方法を
勉強しようってことね
というわけで次回
< Version 8.11 ツリービューコントロールを作ろう! >
につづく!
 MFC は使わないに越したことないから……
でも MFC は便利なんでしょ?
便利なんだよね……
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。