📄 menu.c
字号:
{
Menu = UserGetMenuObject(CurItem->hSubMenu);
if (NULL != Menu)
{
ret = IntGetMenuItemByFlag(Menu, uSearchBy, fFlag,
MenuItem, PrevMenuItem);
if (-1 != ret)
{
return ret;
}
}
}
PrevItem = CurItem;
CurItem = CurItem->Next;
p++;
}
}
return -1;
}
int FASTCALL
IntInsertMenuItemToList(PMENU_OBJECT Menu, PMENU_ITEM MenuItem, int pos)
{
PMENU_ITEM CurItem;
PMENU_ITEM LastItem = NULL;
UINT npos = 0;
CurItem = Menu->MenuItemList;
if(pos <= -1)
{
while(CurItem)
{
LastItem = CurItem;
CurItem = CurItem->Next;
npos++;
}
}
else
{
while(CurItem && (pos > 0))
{
LastItem = CurItem;
CurItem = CurItem->Next;
pos--;
npos++;
}
}
if(CurItem)
{
if(LastItem)
{
/* insert the item before CurItem */
MenuItem->Next = LastItem->Next;
LastItem->Next = MenuItem;
}
else
{
/* insert at the beginning */
Menu->MenuItemList = MenuItem;
MenuItem->Next = CurItem;
}
}
else
{
if(LastItem)
{
/* append item */
LastItem->Next = MenuItem;
MenuItem->Next = NULL;
}
else
{
/* insert first item */
Menu->MenuItemList = MenuItem;
MenuItem->Next = NULL;
}
}
Menu->MenuInfo.MenuItemCount++;
return npos;
}
BOOL FASTCALL
IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */
PMENU_ITEM MenuItem, PROSMENUITEMINFO lpmii)
{
NTSTATUS Status;
if(lpmii->fMask & (MIIM_FTYPE | MIIM_TYPE))
{
lpmii->fType = MenuItem->fType;
}
if(lpmii->fMask & MIIM_BITMAP)
{
lpmii->hbmpItem = MenuItem->hbmpItem;
}
if(lpmii->fMask & MIIM_CHECKMARKS)
{
lpmii->hbmpChecked = MenuItem->hbmpChecked;
lpmii->hbmpUnchecked = MenuItem->hbmpUnchecked;
}
if(lpmii->fMask & MIIM_DATA)
{
lpmii->dwItemData = MenuItem->dwItemData;
}
if(lpmii->fMask & MIIM_ID)
{
lpmii->wID = MenuItem->wID;
}
if(lpmii->fMask & MIIM_STATE)
{
lpmii->fState = MenuItem->fState;
}
if(lpmii->fMask & MIIM_SUBMENU)
{
lpmii->hSubMenu = MenuItem->hSubMenu;
}
if ((lpmii->fMask & MIIM_STRING) ||
((lpmii->fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING)))
{
if (lpmii->dwTypeData == NULL)
{
lpmii->cch = MenuItem->Text.Length / sizeof(WCHAR);
}
else
{
Status = MmCopyToCaller(lpmii->dwTypeData, MenuItem->Text.Buffer,
min(lpmii->cch * sizeof(WCHAR),
MenuItem->Text.MaximumLength));
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
return FALSE;
}
}
}
if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
{
lpmii->Rect = MenuItem->Rect;
lpmii->XTab = MenuItem->XTab;
lpmii->Text = MenuItem->Text.Buffer;
}
return TRUE;
}
BOOL FASTCALL
IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINFO lpmii)
{
PMENU_OBJECT SubMenuObject;
UINT fTypeMask = (MFT_BITMAP | MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_OWNERDRAW | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_SEPARATOR | MF_POPUP);
if(!MenuItem || !MenuObject || !lpmii)
{
return FALSE;
}
if( lpmii->fType & ~fTypeMask)
{
DbgPrint("IntSetMenuItemInfo invalid fType flags %x\n", lpmii->fType & ~fTypeMask);
lpmii->fMask &= ~(MIIM_TYPE | MIIM_FTYPE);
}
if(lpmii->fMask & MIIM_TYPE)
{
if(lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP))
{
DbgPrint("IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
/* this does not happen on Win9x/ME */
SetLastNtError( ERROR_INVALID_PARAMETER);
return FALSE;
}
/*
* Delete the menu item type when changing type from
* MF_STRING.
*/
if (MenuItem->fType != lpmii->fType &&
MENU_ITEM_TYPE(MenuItem->fType) == MFT_STRING)
{
FreeMenuText(MenuItem);
RtlInitUnicodeString(&MenuItem->Text, NULL);
}
if(lpmii->fType & MFT_BITMAP)
{
if(lpmii->hbmpItem)
MenuItem->hbmpItem = lpmii->hbmpItem;
else
{ /* Win 9x/Me stuff */
MenuItem->hbmpItem = (HBITMAP)((ULONG_PTR)(LOWORD(lpmii->dwTypeData)));
}
}
MenuItem->fType |= lpmii->fType;
}
if (lpmii->fMask & MIIM_FTYPE )
{
if(( lpmii->fType & MFT_BITMAP))
{
DbgPrint("IntSetMenuItemInfo: Can not use FTYPE and MFT_BITMAP.\n");
SetLastNtError( ERROR_INVALID_PARAMETER);
return FALSE;
}
MenuItem->fType |= lpmii->fType; /* Need to save all the flags, this fixed MFT_RIGHTJUSTIFY */
}
if(lpmii->fMask & MIIM_BITMAP)
{
MenuItem->hbmpItem = lpmii->hbmpItem;
}
if(lpmii->fMask & MIIM_CHECKMARKS)
{
MenuItem->hbmpChecked = lpmii->hbmpChecked;
MenuItem->hbmpUnchecked = lpmii->hbmpUnchecked;
}
if(lpmii->fMask & MIIM_DATA)
{
MenuItem->dwItemData = lpmii->dwItemData;
}
if(lpmii->fMask & MIIM_ID)
{
MenuItem->wID = lpmii->wID;
}
if(lpmii->fMask & MIIM_STATE)
{
/* remove MFS_DEFAULT flag from all other menu items if this item
has the MFS_DEFAULT state */
if(lpmii->fState & MFS_DEFAULT)
UserSetMenuDefaultItem(MenuObject, -1, 0);
/* update the menu item state flags */
UpdateMenuItemState(MenuItem->fState, lpmii->fState);
}
if(lpmii->fMask & MIIM_SUBMENU)
{
MenuItem->hSubMenu = lpmii->hSubMenu;
/* Make sure the submenu is marked as a popup menu */
if (MenuItem->hSubMenu)
{
SubMenuObject = UserGetMenuObject(MenuItem->hSubMenu);
if (SubMenuObject != NULL)
{
SubMenuObject->MenuInfo.Flags |= MF_POPUP;
MenuItem->fType |= MF_POPUP;
}
else
{
MenuItem->fType &= ~MF_POPUP;
}
}
else
{
MenuItem->fType &= ~MF_POPUP;
}
}
if ((lpmii->fMask & MIIM_STRING) ||
((lpmii->fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING)))
{
FreeMenuText(MenuItem);
if(lpmii->dwTypeData && lpmii->cch)
{
UNICODE_STRING Source;
Source.Length =
Source.MaximumLength = lpmii->cch * sizeof(WCHAR);
Source.Buffer = lpmii->dwTypeData;
MenuItem->Text.Buffer = (PWSTR)ExAllocatePoolWithTag(
PagedPool, Source.Length + sizeof(WCHAR), TAG_STRING);
if(MenuItem->Text.Buffer != NULL)
{
MenuItem->Text.Length = 0;
MenuItem->Text.MaximumLength = Source.Length + sizeof(WCHAR);
RtlCopyUnicodeString(&MenuItem->Text, &Source);
MenuItem->Text.Buffer[MenuItem->Text.Length / sizeof(WCHAR)] = 0;
}
else
{
RtlInitUnicodeString(&MenuItem->Text, NULL);
}
}
else
{
if (0 == (MenuObject->MenuInfo.Flags & MF_SYSMENU))
{
MenuItem->fType |= MF_SEPARATOR;
}
RtlInitUnicodeString(&MenuItem->Text, NULL);
}
}
if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
{
MenuItem->Rect = lpmii->Rect;
MenuItem->XTab = lpmii->XTab;
lpmii->Text = MenuItem->Text.Buffer; /* Send back new allocated string or zero */
}
return TRUE;
}
BOOL FASTCALL
IntInsertMenuItem(PMENU_OBJECT MenuObject, UINT uItem, BOOL fByPosition,
PROSMENUITEMINFO ItemInfo)
{
int pos = (int)uItem;
PMENU_ITEM MenuItem;
if (MAX_MENU_ITEMS <= MenuObject->MenuInfo.MenuItemCount)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
if (fByPosition)
{
/* calculate position */
if(MenuObject->MenuInfo.MenuItemCount < pos)
{
pos = MenuObject->MenuInfo.MenuItemCount;
}
}
else
{
pos = IntGetMenuItemByFlag(MenuObject, uItem, MF_BYCOMMAND, NULL, NULL);
}
if (pos < -1)
{
pos = -1;
}
MenuItem = ExAllocatePoolWithTag(PagedPool, sizeof(MENU_ITEM), TAG_MENUITEM);
if (NULL == MenuItem)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
MenuItem->fType = MFT_STRING;
MenuItem->fState = MFS_ENABLED | MFS_UNCHECKED;
MenuItem->wID = 0;
MenuItem->hSubMenu = (HMENU)0;
MenuItem->hbmpChecked = (HBITMAP)0;
MenuItem->hbmpUnchecked = (HBITMAP)0;
MenuItem->dwItemData = 0;
RtlInitUnicodeString(&MenuItem->Text, NULL);
MenuItem->hbmpItem = (HBITMAP)0;
if (! IntSetMenuItemInfo(MenuObject, MenuItem, ItemInfo))
{
ExFreePool(MenuItem);
return FALSE;
}
/* Force size recalculation! */
MenuObject->MenuInfo.Height = 0;
pos = IntInsertMenuItemToList(MenuObject, MenuItem, pos);
DPRINT("IntInsertMenuItemToList = %i\n", pos);
return (pos >= 0);
}
UINT FASTCALL
IntEnableMenuItem(PMENU_OBJECT MenuObject, UINT uIDEnableItem, UINT uEnable)
{
PMENU_ITEM MenuItem;
UINT res = IntGetMenuItemByFlag(MenuObject, uIDEnableItem, uEnable, &MenuItem, NULL);
if(!MenuItem || (res == (UINT)-1))
{
return (UINT)-1;
}
res = MenuItem->fState & (MF_GRAYED | MF_DISABLED);
if(uEnable & MF_DISABLED)
{
if(!(MenuItem->fState & MF_DISABLED))
MenuItem->fState |= MF_DISABLED;
if(uEnable & MF_GRAYED)
{
if(!(MenuItem->fState & MF_GRAYED))
MenuItem->fState |= MF_GRAYED;
}
}
else
{
if(uEnable & MF_GRAYED)
{
if(!(MenuItem->fState & MF_GRAYED))
MenuItem->fState |= MF_GRAYED;
if(!(MenuItem->fState & MF_DISABLED))
MenuItem->fState |= MF_DISABLED;
}
else
{
if(MenuItem->fState & MF_DISABLED)
MenuItem->fState ^= MF_DISABLED;
if(MenuItem->fState & MF_GRAYED)
MenuItem->fState ^= MF_GRAYED;
}
}
return res;
}
DWORD FASTCALL
IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax)
{
DWORD res = 0;
UINT sz;
ROSMENUITEMINFO mii;
PVOID Buf;
PMENU_ITEM CurItem = MenuObject->MenuItemList;
PWCHAR StrOut;
NTSTATUS Status;
WCHAR NulByte;
if (0 != nMax)
{
if (nMax < MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO))
{
return 0;
}
StrOut = (PWCHAR)((char *) Buffer + MenuObject->MenuInfo.MenuItemCount
* sizeof(ROSMENUITEMINFO));
nMax -= MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO);
sz = sizeof(ROSMENUITEMINFO);
Buf = Buffer;
mii.cbSize = sizeof(ROSMENUITEMINFO);
mii.fMask = 0;
NulByte = L'\0';
while (NULL != CurItem)
{
mii.cch = CurItem->Text.Length / sizeof(WCHAR);
mii.dwItemData = CurItem->dwItemData;
if (0 != CurItem->Text.Length)
{
mii.dwTypeData = StrOut;
}
else
{
mii.dwTypeData = NULL;
}
mii.fState = CurItem->fState;
mii.fType = CurItem->fType;
mii.hbmpChecked = CurItem->hbmpChecked;
mii.hbmpItem = CurItem->hbmpItem;
mii.hbmpUnchecked = CurItem->hbmpUnchecked;
mii.hSubMenu = CurItem->hSubMenu;
mii.Rect = CurItem->Rect;
mii.XTab = CurItem->XTab;
mii.Text = CurItem->Text.Buffer;
Status = MmCopyToCaller(Buf, &mii, sizeof(ROSMENUITEMINFO));
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
return 0;
}
Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO));
if (0 != CurItem->Text.Length
&& (nMax >= CurItem->Text.Length + sizeof(WCHAR)))
{
/* copy string */
Status = MmCopyToCaller(StrOut, CurItem->Text.Buffer,
CurItem->Text.Length);
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
return 0;
}
StrOut += CurItem->Text.Length / sizeof(WCHAR);
Status = MmCopyToCaller(StrOut, &NulByte, sizeof(WCHAR));
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
return 0;
}
StrOut++;
nMax -= CurItem->Text.Length + sizeof(WCHAR);
}
else if (0 != CurItem->Text.Length)
{
break;
}
CurItem = CurItem->Next;
res++;
}
}
else
{
while (NULL != CurItem)
{
res += sizeof(ROSMENUITEMINFO) + CurItem->Text.Length + sizeof(WCHAR);
CurItem = CurItem->Next;
}
}
return res;
}
DWORD FASTCALL
IntCheckMenuItem(PMENU_OBJECT MenuObject, UINT uIDCheckItem, UINT uCheck)
{
PMENU_ITEM MenuItem;
int res = -1;
if((IntGetMenuItemByFlag(MenuObject, uIDCheckItem, uCheck, &MenuItem, NULL) < 0) || !MenuItem)
{
return -1;
}
res = (DWORD)(MenuItem->fState & MF_CHECKED);
if(uCheck & MF_CHECKED)
{
if(!(MenuItem->fState & MF_CHECKED))
MenuItem->fState |= MF_CHECKED;
}
else
{
if(MenuItem->fState & MF_CHECKED)
MenuItem->fState ^= MF_CHECKED;
}
return (DWORD)res;
}
BOOL FASTCALL
IntHiliteMenuItem(PWINDOW_OBJECT WindowObject, PMENU_OBJECT MenuObject,
UINT uItemHilite, UINT uHilite)
{
PMENU_ITEM MenuItem;
BOOL res = IntGetMenuItemByFlag(MenuObject, uItemHilite, uHilite, &MenuItem, NULL);
if(!MenuItem || !res)
{
return FALSE;
}
if(uHilite & MF_HILITE)
{
if(!(MenuItem->fState & MF_HILITE))
MenuItem->fState |= MF_HILITE;
}
else
{
if(MenuItem->fState & MF_HILITE)
MenuItem->fState ^= MF_HILITE;
}
/* FIXME - update the window's menu */
return TRUE;
}
BOOL FASTCALL
UserSetMenuDefaultItem(PMENU_OBJECT MenuObject, UINT uItem, UINT fByPos)
{
BOOL ret = FALSE;
PMENU_ITEM MenuItem = MenuObject->MenuItemList;
if(uItem == (UINT)-1)
{
while(MenuItem)
{
if(MenuItem->fState & MFS_DEFAULT)
MenuItem->fState ^= MFS_DEFAULT;
MenuItem = MenuItem->Next;
}
return TRUE;
}
if(fByPos)
{
UINT pos = 0;
while(MenuItem)
{
if(pos == uItem)
{
if(!(MenuItem->fState & MFS_DEFAULT))
MenuItem->fState |= MFS_DEFAULT;
ret = TRUE;
}
else
{
if(MenuItem->fState & MFS_DEFAULT)
MenuItem->fState ^= MFS_DEFAULT;
}
pos++;
MenuItem = MenuItem->Next;
}
}
else
{
while(MenuItem)
{
if(!ret && (MenuItem->wID == uItem))
{
if(!(MenuItem->fState & MFS_DEFAULT))
MenuItem->fState |= MFS_DEFAULT;
ret = TRUE;
}
else
{
if(MenuItem->fState & MFS_DEFAULT)
MenuItem->fState ^= MFS_DEFAULT;
}
MenuItem = MenuItem->Next;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -