30#define MM_SETMENUHANDLE (WM_USER + 0)
31#define MM_GETMENUHANDLE (WM_USER + 1)
35#define TF_ENDMENU 0x10000
36#define TF_SUSPENDPOPUP 0x20000
37#define TF_SKIPREMOVE 0x40000
43#define MAXMENUDEPTH 30
45#define MNS_STYLE_MASK (MNS_NOCHECK|MNS_MODELESS|MNS_DRAGDROP|MNS_AUTODISMISS|MNS_NOTIFYBYPOS|MNS_CHECKORBMP)
47#define MENUITEMINFO_TYPE_MASK \
48 (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
49 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
50 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY )
52#define TYPE_MASK (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU)
54#define STATE_MASK (~TYPE_MASK)
56#define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT))
58#define MII_STATE_MASK (MFS_GRAYED|MFS_CHECKED|MFS_HILITE|MFS_DEFAULT)
60#define IS_SYSTEM_MENU(MenuInfo) \
61 (!((MenuInfo)->fFlags & MNF_POPUP) && ((MenuInfo)->fFlags & MNF_SYSMENU))
63#define IS_BITMAP_ITEM(flags) (MF_BITMAP == MENU_ITEM_TYPE(flags))
65#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
66#define IS_STRING_ITEM(flags) (MF_STRING == MENU_ITEM_TYPE(flags))
69#define MAX_MENU_ITEMS (0x4000)
70#define MAX_GOINTOSUBMENU (0x10)
73#define MENU_COL_SPACE 4
75#define MENU_ITEM_HBMP_SPACE (5)
76#define MENU_BAR_ITEMS_SPACE (12)
77#define SEPARATOR_HEIGHT (5)
78#define MENU_TAB_SPACE (8)
90#define TPM_INTERNAL 0xF0000000
91#define TPM_BUTTONDOWN 0x40000000
92#define TPM_POPUPMENU 0x20000000
97#define UpdateMenuItemState(state, change) \
99 if((change) & MF_GRAYED) { \
100 (state) |= MF_GRAYED; \
102 (state) &= ~MF_GRAYED; \
104 if((change) & MF_DISABLED) { \
105 (state) |= MF_DISABLED; \
107 (state) &= ~MF_DISABLED; \
109 if((change) & MFS_CHECKED) { \
110 (state) |= MFS_CHECKED; \
112 (state) &= ~MFS_CHECKED; \
114 if((change) & MFS_HILITE) { \
115 (state) |= MFS_HILITE; \
117 (state) &= ~MFS_HILITE; \
119 if((change) & MFS_DEFAULT) { \
120 (state) |= MFS_DEFAULT; \
122 (state) &= ~MFS_DEFAULT; \
124 if((change) & MF_MOUSESELECT) { \
125 (state) |= MF_MOUSESELECT; \
127 (state) &= ~MF_MOUSESELECT; \
185#define FreeMenuText(Menu,MenuItem) \
187 if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
188 (MenuItem)->lpstr.Length) { \
189 DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \
198 Menu->
head.cLockObj++;
209 if (!pMenu)
return NULL;
225 ERR(
"Run away LOOP!\n");
233 ERR(
"Menu is marked for destruction!\n");
282 SubMenu =
item->spSubMenu;
296 if (bRecurse && SubMenu)
340 ERR(
"FIXME Pop up menu window thing'ie\n");
353 TRACE(
"IntDestroyMenuObject %d\n",
ret);
363 NONCLIENTMETRICSW ncm;
368 ncm.cbSize =
sizeof(ncm);
371 ERR(
"MenuInit(): SystemParametersInfo(SPI_GETNONCLIENTMETRICS) failed!\n");
378 ERR(
"MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
385 ERR(
"MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
412 if (!pmenu)
return depth;
423 if( bdepth > subdepth) subdepth = bdepth;
493 for(--
i;
i != 0; --
i) {
513 UINT fallback_pos = 0;
516 if (!menu)
return NULL;
538 else if (
item->wID == *nPos)
545 else if (
item->wID == *nPos)
554 *nPos = fallback_pos;
574 if (!
item->spSubMenu)
578 if (
item->spSubMenu == SubTarget)
603 TRACE(
"(menu=%p pos=%04x flags=%04x)\n",pMenu, nPos,
wFlags);
609 if (bRecurse &&
item->spSubMenu)
621 while (nPos < pMenu->cItems)
653 if (submenu) *submenu = menu;
675 WARN(
"allocation failed\n" );
689 return &newItems[
pos];
705 if (MAX_MENU_ITEMS <= MenuObject->cItems)
711 SubMenu = MenuObject;
725 TRACE(
"IntInsertMenuItemToList = %u %i\n", uItem, (
BOOL)((
INT)uItem >= 0));
782 if(!NewMenuItem)
return FALSE;
788 MenuItem =
Source->rgItems;
789 for (
i = 0;
i <
Source->cItems;
i++, MenuItem++, NewMenuItem++)
793 NewMenuItem->
wID = MenuItem->
wID;
868 ERR(
"SetMenuFlagRtoL\n");
883 if(lpmi->
fMask & MIM_BACKGROUND)
885 if(lpmi->
fMask & MIM_HELPID)
887 if(lpmi->
fMask & MIM_MAXHEIGHT)
889 if(lpmi->
fMask & MIM_MENUDATA)
891 if(lpmi->
fMask & MIM_STYLE)
918 if(lpmi->
fMask & MIM_BACKGROUND)
920 if(lpmi->
fMask & MIM_HELPID)
922 if(lpmi->
fMask & MIM_MAXHEIGHT)
924 if(lpmi->
fMask & MIM_MENUDATA)
926 if(lpmi->
fMask & MIM_STYLE)
928 if(lpmi->
fMask & MIM_APPLYTOSUBMENUS)
934 if (
item->spSubMenu )
954 if ( lpmi->
fMask & MIM_STYLE)
988 lpmii->
wID = MenuItem->
wID;
1037 PMENU SubMenuObject;
1040 if(!MenuItem || !MenuObject || !lpmii)
1046 MenuItem->
fType &= ~MENUITEMINFO_TYPE_MASK;
1054 ERR(
"IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
1089 MenuItem->
fState &= ~MFS_HBMMENUBMP;
1102 MenuItem->
wID = lpmii->
wID;
1123 if (MenuObject == SubMenuObject)
1126 ERR(
"Pop Up Menu Double Trouble!\n");
1131 if (!SubMenuObject)
return FALSE;
1137 ERR(
"Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
1224 if (!(MenuItem =
MENU_FindItem( &MenuObject, &uIDEnableItem, uEnable )))
return (
UINT)-1;
1233 switch (MenuItem->
wID)
1266 if (!(MenuItem =
MENU_FindItem( &MenuObject, &uIDCheckItem, uCheck )))
return -1;
1281 if (!MenuItem)
return FALSE;
1284 for (
i = 0;
i < MenuObject->
cItems;
i++, MenuItem++)
1286 MenuItem->
fState &= ~MFS_DEFAULT;
1290 if(uItem == (
UINT)-1)
1294 MenuItem = MenuObject->
rgItems;
1303 for (
i = 0;
i < MenuObject->
cItems;
i++, MenuItem++)
1305 if (MenuItem->
wID == uItem)
1323 if (!MenuItem)
return -1;
1328 if (
i >= MenuObject->
cItems )
return -1;
1341 if ( -1 !=
ret )
return ret;
1345 return ( fByPos ) ?
i : MenuItem->
wID;
1422 ERR(
"Invalid popup magic bitmap %d\n", (
int)popupMagic);
1468 UINT arrow_bitmap_height;
1470 rect->top += arrow_bitmap_height - menu->
iTop;
1471 rect->bottom += arrow_bitmap_height - menu->
iTop;
1526 if (!menu)
return -1;
1543 TRACE(
"\tlooking for '%c' (0x%02x) in [%p]\n", (
char)
Key,
Key, menu );
1551 if ( !ForceMenuChar )
1568 while (
p !=
NULL &&
p [1] ==
'&');
1645 size->cx = bm.bmWidth;
1646 size->cy = bm.bmHeight;
1664 int bmp_xoffset = 0;
1686 ERR(
"Get Item Data from this Window!!!\n");
1689 ERR(
"Draw Bitmap\n");
1785 top = (
h>bm.bmHeight) ?
rect->top+(
h-bm.bmHeight)/2 :
rect->top;
1797 NtGdiBitBlt(
hdc,
left,
top,
w,
h,
hdcMem, bmp_xoffset, 0,
rop , 0, 0);
1832 UINT arrow_bitmap_width;
1836 TRACE(
"dc=%x owner=%x (%d,%d)\n",
hdc, pwndOwner, orgX, orgY);
1868 TRACE(
"MF_OWNERDRAW id=%04lx size=%dx%d cx %d cy %d\n",
1880 lpitem->
xItem = orgX;
1881 lpitem->
yItem = orgY;
1907 itemheight =
size.cy + 2;
1910 lpitem->
cxItem += 2 * check_bitmap_width;
1913 lpitem->
cxItem += arrow_bitmap_width;
1918 itemheight =
size.cy;
1926 else if (!menuBar) {
1928 lpitem->
cxItem += check_bitmap_width;
1931 lpitem->
cxItem += arrow_bitmap_width;
1938 LONG txtheight, txtwidth;
1969 lpitem->
dxTab += txtwidth;
1970 txtheight =
max( txtheight, tmpheight);
1977 lpitem->
dxTab += txtwidth;
1979 lpitem->
cxItem += 2 + txtwidth;
1980 itemheight =
max( itemheight,
1987 }
else if( menuBar) {
1990 lpitem->
cyItem += itemheight;
2003 return lppop->
cyMax;
2019 int orgX, orgY, maxX, maxTab, maxTabWidth, maxHeight;
2023 if (Menu->
cItems == 0)
return;
2034 while (start < Menu->cItems)
2042 maxTab = maxTabWidth = 0;
2054 maxTab =
max( maxTab, lpitem->
dxTab );
2061 maxX =
max( maxX, maxTab + maxTabWidth );
2066 lpitem->
dxTab = maxTab;
2082 if (Menu->
cyMenu >= maxHeight)
2084 Menu->
cyMenu = maxHeight;
2107 int orgX, orgY, maxY;
2109 if ((lprect ==
NULL) || (lppop ==
NULL))
return;
2110 if (lppop->
cItems == 0)
return;
2118 while (start < lppop->cItems)
2121 orgX = lprect->
left;
2131 TRACE(
"calling MENU_CalcItemSize org=(%d, %d)\n", orgX, orgY );
2136 if (lpitem->cxItem > lprect->
right)
2139 else lpitem->cxItem = lprect->
right;
2141 maxY =
max( maxY, lpitem->cyItem );
2142 orgX = lpitem->cxItem;
2155 lprect->
bottom = maxY + 1;
2160 if (helpPos == ~0
U)
return;
2162 orgY = lpitem->yItem;
2163 orgX = lprect->
right;
2164 for (
i = lppop->
cItems - 1;
i >= helpPos;
i--, lpitem--) {
2165 if (lpitem->yItem != orgY)
break;
2166 if (lpitem->cxItem >= orgX)
break;
2167 lpitem->xItem += orgX - lpitem->cxItem;
2168 lpitem->cxItem = orgX;
2169 orgX = lpitem->xItem;
2180 UINT arrow_bitmap_height;
2189 rect.bottom = arrow_bitmap_height;
2193 rect.top = lppop->
cyMenu - arrow_bitmap_height;
2213 UINT arrow_bitmap_width = 0;
2231 bkgnd = (menuBar && flat_menu) ? COLOR_MENUBAR :
COLOR_MENU;
2237 if(menuBar && !flat_menu) {
2296 TRACE(
"Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, "
2297 "hwndItem=%p, hdc=%p, rcItem={%ld,%ld,%ld,%ld}\n", Wnd,
2415 bmprc.right = bmprc.left + lpitem->
cxBmp;
2422 bmprc.bottom = bmprc.top + lpitem->
cyBmp;
2447 check_bitmap_width, check_bitmap_height,
2456 r.right =
r.left + check_bitmap_width;
2467 bmpRect.
left += check_bitmap_width + 2;
2479 rectTemp.
left = rectTemp.
right - check_bitmap_width;
2484 rect.left += check_bitmap_width;
2485 rect.right -= arrow_bitmap_width;
2487 else if( lpitem->
hbmp)
2498 UINT uFormat = menuBar ?
2552 if (!menuBar &&
L'\0' !=
Text[
i])
2606 TRACE(
"DPM wnd=%p dc=%p menu=%p\n", wnd,
hdc, menu);
2624 if (menu && menu->
cItems)
2676 ERR(
"Already in End loop\n");
2792 TRACE(
"owner=%p hmenu=%p\n", pWndOwner, menu);
2815 if( !pWndCreated )
return FALSE;
2822 pPopupMenu = ((
PMENUWND)pWndCreated)->ppopupmenu;
2848#define SHOW_DEBUGRECT 0
2906 if (pExclude->
bottom + height < monitor->rcMonitor.bottom)
2926 if (pExclude->
right + width < monitor->rcMonitor.right)
2951 TRACE(
"owner=%p menu=%p id=0x%04x x=0x%04x y=0x%04x\n",
2952 pwndOwner, menu,
id,
x,
y);
2962 DebugRect(pExclude,
RGB(255, 0, 0));
2973 if (
flags & TPM_LAYOUTRTL)
2990 DebugPoint(
x,
y,
RGB(0, 0, 255));
3004 if (x < monitor->rcMonitor.left)
3009 if (x < monitor->rcMonitor.left ||
x >= monitor->
rcMonitor.
right || bIsPopup)
3014 if (y < monitor->rcMonitor.top)
3018 if (y < monitor->rcMonitor.top ||
y >= monitor->
rcMonitor.
bottom || bIsPopup)
3038 UINT flag_mods[] = {
3067 DebugRect(&rr,
RGB(0, 255, 0));
3075 ERR(
"menu->hWnd bad hwnd %p\n",menu->
hWnd);
3108 UINT arrow_bitmap_height;
3115 rc.
top += arrow_bitmap_height;
3116 rc.
bottom -= arrow_bitmap_height;
3120 if (
item->cyItem > lppop->
iTop + nMaxHeight)
3122 lppop->
iTop =
item->cyItem - nMaxHeight;
3127 else if (
item->yItem < lppop->
iTop)
3147 TRACE(
"M_SI: owner=%p menu=%p index=0x%04x select=0x%04x\n", pwndOwner, menu, wIndex, sendMenuSelect);
3149 if (!menu || !menu->
cItems)
return;
3155 if (menu->
iItem == wIndex)
return;
3180 menu->
iItem = wIndex;
3194 ip->fType |
ip->fState |
3201 else if (sendMenuSelect)
3232 TRACE(
"pwnd=%x menu=%x off=0x%04x\n", pwndOwner, menu,
offset);
3234 if ((!menu) || (!menu->
rgItems))
return;
3251 i >= 0 && i < menu->cItems ;
i +=
offset)
3267 TRACE(
"owner=%x menu=%x 0x%04x\n", pWndOwner, Menu, SendMenuSelect);
3276 if (!(
Item->spSubMenu) ||
3283 if (
Item->spSubMenu)
3322 TRACE(
"owner=%x menu=%p 0x%04x\n", WndOwner, Menu, SelectFirst);
3324 if (!Menu)
return Menu;
3423 if(
Flags & TPM_LAYOUTRTL)
3432 if(
Flags & TPM_LAYOUTRTL)
3444 Flags &= (~TPM_VERTICAL);
3459 return Item->spSubMenu;
3476 TRACE(
"%p menu=%p\n", pmt, Menu);
3487 if (!(
Item->spSubMenu))
3529 TRACE(
"%x menu=%x 0x%04x\n", pmt, PtMenu,
Index);
3531 if ( pmt->
TopMenu != PtMenu &&
3554 TRACE(
"%x PtMenu=%p\n", pmt, PtMenu);
3571 if (PtMenu->
iItem !=
id)
3597 TRACE(
"%p pmenu=%x\n", pmt, PtMenu);
3615 if (!(
item->spSubMenu))
3618 if (ExecutedMenuId == -1 || ExecutedMenuId == -2)
return -1;
3619 return ExecutedMenuId;
3648 if (!menu)
return NULL;
3654 if ( pItem ) pItem = &pItem[menu->
iItem];
3696 TRACE(
"SystemMenu\n");
3729 return item->spSubMenu;
3755 while (i < pmt->TopMenu->cItems) {
3788 TRACE(
"%p [%p] -> %p [%p]\n",
3818 else hNewMenu =
NULL;
3841 WARN(
" -- got confused.\n");
3925 PMENU MenuPrev, MenuTmp;
3927 MenuPrev = MenuTmp = pmt->
TopMenu;
3952 PMENU MenuTmp, MenuPrev;
3955 MenuPrev = MenuTmp = pmt->
TopMenu;
4003 TRACE(
"MenuKeyRight called, cur %p, top %p.\n",