オーナードローメニュープログラム Ver.7a


これはVBの統合環境やMS Officeなど、最近のプログラムではすっかりお馴染みとなったメニュー項目の左脇に画像表示(右の絵のような)をVBでも実現できるようにするプログラムです。

使い方は簡単。プロジェクトに、付属の標準モジュールを1つ追加するだけです。あとは、数行+α(表示する絵の数)の追加で、簡単に実現できます。

このモジュールで、できることは以下のとおり。

  • メニュー左脇にピクチャを表示できます。
  • チェック、アンチェック時のピクチャに別々のピクチャを設定できます。
    アンチェック時のピクチャしか登録していない場合は、その画像を元にチェック時の表示をします。(1つのピクチャでチェックかアンチェックかわかります。)
  • メニュー項目自体にもピクチャを表示できます。
  • 表示できるピクチャはアイコンとビットマップの2種類が使えます。
    ビットマップの場合でも透明色の指定を正しく行えばアイコンと同じように背景色を透過表示することが可能!!
  • メニュー構造は、自動で取得するので面倒な設定が一切ありません。
  • 階層構造のメニューでも問題なく動作します。
  • メニューの表示スタイルを3種類から選択できます。
  • メニューの左側にグラデーションが表示できます。更にその上に文字列やピクチャを重ね合わせて表示できます。
  • メニュー項目が動的に変化しても、ある程度までなら対応できます。

他、使う人のアイディア次第でいろいろできます。リストも付いているので、腕に覚えのある人は、色々な機能を追加できることでしょう。

メニューサンプル

関数説明


メニュー位置の説明

たとえば、右のようなメニューがあったとします。

このとき「ステータスバー(S)」の位置は
[ 2 , 1 ]

「大きいアイコン(G)」の位置は
[ 2 , 3 ]

「日付順(D)」の位置は
[ 2 , 8 , 3 ]

とあらわします。

メニュー位置説明

それぞれの位置をあらわしている数字の最初の”2”は一番上のメニューの左からの位置を表します。
この時、一番左の「ファイル(F)」を””と数え右に行くにつれて1ずつ増えていきます。
この数え方でいくと「表示(V)」は””となります。

次の数字は、最初に選んだメニュー位置の上から数えた項目の位置をあらわします。
こちらも、先ほどと同様に一番上が””となります。そして、下に行くにしたがって1ずつ増えていきます。この時、セパレータも1つの項目として数えます。
そのために、「大きいアイコン(G)」の位置を表す数値の2番目の値が””となります。

項目がサブメニュー内に存在する場合は、2番目の値がサブメニュー親の項目の位置になり、3番目の値が項目位置になります。
サブメニューのサブメニューがあった場合でも同様になります。

上の方法で、位置を割り出した後、プログラム中で値を設定するときは、SetMenuPosition 関数には、最後の数値以外を指定します。
そして、最後の数値をSetMenuItemPicture 関数などの表示関係の関数に設定します。

実際にプログラム中で設定する場合は、以下のようになります。

「ステータスバー(S)」にピクチャを設定する場合

SetMenuPosition( Me.hWnd , 2 )
SetMenuItemPicture( 1 , , Image1.Picture )

 
「大きいアイコン(G)」にピクチャを設定する場合

SetMenuPosition( Me.hWnd , 2 )
SetMenuItemPicture( 3 , , Image2.Picture )

 
「日付順(D)」にピクチャを設定する場合

SetMenuPosition( Me.hWnd , 2 , 8 )
SetMenuItemPicture( 3 , , Image3.Picture )

位置指定が2段階になっているのは、入力の手間を減らすためと、プログラム的にこの方が簡単だからです。


VB標準プロパティの対応状況

Caption
参照 - デザイン時の値を返します。SetMenuItemString 関数による変更は反映されません。
代入 - Caption プロパティに直接代入せず、SetMenuItemString 関数を使用してください。
直接代入するとオーナードロー属性が解除されてしまい、うまく動作できません。
Checked
参照 - 通常どおり操作できます。
代入 -
Enabled
参照 - 通常どおり操作できます。
代入 -
Visible
参照 - 通常どおり操作できます。
代入 - VisibleMenuItem 関数を使ってください。
直接代入するとオーナードロー属性が解除されてしまい、うまく動作できません。
その他 通常どおり動作すると思います。

基本的に表示のプロパティ( Caption Visible )を変更するときは直接変更せずに、変更用の関数を呼び出して変更してください。
これは、VBが表示を変更する時にオーナードロー属性を解除してしまうためです。オーナードロー属性が解除されると表示が乱れてします。
そのために変更用の関数が存在するわけです。

状態のプロパティ( Checked Enabled )を変更する場合は、そのまま変更しても問題ありません。
ただし、APIを使って変更した状態はVB上から読み出すことができません。
これは、VBのメニューは基本的に代入時はVB内部情報とOS側の状態を変更するのに対し、参照時は内部に格納されている値を返すために起こる現象です。

Visible プロパティは更に特殊で、OS自身に Visible プロパティに相当するものがありません。そこで、メニュー上に項目を挿入・削除することで実現させています。
そのために、AllocMenu 関数を呼び出した時点で表示状態になっていないメニュー項目は読み出すことが出来ません。
出来れば、メニューデザイン時に全てのメニュー項目を表示状態にしておくことをお勧めします。
しかし、どうしてもデザイン時に非表示にする必要がある場合は、最初の表示のときに InsertMenuItem 関数を呼び出してください。その後は VisibleMenuItem 関数を使って変更することが出来ます。

※ここに記してあるVBの内部動作については私が独自に調べたものです。間違い等の報告・質問・苦情等は私宛にお願いします。


その他

このプログラムは私が使いやすいように昔組んだプログラムに組み込みやすいようにを基本コンセプトに作られています。
おかげで、コメントが殆ど入っていません。最適化も殆ど行っていません。
そのため、他の人が使うと案外使いにくいかもしれません。しかも、まだ発展途上でバグが無いとは言い切れません。
そこで、改良・改造・アイディア等々、皆様の意見・感想・苦情・その他諸々なんでもお待ちしています。あて先はこちら

それから、このプログラムはフリーウェアです。著作権も主張しません。自由にプロジェクトに組み込んでもらって結構です。
ただ、このプログラムを利用したことによって、いかなる損害を被っても、作者は一切の責任を負いません。(負えません。) あらかじめご了承ください。


変更履歴

Ver.1 とりあえず完成
Ver.2 表示フォントを設定できるようにした。
Ver.3 ビットマップの Disabled 表示をそれらしくした。
Ver.3a 表示でポカミスがあったのを修正。
Ver.4β 表示中の文字列やピクチャを変更出来るようにした。
最初から設定されてるビットマップを表示する際の表示方法の変更。
Ver.4 動的に変化するメニューに対応
Ver.5 メニューオブジェクトの Visible プロパティに対応
Ver.5a メニューオブジェクトの Visible プロパティの対応強化
Ver.6 メニュー選択時のカーソルの種類を増やした。
Ver.7 ピクチャ脇にタイトルを表示できるようにした。
セパレータのデザインを変更できるようにした。
Ver.7a ハンドルの解放し忘れなどを修正。