#pragma twice

KAB-studio > プログラミング > #pragma twice > 165 Version 9.04 メニューの構造

#pragma twice 165 Version 9.04 メニューの構造

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

 Version 9.04
メニューの構造

前回はメニューにアイテムを追加してみました
でも、追加したのってメニューバーにだよね。なんか違うよーな
だね、だから今回は【ファイル】サブメニューの中に追加してみます
って感じに別にするってことは、ちょっと難しいってこと?
っていうよりはちょっと複雑ってくらい。ま、まずはコードから

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// 略。

    // メニューバーを取得します。
    CMenu *pcMenuBar = GetMenu();
    // 【ファイル】サブメニューを取得します。
    CMenu *pcFileMenu = pcMenuBar->GetSubMenu( 0 );
    // メニューアイテムをインサートします。
    pcFileMenu->InsertMenu
        ( -1
        , MF_BYPOSITION | MF_STRING
        , ID_FILE_OPEN
        , "ファイルを開く(&O)"
        );

    return 0;
}

あんま違わないね
だね、一番の違いは

    // 【ファイル】サブメニューを取得します。
    CMenu *pcFileMenu = pcMenuBar->GetSubMenu( 0 );

の行が追加されてること
わざわざそんなことしてる理由は?
最初に CWnd::GetMenu() で取得したメニュー
 pcMenuBar ね
これは、メニューバーだけ。つまり【ファイル】サブメニューや【編集】
サブメニューは含まれてません
横一列だけってことね
だから、このメニューバーから【ファイル】サブメニューを取得する必要
があるんです
それが CMenu::GetSubMenu() なわけね。 0 は最初の、つまり【ファイ
ル】サブメニューのってこと?
そゆこと。それで取得した pcFileMenu が【ファイル】サブメニュー一列

一列分……そっか、 CMenu はメニューバーもポップアップメニューも、
一列ずつだけなんだ
そう、だからもし【ファイル】サブメニューにさらにサブメニューがあっ
たら
 CMenu::GetSubMenu() でその位置を指定して、また CMenu のポインタ受
け取って、ってなるわけね
そういう仕組みになってるから、 CMenu::GetSubMenu() や 
CMenu::InsertMenu() で位置を指定するのが簡単になってるかな。メニュー
全体だと
かなり大変そうね。そういえば、次の CMenu::InsertMenu() のとこも

    pcFileMenu->InsertMenu

って、その pcFileMenu になってるね
アイテムを追加したいサブメニューで CMenu::InsertMenu() を呼べば
そのサブメニューに追加されるわけね
ちなみに CMenu::InsertMenu() の第1引数に -1 を渡してるから
ホントだ。 -1 だと最後に追加なんだよね。あ、ビルドして実行っと。う
ん、最後に追加されてる
こんな感じに、メニューは一列ごとに管理されてるってことを解ってもら
えればいいかな
これって、 CMenu のじゃないんだよね
そう、 MFC のじゃなくて、ウィンドウズのシステムとしてそうなってる
から。だから HMENU を直接使ってもこうなるからね
その辺はいつものパターンね
さて、今のをもう少し理解してもらうために、今度はメニューを作ってみ
ます
メニューを作る!

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// 略。

    // 新しくサブメニューを作成します。
    CMenu cNewSubMenu;
    cNewSubMenu.CreatePopupMenu();
    cNewSubMenu.InsertMenu
        ( -1
        , MF_BYPOSITION | MF_STRING
        , ID_FILE_OPEN
        , "ファイルを開く(&O)"
        );

    // メニューバーを取得します。
    CMenu *pcMenuBar = GetMenu();
    pcMenuBar->InsertMenu
        ( -1
        , MF_BYPOSITION | MF_STRING | MF_POPUP
        , (UINT)( cNewSubMenu.GetSafeHmenu() )
        , "新規サブメニュー (&N)"
        );

    // CMenu の管理から解放します。
    cNewSubMenu.Detach();

    return 0;
}

って、さっきとあんまり違わないね。えっと、まず最初に……今度はポイ
ンタじゃない CMenu を作ってるね
元々あるメニューじゃない、新しいメニューを作るからね
で、 CMenu::CreatePopupMenu() 、これでメニューを作ってるんだ
あ、そうそう、 CMenu のメンバ関数一覧って見てみて
ほい。あ、 CMenu::CreateMenu() ってのもあるなんで Create なのがふ
たつもあんの?
それは

