« Advanced/W-ZERO3[es]買いました。 | メイン
WindowsMobile用アプリ開発メモ(3)
前回のエントリから2ヶ月ほど経ってますが・・・
今回はメニューバー(この画像の下部)の作成です。
通常のWin32アプリケーションの場合と比べるとWindowsMobileではなかなかの曲者です。
では、実装は"続きを読む"からどうぞ。
今回はメニューバー(この画像の下部)の作成です。
通常のWin32アプリケーションの場合と比べるとWindowsMobileではなかなかの曲者です。
では、実装は"続きを読む"からどうぞ。
サンプルプロジェクトはこちら。
- リソースの作成
まず表示したいメニューリソースを作ります。ちなみに最上位要素のキャプション等といった属性は無視されます。ソフトキーを押したときに出てくるプルダウンメニューをそれぞれ最上位要素でまとめて作るような具合です。
このサンプルではサブメニューを持つ要素は右側のみなので最上位要素は一つのみです。以下に示すようなリソースを使用しています。IDR_MAINMENU MENU
次に最上位項目のキャプションとなる文字列を記録したストリングテーブルを作成します。サンプルコードのリソースではそれぞれIDS_MENU1が左側の、IDS_MENU2が右側の要素のキャプションとなっています。
BEGIN
POPUP ""
BEGIN
MENUITEM "項目(&2)", ID_ELEM002
MENUITEM SEPARATOR
MENUITEM "選択不可(&D)", ID_ELEM003, GRAYED
MENUITEM "項目(&3)", ID_ELEM004
END
END
以下、サンプルコードのストリングテーブル部分です。STRINGTABLE
最後にソフトキーにメニュー項目を対応するための情報を記述するのですが、どうもこれだけはVisual Studioのリソースエディタが利用できないようで.rcファイルを直接編集することになります。ちなみに、この情報を記述した後にVisual Studioのリソースエディタで.rcファイルを編集するとよく分からないデータに変換されてしまいます。サンプルコードのアーカイブの中には変換される前のデータとして"WM003/WM003_Original.rc"というファイルを同梱しているので読むときはこちらを参考にしてください。この部分のサンプルコードは以下の通りです。
BEGIN
IDS_MENU1 "項目1"
IDS_MENU2 "ポップアップ"
ENDIDR_MAINMENU RCDATA DISCARDABLE
BEGIN以後の2つの要素はコメントの通り、そしてそれぞれの要素の部分ですが、各要素に対して
BEGIN
IDR_MAINMENU, // メニューのリソースID
2, // トップレベル要素の数
I_IMAGENONE, ID_ELEM001, TBSTATE_ENABLED,
TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE,
IDS_MENU1, 0, NOMENU // 1つ目の要素
I_IMAGENONE, 0, TBSTATE_ENABLED,
TBSTYLE_DROPDOWN | TBSTYLE_AUTOSIZE,
IDS_MENU2, 0, 0 // 2つ目の要素
END- ボタンに画像を使用するか否か(通常はI_IMAGENONE(画像を使用しない))
- トップレベル要素がボタン要素(選択するとWM_COMMANDメッセージが発行されるもの)である場合、それが押されたとき発行されるコマンドのID
- 要素の初期状態(通常はTB_STATE_ENABLED)
- 要素のスタイル(TBSTYLE_BUTTONを指定すればボタン要素に、TBSTYLE_DROPDOWNを指定すればプルダウンメニューを持つ要素になります。とりあえずはこの2つのいずれかとTBSTYLE_AUTOSIZEの組み合わせがよく使われるものかと思われます。)
- メニューバーに表示するキャプションを格納したストリングテーブル内要素のID
- よく分からないけれどもとりあえず0(予約済み領域?)
- 選択されたときに表示するサブメニューがメニューリソースの何番目の要素であるか(0から開始、ボタン要素の場合はNOMENU)
ここまででリソースの準備は完了です。 - メニューの生成処理を追加
リソースの準備が出来たらメニューを追加したいタイミング(おそらく大抵はWM_CREATEやWM_INITDIALOGメッセージが飛んできたとき)にSHCreateMenuBar関数を呼び出します。
以下はサンプルコードのメニューバー生成部分(WM_CREATEメッセージが発行されたときに実行しています)。SHMENUBARINFO mbi;
SHCreateMenuBar関数に渡すSHMENUBARINFO構造体へはまずゼロクリアした後にcbSizeに構造体のサイズを、hwndParentにメニューを持たせるウィンドウのハンドルを、nToolBarIdにメニューとして設定したいリソースのIDを、hInstResにはリソースを含むインスタンスのハンドルをそれぞれ記録します。その他の項目についてはMSDNライブラリのSHMENUBARINFOの項(リンク先は英語)を参照してください。
memset(&mbi, 0, sizeof(SHMENUBARINFO));
mbi.cbSize = sizeof(SHMENUBARINFO);
mbi.hwndParent = hWnd;
mbi.nToolBarId = IDR_MAINMENU;
mbi.hInstRes = g_hInstance;
if(SHCreateMenuBar(&mbi) != FALSE){
RECT rect, rectMB;
GetWindowRect(hWnd, &rect);
GetWindowRect(mbi.hwndMB, &rectMB);
int cy = IsWindowVisible(mbi.hwndMB) ? rectMB.top - rect.top : rectMB.bottom - rect.top;
SetWindowPos(hWnd, NULL, 0, 0, rect.right - rect.left, cy, SWP_NOZORDER | SWP_NOMOVE);
}else{
MessageBox(hWnd, TEXT("SHCreateMenuBar Failed"), TEXT("Error"), MB_OK);
}
そして、メニューバーの生成が成功したらウィンドウの下にメニューバーを表示する領域が出来るようにウィンドウをリサイズします(おそらくメニューバーはウィンドウの下端にくっつくような配置をされるのでしょう)。
トラックバック
このエントリーのトラックバックURL:
http://arrize.net/mt/mt-tb.cgi/8
コメントを投稿