掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
オーナードロウメニューについて (ID:52815)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
まずは確認で。 CustomMenu.cpp: BEGIN_MESSAGE_MAP(CCustomMenu, CWnd) //{{AFX_MSG_MAP(CCustomMenu) // メモ - ClassWizard はこの位置にマッピング用のマクロを追加または削除します。 //}}AFX_MSG_MAP END_MESSAGE_MAP() このままでは CWnd のプロテクトメンバに引っかかるので とりあえず、CWndをCCustomMenuとして通す。 CCustomMenu:Constructor(); CCustomMenu:Constructor(); CCustomMenu:Constructor(); CCustomMenu:Constructor(); CCustomMenu:Constructor(); CCustomMenu::MeasureItem(itemID=0000000B): Warning: unknown WM_MEASUREITEM for menu item 0x4E80D03. CCustomMenu::MeasureItem(itemID=0000000D): CCustomMenu::DrawItem(itemID=0000000B): CCustomMenu::DrawItem(itemID=04E80D03): CCustomMenu::DrawItem(itemID=0000000D): CCustomMenu:Destructor(); CCustomMenu:Destructor(); CCustomMenu:Destructor(); CCustomMenu:Destructor(); CCustomMenu:Destructor(); 確かにそう出ますね。 でも、コンストラクタ、デストラクタが必要以上に呼ばれているねぇ。 void CCustomMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct ) { TRACE("CCustomMenu::MeasureItem(itemID=%08X):\n",lpMeasureItemStruct->itemID); } TRACE() にブレークポイントを張り、これを呼ぶ元を探ります。 // Measure item implementation relies on unique control/menu IDs void CWnd::OnMeasureItem(int /*nIDCtl*/, LPMEASUREITEMSTRUCT lpMeasureItemStruct) { if (lpMeasureItemStruct->CtlType == ODT_MENU) { ASSERT(lpMeasureItemStruct->CtlID == 0); CMenu* pMenu; _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData(); if (pThreadState->m_hTrackingWindow == m_hWnd) { // start from popup pMenu = CMenu::FromHandle(pThreadState->m_hTrackingMenu); } else { // start from menubar pMenu = GetMenu(); } pMenu = _AfxFindPopupMenuFromID(pMenu, lpMeasureItemStruct->itemID); if (pMenu != NULL) pMenu->MeasureItem(lpMeasureItemStruct); else TRACE1("Warning: unknown WM_MEASUREITEM for menu item 0x%04X.\n", lpMeasureItemStruct->itemID); >>>>....なるメッセージがでています。 これだね! } else { CWnd* pChild = GetDescendantWindow(lpMeasureItemStruct->CtlID, TRUE); if (pChild != NULL && pChild->SendChildNotifyLastMsg()) return; // eaten by child } // not handled - do default Default(); } _AfxFindPopupMenuFromID(pMenu, lpMeasureItemStruct->itemID); が NULL を返しているのを突き止めたので、 ここにブレークポイントを張り、中に潜ります。 AFX_STATIC CMenu* AFXAPI _AfxFindPopupMenuFromID(CMenu* pMenu, UINT nID) { ASSERT_VALID(pMenu); // walk through all items, looking for ID match UINT nItems = pMenu->GetMenuItemCount(); for (int iItem = 0; iItem < (int)nItems; iItem++) { CMenu* pPopup = pMenu->GetSubMenu(iItem); if (pPopup != NULL) { // recurse to child popup pPopup = _AfxFindPopupMenuFromID(pPopup, nID); // check popups on this popup if (pPopup != NULL) return pPopup; } else if (pMenu->GetMenuItemID(iItem) == nID) { // it is a normal item inside our popup pMenu = CMenu::FromHandlePermanent(pMenu->m_hMenu); return pMenu; } } // not found return NULL; } コールスタック: _AfxFindPopupMenuFromID(CMenu * 0x00344f98 {CCustomMenu}, unsigned int 7736337) line 1236 _AfxFindPopupMenuFromID(CMenu * 0x003451c0 {CCustomMenu}, unsigned int 7736337) line 1240 + 13 bytes _AfxFindPopupMenuFromID(CMenu * 0x0012f944 {CCustomMenu}, unsigned int 7736337) line 1240 + 13 bytes CWnd::OnMeasureItem(int 0, tagMEASUREITEMSTRUCT * 0x0012f690) line 1276 + 16 bytes CWnd::OnWndMsg(unsigned int 44, unsigned int 0, long 1242768, long * 0x0012f53c) line 1930 CWnd::WindowProc(unsigned int 44, unsigned int 0, long 1242768) line 1585 + 30 bytes AfxCallWndProc(CWnd * 0x0012fe74 {CDm02Dlg hWnd=0x00720156}, HWND__ * 0x00720156, unsigned int 44, unsigned int 0, long 1242768) line 215 + 26 bytes AfxWndProc(HWND__ * 0x00720156, unsigned int 44, unsigned int 0, long 1242768) line 368 どうやら、サブメニューが存在していると たとえ、現在の pMenu が目的のアイテムを示していても、 再帰してしまい、見つからないということになるようです。 Win98 だとここのロジックが違うのかな。 前述のように当方 Win2K なのですが。 どうなってます? コールスタックを見る以上、 デフォルトで OnMeasureItem() -> MeasureItem() と呼ばれているので、 メッセージハンドラ:OnMeasureItem(), OnDrawItem() を追加し、 そこに処理を記述するのが筋だと思います。 どうでしょうか。 このようにすれば、DrawItem(), MeasureItem() を手書きで 追加する必要もなかったかと思うのですが。
←解決時は質問者本人がここをチェックしてください。
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.