⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menu.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 *  ReactOS W32 Subsystem
 *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/* $Id: menu.c 27161 2007-06-12 19:35:15Z janderwald $
 *
 * COPYRIGHT:        See COPYING in the top level directory
 * PROJECT:          ReactOS kernel
 * PURPOSE:          Menus
 * FILE:             subsys/win32k/ntuser/menu.c
 * PROGRAMER:        Thomas Weidenmueller (w3seek@users.sourceforge.net)
 * REVISION HISTORY:
 *       07/30/2003  CSH  Created
 */
/* INCLUDES ******************************************************************/

#include <w32k.h>

#define NDEBUG
#include <debug.h>

PMENU_OBJECT FASTCALL
IntGetSystemMenu(PWINDOW_OBJECT Window, BOOL bRevert, BOOL RetMenu);



/* STATIC FUNCTION ***********************************************************/

static
BOOL FASTCALL
UserMenuItemInfo(
   PMENU_OBJECT Menu,
   UINT Item,
   BOOL ByPosition,
   PROSMENUITEMINFO UnsafeItemInfo,
   BOOL SetOrGet);

static
BOOL FASTCALL
UserMenuInfo(
   PMENU_OBJECT Menu,
   PROSMENUINFO UnsafeMenuInfo,
   BOOL SetOrGet);

/* INTERNAL ******************************************************************/

/* maximum number of menu items a menu can contain */
#define MAX_MENU_ITEMS (0x4000)
#define MAX_GOINTOSUBMENU (0x10)

#define UpdateMenuItemState(state, change) \
{\
  if((change) & MFS_DISABLED) { \
    (state) |= MFS_DISABLED; \
  } else { \
    (state) &= ~MFS_DISABLED; \
  } \
  if((change) & MFS_CHECKED) { \
    (state) |= MFS_CHECKED; \
  } else { \
    (state) &= ~MFS_CHECKED; \
  } \
  if((change) & MFS_HILITE) { \
    (state) |= MFS_HILITE; \
  } else { \
    (state) &= ~MFS_HILITE; \
  } \
  if((change) & MFS_DEFAULT) { \
    (state) |= MFS_DEFAULT; \
  } else { \
    (state) &= ~MFS_DEFAULT; \
  } \
  if((change) & MF_MOUSESELECT) { \
    (state) |= MF_MOUSESELECT; \
  } else { \
    (state) &= ~MF_MOUSESELECT; \
  } \
}

#define FreeMenuText(MenuItem) \
{ \
  if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
           (MenuItem)->Text.Length) { \
    RtlFreeUnicodeString(&(MenuItem)->Text); \
  } \
}

#define InRect(r, x, y) \
      ( ( ((r).right >=  x)) && \
        ( ((r).left <= x)) && \
        ( ((r).bottom >=  y)) && \
        ( ((r).top <= y)) )

NTSTATUS FASTCALL
InitMenuImpl(VOID)
{
   return(STATUS_SUCCESS);
}

NTSTATUS FASTCALL
CleanupMenuImpl(VOID)
{
   return(STATUS_SUCCESS);
}

PMENU_OBJECT FASTCALL UserGetMenuObject(HMENU hMenu)
{
   PMENU_OBJECT Menu;
   
   if (!hMenu)
   {
      SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
      return NULL;
   }
   
   Menu = (PMENU_OBJECT)UserGetObject(gHandleTable, hMenu, otMenu);
   if (!Menu)
   {
      SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
      return NULL;
   }

   ASSERT(USER_BODY_TO_HEADER(Menu)->RefCount >= 0);
   return Menu;
}


