トップページ> 書庫> Visual C++/MFC 俺的メモ> Windows Moblie 5.0 + Visual Studio 2005 でメニューバーを作成する方法

Windows Moblie 5.0 + Visual Studio 2005 でメニューバーを作成する方法
Windows Mobile 5.0 では画面の下部に「メニューバー」があり、ソフトキーを押すことで操作することができます。
これをVisual Studio 2005で作成するための日本語資料がなかったので書き残しておきます。

メニューバー
実は、eMbedded Visual C++では、普通に項目が2個しかないメニューリソースを作ってSHCreateMenubarを呼べばメニュー作れてました。(W-ZERO3 Monitor がそれです)
が、Visual Studio 2005 で同じ事をしようとするとなぜか失敗し、GetLastError() すると 120 (ERROR_CALL_NOT_IMPLEMENTED) が返ってきてしまいます。

一応Microsoftのサイトに、これの作り方の情報はあります。
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/win_ce/html/pwc_CreatingaSmartphoneMenuBarControl.asp?frame=true
が、英語だけなので日本語で書いておきます。

SHCreateMenuBar
メニューバーを作成するには、SHCreateMenubar API を使います。

BOOL SHCreateMenuBar(
  SHMENUBARINFO * pmb
);

aygshell.h をインクルードし、aygshell.lib とリンクする必要がありますがデフォルトでそのようになってるので何もしなくていいでしょう。
で、この関数の定義だけあっても意味不明なのでSHMENUBARINFO構造体の中身ですけど。

typedef struct tagSHMENUBARINFO {
  DWORD cbSize;
  HWND hwndParent;
  DWORD dwFlags;
  UINT nToolBarId;
  HINSTANCE hInstRes;
  int nBmpId;
  int cBmpImages;
  HWND hwndMB;
  COLORREF clrBk;
} SHMENUBARINFO, *PSHMENUBARINFO;

このうち設定する必要があるのは以下のメンバだけです。

cbSizesizeof(SHMENUBARINFO) を設定します。
hwndParentメニューバーを所有する(WM_COMMANDを処理する)ウィンドウのハンドルを設定します。
dwFlags0 でいいです。
SHCMBF_COLORBK を指定すると clrBk メンバでメニューバーの色を指定できるらしいですがうまくいきません。
nToolBarIdメニューバーを表すリソースのIDを設定します。(後述)
hInstResアプリケーションのインスタンスハンドルを設定します。(::AfxGetInstanceHandle() でOK)
nBmpId必ず 0 を指定します。
cBmpImages必ず 0 を指定します。

以上を指定して SHCreateMenubar を呼ぶとメニューバーが作成され、メニューバーのウィンドウハンドルが hwndMB に入ります。
メニューバーを破棄したり変更するAPIは用意されてないようですが、WM_CLOSE をメニューバーに送ることで消せます。

メニューバーのリソース
これがめんどいです…。

まずは、メニューバーをタップしたときに出したいメニューを、リソースエディタを使って普通に作ります。
あとは、メニューバーに表示したい文字を、String Table リソースにあらかじめ作っておくと最強です。

次にメニューバーのリソースを作りますが、これはリソースエディタでは作成できません。
ソリューションエクスプローラから resourceppc.h と、<プロジェクト名>ppc.rc のファイルを開いてください。
rcファイルはダブルクリックするとリソースエディタが開いてしまうので右クリックしてコードの表示を選びます。

で、rcファイルに以下の書式にしたがってリソーススクリプトを追加します。

<MenuBar ID> RCDATA MOVEABLE PURE 
BEGIN
    <Menu ID>, <Number of buttons>,
    I_IMAGENONE, <Cmd1ID>, <Btn1State>, <Btn1Style>, <String1ID>, 0, <Menu1Index>
    I_IMAGENONE, <Cmd2ID>, <Btn2State>, <Btn2Style>, <String2ID>, 0, <Menu2Index>