CreateMenu()      : メニューバーを作る
CreatePopupMenu() : ポップアップメニュー(サブメニュー)を作る

ってこと
なるほど、メニューバーとポップアップメニューは作り方も違うんだ
この辺も別物ってことだね。そのあと、いつもの CMenu::InsertMenu() 
でメニューアイテムを追加します
この辺は同じね
で、この時点ではこのポップアップメニューはまだ表示されないから、こ
れをメニューのサブメニューとしてくっつける必要があります
それがそのあとのところね。えっと、次の CWnd::GetMenu() でメニュー
バー拾って、そのあとの

    pcMenuBar->InsertMenu
        ( -1
        , MF_BYPOSITION | MF_STRING | MF_POPUP
        , (UINT)( cNewSubMenu.GetSafeHmenu() )
        , "新規サブメニュー (&N)"
        );

 MF_POPUP ってフラグ、ポップアップメニューってこと?
そゆこと。この CMenu::InsertMenu() で、次のサブメニューを表示させ
るメニューアイテムを追加してます
サブメニューを追加するんじゃなくて、メニューアイテムを追加す
る……
 Version 9.02 ( No.163 ) の【ポップアップ】がオンになったメニュー
アイテムを追加するってこと。で、第3引数で
さっき作ったメニューのハンドル渡してるんだね
普段は ID を渡すんだけど、サブメニューをくっつける場合にはここにそ
のメニューハンドルを渡します
なんかキャストしてるしちょっとヤな感じ……
確かにね。 CMenu のポインタを渡せるようにしてくれるとよかったんだ
けど
で……えーっとまとめると、メニューバーの最後にアイテムを追加して、
そのアイテムは【ポップアップ】で、そこにさっき作ったポップメニューを
くっつけるために、そのメニューのハンドルを渡してるわけね
ちょっと混乱するかもね
まー慣れれば大丈夫かな。と、最後の

    // CMenu の管理から解放します。
    cNewSubMenu.Detach();

ってなに?
あ、その前にビルドして実行してみて
ほい。うん、メニューバーの最後に【新規サブメニュー】が追加されて、
それを選ぶと……おお、ちゃんと新しく作ったサブメニューが! アイテム
ひとつだから見栄え悪いけど
これが普通の動作。で、上の CMenu::Detach() 呼んでるところをコメン
トアウトすると
ビルドして実行。あら、選んだらエラーになっちゃった
これは、せっかく作ってくっつけたポップアップメニューが削除されてる
から
あ! そうよ! だって cNewSubMenu ってポインタじゃないじゃん、消
えるときに持ってるメニュー消しちゃうじゃない
そう、だから
 CMenu::Detach() 呼んで、消さないようにしてるわけね。でも……なん
か変くない?
だね、普通はこの cNewSubMenu を CMainFrame のメンバ変数にするだろ
うし
それならずっとあるから大丈夫なわけね
まぁ僕なら CMenu 使わないけど
 HMENU 直接なら、削除される心配もないわけね
必要な時に GetMenu() とかでいつでも取得できるしね。最後に、さっき
言ったメニューバーとポップアップメニューの違いを見ておこうか

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// 略。

    // 新しくサブメニューを作成します。
    CMenu cNewSubMenu;
    cNewSubMenu.CreatePopupMenu();
    cNewSubMenu.InsertMenu
        ( -1
        , MF_BYPOSITION | MF_STRING
        , ID_FILE_OPEN
        , "ファイルを開く(&O)"
        );

    // メニューバーにくっつけます
    SetMenu( &cNewSubMenu );

    // CMenu の管理から解放します。
    cNewSubMenu.Detach();

    return 0;
}

メニューバーにメニューをセットするときは CWnd::SetMenu() を使いま
す。すると
げ、メニューバーが変! また透けてるみたい! しかも固まってるし
というわけで使えなくなります。ちなみに CreatePopupMenu() のところ
を CreateMenu() に変えれば
あ、今度は大丈夫
というわけ。もちろん、今度はポップアップメニューとしては使えないけ
どね

/*
    Preview Next Story!
*/
ポップアップメニューとメニューバー、ねぇ
でも聞けばそんなに難しくないでしょ
訊けばね
でもここからは聞いてもちょっと複雑かも
げげ
というわけで次回
< Version 9.05 右クリックメニューを表示する! >
につづく!
でも右クリックメニュー自体は結構面白いかもね
じゃーその面白いとこだけする!
じゃあプログラミングする意味ないじゃない
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。