#if 0
void FASTCALL
DumpMenuItemList(PMENU_ITEM MenuItem)
{
   UINT cnt = 0;
   while(MenuItem)
   {
      if(MenuItem->Text.Length)
         DbgPrint(" %d. %wZ\n", ++cnt, &MenuItem->Text);
      else
         DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt, (DWORD)MenuItem->Text.Buffer);
      DbgPrint("   fType=");
      if(MFT_BITMAP & MenuItem->fType)
         DbgPrint("MFT_BITMAP ");
      if(MFT_MENUBARBREAK & MenuItem->fType)
         DbgPrint("MFT_MENUBARBREAK ");
      if(MFT_MENUBREAK & MenuItem->fType)
         DbgPrint("MFT_MENUBREAK ");
      if(MFT_OWNERDRAW & MenuItem->fType)
         DbgPrint("MFT_OWNERDRAW ");
      if(MFT_RADIOCHECK & MenuItem->fType)
         DbgPrint("MFT_RADIOCHECK ");
      if(MFT_RIGHTJUSTIFY & MenuItem->fType)
         DbgPrint("MFT_RIGHTJUSTIFY ");
      if(MFT_SEPARATOR & MenuItem->fType)
         DbgPrint("MFT_SEPARATOR ");
      if(MFT_STRING & MenuItem->fType)
         DbgPrint("MFT_STRING ");
      DbgPrint("\n   fState=");
      if(MFS_DISABLED & MenuItem->fState)
         DbgPrint("MFS_DISABLED ");
      else
         DbgPrint("MFS_ENABLED ");
      if(MFS_CHECKED & MenuItem->fState)
         DbgPrint("MFS_CHECKED ");
      else
         DbgPrint("MFS_UNCHECKED ");
      if(MFS_HILITE & MenuItem->fState)
         DbgPrint("MFS_HILITE ");
      else
         DbgPrint("MFS_UNHILITE ");
      if(MFS_DEFAULT & MenuItem->fState)
         DbgPrint("MFS_DEFAULT ");
      if(MFS_GRAYED & MenuItem->fState)
         DbgPrint("MFS_GRAYED ");
      DbgPrint("\n   wId=%d\n", MenuItem->wID);
      MenuItem = MenuItem->Next;
   }
   DbgPrint("Entries: %d\n", cnt);
   return;
}
#endif

PMENU_OBJECT FASTCALL
IntGetMenuObject(HMENU hMenu)
{
   PMENU_OBJECT Menu = UserGetMenuObject(hMenu);
   if (Menu)
   {
      ASSERT(USER_BODY_TO_HEADER(Menu)->RefCount >= 0);

      USER_BODY_TO_HEADER(Menu)->RefCount++;
   }
   return Menu;
}

BOOL FASTCALL
IntFreeMenuItem(PMENU_OBJECT Menu, PMENU_ITEM MenuItem,
                BOOL RemoveFromList, BOOL bRecurse)
{
   FreeMenuText(MenuItem);
   if(RemoveFromList)
   {
      PMENU_ITEM CurItem = Menu->MenuItemList;
      while(CurItem)
      {
         if (CurItem->Next == MenuItem)
         {
            CurItem->Next = MenuItem->Next;
            break;
         }
         else
         {
            CurItem = CurItem->Next;
         }
      }
      Menu->MenuInfo.MenuItemCount--;
   }
   if(bRecurse && MenuItem->hSubMenu)
   {
      PMENU_OBJECT SubMenu;
      SubMenu = UserGetMenuObject(MenuItem->hSubMenu );
      if(SubMenu)
      {
         IntDestroyMenuObject(SubMenu, bRecurse, TRUE);
      }
   }

   /* Free memory */
   ExFreePool(MenuItem);

   return TRUE;
}

BOOL FASTCALL
IntRemoveMenuItem(PMENU_OBJECT Menu, UINT uPosition, UINT uFlags,
                  BOOL bRecurse)
{
   PMENU_ITEM PrevMenuItem, MenuItem;
   if(IntGetMenuItemByFlag(Menu, uPosition, uFlags, &MenuItem,
                           &PrevMenuItem) > -1)
   {
      if(MenuItem)
      {
         if(PrevMenuItem)
            PrevMenuItem->Next = MenuItem->Next;
         else
         {
            Menu->MenuItemList = MenuItem->Next;
         }
         return IntFreeMenuItem(Menu, MenuItem, TRUE, bRecurse);
      }
   }
   return FALSE;
}

UINT FASTCALL
IntDeleteMenuItems(PMENU_OBJECT Menu, BOOL bRecurse)
{
   UINT res = 0;
   PMENU_ITEM NextItem;
   PMENU_ITEM CurItem = Menu->MenuItemList;
   while(CurItem)
   {
      NextItem = CurItem->Next;
      IntFreeMenuItem(Menu, CurItem, FALSE, bRecurse);
      CurItem = NextItem;
      res++;
   }
   Menu->MenuInfo.MenuItemCount = 0;
   Menu->MenuItemList = NULL;
   return res;
}

