メニューの動的追加で発生するIDの値は? – プログラミング – Home

メニューの動的追加で発生するIDの値は...
 
通知
すべてクリア

[解決済] メニューの動的追加で発生するIDの値は?


ケンシロウ
 ケンシロウ
(@ケンシロウ)
ゲスト
結合: 14年前
投稿: 7
Topic starter  

VC++ MFC SDI CFormView です。
メニューを動的に追加したくて、下記のコードを書きました。
追加したメニュー項目をクリックしたとき発生するIDを調べたところ、ヘンな値とな
っています。
これでいいのでしょうか、教えてください。

【メニュー構成】
ファイル ↓
     新規作成
     開く
     北斗の拳 ↓
          ケンシロウ
          ヒューイ
          シュレン
動的に追加するのは、POPUPの「北斗の拳」と、その下に最大10個です。

【発生するIDの値】
「ケンシロウ」をクリックすると 14464 という数値が発生します。
「ヒューイ」では 14465、以下一つずつ増えます。
ID_ADDMENU 80000 なのに、これとは違った値になっているのが疑問です。
ID_ADDMENU を 90000 に変えても、発生する uID の値は同じ 14464 です。

【コード】
<Resource.h>
#define ID_ADDMENU 80000
#define ID_ADDMENU_RANGE 10

<MainFrame.cpp>
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_INITMENU()
END_MESSAGE_MAP()

void CMainFrame::OnInitMenu(CMenu* pMenu)
{
HMENU hMenu = CreatePopupMenu();
CMenu *pSub = pMenu->GetSubMenu(0);
pSub->InsertMenu(2, MF_BYPOSITION | MF_POPUP, (UINT)hMenu, _T(北斗の拳));
CMenu *pHokuto = pSub->GetSubMenu(2);
pHokuto->AppendMenu(MF_BYPOSITION, ID_ADDMENU+0, _T(ケンシロウ));
pHokuto->AppendMenu(MF_BYPOSITION, ID_ADDMENU+1, _T(ヒューイ));
pHokuto->AppendMenu(MF_BYPOSITION, ID_ADDMENU+2, _T(シュレン));
}

<HokotoView.cpp>
BEGIN_MESSAGE_MAP(CHokutoView, CFormView)
ON_COMMAND_RANGE(ID_ADDMENU, ID_ADDMENU+ID_ADDMENU_RANGE-1, OnHokutoGame)
・・・・・・・・
END_MESSAGE_MAP()

void CHokutoView::OnHokutoGame(UINT uID)
{
if (uID == ○○○) ◇◇◇;
と書きたくて、ここに発生する uID の値を調べました。
}


引用未解決
トピックタグ
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

80000 = 0x13880
14464 = 0x03880
これで何か気づかない?

AppendMenuの第二引数のUINTでUINTはunsigned intなんで、80000は表現できるはず
なんだけど、メニューIDはunsigned shortの範囲でしか扱えない。そのため、上位
ワードが切り捨てられたとは考えられない?
# この辺にまだ16ビットの遺産が...

> ID_ADDMENU を 90000 に変えても、発生する uID の値は同じ 14464 です。
これはわかりません。コンパイルが正しく行われていないかも?


返信引用
ケンシロウ
 ケンシロウ
(@ケンシロウ)
ゲスト
結合: 14年前
投稿: 7
Topic starter  

maru様、応答して戴き有り難うございます。

> メニューIDはunsigned shortの範囲でしか扱えない。

unsigned short の最大値は 65535 とのことなので、80000 を 60000 に変えてやってみ
ましたが、やはり 14464 (= 0x03880) が発生します。
USHRT_MAX-10 としても、極端に 2000 としても同じです。

> コンパイルが正しく行われていないかも?

質問するまでは Visual Studio 2010 試用版でビルドしていましたが、今回 VS2005 で
コンパイルしたところ、次の警告が出ました。(VS2005でビルドしても発生するIDの値
は同じ 14464 です。)
「・・・・・warning C4311: '型キャスト' : ポインタを 'HMENU' から 'UINT' へ切り
詰めます。」
この行に対して↓
pSub->InsertMenu(2, MF_BYPOSITION | MF_POPUP, (UINT)hMenu, _T(北斗の拳));
POPUPメニューの作り方が間違っているでしょうか?


返信引用
ケンシロウ
 ケンシロウ
(@ケンシロウ)
ゲスト
結合: 14年前
投稿: 7
Topic starter  

pSub->InsertMenu(2, MF_BYPOSITION | MF_POPUP, (UINT)hMenu, _T(北斗の拳));

この行の中の (UINT) を (UINT_PTR) に変えたら、警告は出なくなりました。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

CMenu::AppendMenu
http://msdn.microsoft.com/ja-jp/library/kb145b0a.aspx

第一引数に MF_BYPOSITION を指定していいとは書いてありませんが…


返信引用
ケンシロウ
 ケンシロウ
(@ケンシロウ)
ゲスト
結合: 14年前
投稿: 7
Topic starter  

有り難うございます。
不注意のミスです。
MF_STRING に書き換えました。
しかし、結果は同じです。14464 (= 0x03880) が発生します。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

まぁともかくも、WM_COMMAND を処理する際にメニューIDは16bitに切り捨てられてしま
うので、65535までにしておくのがいいと思います。

>> ID_ADDMENU を 90000 に変えても、発生する uID の値は同じ 14464 です。
> これはわかりません。コンパイルが正しく行われていないかも?

これは謎ですが…


返信引用
ケンシロウ
 ケンシロウ
(@ケンシロウ)
ゲスト
結合: 14年前
投稿: 7
Topic starter  

aetos様、有り難うございます。
1桁小さい 8000 にしました。

ところで、不思議な現象が出ました。

<手順1>
試しに、メニューをもう1個追加しました。
ファイル ↓
     新規作成
     開く
     北斗の拳 ↓
          ケンシロウ
          ヒューイ
     北斗の拳2 ↓
           ケンシロウ
           ヒューイ
<Resource.h>
#define ID_ADDMENU 8000
#define ID_ADDMENU_RANGE 10
#define ID_ADDMENU2 8100
#define ID_ADDMENU2_RANGE 10
あーら不思議!
北斗の拳→ケンシロウ で 8000 が発生
北斗の拳2→ケンシロウ で 8100 が発生

<手順2>
追加した「北斗の拳2」を削除して、元の状態に戻しました。
北斗の拳→ケンシロウ で 8000 が発生

<手順3>
#define ID_ADDMENU を 9000 に変更しても、8000 が発生します。
どう変えても 8000 が発生します。

コンパイラのバグでしょうか?
VS2005 と VS1010 の両方で同じことをやりましたが、同じ結果です。
1ヶ月以内にすべて(WindowsもVSも)クリーン・インストールするつもりですが、そし
たらまた 14464 が出ることでしょうね。 (^o^)


返信引用
ケンシロウ
 ケンシロウ
(@ケンシロウ)
ゲスト
結合: 14年前
投稿: 7
Topic starter  

(誤)VS2005 と VS1010 の両方で同じことをやりましたが、同じ結果です。
(正)VS2005 と VS2010 の両方で同じことをやりましたが、同じ結果です。


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

> #define ID_ADDMENU を 9000 に変更しても、8000 が発生します。
現象を確認しました。
原因は resource.h のみが変更された場合、ビルドではソースファイルのコンパイル
が実行されないことでしょう。

[ビルド]-[ソリューションのリビルド]を実行してみてください。

resource.h はメインヘッダーにインクルードされているので、本来これが変更され
れば、全てのソースファイルをコンパイル/リンクするべきと思いますが、VCはこの
ファイルを何か特殊処理しているのでしょうね。

元々このメニューIDはリソースには関係しないので、resource.h に記述するのでは
なく、メインヘッダーにでも入れておくほうがよかったのでは?

また、メニューIDの範囲の問題は、プロジェクトのプロパティで警告レベルを4に
あげておけば、
「warning C4310: キャストによって定数値が切り捨てられました。」
という警告があがりますので、それでわかったはずです。
プロジェクトを作成したら、まず警告レベルを上げることをお勧めいたします。


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

> 「warning C4310: キャストによって定数値が切り捨てられました。」
> という警告があがりますので、それでわかったはずです。
ちなみに警告があがるのは、AppendMenuではなくて、ON_COMMAND_RANGEマクロです。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

うーーん
 そういえば、メニュー関連に限らず、リソースIDって32768未満て決まり
 があったとだと思ったのですが。。。


返信引用
ケンシロウ
 ケンシロウ
(@ケンシロウ)
ゲスト
結合: 14年前
投稿: 7
Topic starter  

> [ビルド]-[ソリューションのリビルド]を実行してみてください。
やりました。バッチリ、IDと同じ数値が発生します。

> resource.h に記述するのではなく、メインヘッダーにでも入れておくほうがよかった
のでは?
はい、MainFrame.h に書きました。OKです。
(ネット上で見つけたサンプルが Resource.h に書くようになっていたので、何も考え
ず真似してしまいました。)

> プロジェクトのプロパティで警告レベルを4にあげて・・・
レベル4にして、IDの値が 65535 より大きいと、「warning C4310: キャストによって
定数値が切り捨てられました。」が出るのを確認しました。
(ほかにも沢山警告が出ちゃいました。笑)

ID と同じ uID が発生するようになったので安心しました。
maru様はじめ皆様、ありがとうございました。


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

> そういえば、メニュー関連に限らず、リソースIDって32768未満て決まり
> があったとだと思ったのですが。。。
いえいえそんなことはありません。
AppWizardでMFCアプリを生成すると50000以上の文字列IDをたくさん作ってくれます。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

>いえいえそんなことはありません。
>AppWizardでMFCアプリを生成すると50000以上の文字列IDをたくさん作ってくれます
そうですか、
ありがとうございます。
別のIDと勘違いしたのかも知れませんね。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました