Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

451 lines
12 KiB

/****************************** 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);
}