スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

コンテキストメニュー事前調査・その2

今日はIContextMenu::QueryContextMenuについて調べたことを書きます。

HRESULT QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);

hmenuはコンテキストメニューのハンドルですので説明不要でしょう。indexMenuはコンテキストメニューハンドラがメニューを追加すべき位置を示します。従ってハンドラは、通常はこの引数を使用して、InsertMenuまたはInsertMenuItemをMF_BYPOSITIONで呼び出してアイテムを追加することになると思われます。私の開発環境であるXPでは、調査したところこの値には0が渡されており、QueryContextMenuが呼び出された時点でメニューには21個のアイテムが存在していました。ここから分かることは、(※少なくともXPにおいては)コンテキストメニューは下のグループから順に形成されてきている可能性が高いということです。QueryContextMenu呼び出し時点でログに書き出されたメニューアイテムは以下の通りです。

fType=2048
placeholder:31227
fType=2048
送る(&N):31004
placeholder:31227
fType=2048
切り取り(&T):31001
コピー(&C):31002
fType=2048
ショートカットの作成(&S):30993
削除(&D):30994
名前の変更(&M):30995
fType=2048
fType=2048
placeholder:31227
fType=2048
プロパティ(&R):30996
fType=2048
placeholder:31227
fType=2048
placeholder:31227

fType=2048はMF_SEPARATORです。fTypeがMFT_STRINGの場合には、アイテムの文字列とIDを書き出しています。最初、あれ?と思ったのは「placeholder」なる文字列です。実際にコンテキストメニューが表示されたときには、その位置には何も無さそうです。以下がInvokeCommandが呼び出された時点でのメニュー内容です。

開く(&O):31089
印刷(&P):31090
編集(&E):31093
WZ:31094
fType=2048
個別に書庫を作成(&K):31086
書庫を作成(&A):31087
fType=2048
分割する(&V):31088
fType=2048
プログラムから開く(&H):31077
fType=2048
お忍びツール。(&N):31072
fType=2048
テスト:28378275
テスト3:31071
fType=2048
送る(&N):31004
fType=2048
切り取り(&T):31001
コピー(&C):31002
fType=2048
ショートカットの作成(&S):30993
削除(&D):30994
名前の変更(&M):30995
fType=2048
プロパティ(&R):30996

「お忍びツール。」は現在稼働中のVer.1.0.0のもので、「テスト」と「テスト3」が現在テストで追加しているメニューです。ちなみに「テスト」はポップアップメニューです。どうやら「placeholder」なるものが最初に確保されてはいるものの、最後には消されていると考えて良いでしょうか?

次にidCmdFirstとidCmdLastです。ログを見るとidCmdFirst=31069、idCmdLast=31226の値が渡されています。これは、このコンテキストメニューに追加するアイテムが使用できるIDの最小値と最大値になります。(なんだか使用できる範囲が少ない感じがしますね。)「テスト」には2つのアイテムが含まれ、31069、31070を使用しており、「テスト3」の31071を合わせると3つのIDを使用していることになります。IDを見る限りでは、このテスト用のコンテキストメニューハンドラの次に、現役の「お忍びツール。」が呼び出されているようです。「お忍びツール。」は、ポップアップメニューであるため、それ自体は選択できませんのでIDを割り当てる必要は無さそうですが、以前は割り当てていたことが判明しました。あまりメニューについて詳しくないので、今回は別のテストプログラムでメニューについても試しながら、分かったことをこちらにも反映させています。

uFlagsは、まだ詳しく調べていないので飛ばします。

戻り値は、今回調べるまで私の頭の中でハッキリしてなかったんですが、基本はハンドラで追加したアイテムの内、最大のID-idCmdFirst+1を返せば良いようです。(Windows95ユーザーインターフェイスプログラミングでは追加したアイテム個数を返している。)具体的には、上のケースですと最大のIDが31071、idCmdFirstが31069ですので、31071-31069+1=3ということになるでしょうか。正確にはMAKE_HRESULTを使って、シビリティコードをSEVERITY_SUCCESSとして返すのが行儀が良さそうです。
なぜ単純に追加した個数でないのか疑問に思いますが、おそらく個々のハンドラが使用するアイテムのIDのオフセットが固定されていることが想定されているのだと思われます。たとえば、「お忍びツール。」の場合ですと

