#pragma twice

KAB-studio > プログラミング > #pragma twice > 166 Version 9.05 右クリックメニューを表示する!

#pragma twice 166 Version 9.05 右クリックメニューを表示する!

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

 Version 9.05
右クリックメニューを表示する!

今回は右クリックメニューを表示してみます
おおっ! なんか実用的って感じ
確かに右クリックメニューは便利だからできとくといいかな。じゃ、実際
にしてみましょう。まずは、〈右クリック〉ってイベントを受け取ってみま

やっぱ、メッセージとかイベントハンドラとかそういうとこ?
そういうとこ。まず ClassWizard を開いて
ほい。メッセージ関係だから【メッセージマップ】でいいんだよね
そう、そのページ。まず【クラス名】が CSdiTestView になってることを
確認して
うん、なってる
これがまず重要。えーっとまず、右クリックとかのメッセージを受け取る
のはウィンドウでしょ。だから、ウィンドウのクラスじゃないとまずダメ
ってことは、今回のプロジェクトだと CMainFrame も入るわけね
そう、だからどっちでもイベントハンドラを作れるんだけど、今回の右ク
リックは CSdiTestView の方だけ。なんででしょう
んー……ビューウィンドウがフレームウィンドウの上に乗ってるってゆー
あれのこと?
そうそうそう。 Version 9.01 ( No.162 )でやったように、フレームウィ
ンドウのビューウィンドウが乗ってます。右クリックすると、ビューウィン
ドウにだけメッセージが送られます
フレームウィンドウはビューウィンドウに隠れてるから送られないわけ

だからこういう類のメッセージは必ず CSdiTestView にイベントハンドラ
を作る必要があります
右クリックのね
そう。正確には……えっと、オブジェクト ID を CSdiTestView に、メッ
セージを WM_RBUTTONUP にして【関数の追加】ボタンを押して
 WM_RBUTTONUP ってメッセージ……あれ? これってヂヅラどーりに読む
と、右のボタンが上がった時だよね。押した時じゃないの?
押したときのは WM_RBUTTONDOWN だけど、そっちじゃなくて UP の方。
っていうのも、ボタンなんかも全部マウスのボタンを離したときに反応する
ようになってるから
あ! ホントだ、ボタンもメニューも、上げたときだ! 気付かなかっ
た……
理由は、たぶんだけど、押してから〈あ、間違えた〉って時には全然違う
ところで離せば押したことにしないですむから
よーするにキャンセルできるってことね
そういうこと。だから WM_RBUTTONUP のイベントハンドラを作ります
と、【関数の追加】ボタン押したからもうできてるんだ。【コードの編集
】押してと

void CSdiTestView::OnRButtonUp(UINT nFlags, CPoint point) 
{
    
    CView::OnRButtonUp(nFlags, point);
}

ってメンバ関数ができたよ。ちゃんと CSdiTestView のメンバ関数だね
一応 TRACE() でも書いて、右クリックでちゃんとこれが呼ばれるって確
認しておいて
ほいほい。ちゃーんと右ボタンを離した時に呼ばれるねー。メッセージっ
思いのほか細かいもんなんだね……
さて、ここに右クリックメニューを表示させるコードを追加します
おー
まずはコードを見てもらいましょう

void CSdiTestView::OnRButtonUp(UINT nFlags, CPoint point) 
{
    // 画面上のマウスカーソルの位置を取得します。
    CPoint cPoint;
    GetCursorPos( &cPoint );
    // フレームウィンドウのポインタを取得します。
    CWnd *pcMainFrameWnd
        = AfxGetMainWnd();
    // メニューバーを取得します。
    CMenu *pcMenuBar
         = pcMainFrameWnd->GetMenu();
    // ファイルサブメニューを取得します。
    CMenu *pcFileMenu
        = pcMenuBar->GetSubMenu( 0 );
    // ポップアップメニューを表示します。
    pcFileMenu->TrackPopupMenu
        ( TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON
        , cPoint.x
        , cPoint.y
        , pcMainFrameWnd
        );

    CView::OnRButtonUp(nFlags, point);
}

……短いけど、なんか初めて見るのばっかってゆーか、なんかややこしそ
うってゆーか
ややこしいのはかなりだから覚悟して
げげ
じゃ、ひとつずつ見ていきます

    // 画面上のマウスカーソルの位置を取得します。
    CPoint cPoint;
    GetCursorPos( &cPoint );

 GetCursorPos() は、マウスカーソルのある位置を取得する API です
メンバ関数じゃないのね。あれ? このメンバ関数に CPoint point って
あるけど、これは使えないの?
うん、これじゃダメ。これはビューウィンドウの中でのマウスの位置が
入ってるんだけど、必要なのは画面上の位置だから
クライアント領域の位置みたいなもんね
そゆこと。ポップアップメニューを表示するには TrackPopupMenu() って
いうのを使うんだけど、そのとき渡すのは画面上の位置じゃないといけない
から
じゃ、次

    // フレームウィンドウのポインタを取得します。
    CWnd *pcMainFrameWnd
        = AfxGetMainWnd();

これが謎
フレームウィンドウは分かるよね
ビューウィンドウが乗っかってるのがフレームウィンドウだよね
そのフレームウィンドウへのポインタ、つまり CMainFrame のポインタを
取得するのが AfxGetMainWnd() っていう MFC の関数
その辺がよく分かんないのよねー
前回の CMainFrame::OnCreate() の中での this ポインタとアドレスは同
じになる……んだけど
確かに TRACE() とかで見るとそうだね
ま、その辺はもっと MFC の構造が分からないとどうしようもないから、
あとで
このフレームウィンドウへのポインタは何に使うの?
それは、まず次の行で

    // メニューバーを取得します。
    CMenu *pcMenuBar
         = pcMainFrameWnd->GetMenu();

さっそくフレームウィンドウのポインタを使って…… GetMenu() はいつ
ものメニューバーを取るのだね。あ、そっか! メニューバーはフレーム
ウィンドウに着いてるから
そういうこと。いつものように普通に GetMenu() を呼ぶと、ビューウィ
ンドウのメニューバーを取得しようとするんだけど
そんなもの着いてないからダメなんだ。なるほどねー
後ろにあるフレームウィンドウと、ただの白い四角のビューウィンドウ、
その違いをしっかり理解してないとこういうのは難しいかもね
ってゆーか、こういうコードを見ると分かるってゆーか
それはあるかもね。次は

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

これは前回使ったサブメニューを取得するのだね
実は、右クリックメニューはポップアップメニュー専用。メニューバーは
表示できないんです
ここでもメニューバーとポップアップメニューが違うのね
だからここでサブメニュー、つまりポップアップメニューを取得して、そ
れを右クリックメニューとして表示します。それが

    // ポップアップメニューを表示します。
    pcFileMenu->TrackPopupMenu
        ( TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON
        , cPoint.x
        , cPoint.y
        , pcMainFrameWnd
        );

です
この TrackPopupMenu() ってメンバ関数で右クリックメニューを表示する
のね
これは CWnd のメンバ関数だけど、 API も同名のがあるからね
えっと

        ( TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON

はフラグだね
最初のふたつはメニューをどの辺に表示するか
リファレンス読むと、縦と横があるみたいね。やっぱ一般的なのは、マウ
スカーソルの右下に出すってゆーの?
たぶんね。まぁ使いやすさは場合によって違うかもしれないけど
 TPM_LEFTBUTTON は……何?
これは、表示した右クリックメニューを左クリックで選べる、っていうの
……それって当たり前じゃないの?
だね、だからこれは必ず入れなきゃダメかな。 TPM_RIGHTBUTTON は微妙
だけど
右クリックのもあるんだ
これはアプリによって違うみたいだね。僕は、右クリックメニューだから
右ボタンで選べるようにすると
便利
じゃなくて、間違えて押しちゃいそうかなって思うから TPM_RIGHTBUTTON 
は含めないけど
その辺は人それぞれって感じね。次の

        , cPoint.x
        , cPoint.y

はさっき取ったマウスカーソルの位置ね
この位置に右クリックメニューを表示します。最後に

        , pcMainFrameWnd

あ、またフレームウィンドウのポインタが出てきた
右クリックメニューをの項目、たとえば【ファイルを開く】を選ぶと、そ
の選んだってメッセージが送られるんだけど、その送り先のウィンドウをこ
の第4引数で指定します
ここではフレームウィンドウにしてるわけね
ここで this を渡すと、このメンバ関数は CSdiTestView のメンバ関数だ
からビューウィンドウにメッセージが送られます
それじゃいけないってこと?
少なくともこの右クリックメニューはね。【ファイルを開く】とかのイベ
ントハンドラはフレームウィンドウにしかないから
というわけでビルドして実行! おー、右クリックメニューでファイルメ
ニューが!【ファイルを開く】でファイルダイアログが! 結構すごい!

/*
    Preview Next Story!
*/
フレームウィンドウとビューウィンドウの関係は解るけど
解るけど?
ポインタとか出てくると解んない
実際に変数を作ってる所を見ると解るんだけどね
それはそれで難しそうね
でも MFC は使うだけでも結構複雑なのあるよー
げげ
というわけで次回
< Version 9.06 メニューアイテムのハンドラを作る! >
につづく!
次回は難しいもののひとつ、許可・不許可の選択とかもあります
うー難しいのやだー
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。