BOOL FASTCALL
IntDestroyMenuObject(PMENU_OBJECT Menu,
                     BOOL bRecurse, BOOL RemoveFromProcess)
{
   if(Menu)
   {
      PWINDOW_OBJECT Window;
      PWINSTATION_OBJECT WindowStation;
      NTSTATUS Status;

      /* remove all menu items */
      IntDeleteMenuItems(Menu, bRecurse); /* do not destroy submenus */

      if(RemoveFromProcess)
      {
         RemoveEntryList(&Menu->ListEntry);
      }

      Status = ObReferenceObjectByHandle(Menu->Process->Win32WindowStation,
                                         0,
                                         ExWindowStationObjectType,
                                         KernelMode,
                                         (PVOID*)&WindowStation,
                                         NULL);
      if(NT_SUCCESS(Status))
      {
         if (Menu->MenuInfo.Wnd)
         {
            Window = UserGetWindowObject(Menu->MenuInfo.Wnd);
            if (Window)
            {
               Window->IDMenu = 0;
            }
         }
         ObmDeleteObject(Menu->MenuInfo.Self, otMenu);
         ObDereferenceObject(WindowStation);
         return TRUE;
      }
   }
   return FALSE;
}

PMENU_OBJECT FASTCALL
IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar)
{
   PMENU_OBJECT Menu;

   Menu = (PMENU_OBJECT)ObmCreateObject(
             gHandleTable, Handle,
             otMenu, sizeof(MENU_OBJECT));

   if(!Menu)
   {
      *Handle = 0;
      return NULL;
   }

   Menu->Process = PsGetCurrentProcess();
   Menu->RtoL = FALSE; /* default */
   Menu->MenuInfo.cbSize = sizeof(MENUINFO); /* not used */
   Menu->MenuInfo.fMask = 0; /* not used */
   Menu->MenuInfo.dwStyle = 0; /* FIXME */
   Menu->MenuInfo.cyMax = 0; /* default */
   Menu->MenuInfo.hbrBack =
      NtGdiCreateSolidBrush(RGB(192, 192, 192), 0); /* FIXME: default background color */
   Menu->MenuInfo.dwContextHelpID = 0; /* default */
   Menu->MenuInfo.dwMenuData = 0; /* default */
   Menu->MenuInfo.Self = *Handle;
   Menu->MenuInfo.FocusedItem = NO_SELECTED_ITEM;
   Menu->MenuInfo.Flags = (IsMenuBar ? 0 : MF_POPUP);
   Menu->MenuInfo.Wnd = NULL;
   Menu->MenuInfo.WndOwner = NULL;
   Menu->MenuInfo.Height = 0;
   Menu->MenuInfo.Width = 0;
   Menu->MenuInfo.TimeToHide = FALSE;

   Menu->MenuInfo.MenuItemCount = 0;
   Menu->MenuItemList = NULL;

   /* Insert menu item into process menu handle list */
   InsertTailList(&PsGetCurrentProcessWin32Process()->MenuListHead, &Menu->ListEntry);

   return Menu;
}

