#pragma twice

KAB-studio > プログラミング > #pragma twice > 191 Version 10.13 ポップアップメニューふたたび

#pragma twice 191 Version 10.13 ポップアップメニューふたたび

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

 Version 10.13
ポップアップメニューふたたび

「前回は」
『手抜きでした』
「……否定はしません。えーっと、前回の最後で触れたように、これから手
を加えるのはウィンドウプロシージャの関係だけ。他はほぼ固定かな」
『これだけの機能があればなんとかなるってことね』
「そういうこと。まぁうまくいかない部分があったら微調整は必要だけど、
でもそのくらいだから。で、今回はそのウィンドウプロシージャについて」

// ウィンドウプロシージャ。
LRESULT CALLBACK WndProc
    ( HWND p_hWnd
    , UINT p_uiMessage
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    if( p_uiMessage == WM_DESTROY )
    {
        // ×ボタンが押されました。
        PostQuitMessage( 0 );
        return 0;
    }
    else if( p_uiMessage == WM_COMMAND )
    {
        if( LOWORD( p_wParam ) == ID_MENU_TEST )
        {
            // ID_MENU_TEST メニュー。
            OutputDebugString( "ID_MENU_TEST : 終了します。\n" );
            PostQuitMessage( 0 );
            return 0;
        }
    }

    // 標準的な処理をします。
    return DefWindowProc( p_hWnd, p_uiMessage, p_wParam, p_lParam );
}

「今はこんな感じだけど、ホントは良くない例です」
『良くないの?』
「 MFC みたいに、それぞれのメッセージ毎に別の関数にするのが理想。た
とえばこういうふうに」

// ウィンドウが閉じます。
LRESULT OnDestroy()
{
    PostQuitMessage( 0 );
    return 0;
}


// ID_MENU_TEST が選択されました。
LRESULT OnMenuTest
    ( HWND p_hWnd
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    OutputDebugString( "ID_MENU_TEST : 終了します。\n" );
    PostQuitMessage( 0 );
    return 0;
}

// ウィンドウプロシージャ。
LRESULT CALLBACK WndProc
    ( HWND p_hWnd
    , UINT p_uiMessage
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    if( p_uiMessage == WM_DESTROY )
    {
        return OnDestroy();
    }
    else if( p_uiMessage == WM_COMMAND )
    {
        if( LOWORD( p_wParam ) == ID_MENU_TEST )
        {
            return OnMenuTest( p_hWnd, p_wParam, p_lParam );
        }
    }

    // 標準的な処理をします。
    return DefWindowProc( p_hWnd, p_uiMessage, p_wParam, p_lParam );
}

『つまりメッセージとか ID とかごとに別の関数呼ぶんだ』
「そのままウィンドウプロシージャに書いちゃうと、ウィンドウプロシー
ジャがどんどん長くなっちゃうからね」
『質問!』
「はい火美ちゃん」
『 MSDN 見てるとそういうながーいウィンドウプロシージャがいっぱいある
んですけど』
「全部悪い例です」
『……ホントに悪いの?』
「断言はできないけど、でも悪いと思うよ。ひとつの関数が大きくなるとプ
ログラムが見にくくなるから。特にネストが深くなって右へ右へとずれてい
くと……」
『あー、それはちょっとヤダ』
「まぁ、普通の関数と違うから微妙な部分もあるんだけど、でもやっぱりし
ない方がいいと思うよ」
『もひとつ質問!』
「はい火美ちゃん」
『 OnMenuTest() の引数がいっぱいあるのはなんで? 使ってないのに』
「これは微妙かな。あとで ID_MENU_TEST の処理で LPARAM とかが必要にな
る可能性があるかもしれないから、とか」
『つまりあとの拡張性のため?』
「ひとつはね。あと、こういうふうに引数付きのを用意しておいて、同じ 
WM_COMMAND 用関数が必要になったらコピペするとか」
『使い回し用かー、確かにメニューが増えたらこの関数もいっぱい作る、な
ら引数付きのを用意しておいてコピペしまくり、の方が楽ね』
「でも必要ない引数を渡すっていうのも良くない気もするし、微妙かもね。
さて、今回は Version 9.05 ( No.166 ) で使ったポップアップメニューと
同じものを作ってみます」
『右クリックメニューでってゆーのね』
「さて問題。右クリックしたときに送られてくるメッセージは?」
『 WM_RBUTTONUP !』
「……さらっと出てきたね」
『だってその号に書いてあるもん』
「あ、ホントだ。というわけで、このメッセージが送られてきた時の関数を
まず追加します」

// 右クリックされました。
LRESULT OnRButtonUp
    ( HWND p_hWnd
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    OutputDebugString( "右クリックされました。\n" );
    return 0;
}

// ウィンドウプロシージャ。
LRESULT CALLBACK WndProc
    ( HWND p_hWnd
    , UINT p_uiMessage
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    if( p_uiMessage == WM_DESTROY )
    {
        return OnDestroy();
    }
    if( p_uiMessage == WM_RBUTTONUP )
    {
        return OnRButtonUp( p_hWnd, p_wParam, p_lParam );
    }
    else if( p_uiMessage == WM_COMMAND )
    {
        if( LOWORD( p_wParam ) == ID_MENU_TEST )
        {
            return OnMenuTest( p_hWnd, p_wParam, p_lParam );
        }
    }

    // 標準的な処理をします。
    return DefWindowProc( p_hWnd, p_uiMessage, p_wParam, p_lParam );
}

『ビルドして実行、右クリックっと。うん、〈右クリックされました。〉っ
て出た』
「では次に、この関数の中にポップアップメニューを表示する機能を追加し
ます」

// 右クリックされました。
LRESULT OnRButtonUp
    ( HWND p_hWnd
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    // 画面上のマウスカーソルの位置を取得します。
    POINT stPoint;
    GetCursorPos( &stPoint );
    // メニューバーを読み込みます。
    HMENU hMenuBar
         = LoadMenu
            ( GetModuleHandle( NULL )
            , MAKEINTRESOURCE( IDM_MAIN )
            );
    // サブメニューを取得します。
    HMENU hSubMenu
        = GetSubMenu( hMenuBar, 0 );
    // ポップアップメニューを表示します。
    TrackPopupMenu
        ( hSubMenu
        , TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON
        , stPoint.x
        , stPoint.y
        , 0
        , p_hWnd
        , NULL
        );

    return 0;
}

『結構長い……』
「では次回に続きます」
『え”』

/*
    Preview Next Story!
*/
『さくっと続くね』
「ホントは1回でまとめたいんだけどね」
『そういえば、毎週違う話って感じだよね』
「ひとつのことをずーっとやっても仕方ないし」
『そーゆーもん?』
「その方が詰まらないし」
『そんなんでいいのかな……』
「というわけで次回」
< Version 10.14 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のトップページをご覧ください。