フルパスをコピー
場所をコピー
ファイル名をコピー

の3つがありますが、上から順にオフセットを0、1、2と割り当てます。実際にアイテムを追加する際には、idCmdFirstにこのオフセットを足したものを使用します。アイテムが選択されたときに呼び出されるInvokeCommandでは、選択されたアイテムのIDそのものではなくオフセットが取得できるようになっていますので、ハンドラは自分で追加したアイテム毎のIDを記憶しておく必要が無いわけです。(例えば2が渡されれば「ファイル名をコピー」と分かる。)このような単純なケースにおいては、依然として個数の方がシンプルな感じがしますが、ハンドラにオプション設定があって、メニューに表示するアイテムを選択できるような場合ですと事情が変わってきます。例えば「場所をコピー」を表示しない設定にした場合、使用されるオフセットは0と2になり、戻り値は3を返すべきですが個数は2になります。オフセットを固定せずにフルパスをコピーのオフセットを0、ファイル名をコピーを1にすれば、個数で返しても同じ結果になりますが、InvokeCommandにおいて渡されるオフセットに対応するアイテムがどれなのかを判断することが、固定オフセットに比べて少し複雑になりそうです。

さて、最初にコンテキストメニューハンドラを作成したのが、おそらく10年くらい前になるんですが、今だに分かっていないことがあります。それは、コンテキストメニューハンドラは自分と他のハンドラの境界上にセパレータを追加すべきかどうか?です。2つの考え方が出来ると思います。ハンドラ間にはセパレータを必ず追加すべきと考える人は、シェルがセパレータを追加するのが効率的と考えるでしょう。なぜなら、ハンドラの最初と最後でセパレータを追加すると、ハンドラ間でセパレータが2重になってしまうからです。ハンドラ間のセパレータは各ハンドラの判断でと考えた場合、ハンドラ間ではセパレータを追加しないこともできるようになるわけですが、そこにはハンドラ間のアイテム追加順序に関する知識が必要になりそうです。さらにハンドラの最初のセパレータは任意であるが、最後のセパレータは追加してはならないといったような取り決めをしておかないといけません。この場合、ハンドラ間にセパレータを追加するかどうかは、後から呼ばれたハンドラに依存することになります。これはこれで先に呼ばれたハンドラからすると「勝手に一緒にするなよ!」と言いたくなるところではあります。そう考えると、やはりハンドラ間のセパレータはシェルが追加するべきと考える方が自然な感じがします。ただ、現実そうなってるかどうかがよく分かりません。それを試すには、ハンドラを最低2つ作ってあげる必要があります。面倒くさい・・・。orz
昔、ハンドラ間でセパレータが追加されなかったときがあったんですよね。それがOSの違いによるものなのか・・・。ちゃんと仕様を書いておいて欲しいものです。
関連記事

comment

Secret

カレンダー
03 | 2017/04 | 05
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 - - - - - -
カテゴリー
最近の記事
最近のコメント
タグ

カメラ GH2 GH3 

ブログ内検索
月別アーカイブ
RSSフィード
プロフィール
●オンラインソフト作家。しかし長らく活動休止中。
ソフトウェア

●Dさんの長押しIME起動2
●IME+ (仮称)

・Dさんの長押しIME起動。
・Dさんの日本語じゃなきゃイヤン。
・Dさんの名前変更お手伝い。
・Dさんのダイヤルアップ接続お手伝い。
・DさんのWindows終了お手伝い。

・お忍びランチャー。
・お忍びリネーム。
・デジくいっくサーチ!
・Simple Remote
・計算王?

※過去の開発ソフトの一部はリンク先からダウンロードできます。

リンク
FC2カウンター
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。