BOOL FASTCALL
IntCloneMenuItems(PMENU_OBJECT Destination, PMENU_OBJECT Source)
{
   PMENU_ITEM MenuItem, NewMenuItem = NULL;
   PMENU_ITEM Old = NULL;

   if(!Source->MenuInfo.MenuItemCount)
      return FALSE;

   MenuItem = Source->MenuItemList;
   while(MenuItem)
   {
      Old = NewMenuItem;
      if(NewMenuItem)
         NewMenuItem->Next = MenuItem;
      NewMenuItem = ExAllocatePoolWithTag(PagedPool, sizeof(MENU_ITEM), TAG_MENUITEM);
      if(!NewMenuItem)
         break;
      NewMenuItem->fType = MenuItem->fType;
      NewMenuItem->fState = MenuItem->fState;
      NewMenuItem->wID = MenuItem->wID;
      NewMenuItem->hSubMenu = MenuItem->hSubMenu;
      NewMenuItem->hbmpChecked = MenuItem->hbmpChecked;
      NewMenuItem->hbmpUnchecked = MenuItem->hbmpUnchecked;
      NewMenuItem->dwItemData = MenuItem->dwItemData;
      if((MENU_ITEM_TYPE(NewMenuItem->fType) == MF_STRING))
      {
         if(MenuItem->Text.Length)
         {
            NewMenuItem->Text.Length = 0;
            NewMenuItem->Text.MaximumLength = MenuItem->Text.MaximumLength;
            NewMenuItem->Text.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, MenuItem->Text.MaximumLength, TAG_STRING);
            if(!NewMenuItem->Text.Buffer)
            {
               ExFreePool(NewMenuItem);
               break;
            }
            RtlCopyUnicodeString(&NewMenuItem->Text, &MenuItem->Text);
         }
         else
         {
            NewMenuItem->Text.Buffer = MenuItem->Text.Buffer;
         }
      }
      else
      {
         NewMenuItem->Text.Buffer = MenuItem->Text.Buffer;
      }
      NewMenuItem->hbmpItem = MenuItem->hbmpItem;

      NewMenuItem->Next = NULL;
      if(Old)
         Old->Next = NewMenuItem;
      else
         Destination->MenuItemList = NewMenuItem;
      Destination->MenuInfo.MenuItemCount++;
      MenuItem = MenuItem->Next;
   }

   return TRUE;
}

PMENU_OBJECT FASTCALL
IntCloneMenu(PMENU_OBJECT Source)
{
   HANDLE hMenu;
   PMENU_OBJECT Menu;

   if(!Source)
      return NULL;

   Menu = (PMENU_OBJECT)ObmCreateObject(
             gHandleTable, &hMenu,
             otMenu, sizeof(MENU_OBJECT));

   if(!Menu)
      return NULL;

   Menu->Process = PsGetCurrentProcess();
   Menu->RtoL = Source->RtoL;
   Menu->MenuInfo.cbSize = sizeof(MENUINFO); /* not used */
   Menu->MenuInfo.fMask = Source->MenuInfo.fMask;
   Menu->MenuInfo.dwStyle = Source->MenuInfo.dwStyle;
   Menu->MenuInfo.cyMax = Source->MenuInfo.cyMax;
   Menu->MenuInfo.hbrBack = Source->MenuInfo.hbrBack;
   Menu->MenuInfo.dwContextHelpID = Source->MenuInfo.dwContextHelpID;
   Menu->MenuInfo.dwMenuData = Source->MenuInfo.dwMenuData;
   Menu->MenuInfo.Self = hMenu;
   Menu->MenuInfo.FocusedItem = NO_SELECTED_ITEM;
   Menu->MenuInfo.Wnd = NULL;
   Menu->MenuInfo.WndOwner = NULL;
   Menu->MenuInfo.Height = 0;
   Menu->MenuInfo.Width = 0;
   Menu->MenuInfo.TimeToHide = FALSE;

   Menu->MenuInfo.MenuItemCount = 0;
   Menu->MenuItemList = NULL;

   /* Insert menu item into process menu handle list */
   InsertTailList(&PsGetCurrentProcessWin32Process()->MenuListHead, &Menu->ListEntry);

   IntCloneMenuItems(Menu, Source);

   return Menu;
}

BOOL FASTCALL
IntSetMenuFlagRtoL(PMENU_OBJECT Menu)
{
   Menu->RtoL = TRUE;
   return TRUE;
}

BOOL FASTCALL
IntSetMenuContextHelpId(PMENU_OBJECT Menu, DWORD dwContextHelpId)
{
   Menu->MenuInfo.dwContextHelpID = dwContextHelpId;
   return TRUE;
}

