/****************************** Module Header ******************************\ * Module Name: menuc.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * This module contains * * History: * 01-11-93 DavidPe Created \***************************************************************************/ #include "precomp.h" #pragma hdrstop FUNCLOG3(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, CheckMenuItem, HMENU, hMenu, UINT, uIDCheckItem, UINT, uCheck) DWORD CheckMenuItem( HMENU hMenu, UINT uIDCheckItem, UINT uCheck) { PMENU pMenu; PITEM pItem; pMenu = VALIDATEHMENU(hMenu); if (pMenu == NULL) { return (DWORD)-1; } /* * Get a pointer the the menu item */ if ((pItem = MNLookUpItem(pMenu, uIDCheckItem, (BOOL) (uCheck & MF_BYPOSITION), NULL)) == NULL) return (DWORD)-1; /* * If the item is already in the state we're * trying to set, just return. */ if ((pItem->fState & MFS_CHECKED) == (uCheck & MFS_CHECKED)) { return pItem->fState & MF_CHECKED; } return NtUserCheckMenuItem(hMenu, uIDCheckItem, uCheck); } FUNCLOG3(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, GetMenuDefaultItem, HMENU, hMenu, UINT, fByPosition, UINT, uFlags) UINT GetMenuDefaultItem(HMENU hMenu, UINT fByPosition, UINT uFlags) { PMENU pMenu; pMenu = VALIDATEHMENU(hMenu); if (pMenu == NULL) { return (DWORD)-1; } return _GetMenuDefaultItem(pMenu, (BOOL)fByPosition, uFlags); } /***************************************************************************\ * SetMenuItemInfoStruct * * History: * 07-22-96 GerardoB - Added header and Fixed up for 5.0 \***************************************************************************/ void SetMenuItemInfoStruct(HMENU hMenu, UINT wFlags, UINT_PTR wIDNew, LPWSTR pwszNew, LPMENUITEMINFO pmii) { PMENU pMenu; PITEM pItem; UserAssert(sizeof(MENUITEMINFOW) == sizeof(MENUITEMINFOA)); RtlZeroMemory(pmii, sizeof(*pmii)); pmii->fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE; /* * For compatibility, setting the bitmap drops the string and * viceversa; new apps that want to have sting and bitmaps * must use the MENUITEMINFO APIs */ if (wFlags & MFT_BITMAP) { pmii->fMask |= MIIM_BITMAP | MIIM_STRING; pmii->hbmpItem = (HBITMAP)pwszNew; pmii->dwTypeData = 0; } else if (!(wFlags & MFT_NONSTRING)) { pmii->fMask |= MIIM_BITMAP | MIIM_STRING; pmii->dwTypeData = pwszNew; pmii->hbmpItem = NULL; } if (wFlags & MF_POPUP) { pmii->fMask |= MIIM_SUBMENU; pmii->hSubMenu = (HMENU)wIDNew; } if (wFlags & MF_OWNERDRAW) { pmii->fMask |= MIIM_DATA; pmii->dwItemData = (ULONG_PTR) pwszNew; } pmii->fState = wFlags & MFS_OLDAPI_MASK; pmii->fType = wFlags & MFT_OLDAPI_MASK; pMenu = VALIDATEHMENU(hMenu); if (pMenu && pMenu->cItems) { pItem = &((PITEM)REBASEALWAYS(pMenu, rgItems))[0]; if (pItem && TestMFT(pItem, MFT_RIGHTORDER)) { pmii->fType |= MFT_RIGHTORDER; } } pmii->wID = (UINT)wIDNew; } /***************************************************************************\ * SetMenuItemInfo * * History: * 07-22-96 GerardoB - Added header \***************************************************************************/ FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetMenuInfo, HMENU, hMenu, LPCMENUINFO, lpmi) BOOL SetMenuInfo(HMENU hMenu, LPCMENUINFO lpmi) { if (!ValidateMENUINFO(lpmi, MENUAPI_SET)) { return FALSE; } return NtUserThunkedMenuInfo(hMenu, (LPCMENUINFO)lpmi); } /***************************************************************************\ * ChangeMenu * * Stub routine for compatibility with version < 3.0 * * History: \***************************************************************************/ FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ChangeMenuW, HMENU, hMenu, UINT, cmd, LPCWSTR, lpNewItem, UINT, IdItem, UINT, flags) BOOL ChangeMenuW( HMENU hMenu, UINT cmd, LPCWSTR lpNewItem, UINT IdItem, UINT flags) { /* * These next two statements take care of sleazyness needed for * compatability with old changemenu. */ if ((flags & MF_SEPARATOR) && cmd == MFMWFP_OFFMENU && !(flags & MF_CHANGE)) flags |= MF_APPEND; if (lpNewItem == NULL) flags |= MF_SEPARATOR; /* * MUST be MF_BYPOSITION for Win2.x compatability. */ if (flags & MF_REMOVE) return(NtUserRemoveMenu(hMenu, cmd, (DWORD)((flags & ~MF_REMOVE) | MF_BYPOSITION))); if (flags & MF_DELETE) return(NtUserDeleteMenu(hMenu, cmd, (DWORD)(flags & ~MF_DELETE))); if (flags & MF_CHANGE) return(ModifyMenuW(hMenu, cmd, (DWORD)((flags & ~MF_CHANGE) & (0x07F | MF_HELP | MF_BYPOSITION | MF_BYCOMMAND | MF_SEPARATOR)), IdItem, lpNewItem)); if (flags & MF_APPEND) return(AppendMenuW(hMenu, (UINT)(flags & ~MF_APPEND), IdItem, lpNewItem)); /* * Default is insert */ return(InsertMenuW(hMenu, cmd, (DWORD)(flags & ~MF_INSERT), IdItem, lpNewItem)); } FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ChangeMenuA, HMENU, hMenu, UINT, cmd, LPCSTR, lpNewItem, UINT, IdItem, UINT, flags) BOOL ChangeMenuA( HMENU hMenu, UINT cmd, LPCSTR lpNewItem, UINT IdItem, UINT flags) { /* * These next two statements take care of sleazyness needed for * compatability with old changemenu. */ if ((flags & MF_SEPARATOR) && cmd == MFMWFP_OFFMENU && !(flags & MF_CHANGE)) flags |= MF_APPEND; if (lpNewItem == NULL) flags |= MF_SEPARATOR; /* * MUST be MF_BYPOSITION for Win2.x compatability. */ if (flags & MF_REMOVE) return(NtUserRemoveMenu(hMenu, cmd, (DWORD)((flags & ~MF_REMOVE) | MF_BYPOSITION))); if (flags & MF_DELETE) return(NtUserDeleteMenu(hMenu, cmd, (DWORD)(flags & ~MF_DELETE))); if (flags & MF_CHANGE) return(ModifyMenuA(hMenu, cmd, (DWORD)((flags & ~MF_CHANGE) & (0x07F | MF_HELP | MF_BYPOSITION | MF_BYCOMMAND | MF_SEPARATOR)), IdItem, lpNewItem)); if (flags & MF_APPEND) return(AppendMenuA(hMenu, (UINT)(flags & ~MF_APPEND), IdItem, lpNewItem)); /* * Default is insert */ return(InsertMenuA(hMenu, cmd, (DWORD)(flags & ~MF_INSERT), IdItem, lpNewItem)); } LONG GetMenuCheckMarkDimensions() { return((DWORD)MAKELONG(SYSMET(CXMENUCHECK), SYSMET(CYMENUCHECK))); } /***************************************************************************\ * GetMenuContextHelpId * * Return the help id of a menu. * \***************************************************************************/ FUNCLOG1(LOG_GENERAL, WINUSERAPI DWORD, WINAPI, GetMenuContextHelpId, HMENU, hMenu) WINUSERAPI DWORD WINAPI GetMenuContextHelpId( HMENU hMenu) { PMENU pMenu; pMenu = VALIDATEHMENU(hMenu); if (pMenu == NULL) return 0; return pMenu->dwContextHelpId; } BOOL TrackPopupMenu( HMENU hMenu, UINT fuFlags, int x, int y, int nReserved, HWND hwnd, CONST RECT *prcRect) { UNREFERENCED_PARAMETER(nReserved); UNREFERENCED_PARAMETER(prcRect); return NtUserTrackPopupMenuEx(hMenu, fuFlags, x, y, hwnd, NULL); } /***************************************************************************\ * GetSysMenuHandle * * Returns a handle to the system menu of the given window. NULL if * the window doesn't have a system menu. * * History: \***************************************************************************/ PMENU xxxGetSysMenuHandle( PWND pwnd) { PMENU pMenu; if (TestWF(pwnd, WFSYSMENU)) { pMenu = pwnd->spmenuSys; /* * If the window doesn't have a System Menu, use the default one. */ if (pMenu == NULL) { /* * Change owner so this app can access this menu. */ pMenu = (PMENU)NtUserCallHwndLock(HWq(pwnd), SFI_XXXGETSYSMENUHANDLE); } } else { pMenu = NULL; } return pMenu; } BOOL WINAPI SetMenuItemBitmaps ( HMENU hMenu, UINT nPosition, UINT uFlags, HBITMAP hbmpUnchecked, HBITMAP hbmpChecked ) { MENUITEMINFO mii; mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_CHECKMARKS; mii.hbmpChecked = hbmpChecked; mii.hbmpUnchecked = hbmpUnchecked; return(SetMenuItemInfo(hMenu, nPosition, (BOOL) (uFlags & MF_BYPOSITION), &mii)); } FUNCLOG5(LOG_GENERAL, int, WINAPI, DrawMenuBarTemp, HWND, hwnd, HDC, hdc, LPCRECT, lprc, HMENU, hMenu, HFONT, hFont) int WINAPI DrawMenuBarTemp( HWND hwnd, HDC hdc, LPCRECT lprc, HMENU hMenu, HFONT hFont) { HDC hdcr; if (IsMetaFile(hdc)) return -1; hdcr = GdiConvertAndCheckDC(hdc); if (hdcr == (HDC)0) return -1; if (!hMenu) return -1; return NtUserDrawMenuBarTemp( hwnd, hdc, lprc, hMenu, hFont); } /***************************************************************************\ * * CheckMenuRadioItem() - * * Checks one menu item in a range, unchecking the others. This can be * done either MF_BYCOMMAND or MF_BYPOSITION. It works similarly to * CheckRadioButton(). * * The return value is TRUE if the given item was checked, FALSE if not. * * History * 04/04/97 GerardoB Moved to the client side \***************************************************************************/ FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, CheckMenuRadioItem, HMENU, hMenu, UINT, wIDFirst, UINT, wIDLast, UINT, wIDCheck, UINT, flags) BOOL CheckMenuRadioItem(HMENU hMenu, UINT wIDFirst, UINT wIDLast, UINT wIDCheck, UINT flags) { BOOL fByPosition = (BOOL) (flags & MF_BYPOSITION); PMENU pMenu, pMenuItemIsOn; PITEM pItem; UINT wIDCur; BOOL fChecked = FALSE; BOOL fFirst = TRUE; MENUITEMINFO mii; pMenu = VALIDATEHMENU(hMenu); if (pMenu == NULL) { return FALSE; } mii.cbSize = sizeof(mii); /* * Make sure we won't loop for ever */ wIDLast = min(wIDLast, (UINT)0xFFFFFFFE); for (wIDCur = wIDFirst; wIDCur <= wIDLast; wIDCur++) { pItem = MNLookUpItem(pMenu, wIDCur, fByPosition, &pMenuItemIsOn); /* * Continue searching if it didn't find the item or it's a separator */ if ((pItem == NULL) || TestMFT(pItem, MFT_SEPARATOR)) { continue; } /* * If this is the first one, rememeber what menu it's on because * all items are supposed to be in the same menu. */ if (fFirst) { pMenu = pMenuItemIsOn; hMenu = PtoHq(pMenu); fFirst = FALSE; } /* * If this item is on a different menu, don't touch it */ if (pMenu != pMenuItemIsOn) { continue; } /* * Set the new check state. Avoid the trip to the kernel if possible */ if (wIDCur == wIDCheck) { /* * Check it. */ if (!TestMFT(pItem, MFT_RADIOCHECK) || !TestMFS(pItem, MFS_CHECKED)) { mii.fMask = MIIM_FTYPE | MIIM_STATE; mii.fType = (pItem->fType & MFT_MASK) | MFT_RADIOCHECK; mii.fState = (pItem->fState & MFS_MASK) | MFS_CHECKED; NtUserThunkedMenuItemInfo(hMenu, wIDCheck, fByPosition, FALSE, &mii, NULL); } fChecked = TRUE; } else { /* * Uncheck it * NOTE: don't remove MFT_RADIOCHECK type */ if (TestMFS(pItem, MFS_CHECKED)) { mii.fMask = MIIM_STATE; mii.fState = (pItem->fState & MFS_MASK) & ~MFS_CHECKED; NtUserThunkedMenuItemInfo(hMenu, wIDCur, fByPosition, FALSE, &mii, NULL); } } } /* for */ if (fFirst) { /* * No item was ever found. */ RIPERR0(ERROR_MENU_ITEM_NOT_FOUND, RIP_VERBOSE, "CheckMenuRadioItem, no items found\n"); } return(fChecked); }