END

それぞれの項目の意味は以下の通り。

MenuBar IDこのリソースのIDを指定します。resourceppc.h にリソースIDを手動で作成してから、そのIDを指定する事になると思います。
Menu IDポップアップメニューに使用するメニューのリソースIDを指定します。
Number of buttonsメニューバーのボタンの数(1か2)
I_IMAGENONEボタンに画像を使用しない事を表します。Windows Moblie 5.0 スタイルのメニューバーでは画像は使えないらしいのでこれは固定でよいです。
だれか画像付きを実験してみてください(ぉ
Cmd1ID, Cmd2IDメニューバーのボタンをポップアップではなくボタンとして動作させたときのコマンドID
Btn1State, Btn2Stateメニューバーボタンの初期状態。とりあえず TBSTATE_ENABLED にしておけば普通のボタンになります。他の状態フラグが使えるかは確認したことないです。
Btn1Style, Btn2Styleメニューバーボタンのスタイル。TBSTYLE_AUTOSIZE と、TBSTYLE_BUTTON または TBSTYLE_DROPDOWN を組み合わせて指定しとけばいいようです。
TBSTYLE_BUTTON にするとポップアップメニューが表示されず、メニューバーをタップした時にコマンドが発行されます。
String1ID, String2IDメニューバーボタンに表示する文字列のリソースID。先に String Table に作っておいたリソースのIDを指定します。
00 を指定しろと書いてある資料しか見た覚えがないので 0 でいいんでしょう。
Menu1Index, Menu2Indexメニューバーボタンをタップしたときに表示するサブメニューのインデックスを指定します。サブメニューを出さない場合は NOMENU を指定します。

以上のようにしてリソースを作成し、そのリソースIDをSHCreateMenuBarに渡すSHMENUBARINFO構造体のnToolBarIdメンバに指定すればOKです。

TBSTYLE_BUTTON を指定した場合にはWM_COMMANDが飛んでくるはずですが、ウィンドウのプロパティからハンドラを追加することができないので、BEGIN_MESSAGE_MAP 〜 END_MESSAGE_MAP の間に ON_COMMAND マクロを手動で追加してください。

BEGIN_MESSAGE_MAP(CMenuBarDemoDlg, CDialog)
	(中略)
	ON_COMMAND(IDM_BUTTON1, OnMenuButton1)
	ON_COMMAND(IDM_BUTTON2, OnMenuButton2)
	ON_COMMAND(IDM_BUTTON3, OnMenuButton3)
END_MESSAGE_MAP()

というわけで今回のサンプルソースはこちら

注意
rc ファイルを手動で編集してから閉じ、その後リソースエディタで編集を行うと、上記メニューバーのリソースがバイナリに置き換わってしまい編集が容易に行えなくなります。
こんな感じ。(YTaskMgr のソースから引用)

IDR_MAINMENU1 RCDATA 
BEGIN
    0x008a, 0x0002, 0xfffe, 0x0099, 0x0004, 0x0010, 0x0099, 0x0000, 0xffff, 
    0xfffe, 0x0099, 0x0004, 0x0018, 0x0095, 0x0000, 0x0001
END

これではたまらないので、元のソースをコピペしてどこか別のところに保存しておきましょう。
ちなみにrcファイル内にコメントとして残しておくと勝手に削除されてしまうのでやめましょう(笑)

…ていうかC#だとこんなめんどくさい事しなくても普通にメニューエディタっぽい画面でサクっとメニューバー作れるみたいですね…。

DBWebSystem ver-1.00
このページの内容は… (・∀・)[良い] / (-ω-;)[悪い]
ContentID : VCMemo22, Total Page Views : 7279, Page Score : 0
Last Update : 2006/09/06 23:59:35 (LIRS.txt)
System Designed & Coded by ヨシヲ
[このコンテンツを編集] [このコンテンツにリンクしているページ]