#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のトップページをご覧ください。