BOOL FASTCALL
IntGetMenuInfo(PMENU_OBJECT Menu, PROSMENUINFO lpmi)
{
   if(lpmi->fMask & MIM_BACKGROUND)
      lpmi->hbrBack = Menu->MenuInfo.hbrBack;
   if(lpmi->fMask & MIM_HELPID)
      lpmi->dwContextHelpID = Menu->MenuInfo.dwContextHelpID;
   if(lpmi->fMask & MIM_MAXHEIGHT)
      lpmi->cyMax = Menu->MenuInfo.cyMax;
   if(lpmi->fMask & MIM_MENUDATA)
      lpmi->dwMenuData = Menu->MenuInfo.dwMenuData;
   if(lpmi->fMask & MIM_STYLE)
      lpmi->dwStyle = Menu->MenuInfo.dwStyle;
   if (sizeof(MENUINFO) < lpmi->cbSize)
   {
      RtlCopyMemory((char *) lpmi + sizeof(MENUINFO),
                    (char *) &Menu->MenuInfo + sizeof(MENUINFO),
                    lpmi->cbSize - sizeof(MENUINFO));
   }
   if (sizeof(ROSMENUINFO) == lpmi->cbSize)
   {
     lpmi->maxBmpSize.cx = Menu->MenuInfo.maxBmpSize.cx;
     lpmi->maxBmpSize.cy = Menu->MenuInfo.maxBmpSize.cy;
   }
   return TRUE;
}


BOOL FASTCALL
IntIsMenu(HMENU hMenu)
{
   PMENU_OBJECT Menu;

   if((Menu = UserGetMenuObject(hMenu)))
   {
      return TRUE;
   }
   return FALSE;
}


BOOL FASTCALL
IntSetMenuInfo(PMENU_OBJECT Menu, PROSMENUINFO lpmi)
{
   if(lpmi->fMask & MIM_BACKGROUND)
      Menu->MenuInfo.hbrBack = lpmi->hbrBack;
   if(lpmi->fMask & MIM_HELPID)
      Menu->MenuInfo.dwContextHelpID = lpmi->dwContextHelpID;
   if(lpmi->fMask & MIM_MAXHEIGHT)
      Menu->MenuInfo.cyMax = lpmi->cyMax;
   if(lpmi->fMask & MIM_MENUDATA)
      Menu->MenuInfo.dwMenuData = lpmi->dwMenuData;
   if(lpmi->fMask & MIM_STYLE)
      Menu->MenuInfo.dwStyle = lpmi->dwStyle;
   if(lpmi->fMask & MIM_APPLYTOSUBMENUS)
   {
      /* FIXME */
   }
   if (sizeof(MENUINFO) < lpmi->cbSize)
   {
      Menu->MenuInfo.FocusedItem = lpmi->FocusedItem;
      Menu->MenuInfo.Height = lpmi->Height;
      Menu->MenuInfo.Width = lpmi->Width;
      Menu->MenuInfo.Wnd = lpmi->Wnd;
      Menu->MenuInfo.WndOwner = lpmi->WndOwner;
      Menu->MenuInfo.TimeToHide = lpmi->TimeToHide;
   }
   if (sizeof(ROSMENUINFO) == lpmi->cbSize)
   {
     Menu->MenuInfo.maxBmpSize.cx = lpmi->maxBmpSize.cx;
     Menu->MenuInfo.maxBmpSize.cy = lpmi->maxBmpSize.cy;
   }
   return TRUE;
}


int FASTCALL
IntGetMenuItemByFlag(PMENU_OBJECT Menu, UINT uSearchBy, UINT fFlag,
                     PMENU_ITEM *MenuItem, PMENU_ITEM *PrevMenuItem)
{
   PMENU_ITEM PrevItem = NULL;
   PMENU_ITEM CurItem = Menu->MenuItemList;
   int p;
   int ret;

   if(MF_BYPOSITION & fFlag)
   {
      p = uSearchBy;
      while(CurItem && (p > 0))
      {
         PrevItem = CurItem;
         CurItem = CurItem->Next;
         p--;
      }
      if(CurItem)
      {
         if(MenuItem)
            *MenuItem = CurItem;
         if(PrevMenuItem)
            *PrevMenuItem = PrevItem;
      }
      else
      {
         if(MenuItem)
            *MenuItem = NULL;
         if(PrevMenuItem)
            *PrevMenuItem = NULL; /* ? */
         return -1;
      }

      return uSearchBy - p;
   }
   else
   {
      p = 0;
      while(CurItem)
      {
         if(CurItem->wID == uSearchBy)
         {
            if(MenuItem)
               *MenuItem = CurItem;
            if(PrevMenuItem)
               *PrevMenuItem = PrevItem;
            return p;
         }
         else if (0 != (CurItem->fType & MF_POPUP))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -