Update for Owner Drawn Menu with Icons (2)
Posted
by Jaroslav "Jerry" Pisk
on August 27th, 1998
What's new
- Icon size is not determined every time it's needed but is stored in member variables
- Fixed few unnecesary lines of code
What to use them ?
To be able to use owner draw popup menu items it is neccesary to add following to the main window class:In the message map:
ON_WM_MEASUREITEM()
In the declaration (header) file:
afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct);
And in the definition (source) file:
static CMenu* FindPopupMenuFromID(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 = FindPopupMenuFromID(pPopup, nID);
// check popups on this popup
if (pPopup != NULL)
return pPopup;
}
else if (pMenu->GetMenuItemID(iItem) == nID || (UINT)pMenu->GetSafeHmenu() == nID)
{
// it is a normal item inside our popup
pMenu = CMenu::FromHandlePermanent(pMenu->m_hMenu);
return pMenu;
}
}
// not found
return NULL;
}
void CMainWnd::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
if (lpMeasureItemStruct->CtlType == ODT_MENU)
{
ASSERT(lpMeasureItemStruct->CtlID == 0);
CMenu* pMenu;
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
if (pThreadState->m_hTrackingWindow == m_hWnd)
{
// start from popup
pMenu = CMenu::FromHandle(pThreadState->m_hTrackingMenu);
}
else
{
// start from menubar
pMenu = GetMenu();
}
pMenu = FindPopupMenuFromID(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();
}
Last updated on: August 27, 1998.

Comments
good
Posted by xxl19792003 on 08/24/2010 03:33amgood
ReplyThanks to Jaroslav Pisk !
Posted by Legacy on 01/29/2004 12:00amOriginally posted by: RyuSungMin
Modified FindMenuItem returns pointer of submenu and uId
ReplyCMenu* CCatDDEMgr::FindMenuItem(CMenu* pMenu, CString MenuString, UINT& uId)
{
ASSERT_VALID(pMenu);
int cnt = pMenu->GetMenuItemCount();
for(int i = 0; i < cnt; i++)
{
CString str;
CMenu* pPopup = pMenu->GetSubMenu(i);
if(pPopup)
{
if (pPopup->GetMenuString(i, str, MF_BYPOSITION) &&
(strcmp(str, MenuString) == 0))
{
uId = pPopup->GetMenuItemID(i);
return pPopup;
}
else
{
pPopup = FindMenuItem(pPopup, MenuString, uId);
if(pPopup)
{
return pPopup;
}
}
}
else
if (pMenu->GetMenuString(i, str, MF_BYPOSITION) &&
(strcmp(str, MenuString) == 0))
{
uId = pMenu->GetMenuItemID(i);
return pMenu;
}
}
return NULL;
}
One logical error
Posted by Legacy on 09/12/2001 12:00amOriginally posted by: Paul Nurminsky
ReplyUpdate to CMenuSpawn
Posted by Legacy on 11/02/1998 12:00amOriginally posted by: Alex Waddell
The Menu Spawn class currently only supports checked menu items if there is no bitmap associated with the menu item. Add this line to the Draw() routine to enable "checked" menu items for items that have a bitmap.
Add this line in to the Draw() and you can get "checked" items with the bitmap (instead of just checked items without bitmaps).
if (pItem->iImageIdx >= 0)
{
int ay = (rcImage.Height() - szImage.cy) / 2;
int ax = (rcImage.Width() - szImage.cx) / 2;
>> if (bChecked)
>> pDC->DrawEdge (rcImage, BDR_SUNKENOUTER, BF_RECT);
>> else if (bSelect && bEnab)
pDC->Draw3dRect(rcImage,cr3dHilight,cr3dShadow);
else
if (!bBackBitmap) pDC->Draw3dRect(rcImage,crMenu,crMenu);
if (bEnab)
Reply{
...
}